Avatar billede windcape Praktikant
28. august 2007 - 04:58 Der er 3 kommentarer og
1 løsning

DirectX - Mesh generation fra heightmap

Hejsa

Jeg har et problem med at genere et Mesh ud fra mit heightmap, som jeg bruger til 3D generation.
(Se http://web27190.web08.talkactive.net/upload/files/woot.png for grafisk eksempel).

Jeg har før prøvet at bruge et DirectX.Direct3D Mesh , men jeg kan ikke få understøttelse for antallet af mine polygoner hvilket er omkring 100.000.
Jeg har forsøgt at følge følgende tutorial, men uden held, og derfor gået tilbage til min nuværende kode.

Spørgsmålet er så om nogen herinde kan give mig et tip til hvordan jeg kan generere mine heightmap som Meshes (da jeg gerne vil rendere flere ved siden af hinanden, hvilket burde være nemmere med meshes).

Kode: (MapPanel.cs)

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using KalOnline;
using KalOnline.Maps;

namespace KCM
{
    public class MapPanel
    {
        private int mapWidth  = 256;
        private int mapHeight = 256;
       
        private HeightMap heightMap;
        private ColorMap colorMap;

        private Panel _mapPanel;
        private KCMEditor _parent;

        private Device device;
        private CustomVertex.PositionColored[] vertices;
        private VertexBuffer vertexBuffer;
        private IndexBuffer indexBuffer;
       
        private int[] indices;
        private float zAngle = 0f;

        public MapPanel(ClientMap map,Panel mapPanel,KCMEditor parent)
        {
            heightMap = map.HeightMap;
            colorMap  = map.ColorMap;
           
            _mapPanel = mapPanel;
            _parent  = parent;
           
            Process();
        }
       
        public void DecreaseAngle() {
            zAngle -= 0.03f;
            Draw();
        }
       
        public void IncreaseAngle() {
            zAngle += 0.03f;
            Draw();
        }
       
        private int zoomFactor = 380;
       
        public void ZoomIn() {
            zoomFactor += 10;

            CameraPositioning();
            Draw();   
        }

        public void ZoomOut() {
            zoomFactor -= 10;

            CameraPositioning();
            Draw();   
        }

        public void InitializeDevice()
        {
            PresentParameters presentParams = new PresentParameters();
            presentParams.Windowed  = true;
            presentParams.SwapEffect = SwapEffect.Discard;
            presentParams.AutoDepthStencilFormat = DepthFormat.D16;
            presentParams.EnableAutoDepthStencil = true;
           
            device = new Device(0,
                DeviceType.Hardware,
                _mapPanel,
                CreateFlags.MixedVertexProcessing,
                presentParams
            );
            device.RenderState.FillMode = FillMode.Solid;
            device.RenderState.CullMode = Cull.None;
        }
       
        private void CameraPositioning()
        {
            device.Transform.Projection = Matrix.PerspectiveFovLH(
                (float)Math.PI / 4, 800 / 800, 1f, 800f
            );
            device.Transform.View = Matrix.LookAtLH(
                new Vector3(-180, 180, zoomFactor),
                new Vector3(0, 0, 0),
                new Vector3(0, 0, 1)
            );
            device.RenderState.Lighting = false;
            device.RenderState.CullMode = Cull.None;
        }

        private void VertexDeclaration()
        {
            vertexBuffer = new VertexBuffer(
                typeof(CustomVertex.PositionColored),
                mapWidth * mapWidth,
                device,
                Usage.Dynamic | Usage.WriteOnly,
                CustomVertex.PositionColored.Format,
                Pool.Default
            );
            vertices = new CustomVertex.PositionColored[mapWidth * mapHeight];

            int tmpHeight;
           
            for(int x = 0;x < mapWidth;x++)
            for(int y = 0;y < mapHeight;y++)
            {
                tmpHeight = heightMap.GetHeight(x,y) / 20;
                vertices[x + y * mapWidth].Position = new Vector3(x, y,tmpHeight);
                vertices[x + y * mapWidth].Color    = colorMap.GetColor(x,y).ToArgb();
            }
           
            vertexBuffer.SetData(vertices,0,LockFlags.None);
        }

        private void IndicesDeclaration()
        {
            indexBuffer = new IndexBuffer(
                typeof(int),
                (mapWidth-1) * (mapHeight-1) * 6,
                device,
                Usage.WriteOnly,
                Pool.Default
            );
            indices = new int[(mapWidth - 1) * (mapHeight - 1) * 6];

            for(int x = 0;x < (mapWidth - 1);x++)
            for(int y = 0;y < (mapHeight - 1);y++)
            {
                indices[(x + y * (mapWidth - 1)) * 6]    = (int)(x + y * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 1] = (int)((x + 1) + y * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 2] = (int)((x + 1) + (y + 1) * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 3] = (int)(x + (y + 1) * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 4] = (int)(x + y * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 5] = (int)((x + 1) + (y + 1) * mapWidth);
            }
           
            indexBuffer.SetData(indices,0,LockFlags.None);
        }

        public void Process()
        {
            InitializeDevice();
            CameraPositioning();
            VertexDeclaration();
            IndicesDeclaration();
            Draw();
        }

        public void Draw()
        {
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
            device.BeginScene();

            device.VertexFormat = CustomVertex.PositionColored.Format;
            device.SetStreamSource(0, vertexBuffer, 0);
            device.Indices = indexBuffer;
            device.Transform.World = Matrix.Translation(-mapHeight / 2, -mapWidth / 2, 0) * Matrix.RotationZ(zAngle);
            device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, mapWidth * mapHeight, 0, indices.Length / 3);
           
            device.EndScene();
            device.Present();
        }
       
    }
}
Avatar billede windcape Praktikant
28. august 2007 - 04:59 #1
Avatar billede windcape Praktikant
28. august 2007 - 05:11 #2
numFaces = 130050
numVertices = 65536

