private void Init(TreeSkeleton skeleton) { // Get branch transforms Matrix[] transforms = new Matrix[skeleton.Branches.Count]; skeleton.CopyAbsoluteBranchTransformsTo(transforms); // Create the vertices and indices numlines = skeleton.Branches.Count; numvertices = numlines * 2; VertexPositionColor[] vertices = new VertexPositionColor[numvertices]; short[] 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, VertexPositionColor.VertexDeclaration, numvertices, BufferUsage.None); vbuffer.SetData <VertexPositionColor>(vertices); ibuffer = new IndexBuffer(device, IndexElementSize.SixteenBits, indices.Length, BufferUsage.None); ibuffer.SetData <short>(indices); // Create the effect effect = new BasicEffect(device); }
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); }
public SimpleTree(GraphicsDevice device, TreeSkeleton skeleton) { this.device = device; this.skeleton = skeleton; this.boneEffect = new BasicEffect(device); 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.</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()); }
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; }
public TreeLineMesh(GraphicsDevice device, TreeSkeleton skeleton) { this.device = device; Init(skeleton); }
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.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.Leaves.Count == 0) { return; } Matrix[] 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; LeafVertex[] vertices = new LeafVertex[skeleton.Leaves.Count * 4]; short[] 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 Vector2 right = new Vector2((float)Math.Cos(leaf.Rotation), (float)Math.Sin(leaf.Rotation)); Vector2 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 vertex declaration vdeclaration = new VertexDeclaration(LeafVertex.VertexElements); // Create the buffers vbuffer = new VertexBuffer(device, vdeclaration, vertices.Length, BufferUsage.WriteOnly); vbuffer.SetData <LeafVertex>(vertices); ibuffer = new IndexBuffer(device, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly); ibuffer.SetData <short>(indices); // 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); }
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); }
// 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; }