private static CustomMesh CreateTorus(float inner, float outer, int slices, int stacks) { if (slices < 5) { throw new ArgumentException("Cannot draw a torus with slices less than 5"); } if (slices > 100) { throw new ArgumentException("Cannot draw a torus with slices greater than 100"); } if (stacks < 5) { throw new ArgumentException("Cannot draw a torus with stacks less than 5"); } if (stacks > 100) { throw new ArgumentException("Cannot draw a torus with stacks greater than 100"); } if (inner < 0) { throw new ArgumentException("Inner radius has to be greater than or equal to 0"); } if (outer <= 0) { throw new ArgumentException("Outer radius has to be greater than 0"); } if (inner >= outer) { throw new ArgumentException("Inner radius has to be less than outer radius"); } CustomMesh mesh = new CustomMesh(); List <VertexPositionNormal> vertices = new List <VertexPositionNormal>(); // Add the vertices double thetaIncr = Math.PI * 2 / slices; double thaiIncr = Math.PI * 2 / stacks; int countA, countB = 0; double theta, thai; float c = (outer + inner) / 2; float a = (outer - inner) / 2; double common; Vector3 tubeCenter; for (countA = 0, theta = 0; countA < slices; theta += thetaIncr, countA++) { tubeCenter = Vector3Helper.Get((float)(c * Math.Cos(theta)), 0, (float)(c * Math.Sin(theta))); for (countB = 0, thai = 0; countB < stacks; thai += thaiIncr, countB++) { VertexPositionNormal vert = new VertexPositionNormal(); common = (c + a * Math.Cos(thai)); vert.Position = Vector3Helper.Get((float)(common * Math.Cos(theta)), (float)(a * Math.Sin(thai)), (float)(common * Math.Sin(theta))); vert.Normal = Vector3.Normalize(vert.Position - tubeCenter); vertices.Add(vert); } } mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List <short> indices = new List <short>(); for (int i = 0; i < slices - 1; i++) { for (int j = 0; j < stacks - 1; j++) { indices.Add((short)(i * stacks + j)); indices.Add((short)((i + 1) * stacks + j)); indices.Add((short)(i * stacks + j + 1)); indices.Add((short)(i * stacks + j + 1)); indices.Add((short)((i + 1) * stacks + j)); indices.Add((short)((i + 1) * stacks + j + 1)); } indices.Add((short)((i + 1) * stacks - 1)); indices.Add((short)((i + 2) * stacks - 1)); indices.Add((short)(i * stacks)); indices.Add((short)(i * stacks)); indices.Add((short)((i + 2) * stacks - 1)); indices.Add((short)((i + 1) * stacks)); } for (int j = 0; j < stacks - 1; j++) { indices.Add((short)((slices - 1) * stacks + j)); indices.Add((short)j); indices.Add((short)((slices - 1) * stacks + j + 1)); indices.Add((short)((slices - 1) * stacks + j + 1)); indices.Add((short)j); indices.Add((short)(j + 1)); } indices.Add((short)(slices * stacks - 1)); indices.Add((short)(slices - 1)); indices.Add((short)((slices - 1) * stacks)); indices.Add((short)((slices - 1) * stacks)); indices.Add((short)(slices - 1)); indices.Add((short)0); mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return(mesh); }
private static CustomMesh CreateTorus(float inner, float outer, int slices, int stacks) { if (slices < 5) throw new ArgumentException("Cannot draw a torus with slices less than 5"); if (slices > 100) throw new ArgumentException("Cannot draw a torus with slices greater than 100"); if (stacks < 5) throw new ArgumentException("Cannot draw a torus with stacks less than 5"); if (stacks > 100) throw new ArgumentException("Cannot draw a torus with stacks greater than 100"); if (inner < 0) throw new ArgumentException("Inner radius has to be greater than or equal to 0"); if (outer <= 0) throw new ArgumentException("Outer radius has to be greater than 0"); if (inner >= outer) throw new ArgumentException("Inner radius has to be less than outer radius"); CustomMesh mesh = new CustomMesh(); List<VertexPositionNormal> vertices = new List<VertexPositionNormal>(); // Add the vertices double thetaIncr = Math.PI * 2 / slices; double thaiIncr = Math.PI * 2 / stacks; int countA, countB = 0; double theta, thai; float c = (outer + inner) / 2; float a = (outer - inner) / 2; double common; Vector3 tubeCenter; for (countA = 0, theta = 0; countA < slices; theta += thetaIncr, countA++) { tubeCenter = Vector3Helper.Get((float)(c * Math.Cos(theta)), 0, (float)(c * Math.Sin(theta))); for (countB = 0, thai = 0; countB < stacks; thai += thaiIncr, countB++) { VertexPositionNormal vert = new VertexPositionNormal(); common = (c + a * Math.Cos(thai)); vert.Position = Vector3Helper.Get((float)(common * Math.Cos(theta)), (float)(a * Math.Sin(thai)), (float)(common * Math.Sin(theta))); vert.Normal = Vector3.Normalize(vert.Position - tubeCenter); vertices.Add(vert); } } mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List<short> indices = new List<short>(); for (int i = 0; i < slices - 1; i++) { for (int j = 0; j < stacks - 1; j++) { indices.Add((short)(i * stacks + j)); indices.Add((short)((i + 1) * stacks + j)); indices.Add((short)(i * stacks + j + 1)); indices.Add((short)(i * stacks + j + 1)); indices.Add((short)((i + 1) * stacks + j)); indices.Add((short)((i + 1) * stacks + j + 1)); } indices.Add((short)((i + 1) * stacks - 1)); indices.Add((short)((i + 2) * stacks - 1)); indices.Add((short)(i * stacks)); indices.Add((short)(i * stacks)); indices.Add((short)((i + 2) * stacks - 1)); indices.Add((short)((i + 1) * stacks)); } for (int j = 0; j < stacks - 1; j++) { indices.Add((short)((slices - 1) * stacks + j)); indices.Add((short)j); indices.Add((short)((slices - 1) * stacks + j + 1)); indices.Add((short)((slices - 1) * stacks + j + 1)); indices.Add((short)j); indices.Add((short)(j + 1)); } indices.Add((short)(slices * stacks - 1)); indices.Add((short)(slices - 1)); indices.Add((short)((slices - 1) * stacks)); indices.Add((short)((slices - 1) * stacks)); indices.Add((short)(slices - 1)); indices.Add((short)0); mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return mesh; }
private static CustomMesh CreateCapsule(float radius, float height, int slices) { if (slices < 5) { throw new ArgumentException("Cannot draw a capsule with slices less than 5"); } if (slices > 100) { throw new ArgumentException("Cannot draw a capsule with slices greater than 100"); } if (radius <= 0) { throw new ArgumentException("radius should be greater than zero"); } if (height <= 0) { throw new ArgumentException("height should be greater than zero"); } if (height < radius * 2) { height = radius * 2; } CustomMesh mesh = new CustomMesh(); List <VertexPositionNormal> vertices = new List <VertexPositionNormal>(); float cylinderHeight = height - radius * 2; Vector3 topCenter = Vector3Helper.Get(0, cylinderHeight / 2, 0); Vector3 bottomCenter = Vector3Helper.Get(0, -cylinderHeight / 2, 0); double thai = 0, theta = 0; double thaiIncr = Math.PI / slices; double thetaIncr = Math.PI * 2 / slices; int countB, countA; // Add top hemisphere vertices for (countA = 0, thai = thaiIncr; thai < Math.PI / 2; thai += thaiIncr, countA++) { for (countB = 0, theta = 0; countB < slices; theta += thetaIncr, countB++) { VertexPositionNormal vert = new VertexPositionNormal(); vert.Position = Vector3Helper.Get((float)(radius * Math.Sin(thai) * Math.Cos(theta)), (float)(radius * Math.Cos(thai)) + cylinderHeight / 2, (float)(radius * Math.Sin(thai) * Math.Sin(theta))); vert.Normal = Vector3.Normalize(vert.Position - topCenter); vertices.Add(vert); } } // Add bottom hemisphere vertices for (thai = Math.PI / 2; thai < Math.PI - thaiIncr / 2; thai += thaiIncr, countA++) { for (countB = 0, theta = 0; countB < slices; theta += thetaIncr, countB++) { VertexPositionNormal vert = new VertexPositionNormal(); vert.Position = Vector3Helper.Get((float)(radius * Math.Sin(thai) * Math.Cos(theta)), (float)(radius * Math.Cos(thai)) - cylinderHeight / 2, (float)(radius * Math.Sin(thai) * Math.Sin(theta))); vert.Normal = Vector3.Normalize(vert.Position - bottomCenter); vertices.Add(vert); } } // Add north pole vertex vertices.Add(new VertexPositionNormal(Vector3Helper.Get(0, radius + cylinderHeight / 2, 0), Vector3Helper.Get(0, 1, 0))); // Add south pole vertex vertices.Add(new VertexPositionNormal(Vector3Helper.Get(0, -radius - cylinderHeight / 2, 0), Vector3Helper.Get(0, -1, 0))); mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List <short> indices = new List <short>(); // Create the north and south pole area mesh for (int i = 0, j = (countA - 1) * slices; i < slices - 1; i++, j++) { indices.Add((short)(vertices.Count - 2)); indices.Add((short)i); indices.Add((short)(i + 1)); indices.Add((short)(vertices.Count - 1)); indices.Add((short)(j + 1)); indices.Add((short)j); } indices.Add((short)(vertices.Count - 2)); indices.Add((short)(slices - 1)); indices.Add((short)0); indices.Add((short)(vertices.Count - 1)); indices.Add((short)((countA - 1) * slices)); indices.Add((short)(vertices.Count - 3)); // Create side of the hemispheres for (int i = 0; i < countA - 1; i++) { for (int j = 0; j < slices - 1; j++) { indices.Add((short)(i * slices + j)); indices.Add((short)((i + 1) * slices + j)); indices.Add((short)((i + 1) * slices + j + 1)); indices.Add((short)(i * slices + j)); indices.Add((short)((i + 1) * slices + j + 1)); indices.Add((short)(i * slices + j + 1)); } indices.Add((short)((i + 1) * slices - 1)); indices.Add((short)((i + 2) * slices - 1)); indices.Add((short)((i + 1) * slices)); indices.Add((short)((i + 1) * slices - 1)); indices.Add((short)((i + 1) * slices)); indices.Add((short)(i * slices)); } mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return(mesh); }
private static CustomMesh CreateChamferCylinder(float radius, float height, int slices) { if(slices < 5) throw new ArgumentException("Cannot draw a capsule with slices less than 5"); if (slices > 100) throw new ArgumentException("Cannot draw a capsule with slices greater than 100"); if (radius <= 0) throw new ArgumentException("radius should be greater than zero"); if (height <= 0) throw new ArgumentException("height should be greater than zero"); CustomMesh mesh = new CustomMesh(); List<VertexPositionNormal> vertices = new List<VertexPositionNormal>(); float halfH = height / 2; Vector3 topCenter = Vector3Helper.Get(0, halfH, 0); Vector3 bottomCenter = Vector3Helper.Get(0, -halfH, 0); double thai = 0, theta = 0; double thaiIncr = Math.PI / slices; double thetaIncr = Math.PI * 2 / slices; int countB, countA; // Add side vertices for (countA = 0, thai = 0; thai <= Math.PI; thai += thaiIncr, countA++) { for (countB = 0, theta = 0; countB < slices; theta += thetaIncr, countB++) { VertexPositionNormal vert = new VertexPositionNormal(); vert.Position = Vector3Helper.Get((float)(halfH * Math.Sin(thai) * Math.Cos(theta) + radius * Math.Cos(theta)), (float)(halfH * Math.Cos(thai)), (float)(halfH * Math.Sin(thai) * Math.Sin(theta) + radius * Math.Sin(theta))); vert.Normal = Vector3.Normalize(vert.Position); vertices.Add(vert); } } // Add north pole vertex vertices.Add(new VertexPositionNormal(topCenter, new Vector3(0, 1, 0))); // Add south pole vertex vertices.Add(new VertexPositionNormal(bottomCenter, new Vector3(0, -1, 0))); mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List<short> indices = new List<short>(); // Create side of the hemispheres for (int i = 0; i < countA - 1; i++) { for (int j = 0; j < slices - 1; j++) { indices.Add((short)(i * slices + j)); indices.Add((short)((i + 1) * slices + j)); indices.Add((short)((i + 1) * slices + j + 1)); indices.Add((short)(i * slices + j)); indices.Add((short)((i + 1) * slices + j + 1)); indices.Add((short)(i * slices + j + 1)); } indices.Add((short)((i + 1) * slices - 1)); indices.Add((short)((i + 2) * slices - 1)); indices.Add((short)((i + 1) * slices)); indices.Add((short)((i + 1) * slices - 1)); indices.Add((short)((i + 1) * slices)); indices.Add((short)(i * slices )); } // Create the north and south pole area mesh for (int i = 0, j = (countA - 1) * slices; i < slices - 1; i++, j++) { indices.Add((short)(vertices.Count - 2)); indices.Add((short)i); indices.Add((short)(i + 1)); indices.Add((short)(vertices.Count - 1)); indices.Add((short)(j + 1)); indices.Add((short)j); } indices.Add((short)(vertices.Count - 2)); indices.Add((short)(slices - 1)); indices.Add(0); indices.Add((short)(vertices.Count - 1)); indices.Add((short)((countA - 1) * slices)); indices.Add((short)(vertices.Count - 3)); mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return mesh; }
private static CustomMesh CreateBox(float xdim, float ydim, float zdim) { CustomMesh mesh = new CustomMesh(); VertexPositionNormal[] vertices = new VertexPositionNormal[24]; Vector3 halfExtent = new Vector3(); halfExtent.X = xdim / 2; halfExtent.Y = ydim / 2; halfExtent.Z = zdim / 2; Vector3 v0 = Vector3Helper.Get(-halfExtent.X, -halfExtent.Y, -halfExtent.Z); Vector3 v1 = Vector3Helper.Get(halfExtent.X, -halfExtent.Y, -halfExtent.Z); Vector3 v2 = Vector3Helper.Get(-halfExtent.X, halfExtent.Y, -halfExtent.Z); Vector3 v3 = Vector3Helper.Get(halfExtent.X, halfExtent.Y, -halfExtent.Z); Vector3 v4 = Vector3Helper.Get(halfExtent.X, halfExtent.Y, halfExtent.Z); Vector3 v5 = Vector3Helper.Get(-halfExtent.X, halfExtent.Y, halfExtent.Z); Vector3 v6 = Vector3Helper.Get(halfExtent.X, -halfExtent.Y, halfExtent.Z); Vector3 v7 = Vector3Helper.Get(-halfExtent.X, -halfExtent.Y, halfExtent.Z); Vector3 nZ = -Vector3.UnitZ; Vector3 pZ = Vector3.UnitZ; Vector3 nX = -Vector3.UnitX; Vector3 pX = Vector3.UnitX; Vector3 nY = -Vector3.UnitY; Vector3 pY = Vector3.UnitY; vertices[0].Position = v0; vertices[1].Position = v1; vertices[2].Position = v2; vertices[3].Position = v3; vertices[4].Position = v0; vertices[5].Position = v7; vertices[6].Position = v2; vertices[7].Position = v5; vertices[8].Position = v4; vertices[9].Position = v5; vertices[10].Position = v7; vertices[11].Position = v6; vertices[12].Position = v4; vertices[13].Position = v3; vertices[14].Position = v1; vertices[15].Position = v6; vertices[16].Position = v2; vertices[17].Position = v4; vertices[18].Position = v5; vertices[19].Position = v3; vertices[20].Position = v0; vertices[21].Position = v1; vertices[22].Position = v6; vertices[23].Position = v7; for (int i = 0; i < 4; i++) { vertices[i].Normal = nZ; } for (int i = 4; i < 8; i++) { vertices[i].Normal = nX; } for (int i = 8; i < 12; i++) { vertices[i].Normal = pZ; } for (int i = 12; i < 16; i++) { vertices[i].Normal = pX; } for (int i = 16; i < 20; i++) { vertices[i].Normal = pY; } for (int i = 20; i < 24; i++) { vertices[i].Normal = nY; } mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), 24, BufferUsage.None); mesh.VertexBuffer.SetData <VertexPositionNormal>(vertices); short [] indices = new short[36]; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 2; indices[4] = 1; indices[5] = 3; indices[6] = 4; indices[7] = 6; indices[8] = 5; indices[9] = 6; indices[10] = 7; indices[11] = 5; indices[12] = 11; indices[13] = 10; indices[14] = 9; indices[15] = 11; indices[16] = 9; indices[17] = 8; indices[18] = 14; indices[19] = 15; indices[20] = 13; indices[21] = 15; indices[22] = 12; indices[23] = 13; indices[24] = 19; indices[25] = 17; indices[26] = 18; indices[27] = 19; indices[28] = 18; indices[29] = 16; indices[30] = 21; indices[31] = 20; indices[32] = 23; indices[33] = 21; indices[34] = 23; indices[35] = 22; mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), 36, BufferUsage.None); mesh.IndexBuffer.SetData(indices); mesh.NumberOfVertices = 24; mesh.NumberOfPrimitives = 12; return(mesh); }
private static CustomMesh CreateShape(float xDim, float yDim, float zDim) { // Create a primitive mesh for creating our custom pyramid shape CustomMesh pyramid = new CustomMesh(); // Even though we really need 5 vertices to create a pyramid shape, since // we want to assign different normals for points with same position to have // more accurate lighting effect, we will use 16 vertices. VertexPositionNormal[] verts = new VertexPositionNormal[16]; Vector3 vBase0 = new Vector3(-xDim / 2, 0, zDim / 2); Vector3 vBase1 = new Vector3(xDim / 2, 0, zDim / 2); Vector3 vBase2 = new Vector3(xDim / 2, 0, -zDim / 2); Vector3 vBase3 = new Vector3(-xDim / 2, 0, -zDim / 2); Vector3 vTop = new Vector3(0, yDim, 0); verts[0].Position = vTop; verts[1].Position = vBase1; verts[2].Position = vBase0; verts[3].Position = vTop; verts[4].Position = vBase2; verts[5].Position = vBase1; verts[6].Position = vTop; verts[7].Position = vBase3; verts[8].Position = vBase2; verts[9].Position = vTop; verts[10].Position = vBase0; verts[11].Position = vBase3; verts[12].Position = vBase0; verts[13].Position = vBase1; verts[14].Position = vBase2; verts[15].Position = vBase3; verts[0].Normal = verts[1].Normal = verts[2].Normal = CalcNormal(vTop, vBase1, vBase0); verts[3].Normal = verts[4].Normal = verts[5].Normal = CalcNormal(vTop, vBase2, vBase1); verts[6].Normal = verts[7].Normal = verts[8].Normal = CalcNormal(vTop, vBase3, vBase2); verts[9].Normal = verts[10].Normal = verts[11].Normal = CalcNormal(vTop, vBase0, vBase3); verts[12].Normal = verts[13].Normal = verts[14].Normal = verts[15].Normal = CalcNormal(vBase0, vBase1, vBase3); pyramid.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), 16, BufferUsage.None); pyramid.VertexDeclaration = VertexPositionNormal.VertexDeclaration; pyramid.VertexBuffer.SetData(verts); pyramid.NumberOfVertices = 16; short[] indices = new short[18]; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 3; indices[4] = 4; indices[5] = 5; indices[6] = 6; indices[7] = 7; indices[8] = 8; indices[9] = 9; indices[10] = 10; indices[11] = 11; indices[12] = 12; indices[13] = 13; indices[14] = 15; indices[15] = 13; indices[16] = 14; indices[17] = 15; pyramid.IndexBuffer = new IndexBuffer(State.Device, typeof(short), 18, BufferUsage.WriteOnly); pyramid.IndexBuffer.SetData(indices); pyramid.PrimitiveType = PrimitiveType.TriangleList; pyramid.NumberOfPrimitives = 6; return pyramid; }
private static CustomMesh CreateDisk(float inner, float outer, int slices, double start, double sweep, bool twoSided) { if (slices < 3) throw new ArgumentException("Cannot draw a disk with slices less than 3"); if (inner < 0) throw new ArgumentException("Inner radius has to be greater than or equal to 0"); if (outer <= 0) throw new ArgumentException("Outer radius has to be greater than 0"); if (inner >= outer) throw new ArgumentException("Inner radius has to be less than outer radius"); CustomMesh mesh = new CustomMesh(); List<VertexPositionNormal> vertices = new List<VertexPositionNormal>(); double angle = start; double incr = sweep / slices; float cos, sin; bool hasInner = (inner > 0); // Add top & bottom side vertices if (!hasInner) { VertexPositionNormal front = new VertexPositionNormal(); front.Position = Vector3Helper.Get(0, 0, 0); front.Normal = Vector3Helper.Get(0, 1, 0); vertices.Add(front); if (twoSided) { VertexPositionNormal back = new VertexPositionNormal(); back.Position = Vector3Helper.Get(0, 0, 0); back.Normal = Vector3Helper.Get(0, -1, 0); vertices.Add(back); } } // Add inner & outer vertices for (int i = 0; i <= slices; i++, angle += incr) { cos = (float)Math.Cos(angle); sin = (float)Math.Sin(angle); if (hasInner) { VertexPositionNormal inside = new VertexPositionNormal(); inside.Position = Vector3Helper.Get(cos * inner, 0, sin * inner); inside.Normal = Vector3Helper.Get(0, 1, 0); vertices.Add(inside); if (twoSided) vertices.Add(new VertexPositionNormal(inside.Position, Vector3Helper.Get(0, -1, 0))); } VertexPositionNormal outside = new VertexPositionNormal(); outside.Position = Vector3Helper.Get(cos * outer, 0, sin * outer); outside.Normal = Vector3Helper.Get(0, 1, 0); vertices.Add(outside); if (twoSided) vertices.Add(new VertexPositionNormal(outside.Position, Vector3Helper.Get(0, -1, 0))); } mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List<short> indices = new List<short>(); // Create front side if (twoSided) { if (hasInner) { for (int i = 0; i < vertices.Count - 2; i++) { indices.Add((short)(2 * i)); indices.Add((short)(2 * (i + 2 - (i+1)%2))); indices.Add((short)(2 * (i + 2 - i%2))); indices.Add((short)(2 * i - 1)); indices.Add((short)(2 * (i + 2 - (i + 1) % 2) - 1)); indices.Add((short)(2 * (i + 2 - i % 2) - 1)); } } else { for (int i = 1; i < vertices.Count - 1; i++) { indices.Add((short)0); indices.Add((short)(2 * i)); indices.Add((short)(2 * (i + 1))); indices.Add((short)0); indices.Add((short)(i + 3)); indices.Add((short)(i + 1)); } } } else { if (hasInner) { for (int i = 0; i < vertices.Count - 2; i++) { indices.Add((short)i); indices.Add((short)(i + 2 - (i+1)%2)); indices.Add((short)(i + 2 - i%2)); } } else { for (int i = 1; i < vertices.Count - 1; i++) { indices.Add((short)0); indices.Add((short)(i)); indices.Add((short)(i + 1)); } } } mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return mesh; }
private static CustomMesh CreateCylinder(float bottom, float top, float height, int slices) { if (slices < 3) { throw new ArgumentException("Cannot draw a cylinder with slices less than 3"); } if (top < 0) { throw new ArgumentException("Top has to be a positive natural number"); } if (bottom <= 0) { throw new ArgumentException("Bottom has to be greater than zero"); } if (height <= 0) { throw new ArgumentException("Height should be greater than zero"); } CustomMesh mesh = new CustomMesh(); List <VertexPositionNormal> vertices = new List <VertexPositionNormal>(); // Add top center vertex VertexPositionNormal topCenter = new VertexPositionNormal(); topCenter.Position = Vector3Helper.Get(0, height / 2, 0); topCenter.Normal = Vector3Helper.Get(0, 1, 0); vertices.Add(topCenter); // Add bottom center vertex VertexPositionNormal bottomCenter = new VertexPositionNormal(); bottomCenter.Position = Vector3Helper.Get(0, -height / 2, 0); bottomCenter.Normal = Vector3Helper.Get(0, -1, 0); vertices.Add(bottomCenter); double angle = 0; double incr = Math.PI * 2 / slices; float cos, sin; bool hasTop = (top > 0); Vector3 u, v; Matrix mat; bool tilted = (top != bottom); float rotAngle = (float)Math.Atan(bottom / height); Vector3 down = -Vector3.UnitY; if (hasTop) { // Add top & bottom side vertices for (int i = 0; i <= slices; i++, angle += incr) { cos = (float)Math.Cos(angle); sin = (float)Math.Sin(angle); VertexPositionNormal topSide = new VertexPositionNormal(); topSide.Position = Vector3Helper.Get(cos * top, height / 2, sin * top); topSide.Normal = Vector3.Normalize(topSide.Position - topCenter.Position); VertexPositionNormal topSide2 = new VertexPositionNormal(); topSide2.Position = Vector3Helper.Get(cos * top, height / 2, sin * top); topSide2.Normal = topCenter.Normal; // Add bottom side vertices VertexPositionNormal bottomSide = new VertexPositionNormal(); bottomSide.Position = Vector3Helper.Get(cos * bottom, -height / 2, sin * bottom); bottomSide.Normal = Vector3.Normalize(bottomSide.Position - bottomCenter.Position); VertexPositionNormal bottomSide2 = new VertexPositionNormal(); bottomSide2.Position = Vector3Helper.Get(cos * bottom, -height / 2, sin * bottom); bottomSide2.Normal = bottomCenter.Normal; if (tilted) { v = topSide.Normal; u = Vector3.Cross(v, down); mat = Matrix.CreateTranslation(v) * Matrix.CreateFromAxisAngle(u, -rotAngle); topSide.Normal = bottomSide.Normal = Vector3.Normalize(mat.Translation); } vertices.Add(topSide); vertices.Add(topSide2); vertices.Add(bottomSide); vertices.Add(bottomSide2); } } else { // Add top & bottom side vertices for (int i = 0; i <= slices; i++, angle += incr) { cos = (float)Math.Cos(angle); sin = (float)Math.Sin(angle); VertexPositionNormal topSide = new VertexPositionNormal(); topSide.Position = topCenter.Position; // Add bottom side vertices VertexPositionNormal bottomSide = new VertexPositionNormal(); bottomSide.Position = Vector3Helper.Get(cos * bottom, -height / 2, sin * bottom); bottomSide.Normal = Vector3.Normalize(bottomSide.Position - bottomCenter.Position); VertexPositionNormal bottomSide2 = new VertexPositionNormal(); bottomSide2.Position = Vector3Helper.Get(cos * bottom, -height / 2, sin * bottom); bottomSide2.Normal = bottomCenter.Normal; v = bottomSide.Normal; u = Vector3.Cross(v, down); mat = Matrix.CreateTranslation(v) * Matrix.CreateFromAxisAngle(u, rotAngle); topSide.Normal = bottomSide.Normal = Vector3.Normalize(mat.Translation); vertices.Add(topSide); vertices.Add(bottomSide); vertices.Add(bottomSide2); } } mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List <short> indices = new List <short>(); if (hasTop) { // Create top & bottom circle for (int i = 2; i < vertices.Count - 7; i += 4) { indices.Add(0); indices.Add((short)(i + 1)); indices.Add((short)(i + 5)); indices.Add(1); indices.Add((short)(i + 7)); indices.Add((short)(i + 3)); } // Create side for (int i = 2; i < vertices.Count - 7; i += 4) { indices.Add((short)i); indices.Add((short)(i + 2)); indices.Add((short)(i + 4)); indices.Add((short)(i + 4)); indices.Add((short)(i + 2)); indices.Add((short)(i + 6)); } } else { // Create bottom circle for (int i = 2; i < vertices.Count - 5; i += 3) { indices.Add(1); indices.Add((short)(i + 5)); indices.Add((short)(i + 2)); } // Create side for (int i = 2; i < vertices.Count - 5; i += 3) { indices.Add((short)i); indices.Add((short)(i + 1)); indices.Add((short)(i + 4)); } } mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return(mesh); }
private static CustomMesh CreateCylinder(float bottom, float top, float height, int slices) { if(slices < 3) throw new ArgumentException("Cannot draw a cylinder with slices less than 3"); if (top < 0) throw new ArgumentException("Top has to be a positive natural number"); if (bottom <= 0) throw new ArgumentException("Bottom has to be greater than zero"); if (height <= 0) throw new ArgumentException("Height should be greater than zero"); CustomMesh mesh = new CustomMesh(); List<VertexPositionNormal> vertices = new List<VertexPositionNormal>(); // Add top center vertex VertexPositionNormal topCenter = new VertexPositionNormal(); topCenter.Position = Vector3Helper.Get(0, height / 2, 0); topCenter.Normal = Vector3Helper.Get(0, 1, 0); vertices.Add(topCenter); // Add bottom center vertex VertexPositionNormal bottomCenter = new VertexPositionNormal(); bottomCenter.Position = Vector3Helper.Get(0, -height / 2, 0); bottomCenter.Normal = Vector3Helper.Get(0, -1, 0); vertices.Add(bottomCenter); double angle = 0; double incr = Math.PI * 2 / slices; float cos, sin; bool hasTop = (top > 0); Vector3 u, v; Matrix mat; bool tilted = (top != bottom); float rotAngle = (float)Math.Atan(bottom / height); Vector3 down = -Vector3.UnitY; if (hasTop) { // Add top & bottom side vertices for (int i = 0; i <= slices; i++, angle += incr) { cos = (float)Math.Cos(angle); sin = (float)Math.Sin(angle); VertexPositionNormal topSide = new VertexPositionNormal(); topSide.Position = Vector3Helper.Get(cos * top, height / 2, sin * top); topSide.Normal = Vector3.Normalize(topSide.Position - topCenter.Position); VertexPositionNormal topSide2 = new VertexPositionNormal(); topSide2.Position = Vector3Helper.Get(cos * top, height / 2, sin * top); topSide2.Normal = topCenter.Normal; // Add bottom side vertices VertexPositionNormal bottomSide = new VertexPositionNormal(); bottomSide.Position = Vector3Helper.Get(cos * bottom, -height / 2, sin * bottom); bottomSide.Normal = Vector3.Normalize(bottomSide.Position - bottomCenter.Position); VertexPositionNormal bottomSide2 = new VertexPositionNormal(); bottomSide2.Position = Vector3Helper.Get(cos * bottom, -height / 2, sin * bottom); bottomSide2.Normal = bottomCenter.Normal; if (tilted) { v = topSide.Normal; u = Vector3.Cross(v, down); mat = Matrix.CreateTranslation(v) * Matrix.CreateFromAxisAngle(u, -rotAngle); topSide.Normal = bottomSide.Normal = Vector3.Normalize(mat.Translation); } vertices.Add(topSide); vertices.Add(topSide2); vertices.Add(bottomSide); vertices.Add(bottomSide2); } } else { // Add top & bottom side vertices for (int i = 0; i <= slices; i++, angle += incr) { cos = (float)Math.Cos(angle); sin = (float)Math.Sin(angle); VertexPositionNormal topSide = new VertexPositionNormal(); topSide.Position = topCenter.Position; // Add bottom side vertices VertexPositionNormal bottomSide = new VertexPositionNormal(); bottomSide.Position = Vector3Helper.Get(cos * bottom, -height / 2, sin * bottom); bottomSide.Normal = Vector3.Normalize(bottomSide.Position - bottomCenter.Position); VertexPositionNormal bottomSide2 = new VertexPositionNormal(); bottomSide2.Position = Vector3Helper.Get(cos * bottom, -height / 2, sin * bottom); bottomSide2.Normal = bottomCenter.Normal; v = bottomSide.Normal; u = Vector3.Cross(v, down); mat = Matrix.CreateTranslation(v) * Matrix.CreateFromAxisAngle(u, rotAngle); topSide.Normal = bottomSide.Normal = Vector3.Normalize(mat.Translation); vertices.Add(topSide); vertices.Add(bottomSide); vertices.Add(bottomSide2); } } mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List<short> indices = new List<short>(); if (hasTop) { // Create top & bottom circle for (int i = 2; i < vertices.Count - 7; i += 4) { indices.Add(0); indices.Add((short)(i + 1)); indices.Add((short)(i + 5)); indices.Add(1); indices.Add((short)(i + 7)); indices.Add((short)(i + 3)); } // Create side for (int i = 2; i < vertices.Count - 7; i += 4) { indices.Add((short)i); indices.Add((short)(i + 2)); indices.Add((short)(i + 4)); indices.Add((short)(i + 4)); indices.Add((short)(i + 2)); indices.Add((short)(i + 6)); } } else { // Create bottom circle for (int i = 2; i < vertices.Count - 5; i += 3) { indices.Add(1); indices.Add((short)(i + 5)); indices.Add((short)(i + 2)); } // Create side for (int i = 2; i < vertices.Count - 5; i += 3) { indices.Add((short)i); indices.Add((short)(i + 1)); indices.Add((short)(i + 4)); } } mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return mesh; }
private static CustomMesh CreateSphere(float radius, int slices, int stacks) { if (slices < 5) { throw new ArgumentException("Cannot draw a sphere with slices less than 5"); } if (slices > 100) { throw new ArgumentException("Cannot draw a sphere with slices greater than 100"); } if (stacks < 5) { throw new ArgumentException("Cannot draw a sphere with stacks less than 5"); } if (stacks > 100) { throw new ArgumentException("Cannot draw a sphere with stacks greater than 100"); } if (radius <= 0) { throw new ArgumentException("Radius has to be greater than 0"); } CustomMesh mesh = new CustomMesh(); List <VertexPositionNormal> vertices = new List <VertexPositionNormal>(); double thai = 0, theta = 0; double thaiIncr = Math.PI / stacks; double thetaIncr = Math.PI * 2 / slices; int countB, countA; // Add sphere vertices for (countA = 0, thai = thaiIncr; thai < Math.PI - thaiIncr / 2; thai += thaiIncr, countA++) { for (countB = 0, theta = 0; countB < slices; theta += thetaIncr, countB++) { VertexPositionNormal vert = new VertexPositionNormal(); vert.Position = Vector3Helper.Get((float)(radius * Math.Sin(thai) * Math.Cos(theta)), (float)(radius * Math.Cos(thai)), (float)(radius * Math.Sin(thai) * Math.Sin(theta))); vert.Normal = Vector3.Normalize(vert.Position); vertices.Add(vert); } } // Add north pole vertex vertices.Add(new VertexPositionNormal(Vector3Helper.Get(0, radius, 0), Vector3Helper.Get(0, 1, 0))); // Add south pole vertex vertices.Add(new VertexPositionNormal(Vector3Helper.Get(0, -radius, 0), Vector3Helper.Get(0, -1, 0))); mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List <short> indices = new List <short>(); // Create the north and south pole area mesh for (int i = 0, j = (countA - 1) * slices; i < slices - 1; i++, j++) { indices.Add((short)(vertices.Count - 2)); indices.Add((short)i); indices.Add((short)(i + 1)); indices.Add((short)(vertices.Count - 1)); indices.Add((short)(j + 1)); indices.Add((short)j); } indices.Add((short)(vertices.Count - 2)); indices.Add((short)(slices - 1)); indices.Add(0); indices.Add((short)(vertices.Count - 1)); indices.Add((short)((countA - 1) * slices)); indices.Add((short)(vertices.Count - 3)); // Create side of the sphere for (int i = 0; i < countA - 1; i++) { for (int j = 0; j < slices - 1; j++) { indices.Add((short)(i * slices + j)); indices.Add((short)((i + 1) * slices + j)); indices.Add((short)((i + 1) * slices + j + 1)); indices.Add((short)(i * slices + j)); indices.Add((short)((i + 1) * slices + j + 1)); indices.Add((short)(i * slices + j + 1)); } indices.Add((short)((i + 1) * slices - 1)); indices.Add((short)((i + 2) * slices - 1)); indices.Add((short)((i + 1) * slices)); indices.Add((short)((i + 1) * slices - 1)); indices.Add((short)((i + 1) * slices)); indices.Add((short)(i * slices)); } mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return(mesh); }
private static CustomMesh CreateDisk(float inner, float outer, int slices, double start, double sweep, bool twoSided) { if (slices < 3) { throw new ArgumentException("Cannot draw a disk with slices less than 3"); } if (inner < 0) { throw new ArgumentException("Inner radius has to be greater than or equal to 0"); } if (outer <= 0) { throw new ArgumentException("Outer radius has to be greater than 0"); } if (inner >= outer) { throw new ArgumentException("Inner radius has to be less than outer radius"); } CustomMesh mesh = new CustomMesh(); List <VertexPositionNormal> vertices = new List <VertexPositionNormal>(); double angle = start; double incr = sweep / slices; float cos, sin; bool hasInner = (inner > 0); // Add top & bottom side vertices if (!hasInner) { VertexPositionNormal front = new VertexPositionNormal(); front.Position = Vector3Helper.Get(0, 0, 0); front.Normal = Vector3Helper.Get(0, 1, 0); vertices.Add(front); if (twoSided) { VertexPositionNormal back = new VertexPositionNormal(); back.Position = Vector3Helper.Get(0, 0, 0); back.Normal = Vector3Helper.Get(0, -1, 0); vertices.Add(back); } } // Add inner & outer vertices for (int i = 0; i <= slices; i++, angle += incr) { cos = (float)Math.Cos(angle); sin = (float)Math.Sin(angle); if (hasInner) { VertexPositionNormal inside = new VertexPositionNormal(); inside.Position = Vector3Helper.Get(cos * inner, 0, sin * inner); inside.Normal = Vector3Helper.Get(0, 1, 0); vertices.Add(inside); if (twoSided) { vertices.Add(new VertexPositionNormal(inside.Position, Vector3Helper.Get(0, -1, 0))); } } VertexPositionNormal outside = new VertexPositionNormal(); outside.Position = Vector3Helper.Get(cos * outer, 0, sin * outer); outside.Normal = Vector3Helper.Get(0, 1, 0); vertices.Add(outside); if (twoSided) { vertices.Add(new VertexPositionNormal(outside.Position, Vector3Helper.Get(0, -1, 0))); } } mesh.VertexDeclaration = VertexPositionNormal.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); mesh.VertexBuffer.SetData(vertices.ToArray()); List <short> indices = new List <short>(); // Create front side if (twoSided) { if (hasInner) { for (int i = 0; i < vertices.Count - 2; i++) { indices.Add((short)(2 * i)); indices.Add((short)(2 * (i + 2 - (i + 1) % 2))); indices.Add((short)(2 * (i + 2 - i % 2))); indices.Add((short)(2 * i - 1)); indices.Add((short)(2 * (i + 2 - (i + 1) % 2) - 1)); indices.Add((short)(2 * (i + 2 - i % 2) - 1)); } } else { for (int i = 1; i < vertices.Count - 1; i++) { indices.Add((short)0); indices.Add((short)(2 * i)); indices.Add((short)(2 * (i + 1))); indices.Add((short)0); indices.Add((short)(i + 3)); indices.Add((short)(i + 1)); } } } else { if (hasInner) { for (int i = 0; i < vertices.Count - 2; i++) { indices.Add((short)i); indices.Add((short)(i + 2 - (i + 1) % 2)); indices.Add((short)(i + 2 - i % 2)); } } else { for (int i = 1; i < vertices.Count - 1; i++) { indices.Add((short)0); indices.Add((short)(i)); indices.Add((short)(i + 1)); } } } mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), indices.Count, BufferUsage.None); mesh.IndexBuffer.SetData(indices.ToArray()); mesh.NumberOfVertices = vertices.Count; mesh.NumberOfPrimitives = indices.Count / 3; return(mesh); }