예제 #1
0
        //Generates a mesh from required parameters, as well as specifying a parent bone to be used, used to simplify and clean up code.
        public static ModelMesh makeMeshFromPolygonList(List <Polygon> polys, GraphicsDevice graphics, ModelBone parentBone)
        {
            List <ModelMeshPart> parts = new List <ModelMeshPart>();
            ModelBone            bone  = new ModelBone();

            bone.Transform      = Matrix.CreateTranslation(0, 0, 0);
            bone.ModelTransform = parentBone.ModelTransform;

            List <Vector3> points = new List <Vector3>();

            foreach (Polygon p in polys)
            {
                ModelMeshPart part = makePartFromPolygon(p, graphics);
                parts.Add(part);
                foreach (Vector3 point in p.points)
                {
                    points.Add(point);
                }
            }

            ModelMesh mesh = new ModelMesh(graphics, parts);

            bone.AddMesh(mesh);
            parentBone.AddChild(bone);
            bone.Parent         = parentBone;
            mesh.ParentBone     = bone;
            mesh.BoundingSphere = BoundingSphere.CreateFromPoints(points);

            return(mesh);
        }
예제 #2
0
        //Generates a mesh from required parameters, used to simplify and clean up code.
        public static ModelMesh makeMeshFromPolygonList(List <Polygon> polys, GraphicsDevice graphics)
        {
            List <ModelMeshPart> parts = new List <ModelMeshPart>();
            ModelBone            bone  = new ModelBone();

            bone.Transform      = Matrix.CreateTranslation(0, 0, 0);
            bone.ModelTransform = Matrix.CreateTranslation(0, 0, 0);

            Vector3 center     = new Vector3(float.MaxValue, 0, 0);
            int     pointCount = 0;

            foreach (Polygon p in polys)
            {
                ModelMeshPart part = makePartFromPolygon(p, graphics);
                parts.Add(part);
                foreach (Vector3 point in p.points)
                {
                    pointCount++;
                    if (center.X == float.MaxValue)
                    {
                        center = point;
                    }
                    else
                    {
                        center += point;
                    }
                }
            }

            center /= pointCount;
            float radius = 0;

            foreach (Polygon p in polys)
            {
                foreach (Vector3 point in p.points)
                {
                    radius = Vector3.Distance(point, center) > radius?Vector3.Distance(point, center) : radius;
                }
            }

            ModelMesh mesh = new ModelMesh(graphics, parts);

            bone.AddMesh(mesh);
            mesh.ParentBone     = bone;
            mesh.BoundingSphere = new BoundingSphere(center, radius);

            return(mesh);
        }
