public static void CullSphereToHemisphere(MeshTool geometry) { int lastTri = geometry.indices.Length / 3 - 1; var vertUse = new byte[geometry.VertexCount]; for (int i = 0; i <= lastTri; ++i) { var triangle = geometry.GetTriangle(i); Vector3 a = geometry.positions[triangle.x]; Vector3 b = geometry.positions[triangle.y]; Vector3 c = geometry.positions[triangle.z]; if (Vector3.Cross(b - a, c - a).y < 0) { geometry.SwapTriangle(i, lastTri); lastTri -= 1; i -= 1; } else { vertUse[triangle.x] += 1; vertUse[triangle.y] += 1; vertUse[triangle.z] += 1; } } int lastVert = geometry.VertexCount - 1; for (int i = 0; i <= lastVert; ++i) { if (vertUse[i] == 0) { geometry.SwapVertex(i, lastVert, indices: true); Swap(ref vertUse[i], ref vertUse[lastVert]); lastVert -= 1; i -= 1; } } geometry.SetVertexCount(lastVert + 1); geometry.SetIndexCount((lastTri + 1) * 3, preserve: true, lazy: false); geometry.mesh.Clear(); geometry.Apply(positions: true, normals: true, indices: true); }
public static void HemisphereOld(MeshTool geometry, float radius, int complexity, bool correction) { int subdivisions = complexity / 6; int sides = (complexity % 6) + 3; if (correction) { // try to make the average of apoth/radius = desired radius // * desired = (radius + apoth) / 2 // apoth = radius * cos(pi / sides) // * desired = (radius + radius * cos(pi / sides)) / 2 // * desired = radius * (1 + cos(pi / sides)) / 2 // rearrange to determine radius from desired radius // * radius = desired / ((1 + cos(pi / sides)) / 2) radius = radius * 2 / (1 + Mathf.Cos(Mathf.PI / (sides * (subdivisions + 1)))); } // pyramid int vertCount = sides + 1; int faceCount = sides; int edgeCount = sides * 2; for (int i = 0; i < subdivisions; ++i) { vertCount += edgeCount; edgeCount += faceCount * 6; faceCount *= 4; } geometry.SetVertexCount(vertCount); geometry.SetIndexCount(faceCount * 3, lazy: true); geometry.ActiveVertices = sides + 1; geometry.ActiveIndices = sides * 3; geometry.positions[0] = new Vector3(0, radius, 0); geometry.normals[0] = new Vector3(0, 1, 0); float da = Mathf.PI * 2 / sides; for (int i = 1; i < vertCount; ++i) { var normal = new Vector3(Mathf.Cos(da * i), 0, Mathf.Sin(da * i)); geometry.positions[i] = FasterMath.Mul(normal, radius); geometry.normals[i] = normal; } for (int i = 1; i < sides; ++i) { geometry.SetTriangle(i, 0, i + 1, i); } geometry.SetTriangle(0, 0, 1, sides); int prevTriCount = geometry.ActiveIndices / 3; int nextTriCount = 0; var edges = new Dictionary <int, ushort>(prevTriCount * 6); for (int i = 0; i < subdivisions; i++) { nextTriCount = prevTriCount * 4; for (int j = 0; j < prevTriCount; ++j) { var tri = geometry.GetTriangle(j); int a = GetMiddlePoint((ushort)tri.x, (ushort)tri.y, geometry, radius, edges); int b = GetMiddlePoint((ushort)tri.y, (ushort)tri.z, geometry, radius, edges); int c = GetMiddlePoint((ushort)tri.z, (ushort)tri.x, geometry, radius, edges); geometry.SetTriangle(prevTriCount + j * 3 + 0, tri.x, a, c); geometry.SetTriangle(prevTriCount + j * 3 + 1, tri.y, b, a); geometry.SetTriangle(prevTriCount + j * 3 + 2, tri.z, c, b); geometry.SetTriangle(j, a, b, c); } prevTriCount = nextTriCount; edges.Clear(); } geometry.mesh.Clear(); geometry.Apply(positions: true, normals: true, indices: true); }
public static void Sphere(MeshTool geometry, float radius, int level, bool correction) { var geodesic = geodesics[Mathf.Min(level, geodesics.Count - 1)]; geometry.Topology = MeshTopology.Triangles; geometry.SetVertexCount(geodesic.VertexCount); geometry.SetIndexCount(geodesic.FaceCount * 3, lazy: true); if (correction) { radius *= geodesic.Correction; } if (geodesic.Base == Solid.Tetrahedron) { Tetrahedron(geometry, radius); } if (geodesic.Base == Solid.Octahedron) { Octahedron(geometry, radius); } if (geodesic.Base == Solid.Icosohedron) { Icosohedron(geometry, radius); } int prevTriCount = geometry.ActiveIndices / 3; int nextTriCount = 0; // only need as much edge memory as the last iteration, which adds an six // edges per triangle of the previous iteration int penulTriCount = geodesic.FaceCount / 4; var edges = new Dictionary <int, ushort>(penulTriCount * 6); for (int i = 0; i < geodesic.Subdivisions; i++) { nextTriCount = prevTriCount * 4; for (int j = 0; j < prevTriCount; ++j) { var tri = geometry.GetTriangle(j); int a = GetMiddlePoint((ushort)tri.x, (ushort)tri.y, geometry, radius, edges); int b = GetMiddlePoint((ushort)tri.y, (ushort)tri.z, geometry, radius, edges); int c = GetMiddlePoint((ushort)tri.z, (ushort)tri.x, geometry, radius, edges); geometry.SetTriangle(prevTriCount + j * 3 + 0, tri.x, a, c); geometry.SetTriangle(prevTriCount + j * 3 + 1, tri.y, b, a); geometry.SetTriangle(prevTriCount + j * 3 + 2, tri.z, c, b); geometry.SetTriangle(j, a, b, c); } prevTriCount = nextTriCount; edges.Clear(); } geometry.mesh.Clear(); geometry.Apply(positions: true, normals: true, indices: true); }