Koden som benytter Mesh ses her, men skaber en DirectX fejl i

meshTerrain = new Mesh(
                numFaces,
                numVertices,
                MeshFlags.Managed,
                CustomVertex.PositionColored.Format,
                device
            );

Fejlen er ikke angivet explicit pga. DirectX har et dårlig debug api, men det er noget i retning af at der er for mange faces eller vertices.

Kode:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using KalOnline;
using KalOnline.Maps;

namespace KCM
{
    public class MapPanel
    {
        private int mapWidth  = 256;
        private int mapHeight = 256;
       
        private HeightMap heightMap;
        private ColorMap colorMap;

        private Panel _mapPanel;
        private KCMEditor _parent;

        private Device device;
        private CustomVertex.PositionColored[] vertices;
       
        //private VertexBuffer vertexBuffer;
        //private IndexBuffer indexBuffer;
        //private int[] indices;
       
        private short[] indices;

        private float zAngle = 0f;
       
        private Mesh meshTerrain;

        public MapPanel(ClientMap map,Panel mapPanel,KCMEditor parent)
        {
            heightMap = map.HeightMap;
            colorMap  = map.ColorMap;
           
            _mapPanel = mapPanel;
            _parent  = parent;
           
            Process();
        }
       
        public void DecreaseAngle() {
            zAngle -= 0.03f;
            Draw();
        }
       
        public void IncreaseAngle() {
            zAngle += 0.03f;
            Draw();
        }
       
        private int zoomFactor = 380;
       
        public void ZoomIn() {
            zoomFactor += 10;

            CameraPositioning();
            Draw();   
        }

        public void ZoomOut() {
            zoomFactor -= 10;

            CameraPositioning();
            Draw();   
        }

        public void InitializeDevice()
        {
            PresentParameters presentParams = new PresentParameters();
            presentParams.Windowed  = true;
            presentParams.SwapEffect = SwapEffect.Discard;
            presentParams.AutoDepthStencilFormat = DepthFormat.D16;
            presentParams.EnableAutoDepthStencil = true;
           
            device = new Device(0,
                DeviceType.Hardware,
                _mapPanel,
                CreateFlags.MixedVertexProcessing,
                presentParams
            );
            device.RenderState.FillMode = FillMode.Solid;
            device.RenderState.CullMode = Cull.None;
        }
       
        private void CameraPositioning()
        {
            device.Transform.Projection = Matrix.PerspectiveFovLH(
                (float)Math.PI / 4, 800 / 800, 1f, 800f
            );
            device.Transform.View = Matrix.LookAtLH(
                new Vector3(-180, 180, zoomFactor),
                new Vector3(0, 0, 0),
                new Vector3(0, 0, 1)
            );
            device.RenderState.Lighting = false;
            device.RenderState.CullMode = Cull.None;
        }

        private void VertexDeclaration()
        {
            //vertexBuffer = new VertexBuffer(
            //    typeof(CustomVertex.PositionColored),
            //    mapWidth * mapWidth,
            //    device,
            //    Usage.Dynamic | Usage.WriteOnly,
            //    CustomVertex.PositionColored.Format,
            //    Pool.Default
            //);
            vertices = new CustomVertex.PositionColored[mapWidth * mapHeight];

            int tmpHeight;
           
            for(int x = 0;x < mapWidth;x++)
            for(int y = 0;y < mapHeight;y++)
            {
                tmpHeight = heightMap.GetHeight(x,y) / 20;
                vertices[x + y * mapWidth].Position = new Vector3(x, y,tmpHeight);
                vertices[x + y * mapWidth].Color    = colorMap.GetColor(x,y).ToArgb();
            }
           
            //vertexBuffer.SetData(vertices,0,LockFlags.None);
        }