예제 #3
0
        public void Load()
        {
            CHeightmap heightmap = null;

            // for each heightmap component, create Model instance to enable Draw calls when rendering
            foreach (var renderable in Game1.Inst.Scene.GetComponents <C3DRenderable>())
            {
                if (renderable.Value.GetType() != typeof(CHeightmap))
                {
                    continue;
                }
                heightmap = (CHeightmap)renderable.Value;
                int key = renderable.Key;

                /* use each color channel for different data, e.g.
                 * R for height,
                 * G for texture/material/terrain type,
                 * B for fixed spawned models/entities (houses, trees etc.),
                 * A for additional data
                 */


                List <ModelMesh> meshes = new List <ModelMesh>();
                var bones = new List <ModelBone>();

                var indices  = new Dictionary <int, int[]>();
                var vertices = new Dictionary <int, VertexPositionNormalColor[]>();

                CreateIndicesChunk(heightmap, ref indices, 0);
                CalculateHeightData(heightmap, key);
                CreateVerticesChunks(heightmap, ref vertices, 0, 0);
                //basicEffect.Texture = heightmap.Image;
                basicEffect.DiffuseColor  = new Vector3(1, 1, 1);
                basicEffect.SpecularPower = 100;
                basicEffect.SpecularColor = new Vector3(0.25f);

                basicEffect.EnableDefaultLighting();
                basicEffect.LightingEnabled   = true;
                basicEffect.AmbientLightColor = Game1.Inst.Scene.LightConfig.AmbientColor;
                basicEffect.DirectionalLight0.SpecularColor = Game1.Inst.Scene.LightConfig.SpecularColor;
                basicEffect.DirectionalLight0.Direction     = Game1.Inst.Scene.LightConfig.Direction;
                basicEffect.DirectionalLight0.DiffuseColor  = Game1.Inst.Scene.LightConfig.DiffuseColor;
                basicEffect.DirectionalLight0.Enabled       = true;
                basicEffect.PreferPerPixelLighting          = true;


                for (int j = 0; j < vertices.Values.Count; j++)
                {
                    var vert = vertices[j];
                    var ind  = indices[j];
                    CalculateNormals(ref vert, ref ind);

                    /*
                     * for(int i = 0; i < vertices[j].Length; i++)
                     *  vertices[j][i].Color = Color.ForestGreen;
                     */
                    vertices[j] = vert;
                    indices[j]  = ind;

                    var modelpart = CreateModelPart(vert, ind);
                    List <ModelMeshPart> meshParts = new List <ModelMeshPart>();
                    meshParts.Add(modelpart);

                    ModelMesh modelMesh = new ModelMesh(mGraphicsDevice, meshParts);
                    modelMesh.BoundingSphere = new BoundingSphere();
                    ModelBone modelBone = new ModelBone();
                    modelBone.AddMesh(modelMesh);
                    modelBone.Transform = Matrix.CreateTranslation(new Vector3(0, 0, 0));                     // changing object world (frame) / origo

                    modelMesh.ParentBone = modelBone;
                    bones.Add(modelBone);
                    meshes.Add(modelMesh);
                    modelMesh.BoundingSphere = BoundingSphere.CreateFromBoundingBox(GenericUtil.BuildBoundingBoxForVertex(vert, Matrix.Identity));
                    modelpart.Effect         = basicEffect;
                }
                ModelMeshPart        ground          = buildGround(heightmap, 20);
                List <ModelMeshPart> groundMeshParts = new List <ModelMeshPart>();
                groundMeshParts.Add(ground);
                ModelMesh groundMesh = new ModelMesh(mGraphicsDevice, groundMeshParts);
                groundMesh.BoundingSphere = new BoundingSphere();
                ModelBone groundBone = new ModelBone();
                groundBone.AddMesh(groundMesh);
                groundBone.Transform  = Matrix.CreateTranslation(new Vector3(0, 0, 0));
                groundMesh.ParentBone = groundBone;
                groundMesh.Name       = "FrontFace";
                bones.Add(groundBone);
                meshes.Add(groundMesh);
                ground.Effect = basicEffect;

                heightmap.model = new Model(mGraphicsDevice, bones, meshes);

                heightmap.model.Tag = "Map";
            }
        }
