Example #1
0
        public Terrain(ContentManager content, GraphicsDevice device, string heightMapPath, string texturePath)
        {
            mContent  = content;
            mGraphics = device;

            mHeightMapPath = heightMapPath;
            mTexturePath   = texturePath;

            var meshData = new MeshData();

            var heightMapStream = new FileStream(heightMapPath, FileMode.Open, FileAccess.Read);
            var heightmap       = Texture2D.FromStream(device, heightMapStream);

            heightMapStream.Close();

            mWidth  = heightmap.Width;
            mHeight = heightmap.Height;

            meshData.mVertices = new VertexPositionTexture[mWidth * mHeight];
            meshData.mIndices  = new int[(mWidth * 2 + 2) * (mHeight - 1)];

            var subData  = new MeshData.SubData();
            var material = new Material();

            var textureStream = new FileStream(texturePath, FileMode.Open, FileAccess.Read);

            material.mDiffuseMap      = Texture2D.FromStream(device, textureStream);
            material.DiffuseMapStream = textureStream;
            material.mGraphicsDevice  = device;
            textureStream.Close();

            material.mDiffuseColor = new Vector3(1.0f);

            subData.mIndicesOffset = 0;
            subData.mMaterialIndex = 0;
            subData.mNumPrimitives = (heightmap.Width * 2 + 2) * (heightmap.Height - 1);

            meshData.mMaterials.Add(material);
            meshData.mSubDatas.Add(subData);

            meshData.mPrimitiveType      = PrimitiveType.TriangleStrip;
            meshData.mTotalNumPrimitives = (heightmap.Width * 2 + 2) * (heightmap.Height - 1);

            meshData.mBoundingSphere.Radius = (float)Math.Sqrt(Math.Pow(heightmap.Width / 2.0f, 2) + Math.Pow(heightmap.Height / 2.0f, 2));
            meshData.mIsTerrain             = true;

            Actor = new Actor(new Mesh.Mesh(mGraphics, meshData), null)
            {
                mCastShadow = false
            };
            Size = mWidth;

            LoadVertices(heightmap);

            LoadIndices();

            Actor.mMesh.UpdateData();

            mGrass = new Grass(this);
            mGrass.Generate();
        }
