List <IndexTriangle> StitchCircles(List <IndexedVertex> circle1, List <IndexedVertex> circle2) { // Create triangles that connect circle1 to circle2, forming a band of a surface. if (circle1.Count != circle2.Count) { throw new System.Exception("Circles do not have the same number of vertices."); } List <IndexTriangle> triangles = new List <IndexTriangle>(); for (int i = 0; i < circle1.Count; i++) { // Create the triangles that have 2 points each on circle1. // These all have the ordering (c2[i], c1[i+1], c1[i]). int iPlus = (i + 1) % circle1.Count; IndexedVertex iv1 = circle2[i]; IndexedVertex iv2 = circle1[iPlus]; IndexedVertex iv3 = circle1[i]; IndexTriangle tri = new IndexTriangle(iv1, iv2, iv3); triangles.Add(tri); // Create the triangles that have 2 points each on circle2. // These have the ordering (c2[i], c2[i+1], c1[i+1]. iv1 = circle2[i]; iv2 = circle2[iPlus]; iv3 = circle1[iPlus]; tri = new IndexTriangle(iv1, iv2, iv3); triangles.Add(tri); } return(triangles); }
List <IndexTriangle> CloseCylinderCaps(CylinderMesh cylinder, List <IndexedVertex> verts) { List <IndexTriangle> triangles = new List <IndexTriangle>(); List <IndexedVertex> bottomCircle = cylinder.circleCuts[0]; List <IndexedVertex> topCircle = cylinder.circleCuts[cylinder.circleCuts.Count - 1]; // Compute center point of bottom circle. Vector3 bottomCenter = Vector3.zero; foreach (IndexedVertex v in bottomCircle) { bottomCenter += v.vertex; } bottomCenter /= bottomCircle.Count; // Compute center point of top circle. Vector3 topCenter = Vector3.zero; foreach (IndexedVertex v in topCircle) { topCenter += v.vertex; } topCenter /= topCircle.Count; // Add the two points to the mesh. IndexedVertex bottomCenterVert = new IndexedVertex(bottomCenter, currentIndex); currentIndex++; IndexedVertex topCenterVert = new IndexedVertex(topCenter, currentIndex); currentIndex++; verts.Add(bottomCenterVert); verts.Add(topCenterVert); // Add triangle fans. for (int i = 0; i < bottomCircle.Count; i++) { // Bottom circle gets CCW order int iPlus = (i + 1) % bottomCircle.Count; IndexedVertex i1 = bottomCenterVert; IndexedVertex i2 = bottomCircle[i]; IndexedVertex i3 = bottomCircle[iPlus]; IndexTriangle tri = new IndexTriangle(i1, i2, i3); triangles.Add(tri); } for (int i = 0; i < topCircle.Count; i++) { // Top circle gets CW order int iPlus = (i + 1) % topCircle.Count; IndexedVertex i1 = topCenterVert; IndexedVertex i2 = topCircle[iPlus]; IndexedVertex i3 = topCircle[i]; IndexTriangle tri = new IndexTriangle(i1, i2, i3); triangles.Add(tri); } return(triangles); }
List <IndexTriangle> stitchCylinderEnds(CylinderMesh outer, CylinderMesh inner) { if (outer.circleCuts.Count != inner.circleCuts.Count) { throw new System.Exception("Cylinders do not have same number of cuts."); } int numCuts = outer.circleCuts.Count; List <IndexTriangle> triangles = new List <IndexTriangle>(); List <IndexedVertex> topOuter = outer.circleCuts[numCuts - 1]; List <IndexedVertex> topInner = inner.circleCuts[numCuts - 1]; topVerts = topOuter.ConvertAll <Vector3>(new Converter <IndexedVertex, Vector3>(IndexedVertex.toVector3)); if (topOuter.Count != topInner.Count) { throw new System.Exception("Circles do not have same number of vertices."); } // Since the cuts are not necessarily aligned (in the case of curvature // or torsion changes), we want to stitch using the closest pairs of vertices. // Since we start with outer vertex i = 0, find the index of the inner vertex // closest to outer 0. Vector3 outer0top = topOuter[0].vertex; int topInnerOffset = 0; float closestDistance = Vector3.Distance(outer0top, topInner[0].vertex); for (int i = 0; i < topInner.Count; i++) { float dist = Vector3.Distance(topInner[i].vertex, outer0top); if (dist < closestDistance) { closestDistance = dist; topInnerOffset = i; } } // To join the top rim, we need to add the triangles with // counterclockwise ordering, since the vertices are clockwise // when viewed from below (not above). for (int outerI = 0; outerI < topOuter.Count; outerI++) { int outerIPlus = (outerI + 1) % topOuter.Count; int innerI = (outerI + topInnerOffset) % topInner.Count; int innerIPlus = (innerI + 1) % topInner.Count; // The triangles with two vertices in the outer circle have // the order outer[i], inner[i], outer[i+1]. IndexedVertex iv1 = topOuter[outerI]; IndexedVertex iv2 = topInner[innerI]; IndexedVertex iv3 = topOuter[outerIPlus]; IndexTriangle tri = new IndexTriangle(iv1, iv2, iv3); triangles.Add(tri); // The triangles with two vertices in the inner circle have // the order inner[i], inner[i+1], outer[i+1]. iv1 = topInner[innerI]; iv2 = topInner[innerIPlus]; iv3 = topOuter[outerIPlus]; tri = new IndexTriangle(iv1, iv2, iv3); triangles.Add(tri); } List <IndexedVertex> bottomOuter = outer.circleCuts[0]; List <IndexedVertex> bottomInner = inner.circleCuts[0]; bottomVerts = bottomOuter.ConvertAll <Vector3>(new Converter <IndexedVertex, Vector3>(IndexedVertex.toVector3)); if (bottomOuter.Count != bottomInner.Count) { throw new System.Exception("Circles do not have same number of vertices."); } // Same procedure as top ring: find starting vertex closest to // vertex 0 of outer ring. Vector3 outer0bottom = bottomOuter[0].vertex; int bottomInnerOffset = 0; closestDistance = Vector3.Distance(outer0bottom, bottomInner[0].vertex); for (int i = 0; i < bottomInner.Count; i++) { float dist = Vector3.Distance(bottomInner[i].vertex, outer0bottom); if (dist < closestDistance) { closestDistance = dist; bottomInnerOffset = i; } } // To join the bottom faces, we add triangles with vertices in clockwise order. for (int outerI = 0; outerI < bottomOuter.Count; outerI++) { int outerIPlus = (outerI + 1) % bottomOuter.Count; int innerI = (outerI + bottomInnerOffset) % bottomInner.Count; int innerIPlus = (innerI + 1) % bottomInner.Count; // The triangles with two vertices in the outer circle have // the order outer[i], outer[i+1], inner[i]. IndexedVertex iv1 = bottomOuter[outerI]; IndexedVertex iv2 = bottomOuter[outerIPlus]; IndexedVertex iv3 = bottomInner[innerI]; IndexTriangle tri = new IndexTriangle(iv1, iv2, iv3); triangles.Add(tri); // The triangles with two vertices in the inner circle have // the order inner[i], outer[i+1], inner[i+1]. iv1 = bottomInner[innerI]; iv2 = bottomOuter[outerIPlus]; iv3 = bottomInner[innerIPlus]; tri = new IndexTriangle(iv1, iv2, iv3); triangles.Add(tri); } return(triangles); }
/// <summary> /// Create a set of vertices arranged evenly spaced in a circle, with the specified radius, /// centered at centerPoint, and with the specified normal direction. The number of vertices /// is given by verticesPerCircle. /// </summary> /// <param name="centerPoint"></param> /// <param name="direction"></param> /// <param name="radius"></param> /// <returns></returns> List <IndexedVertex> GenerateCircle(int circNum, Vector3 centerPoint, Vector3 direction, Vector3 normal, float radius, bool addInnerGrooves = false, bool addOuterGroove = false) { float angleStep = (2 * Mathf.PI) / Constants.VERTS_PER_CIRCLE; float degreeStep = angleStep * Mathf.Rad2Deg; int twistCuts = Mathf.CeilToInt(Mathf.Abs(nextTwistAngle) / degreeStep); twistCuts *= Mathf.RoundToInt(Mathf.Sign(nextTwistAngle)); List <IndexedVertex> verts = new List <IndexedVertex>(); int grooveRange = Constants.GROOVE_CUT_RADIUS; // First create points in a circle in the XY plane, facing the forward direction. // Then apply the rotation that will rotate the normal onto the desired direction. // Finally, offset it in space to the desired location. Quaternion circleRotation = Quaternion.FromToRotation(Vector3.forward, direction); Vector3 initNormal = Vector3.up; Vector3 rotatedNormal = circleRotation * initNormal; float angle = TelescopeUtils.AngleBetween(rotatedNormal, normal, direction); Quaternion normalRotation = Quaternion.AngleAxis(angle, direction); for (int i = 0; i < Constants.VERTS_PER_CIRCLE; i++) { float currentAngle = i * angleStep; float radiusOffset = 0; if (i < grooveRange || Mathf.Abs(i - Constants.VERTS_PER_CIRCLE / 2) < grooveRange || Mathf.Abs(i - Constants.VERTS_PER_CIRCLE) < grooveRange) { if (addInnerGrooves) { radiusOffset = (thickness - Constants.SHELL_GAP) * Constants.INDENT_RATIO; } else if (addOuterGroove) { radiusOffset = (thickness - Constants.SHELL_GAP / 2) * Constants.INDENT_RATIO; } } else if (circNum >= Constants.CUTS_PER_CYLINDER - 1 && circNum < Constants.CUTS_PER_CYLINDER + Constants.FIN_CUTS) { if (addInnerGrooves && (IsInRadius(i, 0, twistCuts, grooveRange) || IsInRadius(i, Constants.VERTS_PER_CIRCLE, Constants.VERTS_PER_CIRCLE + twistCuts, grooveRange) || IsInRadius(i, Constants.VERTS_PER_CIRCLE / 2, Constants.VERTS_PER_CIRCLE / 2 + twistCuts, grooveRange))) { radiusOffset = (thickness - Constants.SHELL_GAP) * Constants.INDENT_RATIO; } } // Make the vertices in clockwise order Vector3 vert = new Vector3(Mathf.Cos(currentAngle), -Mathf.Sin(currentAngle)); // Scale by radius. vert *= (radius + radiusOffset); // Rotate it to orbit the desired direction. vert = circleRotation * vert; // Rotate it again so that the curvature normal is aligned. vert = normalRotation * vert; // Offset in space to the center point. vert += centerPoint; IndexedVertex iv = new IndexedVertex(vert, currentIndex); currentIndex++; verts.Add(iv); } return(verts); }
public IndexTriangle(IndexedVertex iv1, IndexedVertex iv2, IndexedVertex iv3) { i1 = iv1.index; i2 = iv2.index; i3 = iv3.index; }