예제 #4
0
        public void Load()
        {
            Model model = null;

            foreach (var renderable in Game1.Inst.Scene.GetComponents <C3DRenderable>())
            {
                if (renderable.Value.GetType() != typeof(CHeightmap))
                {
                    continue;
                }
                CHeightmap heightmap = (CHeightmap)renderable.Value;

                //                heightmap.HeightData
                // Create vertices
                Random rnd = new Random(1990);


                var terrainHeight = 1081;
                var terrainWidth  = 1081;
                //
                int counter = 0;
                indices     = new int[(terrainWidth - 1) * (terrainHeight - 1) * 6];
                vertices    = new VertexPositionNormalColor[terrainWidth * terrainHeight];
                vibirations = new int[terrainWidth * terrainHeight];
                // Create vertices
                for (int x = 0; x < terrainWidth; x++)
                {
                    for (int y = 0; y < terrainHeight; y++)
                    {
                        vertices[x + y * terrainWidth].Position = new Vector3(x, heightmap.LowestPoint + 10, y);
                        var color = Color.Blue;
                        color.A = 100;
                        vertices[x + y * terrainWidth].Color = color;

                        // Randomly set the direction of the vertex up or down
                        vibirations[x + y * terrainWidth] = rnd.Next(0, 100) > 50 ? -1 : 1;
                    }
                }
                for (int y = 0; y < terrainHeight - 1; y++)
                {
                    for (int x = 0; x < terrainWidth - 1; x++)
                    {
                        int topLeft    = x + y * terrainWidth;
                        int topRight   = (x + 1) + y * terrainWidth;
                        int lowerLeft  = x + (y + 1) * terrainWidth;
                        int lowerRight = (x + 1) + (y + 1) * terrainWidth;

                        indices[counter++] = (int)topLeft;
                        indices[counter++] = (int)lowerRight;
                        indices[counter++] = (int)lowerLeft;

                        indices[counter++] = (int)topLeft;
                        indices[counter++] = (int)topRight;
                        indices[counter++] = (int)lowerRight;
                    }
                }
                // Calculate normals
                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i].Normal = new Vector3(0, 0, 0);
                }

                for (int i = 0; i < indices.Length / 3; i++)
                {
                    int index1 = indices[i * 3];
                    int index2 = indices[i * 3 + 1];
                    int index3 = indices[i * 3 + 2];

                    Vector3 side1  = vertices[index1].Position - vertices[index3].Position;
                    Vector3 side2  = vertices[index1].Position - vertices[index2].Position;
                    Vector3 normal = Vector3.Cross(side1, side2);

                    vertices[index1].Normal += normal;
                    vertices[index2].Normal += normal;
                    vertices[index3].Normal += normal;
                }



                var vertexBuffer = new VertexBuffer(mGraphicsDevice, VertexPositionNormalColor.VertexDeclaration,
                                                    vertices.Length, BufferUsage.None);
                vertexBuffer.SetData(vertices);
                var indexBuffer = new IndexBuffer(mGraphicsDevice, typeof(int), indices.Length, BufferUsage.None);
                indexBuffer.SetData(indices);

                var bones  = new List <ModelBone>();
                var meshes = new List <ModelMesh>();

                List <ModelMeshPart> parts    = new List <ModelMeshPart>();
                ModelMeshPart        meshPart = new ModelMeshPart();
                meshPart.VertexBuffer   = vertexBuffer;
                meshPart.IndexBuffer    = indexBuffer;
                meshPart.NumVertices    = indices.Length;
                meshPart.PrimitiveCount = indices.Length / 3;
                parts.Add(meshPart);

                ModelMesh mesh = new ModelMesh(mGraphicsDevice, parts);
                meshPart.Effect = bEffect;

                mesh.Name = "water";
                ModelBone bone = new ModelBone();
                bone.Name = "Water";
                bone.AddMesh(mesh);
                bone.Transform  = Matrix.Identity;
                mesh.ParentBone = bone;

                bones.Add(bone);
                meshes.Add(mesh);
                model = new Model(Game1.Inst.GraphicsDevice, bones, meshes);
            }
            int id = Game1.Inst.Scene.AddEntity();

            Game1.Inst.Scene.AddComponent(id, new CTransform()
            {
                Position = new Vector3(-590, -900, -590) * 0.01f, Orientation = Quaternion.CreateFromRotationMatrix(Matrix.Identity), Scale = new Vector3(0.01f)
            });
            CModel = new CImportedModel()
            {
                model = model
            };
            Game1.Inst.Scene.AddComponent <C3DRenderable>(id, CModel);
        }
