/// <summary> /// The three points p0, p0 + u and p0 + v make up a triangle. If 'divisions' is 1 and 'doQuad' is false,<para/> /// exactly this triangle will be added to the mesh. If 'divisions' is larger than 1, the triangle will be subdivided.<para/> /// If 'doQuad' is true, the triangle is expanded to a parallelogram using the fourth point p0 + u + v. /// </summary> static public void AddTriangles(MeshGeometry3D mesh, int divisions, Point3D p0, Vector3D u, Vector3D v, double tu0, double tu1, bool doQuad = true) { TextureTransform tt = new TextureTransform(0, divisions, tu0, tu1, 1, 0); Vector3D du = u / (double)divisions; Vector3D dv = v / (double)divisions; Vector3D n = u.Cross(v); n.Normalize(); for (int iv = 0; iv < divisions; iv++) { int iuMax = doQuad ? divisions : divisions - iv; for (int iu = 0; iu < iuMax; iu++) { Point3D p1 = p0 + iu * du + iv * dv; Point3D p2 = p1 + du; Point3D p3 = p1 + dv; Point3D p4 = p2 + dv; mesh.Positions.Add(p1); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu, iv)); mesh.Positions.Add(p2); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu + 1, iv)); mesh.Positions.Add(p3); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu, iv + 1)); int i = mesh.Positions.Count - 3; AddTriangleIndices(mesh, i, i + 1, i + 2); bool doUpperTriangle = doQuad ? true : iu < iuMax - 1; if (doUpperTriangle) { mesh.Positions.Add(p4); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu + 1, iv + 1)); AddTriangleIndices(mesh, i + 1, i + 3, i + 2); continue; } } } }
/// <summary> /// The three points p0, p0 + u and p0 + v make up a triangle. If 'divisions' is 1 and 'doQuad' is false,<para/> /// exactly this triangle will be added to the mesh. If 'divisions' is larger than 1, the triangle will be subdivided.<para/> /// If 'doQuad' is true, the triangle is expanded to a parallelogram using the fourth point p0 + u + v. /// </summary> public static void AddTriangles(MeshGeometry3D mesh, int divisions, Point3D p0, Vector3D u, Vector3D v, double tu0, double tu1, bool doQuad = true) { TextureTransform tt = new TextureTransform(0, divisions, tu0, tu1, 1, 0); Vector3D du = u / (double)divisions; Vector3D dv = v / (double)divisions; Vector3D n = u.Cross(v); n.Normalize(); for (int iv = 0; iv < divisions; iv++) { int iuMax = doQuad ? divisions : divisions - iv; for (int iu = 0; iu < iuMax; iu++) { Point3D p1 = p0 + iu * du + iv * dv; Point3D p2 = p1 + du; Point3D p3 = p1 + dv; Point3D p4 = p2 + dv; mesh.Positions.Add(p1); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu, iv)); mesh.Positions.Add(p2); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu + 1, iv)); mesh.Positions.Add(p3); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu, iv + 1)); int i = mesh.Positions.Count - 3; AddTriangleIndices(mesh, i, i + 1, i + 2); bool doUpperTriangle = doQuad ? true : iu < iuMax - 1; if (doUpperTriangle) { mesh.Positions.Add(p4); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu + 1, iv + 1)); AddTriangleIndices(mesh, i + 1, i + 3, i + 2); continue; } } } }
/// <summary> /// Mesh for a cone in the xy plane from z = 0 to z = 1. /// </summary> static public MeshGeometry3D CreateCone(int divisions, bool isClosed) { if (divisions < 3 || divisions > 999) { return(null); } TextureTransform tt = new TextureTransform(-1, 1, 0, 1, 1, 0); MeshGeometry3D mesh = new MeshGeometry3D(); mesh.Positions.Add(new Point3D(0, 0, 1)); mesh.Normals.Add(new Vector3D(0, 0, 1)); mesh.TextureCoordinates.Add(tt.Transform(0, 0)); double dPhi = MathUtils.PIx2 / divisions; double phi0 = dPhi * 0.5; for (int id = 0; id <= divisions; id++) { double phi = phi0 + id * dPhi; double tx = phi / MathUtils.PIx2; double x = Math.Cos(phi); double y = Math.Sin(phi); mesh.Positions.Add(new Point3D(x, y, 0)); mesh.Normals.Add(new Vector3D(x, y, 0)); mesh.TextureCoordinates.Add(tt.Transform(x, y)); if (id > 0) { AddTriangleIndices(mesh, id, id + 1, 0); } } if (isClosed) { AddTriangles(mesh, divisions, 1, 0, 0, 360, 0); } return(mesh); }
/// <summary> /// Add triangles for a disk segment parallel to the xy plane at a certain z value. /// If startDegrees > stopDegrees, the triangle faces will go down the negative z axis. /// </summary> static void AddTriangles(MeshGeometry3D mesh, int divisions, double outerRadius, double innerRadius, double z, double startDegrees, double stopDegrees) { double start = MathUtils.ToRadians(startDegrees); double stop = MathUtils.ToRadians(stopDegrees); double dPhi = (stop - start) / divisions; double phi0 = start; if (IsNotMeantToBeRound(divisions, startDegrees, stopDegrees)) { phi0 = dPhi * 0.5; } Vector3D n = new Vector3D(0, 0, Math.Sign(dPhi)); TextureTransform tt = new TextureTransform(-outerRadius, outerRadius, 0, 1, 1, 0); int i0 = mesh.Positions.Count; if (innerRadius == 0) { mesh.Positions.Add(new Point3D(0, 0, z)); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(new Point(0.5, 0.5)); } for (int id = 0; id <= divisions; id++) { double phi = phi0 + id * dPhi; double cos = Math.Cos(phi); double sin = Math.Sin(phi); double x = outerRadius * cos; double y = outerRadius * sin; mesh.Positions.Add(new Point3D(x, y, z)); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(x, y)); if (innerRadius == 0) { if (id > 0) { int i = mesh.Positions.Count - 2; AddTriangleIndices(mesh, i0, i, i + 1); } continue; } x = innerRadius * cos; y = innerRadius * sin; mesh.Positions.Add(new Point3D(x, y, z)); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(x, y)); if (id > 0) { int i = mesh.Positions.Count - 2; AddTriangleIndices(mesh, i, i - 1, i - 2); AddTriangleIndices(mesh, i, i + 1, i - 1); } } }
/// <summary> /// Add triangles for a disk segment parallel to the xy plane at a certain z value. /// If startDegrees > stopDegrees, the triangle faces will go down the negative z axis. /// </summary> static void AddTriangles(MeshGeometry3D mesh, int divisions, double outerRadius, double innerRadius, double z, double startDegrees, double stopDegrees) { double start = MathUtils.ToRadians(startDegrees); double stop = MathUtils.ToRadians(stopDegrees); double dPhi = (stop - start) / divisions; double phi0 = start; if (IsNotMeantToBeRound(divisions, startDegrees, stopDegrees)) phi0 = dPhi * 0.5; Vector3D n = new Vector3D(0, 0, Math.Sign(dPhi)); TextureTransform tt = new TextureTransform(-outerRadius, outerRadius, 0, 1, 1, 0); int i0 = mesh.Positions.Count; if (innerRadius == 0) { mesh.Positions.Add(new Point3D(0, 0, z)); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(new Point(0.5, 0.5)); } for (int id = 0; id <= divisions; id++) { double phi = phi0 + id * dPhi; double cos = Math.Cos(phi); double sin = Math.Sin(phi); double x = outerRadius * cos; double y = outerRadius * sin; mesh.Positions.Add(new Point3D(x, y, z)); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(x, y)); if (innerRadius == 0) { if (id > 0) { int i = mesh.Positions.Count - 2; AddTriangleIndices(mesh, i0, i, i + 1); } continue; } x = innerRadius * cos; y = innerRadius * sin; mesh.Positions.Add(new Point3D(x, y, z)); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(x, y)); if (id > 0) { int i = mesh.Positions.Count - 2; AddTriangleIndices(mesh, i, i - 1, i - 2); AddTriangleIndices(mesh, i, i + 1, i - 1); } } }
/// <summary> /// Mesh for a cone in the xy plane from z = 0 to z = 1. /// </summary> public static MeshGeometry3D CreateCone(int divisions, bool isClosed) { if (divisions < 3 || divisions > 999) return null; TextureTransform tt = new TextureTransform(-1, 1, 0, 1, 1, 0); MeshGeometry3D mesh = new MeshGeometry3D(); mesh.Positions.Add(new Point3D(0, 0, 1)); mesh.Normals.Add(new Vector3D(0, 0, 1)); mesh.TextureCoordinates.Add(tt.Transform(0, 0)); double dPhi = MathUtils.PIx2 / divisions; double phi0 = dPhi * 0.5; for (int id = 0; id <= divisions; id++) { double phi = phi0 + id * dPhi; double tx = phi / MathUtils.PIx2; double x = Math.Cos(phi); double y = Math.Sin(phi); mesh.Positions.Add(new Point3D(x, y, 0)); mesh.Normals.Add(new Vector3D(x, y, 0)); mesh.TextureCoordinates.Add(tt.Transform(x, y)); if (id > 0) AddTriangleIndices(mesh, id, id + 1, 0); } if (isClosed) AddTriangles(mesh, divisions, 1, 0, 0, 360, 0); return mesh; }