private static ushort GetMiddlePoint(ushort a, ushort b, MeshTool geometry, float radius, Dictionary <int, ushort> edges) { ushort i; int min = a < b ? a : b; int max = a < b ? b : a; int key = (min << 16) | max; if (!edges.TryGetValue(key, out i)) { Vector3 middle = FasterMath.Mul(FasterMath.Add(geometry.positions[a], geometry.positions[b]), 0.5f); middle.Normalize(); i = (ushort)geometry.ActiveVertices; geometry.ActiveVertices += 1; geometry.positions[i] = FasterMath.Mul(middle, radius); geometry.normals[i] = middle; edges[key] = i; } return(i); }
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); }