예제 #5
0
파일: MapSystem.cs 프로젝트: Tkocz/CG_lab3
        public void Load()
        {
            // for each heightmap component, create Model instance to enable Draw calls when rendering
            foreach (var renderable in Game1.Inst.Scene.GetComponents <C3DRenderable>())
            {
                if (renderable.Value.GetType() != typeof(CHeightmap))
                {
                    continue;
                }
                CHeightmap heightmap = (CHeightmap)renderable.Value;

                /* use each color channel for different data, e.g.
                 * R for height,
                 * G for texture/material/terrain type,
                 * B for fixed spawned models/entities (houses, trees etc.),
                 * A for additional data
                 */


                List <ModelMesh> meshes = new List <ModelMesh>();
                var bones = new List <ModelBone>();

                var indices  = new Dictionary <int, int[]>();
                var vertices = new Dictionary <int, VertexPositionNormalColor[]>();

                CreateIndicesChunk(heightmap, ref indices, 0);
                CalculateHeightData(heightmap);
                CreateVerticesChunks(heightmap, ref vertices, 0, 0);
                for (int j = 0; j < vertices.Values.Count; j++)
                {
                    var vert = vertices[j];
                    var ind  = indices[j];
                    CalculateNormals(ref vert, ref ind);
                    vertices[j] = vert;
                    indices[j]  = ind;

                    var modelpart = CreateModelPart(vert, ind);
                    List <ModelMeshPart> meshParts = new List <ModelMeshPart>();
                    meshParts.Add(modelpart);

                    ModelMesh modelMesh = new ModelMesh(mGraphicsDevice, meshParts);
                    modelMesh.BoundingSphere = new BoundingSphere();
                    ModelBone modelBone = new ModelBone();
                    modelBone.AddMesh(modelMesh);
                    modelBone.Transform = Matrix.CreateTranslation(new Vector3(0, 0, 0));                     // changing object world (frame) / origo

                    modelMesh.ParentBone = modelBone;
                    bones.Add(modelBone);
                    meshes.Add(modelMesh);
                    modelMesh.BoundingSphere = BoundingSphere.CreateFromBoundingBox(GenericUtil.BuildBoundingBoxForVertex(vert, Matrix.Identity));
                    modelpart.Effect         = basicEffect;
                }
                ModelMeshPart        ground          = buildGround(heightmap, 20);
                List <ModelMeshPart> groundMeshParts = new List <ModelMeshPart>();
                groundMeshParts.Add(ground);
                ModelMesh groundMesh = new ModelMesh(mGraphicsDevice, groundMeshParts);
                groundMesh.BoundingSphere = new BoundingSphere();
                ModelBone groundBone = new ModelBone();
                groundBone.AddMesh(groundMesh);
                groundBone.Transform  = Matrix.CreateTranslation(new Vector3(0, 0, 0));
                groundMesh.ParentBone = groundBone;
                groundMesh.Name       = "FrontFace";
                bones.Add(groundBone);
                meshes.Add(groundMesh);
                ground.Effect = basicEffect;

                heightmap.model     = new Model(mGraphicsDevice, bones, meshes);
                heightmap.model.Tag = "Map";
            }
        }
예제 #6
0
        public static void CreateSplatter(float x, float z, Heightmap heightmap)
        {
            var graphicsDevice = Game1.Inst.GraphicsDevice;
            var scene          = Game1.Inst.Scene;
            // vertical offset to avoid flickering
            var yOffset = 0.1f;

            var y = heightmap.HeightAt(x, z);

            var A = new Vector3(-0.5f, 0.0f, -0.5f);
            var B = new Vector3(0.5f, 0.0f, -0.5f);
            var C = new Vector3(0.5f, 0.0f, 0.5f);
            var D = new Vector3(-0.5f, 0.0f, 0.5f);

            A.Y = heightmap.HeightAt(x + A.X, z + A.Z) - y;
            B.Y = heightmap.HeightAt(x + B.X, z + B.Z) - y;
            C.Y = heightmap.HeightAt(x + C.X, z + C.Z) - y;
            D.Y = heightmap.HeightAt(x + D.X, z + D.Z) - y;

            var N = -Vector3.Cross(A - B, A - D);

            N.Normalize();

            var vertices = new VertexPositionNormalTexture[4];

            vertices[0] = new VertexPositionNormalTexture(A, N, new Vector2(0, 0));
            vertices[1] = new VertexPositionNormalTexture(B, N, new Vector2(1, 0));
            vertices[2] = new VertexPositionNormalTexture(C, N, new Vector2(1, 1));
            vertices[3] = new VertexPositionNormalTexture(D, N, new Vector2(0, 1));

            var indices = new short[6];

            indices[0] = 0;
            indices[1] = 1;
            indices[2] = 2;

            indices[3] = 0;
            indices[4] = 2;
            indices[5] = 3;

            var vertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.None);

            vertexBuffer.SetData(vertices);

            var indexBuffer = new IndexBuffer(graphicsDevice, typeof(short), indices.Length, BufferUsage.None);

            indexBuffer.SetData(indices);

            var bEffect = new BasicEffect(graphicsDevice);

            bEffect.TextureEnabled = true;
            bEffect.Texture        = Game1.Inst.Content.Load <Texture2D>("Textures/splatter");

            var meshes = new List <ModelMesh>();
            var parts  = new List <ModelMeshPart>();
            var bones  = new List <ModelBone>();

            parts.Add(new ModelMeshPart {
                VertexBuffer   = vertexBuffer,
                NumVertices    = vertices.Length,
                IndexBuffer    = indexBuffer,
                PrimitiveCount = indices.Length / 3
            });
            var mesh = new ModelMesh(graphicsDevice, parts);

            parts[0].Effect = bEffect;

            var bone = new ModelBone {
                Name      = "Splatter",
                Transform = Matrix.Identity
            };

            bone.AddMesh(mesh);
            mesh.ParentBone = bone;

            bones.Add(bone);
            meshes.Add(mesh);

            var model = new Model(graphicsDevice, bones, meshes);

            var id = scene.AddEntity();

            scene.AddComponent <C3DRenderable>(id, new CImportedModel {
                model = model
            });
            scene.AddComponent(id, new CTransform {
                Position = new Vector3(x, y + yOffset, z), Scale = new Vector3((float)rnd.NextDouble() * 0.5f + 1.5f)
            });
        }
