Exemple #1
0
        private void Init(TreeSkeleton skeleton)
        {
            if (skeleton.Branches.Count == 0)
            {
                throw new ArgumentException("Tree skeleton had no branches");
            }

            if (maxRadialSegments < 3)
            {
                throw new ArgumentException("Tree must have at least 3 radial segments");
            }

            // min and max keep track of the mesh's bounding box.
            Vector3 min = new Vector3(10000, 10000, 10000);
            Vector3 max = new Vector3(-10000, -10000, -10000);

            // Create lists for vertices and indices
            List <TreeVertex> vertices = new List <TreeVertex>();
            List <int>        indices  = new List <int>();

            // Absolute transformation of branches
            Matrix[] transforms = new Matrix[skeleton.Branches.Count];
            skeleton.CopyAbsoluteBranchTransformsTo(transforms);

            // Branch topological distances from root
            float[] distances = new float[skeleton.Branches.Count];
            skeleton.GetLongestBranching(distances);

            //
            //  Create vertices and indices
            //
            for (int i = 0; i < skeleton.Branches.Count; i++)
            {
                int bottomRadials = GetRadialSegmentsBottom(i, skeleton);

                // Add bottom vertices
                int    parentIndex     = skeleton.Branches[i].ParentIndex;
                int    bottomIndex     = vertices.Count;
                Matrix bottomTransform = transforms[i];
                if (parentIndex != -1 && skeleton.Branches[i].ParentPosition > 0.99f && Vector3.Dot(transforms[i].Up, transforms[parentIndex].Up) > 0.7f)
                {
                    bottomTransform              = transforms[parentIndex];
                    bottomTransform.Translation += bottomTransform.Up * skeleton.Branches[parentIndex].Length;

                    // Rotate bottomTransform to the best fit to avoid twisting
                    Vector3 childDir = Vector3.Transform(Vector3.Right, skeleton.Branches[i].Rotation);

                    float  maxdot    = -2.0f;
                    double bestangle = 0.0;
                    for (int j = 0; j < bottomRadials; j++)
                    {
                        double  angle = j / (double)bottomRadials * Math.PI * 2.0;
                        Vector3 vec   = new Vector3((float)Math.Cos(angle), 0, (float)Math.Sin(angle));

                        float dot = Vector3.Dot(childDir, vec);
                        if (dot > maxdot)
                        {
                            maxdot    = dot;
                            bestangle = angle;
                        }
                    }

                    float   cos   = (float)Math.Cos(bestangle);
                    float   sin   = (float)Math.Sin(bestangle);
                    Vector3 right = bottomTransform.Right * cos + bottomTransform.Backward * sin;
                    Vector3 back  = -bottomTransform.Right * sin + bottomTransform.Backward * cos;

                    bottomTransform.Right    = right;
                    bottomTransform.Backward = back;
                }

                // Texture coordinates
                float ty     = (distances[i] - skeleton.Branches[i].Length) / skeleton.TextureHeight;
                float txspan = 0.25f + 0.75f * skeleton.Branches[i].StartRadius / skeleton.TrunkRadius;

                // Bones
                int parentBoneIndex = (parentIndex == -1? skeleton.Branches[i].BoneIndex : skeleton.Branches[parentIndex].BoneIndex);
                int branchBoneIndex = skeleton.Branches[i].BoneIndex;

                AddCircleVertices(ref bottomTransform, skeleton.Branches[i].StartRadius, bottomRadials, ty, 0.0f, txspan, vertices, parentBoneIndex, parentBoneIndex);

                // Add top vertices
                int    topRadials   = GetRadialSegmentsTop(i, skeleton);
                int    topIndex     = vertices.Count;
                Matrix topTransform = transforms[i];
                topTransform.Translation += topTransform.Up * skeleton.Branches[i].Length;

                ty     = ty + skeleton.Branches[i].Length / skeleton.TextureHeight;
                txspan = 0.25f + 0.75f * skeleton.Branches[i].EndRadius / skeleton.TrunkRadius;

                AddCircleVertices(ref topTransform, skeleton.Branches[i].EndRadius, topRadials, ty, 0.0f, txspan, vertices, branchBoneIndex, branchBoneIndex);

                // Add indices
                AddCylinderIndices(bottomIndex, bottomRadials, topIndex, topRadials, indices);

                // Updates bounds
                SetMin(ref min, bottomTransform.Translation);
                SetMin(ref min, topTransform.Translation);
                SetMax(ref max, bottomTransform.Translation);
                SetMax(ref max, topTransform.Translation);
            }

            numvertices  = vertices.Count;
            numtriangles = indices.Count / 3;

            // Create the buffers
            vbuffer = new VertexBuffer(device, TreeVertex.VertexDeclaration, vertices.Count, BufferUsage.None);
            vbuffer.SetData <TreeVertex>(vertices.ToArray());

            if (vertices.Count > 0xFFFF)
            {
                ibuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits, indices.Count, BufferUsage.None);
                ibuffer.SetData <int>(indices.ToArray());
            }
            else
            {
                ibuffer = new IndexBuffer(device, IndexElementSize.SixteenBits, indices.Count, BufferUsage.None);
                ibuffer.SetData <short>(Create16BitArray(indices));
            }

            // Set the bounding sphere
            boundingSphere.Center = (min + max) / 2.0f;
            boundingSphere.Radius = (max - min).Length() / 2.0f;
        }
        private void Init(TreeSkeleton skeleton)
        {
            if (skeleton.Branches.Count == 0)
                throw new ArgumentException("Tree skeleton had no branches");

            if (maxRadialSegments < 3)
                throw new ArgumentException("Tree must have at least 3 radial segments");

            // min and max keep track of the mesh's bounding box.
            Vector3 min = new Vector3(10000, 10000, 10000);
            Vector3 max = new Vector3(-10000, -10000, -10000);

            // Create lists for vertices and indices
            List<TreeVertex> vertices = new List<TreeVertex>();
            List<int> indices = new List<int>();

            // Absolute transformation of branches
            Matrix[] transforms = new Matrix[skeleton.Branches.Count];
            skeleton.CopyAbsoluteBranchTransformsTo(transforms);

            // Branch topological distances from root
            float[] distances = new float[skeleton.Branches.Count];
            skeleton.GetLongestBranching(distances);

            //
            //  Create vertices and indices
            //
            for (int i = 0; i < skeleton.Branches.Count; i++)
            {
                int bottomRadials = GetRadialSegmentsBottom(i, skeleton);

                // Add bottom vertices
                int parentIndex = skeleton.Branches[i].ParentIndex;
                int bottomIndex = vertices.Count;
                Matrix bottomTransform = transforms[i];
                if (parentIndex != -1 && skeleton.Branches[i].ParentPosition > 0.99f && Vector3.Dot(transforms[i].Up, transforms[parentIndex].Up) > 0.7f)
                {
                    bottomTransform = transforms[parentIndex];
                    bottomTransform.Translation += bottomTransform.Up * skeleton.Branches[parentIndex].Length;

                    // Rotate bottomTransform to the best fit to avoid twisting
                    Vector3 childDir = Vector3.Transform(Vector3.Right, skeleton.Branches[i].Rotation);

                    float maxdot = -2.0f;
                    double bestangle = 0.0;
                    for (int j = 0; j < bottomRadials; j++)
                    {
                        double angle = j / (double)bottomRadials * Math.PI * 2.0;
                        Vector3 vec = new Vector3((float)Math.Cos(angle), 0, (float)Math.Sin(angle));

                        float dot = Vector3.Dot(childDir, vec);
                        if (dot > maxdot)
                        {
                            maxdot = dot;
                            bestangle = angle;
                        }
                    }

                    float cos = (float)Math.Cos(bestangle);
                    float sin = (float)Math.Sin(bestangle);
                    Vector3 right = bottomTransform.Right * cos + bottomTransform.Backward * sin;
                    Vector3 back = -bottomTransform.Right * sin + bottomTransform.Backward * cos;

                    bottomTransform.Right = right;
                    bottomTransform.Backward = back;
                }

                // Texture coordinates
                float ty = (distances[i] - skeleton.Branches[i].Length) / skeleton.TextureHeight;
                float txspan = 0.25f + 0.75f * skeleton.Branches[i].StartRadius / skeleton.TrunkRadius;

                // Bones
                int parentBoneIndex = (parentIndex == -1? skeleton.Branches[i].BoneIndex : skeleton.Branches[parentIndex].BoneIndex);
                int branchBoneIndex = skeleton.Branches[i].BoneIndex;

                AddCircleVertices(ref bottomTransform, skeleton.Branches[i].StartRadius, bottomRadials, ty, 0.0f, txspan, vertices, parentBoneIndex, parentBoneIndex);
                
                // Add top vertices
                int topRadials = GetRadialSegmentsTop(i, skeleton);
                int topIndex = vertices.Count;
                Matrix topTransform = transforms[i];
                topTransform.Translation += topTransform.Up * skeleton.Branches[i].Length;

                ty = ty + skeleton.Branches[i].Length / skeleton.TextureHeight;
                txspan = 0.25f + 0.75f * skeleton.Branches[i].EndRadius / skeleton.TrunkRadius;

                AddCircleVertices(ref topTransform, skeleton.Branches[i].EndRadius, topRadials, ty, 0.0f, txspan, vertices, branchBoneIndex, branchBoneIndex);

                // Add indices
                AddCylinderIndices(bottomIndex, bottomRadials, topIndex, topRadials, indices);

                // Updates bounds
                SetMin(ref min, bottomTransform.Translation);
                SetMin(ref min, topTransform.Translation);
                SetMax(ref max, bottomTransform.Translation);
                SetMax(ref max, topTransform.Translation);
            }
            
            numvertices = vertices.Count;
            numtriangles = indices.Count / 3;

            vdeclaration = new VertexDeclaration(TreeVertex.VertexElements);

            // Create the buffers
            vbuffer = new VertexBuffer(device, vdeclaration, vertices.Count, BufferUsage.WriteOnly);
            vbuffer.SetData<TreeVertex>(vertices.ToArray());

            if (vertices.Count > 0xFFFF)
            {
                ibuffer = new IndexBuffer(device, IndexElementSize.ThirtyTwoBits,  indices.Count , BufferUsage.WriteOnly);
                ibuffer.SetData<int>(indices.ToArray());
            }
            else
            {
                ibuffer = new IndexBuffer(device, IndexElementSize.SixteenBits, indices.Count , BufferUsage.WriteOnly);
                ibuffer.SetData<short>(Create16BitArray(indices));
            }
            
            
            // Set the bounding sphere
            boundingSphere.Center = (min + max) / 2.0f;
            boundingSphere.Radius = (max - min).Length() / 2.0f;
        }