// adds a mesh face, not a polytope face // give vertices in clockwise order private void AddFace(List <Vector4> vs, int subMesh) { int n = vs.Count; for (int i = 0; i < n; i++) { uvs.Add(new Vector2((float)Mathf.Cos(i * 2 * Mathf.PI / n) * 0.5f + 0.5f, (float)Mathf.Sin(i * 2 * Mathf.PI / n) * 0.5f + 0.5f)); } pos.AddRange(vs); Vector4[] cross = new Vector4[n]; cross[0] = Rot4.Cross(vs[0], vs[1], vs[2]).normalized; for (int i = 1; i < n; i++) { cross[i] = cross[0]; } nor.AddRange(cross); for (int i = 2; i < n; i++) { idx[subMesh].AddRange(new[] { inext, inext + i - 1, inext + i }); } inext += n; }
// breaks a face into smaller triangles // WARNING: modifies input private void AddFaceRefined(List <Vector4> vs, int lod, int subMesh, int totalVertices = -1) { if (vs.Count < 3) { return; } int n = (lod + 2) * (lod + 1) / 2; // total # of new vertices if (totalVertices == -1) // in all child calls of this function totalVertices will remain the same { totalVertices = vs.Count; } Vector4[] cross = new Vector4[n]; cross[0] = Rot4.Cross(vs[0], vs[1], vs[2]).normalized; for (int i = 1; i < n; i++) { cross[i] = cross[0]; } nor.AddRange(cross); // uvs of the three main vertices in question Vector2 uv0 = new Vector2(1.0f, 0.5f); Vector2 uv1 = new Vector2((float)Mathf.Cos((1 - vs.Count) * 2 * Mathf.PI / totalVertices) * 0.5f + 0.5f, (float)Mathf.Sin((1 - vs.Count) * 2 * Mathf.PI / totalVertices) * 0.5f + 0.5f); Vector2 uv2 = new Vector2((float)Mathf.Cos((2 - vs.Count) * 2 * Mathf.PI / totalVertices) * 0.5f + 0.5f, (float)Mathf.Sin((2 - vs.Count) * 2 * Mathf.PI / totalVertices) * 0.5f + 0.5f); // square for loop iterates over rows of increasing length for (int i = 0; i <= lod; i++) { inext += i; // the ends of the current row Quaternion start = Quaternion.Slerp((R4)vs[1], (R4)vs[0], i / (float)lod); Quaternion end = Quaternion.Slerp((R4)vs[1], (R4)vs[2], i / (float)lod); Vector2 startUV = Vector2.Lerp(uv1, uv0, i / (float)lod); Vector2 endUV = Vector2.Lerp(uv1, uv2, i / (float)lod); for (int j = 0; j <= i; j++) { // numerical instability when start == end if (i > 0) { pos.Add((R4)Quaternion.Slerp(start, end, j / (float)i)); uvs.Add(Vector2.Lerp(startUV, endUV, j / (float)i)); } else { pos.Add(vs[1]); uvs.Add(uv1); } // two orientations of triangles int cur = inext + j; if (j < i) { idx[subMesh].AddRange(new[] { cur, cur - i, cur + 1 }); } if (j > 0 && j < i) { idx[subMesh].AddRange(new[] { cur, cur - i - 1, cur - i }); } } } inext += lod + 1; vs.RemoveAt(1); AddFaceRefined(vs, lod, subMesh, totalVertices); }