예제 #7
0
        public static void Create(float WaterHeight = -33, float TerrainWidth = 300f, float TerrainDepth = 300f)
        {
            byte  WaterOpacity = 100;
            int   Resolution   = 100; // vertices per direction
            float Frequency    = 1.5f;
            float Amplitude    = 0.2f;

            GraphicsDevice mGraphicsDevice = Game1.Inst.GraphicsDevice;

            int[] indices = null;
            VertexPositionNormalTexture[] vertices;
            Effect bEffect = Game1.Inst.Content.Load <Effect>("Effects/Water");

            bEffect.Parameters["Frequency"].SetValue(Frequency);
            bEffect.Parameters["Amplitude"].SetValue(Amplitude);
            var lightConfig = Game1.Inst.Scene.LightConfig;

            bEffect.Parameters["FogStart"].SetValue(lightConfig.FogStart);
            bEffect.Parameters["FogEnd"].SetValue(lightConfig.FogEnd);
            bEffect.Parameters["FogColor"].SetValue(lightConfig.ClearColor);

            int counter = 0;

            indices  = new int[(Resolution - 1) * (Resolution - 1) * 6];
            vertices = new VertexPositionNormalTexture[Resolution * Resolution];
            // Create vertices
            for (int x = 0; x < Resolution; x++)
            {
                for (int y = 0; y < Resolution; y++)
                {
                    var vx = TerrainWidth * (float)((float)x / Resolution - 0.5f);
                    var vy = TerrainDepth * (float)((float)y / Resolution - 0.5f);

                    var txs = 1.0f;
                    var u   = txs * (float)x / Resolution;
                    var v   = txs * (float)y / Resolution;


                    vertices[x + y * Resolution].Position = new Vector3(vx, WaterHeight, vy);
                    var color = Color.Blue;
                    color.A = WaterOpacity;
                    vertices[x + y * Resolution].TextureCoordinate = new Vector2(u, v);
                }
            }
            for (int y = 0; y < Resolution - 1; y++)
            {
                for (int x = 0; x < Resolution - 1; x++)
                {
                    int topLeft    = x + y * Resolution;
                    int topRight   = (x + 1) + y * Resolution;
                    int lowerLeft  = x + (y + 1) * Resolution;
                    int lowerRight = (x + 1) + (y + 1) * Resolution;

                    indices[counter++] = (int)topLeft;
                    indices[counter++] = (int)lowerRight;
                    indices[counter++] = (int)lowerLeft;

                    indices[counter++] = (int)topLeft;
                    indices[counter++] = (int)topRight;
                    indices[counter++] = (int)lowerRight;
                }
            }
            // Calculate normals
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Normal = new Vector3(0, 0, 0);
            }

            for (int i = 0; i < indices.Length / 3; i++)
            {
                int index1 = indices[i * 3];
                int index2 = indices[i * 3 + 1];
                int index3 = indices[i * 3 + 2];

                Vector3 side1  = vertices[index1].Position - vertices[index3].Position;
                Vector3 side2  = vertices[index1].Position - vertices[index2].Position;
                Vector3 normal = Vector3.Cross(side1, side2);

                vertices[index1].Normal += normal;
                vertices[index2].Normal += normal;
                vertices[index3].Normal += normal;
            }



            var vertexBuffer = new VertexBuffer(mGraphicsDevice, VertexPositionNormalTexture.VertexDeclaration,
                                                vertices.Length, BufferUsage.None);

            vertexBuffer.SetData(vertices);
            var indexBuffer = new IndexBuffer(mGraphicsDevice, typeof(int), indices.Length, BufferUsage.None);

            indexBuffer.SetData(indices);

            var bones  = new List <ModelBone>();
            var meshes = new List <ModelMesh>();

            List <ModelMeshPart> parts    = new List <ModelMeshPart>();
            ModelMeshPart        meshPart = new ModelMeshPart();

            meshPart.VertexBuffer   = vertexBuffer;
            meshPart.IndexBuffer    = indexBuffer;
            meshPart.NumVertices    = indices.Length;
            meshPart.PrimitiveCount = indices.Length / 3;
            parts.Add(meshPart);

            ModelMesh mesh = new ModelMesh(mGraphicsDevice, parts);

            meshPart.Effect = bEffect;


            mesh.Name           = "water";
            mesh.BoundingSphere = BoundingSphere.CreateFromBoundingBox(new BoundingBox(new Vector3(0, WaterHeight, 0), new Vector3(TerrainWidth, WaterHeight, TerrainDepth)));
            ModelBone bone = new ModelBone();

            bone.Name = "water";
            bone.AddMesh(mesh);
            bone.Transform  = Matrix.Identity;
            mesh.ParentBone = bone;

            bones.Add(bone);
            meshes.Add(mesh);
            var model = new Model(Game1.Inst.GraphicsDevice, bones, meshes);

            int id = Game1.Inst.Scene.AddEntity();

            Game1.Inst.Scene.AddComponent(id, new CTransform {
                Position = Vector3.Zero, Rotation = Matrix.Identity, Scale = new Vector3(1f)
            });
            var CModel = new CWater()
            {
                model     = model,
                materials = new Dictionary <int, MaterialShader> {
                    { 0, new MaterialShader(bEffect) }
                }
            };

            Game1.Inst.Scene.AddComponent(id, CModel);
        }