Example #2
0
        /// <summary>
        /// Loads a mesh from a file
        /// </summary>
        /// <param name="filename">The name of the file</param>
        /// <returns>A mesh which contains the data of the file</returns>
        public Mesh.Mesh LoadMesh(string filename)
        {
            var vertexCount = 0;
            var indexCount  = 0;
            var bonesCount  = 0;

            var directory = Path.GetDirectoryName(filename);

            directory += "/";

            var meshData = new MeshData();
            var importer = new AssimpContext();

            var boneConfig = new MaxBoneCountConfig(4);

            importer.SetConfig(boneConfig);

            var scene = importer.ImportFile(filename,
                                            PostProcessSteps.ImproveCacheLocality |
                                            PostProcessSteps.JoinIdenticalVertices |
                                            PostProcessSteps.LimitBoneWeights |
                                            PostProcessSteps.Triangulate |
                                            PostProcessSteps.OptimizeMeshes |
                                            PostProcessSteps.RemoveRedundantMaterials |
                                            PostProcessSteps.MakeLeftHanded |
                                            PostProcessSteps.OptimizeGraph);

            // We want to sort all the meshes to their corresponding materials
            var meshSorted = new List <Assimp.Mesh> [scene.MaterialCount];

            for (var i = 0; i < scene.MaterialCount; i++)
            {
                meshSorted[i] = new List <Assimp.Mesh>();
            }

            foreach (var mesh in scene.Meshes)
            {
                var index = mesh.MaterialIndex;

                meshSorted[index].Add(mesh);

                vertexCount += mesh.VertexCount;
                indexCount  += mesh.FaceCount * 3;
                bonesCount  += mesh.BoneCount;
            }

            // Load bones and animations
            if (scene.HasAnimations || bonesCount > 0)
            {
                meshData.mIsSkinned = true;
                meshData.mBones     = CreateBoneHierarchy(scene);

                foreach (var animation in scene.Animations)
                {
                    meshData.mAnimations.Add(new Animation.Animation(animation, meshData.mBones));
                }

                meshData.mVerticesExt = new VertexPositionTextureSkinned[vertexCount];

                // Set the skinning informatio to 0
                for (var i = 0; i < meshData.mVerticesExt.Length; i++)
                {
                    meshData.mVerticesExt[i].BoneWeights.X = 0.0f;
                    meshData.mVerticesExt[i].BoneWeights.Y = 0.0f;
                    meshData.mVerticesExt[i].BoneWeights.Z = 0.0f;
                    meshData.mVerticesExt[i].BoneWeights.W = 0.0f;
                    meshData.mVerticesExt[i].BoneIndex     = new Byte4(0.0f, 0.0f, 0.0f, 0.0f);
                }
            }
            else
            {
                meshData.mVertices = new VertexPositionTexture[vertexCount];
            }

            meshData.mIndices = new int[indexCount];

            var usedFaces      = 0;
            var usedVertices   = 0;
            var loadedVertices = 0;

            for (var i = 0; i < scene.MaterialCount; i++)
            {
                var material = LoadMaterial(scene.Materials[i], directory);

                var subData = new MeshData.SubData
                {
                    mIndicesOffset = usedFaces * 3,
                    mMaterialIndex = i
                };


                foreach (var mesh in meshSorted[i])
                {
                    for (var j = 0; j < mesh.BoneCount; j++)
                    {
                        var boneIndex = Array.FindIndex(meshData.mBones, ele => ele.mName == mesh.Bones[j].Name);
                        var bone      = meshData.mBones[boneIndex];
                        bone.mOffset = AssimpToXna(mesh.Bones[j].OffsetMatrix);

                        var bonePosition = new Vector4(0.0f);

                        for (var k = 0; k < mesh.Bones[j].VertexWeightCount; k++)
                        {
                            var weight = mesh.Bones[j].VertexWeights[k];

                            bonePosition += new Vector4(mesh.Vertices[weight.VertexID].X * weight.Weight, mesh.Vertices[weight.VertexID].Y * weight.Weight, mesh.Vertices[weight.VertexID].Z * weight.Weight, weight.Weight);

                            var indices = meshData.mVerticesExt[usedVertices + weight.VertexID].BoneIndex.ToVector4();

                            if (!(meshData.mVerticesExt[usedVertices + weight.VertexID].BoneWeights.X > 0.0f))
                            {
                                meshData.mVerticesExt[usedVertices + weight.VertexID].BoneWeights.X = weight.Weight;
                                indices.X = boneIndex;
                            }
                            else if (!(meshData.mVerticesExt[usedVertices + weight.VertexID].BoneWeights.Y > 0.0f))
                            {
                                meshData.mVerticesExt[usedVertices + weight.VertexID].BoneWeights.Y = weight.Weight;
                                indices.Y = boneIndex;
                            }
                            else if (!(meshData.mVerticesExt[usedVertices + weight.VertexID].BoneWeights.Z > 0.0f))
                            {
                                meshData.mVerticesExt[usedVertices + weight.VertexID].BoneWeights.Z = weight.Weight;
                                indices.Z = boneIndex;
                            }
                            else if (!(meshData.mVerticesExt[usedVertices + weight.VertexID].BoneWeights.W > 0.0f))
                            {
                                meshData.mVerticesExt[usedVertices + weight.VertexID].BoneWeights.W = weight.Weight;
                                indices.W = boneIndex;
                            }

                            meshData.mVerticesExt[usedVertices + weight.VertexID].BoneIndex = new Byte4(indices);
                        }

                        bonePosition  /= bonePosition.W;
                        bone.mPosition = new Vector3(bonePosition.X, bonePosition.Y, bonePosition.Z);
                    }

                    // Copy the vertices
                    for (var j = 0; j < mesh.VertexCount; j++)
                    {
                        float radius;

                        if (meshData.mVertices != null)
                        {
                            meshData.mVertices[usedVertices].Position.X = mesh.Vertices[j].X;
                            meshData.mVertices[usedVertices].Position.Y = mesh.Vertices[j].Y;
                            meshData.mVertices[usedVertices].Position.Z = mesh.Vertices[j].Z;

                            radius = meshData.mVertices[usedVertices].Position.Length();
                        }
                        else
                        {
                            meshData.mVerticesExt[usedVertices].Position.X = mesh.Vertices[j].X;
                            meshData.mVerticesExt[usedVertices].Position.Y = mesh.Vertices[j].Y;
                            meshData.mVerticesExt[usedVertices].Position.Z = mesh.Vertices[j].Z;

                            radius = meshData.mVerticesExt[usedVertices].Position.Length();
                        }

                        var vertex = meshData.mVertices?[usedVertices].Position ?? meshData.mVerticesExt[usedVertices].Position;



                        meshData.mBoundingSphere.Radius = Math.Max(radius, meshData.mBoundingSphere.Radius);

                        if (mesh.UVComponentCount[0] != 0)
                        {
                            if (meshData.mVertices != null)
                            {
                                meshData.mVertices[usedVertices].TextureCoordinate.X =
                                    mesh.TextureCoordinateChannels[0][j].X;
                                meshData.mVertices[usedVertices].TextureCoordinate.Y =
                                    mesh.TextureCoordinateChannels[0][j].Y;
                            }
                            else
                            {
                                meshData.mVerticesExt[usedVertices].TextureCoordinate.X =
                                    mesh.TextureCoordinateChannels[0][j].X;
                                meshData.mVerticesExt[usedVertices].TextureCoordinate.Y =
                                    mesh.TextureCoordinateChannels[0][j].Y;
                            }
                        }

                        usedVertices++;
                    }

                    // Copy the indices
                    for (var j = 0; j < mesh.FaceCount; j++)
                    {
                        for (var k = 0; k < 3; k++)
                        {
                            meshData.mIndices[usedFaces * 3 + k] = mesh.Faces[j].Indices[k] + loadedVertices;
                        }

                        usedFaces++;
                    }

                    loadedVertices = usedVertices;
                }

                subData.mNumPrimitives = usedFaces - subData.mIndicesOffset / 3;
                meshData.mSubDatas.Add(subData);
                meshData.mMaterials.Add(material);
            }

            if (meshData.mIsSkinned)
            {
                for (var i = 0; i < meshData.mVerticesExt.Length; i++)
                {
                    var vertex = meshData.mVerticesExt[i].BoneWeights;

                    // Should fix bone weights which are zero
                    if (vertex.X + vertex.Y + vertex.Z + vertex.W == 10000.0f)
                    {
                        //meshData.mVerticesExt[i].BoneWeights = meshData.mVerticesExt[i - 1].BoneWeights;
                        //meshData.mVerticesExt[i].BoneIndex = meshData.mVerticesExt[i - 1].BoneIndex;
                    }
                    else
                    {
                        meshData.mVerticesExt[i].BoneWeights *= 1.0f / (vertex.X + vertex.Y + vertex.Z +
                                                                        vertex.W);
                    }
                }
            }


            meshData.mTotalNumPrimitives = usedFaces;
            meshData.mRootTransformation = AssimpToXna(scene.RootNode.Transform);

            meshData.mBoundingRectangle = CalculateBoundingRectangle(meshData);

            return(new Mesh.Mesh(mGraphicsDevice, meshData));
        }