public SimpleTree(GraphicsDevice device, TreeSkeleton skeleton)
 {
     this.device = device;
     this.skeleton = skeleton;
     BoneEffect = new BasicEffect(device, new EffectPool());
     UpdateSkeleton();
 }
        /// <summary>
        /// Creates a mesh of a tree.
        /// </summary>
        /// <param name="device">Graphics device.</param>
        /// <param name="skeleton">The tree to create a mesh for. This reference is not used after creation, and can be used independently afterwards.</param>
        /// <param name="numberOfRadialSegments">Number of radial segments on the trunk. Default value is 8. Higher values gives more polygons. Radial segments will always decrease towards 3 in the smaller branches.</param>
        public TreeMesh(GraphicsDevice device, TreeSkeleton skeleton, int numberOfRadialSegments)
        {
            this.device = device;
            this.maxRadialSegments = numberOfRadialSegments;

            Init(skeleton);
        }
        /// <summary>
        /// Creates a mesh of a tree.
        /// </summary>
        /// <param name="device">Graphics device.</param>
        /// <param name="skeleton">The tree to create a mesh for.</param>
        /// <remarks>
        /// The mesh does not remember the skeleton that generated it. The skeleton may be changed
        /// without affecting previously generated meshes.
        /// </remarks>
        public TreeMesh(GraphicsDevice device, TreeSkeleton skeleton)
        {
            this.device = device;
            this.maxRadialSegments = 8;

            Init(skeleton);
        }
 /// <summary>
 /// Creates an animation state for the given tree skeleton, initially setting
 /// each bone's rotation to its rotation at the frame of reference.
 /// </summary>
 /// <param name="skeleton">The skeleton to create an animation state for.</param>
 public TreeAnimationState(TreeSkeleton skeleton)
 {
     rotations = new Quaternion[skeleton.Bones.Count];
     for (int i = 0; i < skeleton.Bones.Count; i++)
     {
         rotations[i] = skeleton.Bones[i].Rotation;
     }
 }
        private void Init(TreeSkeleton skeleton)
        {
            // Get branch transforms
            var transforms = new Matrix[skeleton.Branches.Count];
            skeleton.CopyAbsoluteBranchTransformsTo(transforms);

            // Create the vertices and indices
            numlines = skeleton.Branches.Count;
            numvertices = numlines*2;
            var vertices = new VertexPositionColor[numvertices];
            var indices = new short[numlines*2];

            int vidx = 0;
            int iidx = 0;

            for (int i = 0; i < skeleton.Branches.Count; i++)
            {
                TreeBranch branch = skeleton.Branches[i];

                indices[iidx++] = (short) vidx;
                indices[iidx++] = (short) (vidx + 1);

                vertices[vidx++] = new VertexPositionColor(transforms[i].Translation, Color.White);
                vertices[vidx++] =
                    new VertexPositionColor(Vector3.Transform(new Vector3(0, branch.Length, 0), transforms[i]),
                                            Color.White);
            }

            // Create buffers
            vbuffer = new VertexBuffer(device, numvertices*VertexPositionColor.SizeInBytes, BufferUsage.None);
            vbuffer.SetData<VertexPositionColor>(vertices);
            ibuffer = new IndexBuffer(device, indices.Length*sizeof (short), BufferUsage.None,
                                      IndexElementSize.SixteenBits);
            ibuffer.SetData<short>(indices);

            // Create vertex declaration
            declaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);

            // Create the effect
            effect = new BasicEffect(device, new EffectPool());
        }
        public TreeLineMesh(GraphicsDevice device, TreeSkeleton skeleton)
        {
            this.device = device;

            Init(skeleton);
        }
 //        public SunlitSimpleTree(GraphicsDevice device)
 //            : base(device)
 //        {
 //        }
 public SunlitSimpleTree(GraphicsDevice device, TreeSkeleton skeleton)
     : base(device, skeleton)
 {
 }
        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;
        }
 private int GetRadialSegmentsTop(int index, TreeSkeleton skeleton)
 {
     float ratio = skeleton.Branches[index].EndRadius / skeleton.Branches[0].StartRadius;
     return 3 + (int)(ratio * (maxRadialSegments - 3) + 0.50f);
 }
        private void Init(TreeSkeleton skeleton)
        {
            if (skeleton.Leaves.Count == 0)
                return;

            var transforms = new Matrix[skeleton.Branches.Count];
            skeleton.CopyAbsoluteBranchTransformsTo(transforms);

            Vector3 center = Vector3.Zero;
            for (int i = 0; i < skeleton.Leaves.Count; i++)
            {
                center += transforms[skeleton.Leaves[i].ParentIndex].Translation;
            }
            center = center/(float) skeleton.Leaves.Count;

            var vertices = new LeafVertex[skeleton.Leaves.Count*4];
            var indices = new short[skeleton.Leaves.Count*6];

            int vindex = 0;
            int iindex = 0;

            boundingSphere.Center = center;
            boundingSphere.Radius = 0.0f;

            foreach (TreeLeaf leaf in skeleton.Leaves)
            {
                // Get the position of the leaf
                Vector3 position = transforms[leaf.ParentIndex].Translation +
                                   transforms[leaf.ParentIndex].Up*skeleton.Branches[leaf.ParentIndex].Length;
                if (skeleton.LeafAxis != null)
                {
                    position += skeleton.LeafAxis.Value*leaf.AxisOffset;
                }

                // Orientation
                var right = new Vector2((float) Math.Cos(leaf.Rotation), (float) Math.Sin(leaf.Rotation));
                var up = new Vector2(-right.Y, right.X);

                // Scale vectors by size
                right = leaf.Size.X*right;
                up = leaf.Size.Y*up;

                // Choose a normal vector for lighting calculations
                float distanceFromCenter = Vector3.Distance(position, center);
                Vector3 normal = (position - center)/distanceFromCenter; // normalize the normal

                //                    0---1
                // Vertex positions:  | \ |
                //                    3---2
                int vidx = vindex;
                vertices[vindex++] = new LeafVertex(position, new Vector2(0, 0), -right + up, leaf.Color, leaf.BoneIndex,
                                                    normal);
                vertices[vindex++] = new LeafVertex(position, new Vector2(1, 0), right + up, leaf.Color, leaf.BoneIndex,
                                                    normal);
                vertices[vindex++] = new LeafVertex(position, new Vector2(1, 1), right - up, leaf.Color, leaf.BoneIndex,
                                                    normal);
                vertices[vindex++] = new LeafVertex(position, new Vector2(0, 1), -right - up, leaf.Color, leaf.BoneIndex,
                                                    normal);

                // Add indices
                indices[iindex++] = (short) (vidx);
                indices[iindex++] = (short) (vidx + 1);
                indices[iindex++] = (short) (vidx + 2);

                indices[iindex++] = (short) (vidx);
                indices[iindex++] = (short) (vidx + 2);
                indices[iindex++] = (short) (vidx + 3);

                // Update the bounding sphere
                float size = leaf.Size.Length()/2.0f;
                boundingSphere.Radius = Math.Max(boundingSphere.Radius, distanceFromCenter + size);
            }

            // Create the buffers
            vbuffer = new VertexBuffer(device, vertices.Length*LeafVertex.SizeInBytes, BufferUsage.None);
            vbuffer.SetData<LeafVertex>(vertices);

            ibuffer = new IndexBuffer(device, indices.Length*sizeof (short), BufferUsage.None,
                                      IndexElementSize.SixteenBits);
            ibuffer.SetData<short>(indices);

            // Create the vertex declaration
            vdeclaration = new VertexDeclaration(device, LeafVertex.VertexElements);

            // Remember the number of leaves
            numleaves = skeleton.Leaves.Count;
        }
        /// <summary>
        /// Creates a leaf cloud displaying the leaves on the specified tree skeleton.
        /// </summary>
        /// <param name="device">The graphics device.</param>
        /// <param name="skeleton">The tree skeleton whose leaves you want to display.</param>
        /// <remarks>
        /// The leaf cloud does not remember the skeleton that generated it. The skeleton may be changed
        /// without affecting previously generated leaf clouds.
        /// </remarks>
        public TreeLeafCloud(GraphicsDevice device, TreeSkeleton skeleton)
        {
            this.device = device;

            Init(skeleton);
        }