예제 #8
0
        /// <summary>Creates the MonoGame/XNA renderable model.</summary>
        /// <param name="indices">The triangle indices.</param>
        /// <param name="verts">The model vertices.</param>
        private void CreateModel(int[] indices, VertexPositionNormalColor[] verts, Func <float, float, float, Color> calcColor)
        {
            //--------------------
            // Compute normals.
            //--------------------

            for (var i = 0; i < indices.Length - 2; i += 3)
            {
                var i0 = indices[i];
                var i1 = indices[i + 1];
                var i2 = indices[i + 2];

                Vector3 a = verts[i0].Position - verts[i2].Position;
                Vector3 b = verts[i0].Position - verts[i1].Position;
                Vector3 n = Vector3.Cross(a, b);

                verts[i0].Normal += n;
                verts[i1].Normal += n;
                verts[i2].Normal += n;

                if (true || !mSmooth)
                {
                    var c = new Color((verts[i0].Color.R + verts[i1].Color.R + verts[i2].Color.R) / 3,
                                      (verts[i0].Color.G + verts[i1].Color.G + verts[i2].Color.G) / 3,
                                      (verts[i0].Color.B + verts[i1].Color.B + verts[i2].Color.B) / 3);

                    verts[i0].Color = verts[i1].Color = verts[i2].Color = c;
                }
            }

            for (var i = 0; i < verts.Length; i++)
            {
                verts[i].Normal.Normalize();
            }

            //--------------------
            // Setup model.
            //--------------------

            // TODO: The code below is retarded. Blame XNA/MonoGame. :-(

            var device = Game1.Inst.GraphicsDevice;

            var ibo = new IndexBuffer(device, typeof(int), indices.Length, BufferUsage.None);

            ibo.SetData(indices);

            var vbo = new VertexBuffer(device,
                                       VertexPositionNormalColor.VertexDeclaration,
                                       verts.Length,
                                       BufferUsage.None);

            vbo.SetData(verts);

            var meshes = new List <ModelMesh>();
            var parts  = new List <ModelMeshPart>();
            var bones  = new List <ModelBone>();

            parts.Add(new ModelMeshPart {
                VertexBuffer = vbo,
                NumVertices  = verts.Length,

                IndexBuffer    = ibo,
                PrimitiveCount = indices.Length / 3,
            });

            var mesh = new ModelMesh(device, parts);

            parts[0].Effect = new BasicEffect(device);

            var bone = new ModelBone {
                Name      = "Heightmap",
                Transform = Matrix.Identity
            };

            bone.AddMesh(mesh);
            mesh.ParentBone = bone;

            bones.Add(bone);
            meshes.Add(mesh);

            Model     = new Model(device, bones, meshes);
            Model.Tag = "Heightmap";
        }