        //private void IndicesDeclaration()
        //{
        //    indexBuffer = new IndexBuffer(
        //        typeof(int),
        //        (mapWidth-1) * (mapHeight-1) * 6,
        //        device,
        //        Usage.WriteOnly,
        //        Pool.Default
        //    );
        //    indices = new int[(mapWidth - 1) * (mapHeight - 1) * 6];

        //    for(int x = 0;x < (mapWidth - 1);x++)
        //    for(int y = 0;y < (mapHeight - 1);y++)
        //    {
        //        indices[(x + y * (mapWidth - 1)) * 6]    = (int)(x + y * mapWidth);
        //        indices[(x + y * (mapWidth - 1)) * 6 + 1] = (int)((x + 1) + y * mapWidth);
        //        indices[(x + y * (mapWidth - 1)) * 6 + 2] = (int)((x + 1) + (y + 1) * mapWidth);
        //        indices[(x + y * (mapWidth - 1)) * 6 + 3] = (int)(x + (y + 1) * mapWidth);
        //        indices[(x + y * (mapWidth - 1)) * 6 + 4] = (int)(x + y * mapWidth);
        //        indices[(x + y * (mapWidth - 1)) * 6 + 5] = (int)((x + 1) + (y + 1) * mapWidth);
        //    }
           
        //    indexBuffer.SetData(indices,0,LockFlags.None);
        //}
       
        /// <summary>
        /// Mesh Version
        /// </summary>
        private void IndicesDeclaration()
        {
            indices = new short[(mapWidth - 1) * (mapHeight - 1) * 6];

            for(int x = 0;x < (mapWidth - 1);x++)
            for(int y = 0;y < (mapHeight - 1);y++)
            {
                indices[(x + y * (mapWidth - 1)) * 6]    = (short)(x + y * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 1] = (short)((x + 1) + y * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 2] = (short)((x + 1) + (y + 1) * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 3] = (short)(x + (y + 1) * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 4] = (short)(x + y * mapWidth);
                indices[(x + y * (mapWidth - 1)) * 6 + 5] = (short)((x + 1) + (y + 1) * mapWidth);
            }
        }

        private void CreateMesh()
        {
            int numFaces    = (mapWidth - 1) * (mapHeight - 1) * 2;
            int numVertices = (mapWidth * mapHeight);

            meshTerrain = new Mesh(
                numFaces,
                numVertices,
                MeshFlags.Managed,
                CustomVertex.PositionColored.Format,
                device
            );
            meshTerrain.SetVertexBufferData(vertices, LockFlags.None);
            meshTerrain.SetIndexBufferData(indices, LockFlags.None);

            int[] adjac = new int[meshTerrain.NumberFaces * 3];
            meshTerrain.GenerateAdjacency(0.5f, adjac);
            meshTerrain.OptimizeInPlace(MeshFlags.OptimizeVertexCache, adjac);
        }

        public void Process()
        {
            InitializeDevice();
            CameraPositioning();
            VertexDeclaration();
            IndicesDeclaration();
           
            CreateMesh();
           
            Draw();
        }

        public void Draw()
        {
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
            device.BeginScene();

            //device.VertexFormat = CustomVertex.PositionColored.Format;
            //device.SetStreamSource(0, vertexBuffer, 0);
            //device.Indices = indexBuffer;
            //device.Transform.World = Matrix.Translation(-mapHeight / 2, -mapWidth / 2, 0) * Matrix.RotationZ(zAngle);
            //device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, mapWidth * mapHeight, 0, indices.Length / 3);

            device.Transform.World = Matrix.Translation(-mapHeight / 2, -mapWidth / 2, 0) * Matrix.RotationZ(zAngle);

            int numSubSets = meshTerrain.GetAttributeTable().Length;
            for(int i = 0;i < numSubSets;++i) {
                meshTerrain.DrawSubset(i);
            }
           
            device.EndScene();
            device.Present();
        }
       
    }
}
Avatar billede windcape Praktikant
28. august 2007 - 20:05 #3
Det skal siges at koden virker hvis jeg reducere størrelsen på mit map, men det virker da latterligt at .NET kun kan håntere MEGET SMÅ 3D meshes?
Avatar billede windcape Praktikant
28. august 2007 - 21:51 #4
Problemstilling løst ved at indele i mindre Meshes , DirectX er åbenbart noget skrammel :p

Men ville fandme ønske Microsoft kunne dokumentere det *sigh*
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester