public override MeshGenerator Generate() { int N = EdgeVertices; int Nm2 = N - 2; int NT = N - 1; int N2 = N * N; vertices = new VectorArray3d((NoSharedVertices) ? (N2 * 6) : (8 + Nm2 * 12 + Nm2 * Nm2 * 6)); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); triangles = new IndexArray3i(2 * NT * NT * 6); groups = new int[triangles.Count]; Vector3d[] boxvertices = Box.ComputeVertices(); int vi = 0; int ti = 0; if (NoSharedVertices) { for (int fi = 0; fi < 6; ++fi) { // get corner vertices Vector3d v00 = boxvertices[gIndices.BoxFaces[fi, 0]]; Vector3d v01 = boxvertices[gIndices.BoxFaces[fi, 1]]; Vector3d v11 = boxvertices[gIndices.BoxFaces[fi, 2]]; Vector3d v10 = boxvertices[gIndices.BoxFaces[fi, 3]]; Vector3f faceN = Math.Sign(gIndices.BoxFaceNormals[fi]) * (Vector3f)Box.Axis(Math.Abs(gIndices.BoxFaceNormals[fi]) - 1); // add vertex rows int start_vi = vi; for (int yi = 0; yi < N; ++yi) { double ty = (double)yi / (double)(N - 1); for (int xi = 0; xi < N; ++xi) { double tx = (double)xi / (double)(N - 1); normals[vi] = faceN; uv[vi] = new Vector2f(tx, ty); vertices[vi++] = bilerp(ref v00, ref v01, ref v11, ref v10, tx, ty); } } // add faces for (int y0 = 0; y0 < NT; ++y0) { for (int x0 = 0; x0 < NT; ++x0) { int i00 = start_vi + y0 * N + x0; int i10 = start_vi + (y0 + 1) * N + x0; int i01 = i00 + 1, i11 = i10 + 1; groups[ti] = fi; triangles.Set(ti++, i00, i01, i11, Clockwise); groups[ti] = fi; triangles.Set(ti++, i00, i11, i10, Clockwise); } } } } else { // construct integer coordinates Vector3i[] intvertices = new Vector3i[boxvertices.Length]; for (int k = 0; k < boxvertices.Length; ++k) { Vector3d v = boxvertices[k] - Box.Center; intvertices[k] = new Vector3i( v.x < 0 ? 0 : N - 1, v.y < 0 ? 0 : N - 1, v.z < 0 ? 0 : N - 1); } int[] faceIndicesV = new int[N2]; // add edge vertices and store in this map // todo: don't use a map (?) how do we do that, though... // - each index is in range [0,N). If we have (i,j,k), then for a given // i, we have a finite number of j and k (< 2N?). // make N array of 2N length, key on i, linear search for matching j/k? Dictionary <Vector3i, int> edgeVerts = new Dictionary <Vector3i, int>(); for (int fi = 0; fi < 6; ++fi) { // get corner vertices int c00 = gIndices.BoxFaces[fi, 0], c01 = gIndices.BoxFaces[fi, 1], c11 = gIndices.BoxFaces[fi, 2], c10 = gIndices.BoxFaces[fi, 3]; Vector3d v00 = boxvertices[c00]; Vector3i vi00 = intvertices[c00]; Vector3d v01 = boxvertices[c01]; Vector3i vi01 = intvertices[c01]; Vector3d v11 = boxvertices[c11]; Vector3i vi11 = intvertices[c11]; Vector3d v10 = boxvertices[c10]; Vector3i vi10 = intvertices[c10]; Action <Vector3d, Vector3d, Vector3i, Vector3i> do_edge = (a, b, ai, bi) => { for (int i = 0; i < N; ++i) { double t = (double)i / (double)(N - 1); Vector3i vidx = lerp(ref ai, ref bi, t); if (edgeVerts.ContainsKey(vidx) == false) { Vector3d v = Vector3d.Lerp(ref a, ref b, t); normals[vi] = (Vector3f)v.Normalized; uv[vi] = Vector2f.Zero; edgeVerts[vidx] = vi; vertices[vi++] = v; } } }; do_edge(v00, v01, vi00, vi01); do_edge(v01, v11, vi01, vi11); do_edge(v11, v10, vi11, vi10); do_edge(v10, v00, vi10, vi00); } // now generate faces for (int fi = 0; fi < 6; ++fi) { // get corner vertices int c00 = gIndices.BoxFaces[fi, 0], c01 = gIndices.BoxFaces[fi, 1], c11 = gIndices.BoxFaces[fi, 2], c10 = gIndices.BoxFaces[fi, 3]; Vector3d v00 = boxvertices[c00]; Vector3i vi00 = intvertices[c00]; Vector3d v01 = boxvertices[c01]; Vector3i vi01 = intvertices[c01]; Vector3d v11 = boxvertices[c11]; Vector3i vi11 = intvertices[c11]; Vector3d v10 = boxvertices[c10]; Vector3i vi10 = intvertices[c10]; Vector3f faceN = Math.Sign(gIndices.BoxFaceNormals[fi]) * (Vector3f)Box.Axis(Math.Abs(gIndices.BoxFaceNormals[fi]) - 1); // add vertex rows, using existing vertices if we have them in map for (int yi = 0; yi < N; ++yi) { double ty = (double)yi / (double)(N - 1); for (int xi = 0; xi < N; ++xi) { double tx = (double)xi / (double)(N - 1); Vector3i vidx = bilerp(ref vi00, ref vi01, ref vi11, ref vi10, tx, ty); int use_vi; if (edgeVerts.TryGetValue(vidx, out use_vi) == false) { Vector3d v = bilerp(ref v00, ref v01, ref v11, ref v10, tx, ty); use_vi = vi++; normals[use_vi] = faceN; uv[use_vi] = new Vector2f(tx, ty); vertices[use_vi] = v; } faceIndicesV[yi * N + xi] = use_vi; } } // add faces for (int y0 = 0; y0 < NT; ++y0) { int y1 = y0 + 1; for (int x0 = 0; x0 < NT; ++x0) { int x1 = x0 + 1; int i00 = faceIndicesV[y0 * N + x0]; int i01 = faceIndicesV[y0 * N + x1]; int i11 = faceIndicesV[y1 * N + x1]; int i10 = faceIndicesV[y1 * N + x0]; groups[ti] = fi; triangles.Set(ti++, i00, i01, i11, Clockwise); groups[ti] = fi; triangles.Set(ti++, i00, i11, i10, Clockwise); } } } } return(this); }
override public void Generate() { if (Polygon == null) { Polygon = Polygon2d.MakeCircle(1.0f, 8); } int Slices = Polygon.VertexCount; int nRings = Vertices.Count; int nRingSize = (NoSharedVertices) ? Slices + 1 : Slices; int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1; if (Capped == false) { nCapVertices = 0; } vertices = new VectorArray3d(nRings * nRingSize + 2 * nCapVertices); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); int nSpanTris = (Vertices.Count - 1) * (2 * Slices); int nCapTris = (Capped) ? 2 * Slices : 0; triangles = new IndexArray3i(nSpanTris + nCapTris); Frame3f fCur = new Frame3f(Frame); Vector3d dv = CurveUtils.GetTangent(Vertices, 0);; fCur.Origin = (Vector3f)Vertices[0]; fCur.AlignAxis(2, (Vector3f)dv); Frame3f fStart = new Frame3f(fCur); // generate tube for (int ri = 0; ri < nRings; ++ri) { // propagate frame if (ri != 0) { Vector3d tan = CurveUtils.GetTangent(Vertices, ri); fCur.Origin = (Vector3f)Vertices[ri]; if (ri == 11) { dv = tan; } fCur.AlignAxis(2, (Vector3f)tan); } float uv_along = (float)ri / (float)(nRings - 1); // generate vertices int nStartR = ri * nRingSize; for (int j = 0; j < nRingSize; ++j) { float uv_around = (float)j / (float)(nRings); int k = nStartR + j; Vector2d pv = Polygon.Vertices[j % Slices]; Vector3d v = fCur.FromFrameP((Vector2f)pv, 2); vertices[k] = v; uv[k] = new Vector2f(uv_along, uv_around); Vector3f n = (Vector3f)(v - fCur.Origin).Normalized; normals[k] = n; } } // generate triangles int ti = 0; for (int ri = 0; ri < nRings - 1; ++ri) { int r0 = ri * nRingSize; int r1 = r0 + nRingSize; for (int k = 0; k < nRingSize - 1; ++k) { triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise); triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise); } if (NoSharedVertices == false) // close disc if we went all the way { triangles.Set(ti++, r1 - 1, r0, r1, Clockwise); triangles.Set(ti++, r1 - 1, r1, r1 + nRingSize - 1, Clockwise); } } if (Capped) { // add endcap verts int nBottomC = nRings * nRingSize; vertices[nBottomC] = fStart.Origin; uv[nBottomC] = new Vector2f(0.5f, 0.5f); normals[nBottomC] = -fStart.Z; startCapCenterIndex = nBottomC; int nTopC = nBottomC + 1; vertices[nTopC] = fCur.Origin; uv[nTopC] = new Vector2f(0.5f, 0.5f); normals[nTopC] = fCur.Z; endCapCenterIndex = nTopC; if (NoSharedVertices) { // duplicate first loop and make a fan w/ bottom-center int nExistingB = 0; int nStartB = nTopC + 1; for (int k = 0; k < Slices; ++k) { vertices[nStartB + k] = vertices[nExistingB + k]; uv[nStartB + k] = (Vector2f)Polygon.Vertices[k].Normalized; normals[nStartB + k] = normals[nBottomC]; } append_disc(Slices, nBottomC, nStartB, true, Clockwise, ref ti); // duplicate second loop and make fan int nExistingT = nRingSize * (nRings - 1); int nStartT = nStartB + Slices; for (int k = 0; k < Slices; ++k) { vertices[nStartT + k] = vertices[nExistingT + k]; uv[nStartT + k] = (Vector2f)Polygon.Vertices[k].Normalized; normals[nStartT + k] = normals[nTopC]; } append_disc(Slices, nTopC, nStartT, true, !Clockwise, ref ti); } else { append_disc(Slices, nBottomC, 0, true, Clockwise, ref ti); append_disc(Slices, nTopC, nRingSize * (nRings - 1), true, !Clockwise, ref ti); } } }
override public void Generate() { vertices = new VectorArray3d(4); uv = new VectorArray2f(4); normals = new VectorArray3f(4); triangles = new IndexArray3i(2); vertices[0] = new Vector3d(-Width / 2.0f, 0, -Height / 2.0f); vertices[1] = new Vector3d(Width / 2.0f, 0, -Height / 2.0f); vertices[2] = new Vector3d(Width / 2.0f, 0, Height / 2.0f); vertices[3] = new Vector3d(-Width / 2.0f, 0, Height / 2.0f); normals[0] = normals[1] = normals[2] = normals[3] = Vector3f.AxisY; float uvleft = 0.0f, uvright = 1.0f, uvbottom = 0.0f, uvtop = 1.0f; // if we want the UV subregion, we assume it is if (UVMode != UVModes.FullUVSquare) { if (Width > Height) { float a = Height / Width; if (UVMode == UVModes.CenteredUVRectangle) { uvbottom = 0.5f - a / 2.0f; uvtop = 0.5f + a / 2.0f; } else { uvtop = a; } } else if (Height > Width) { float a = Width / Height; if (UVMode == UVModes.CenteredUVRectangle) { uvleft = 0.5f - a / 2.0f; uvright = 0.5f + a / 2.0f; } else { uvright = a; } } } uv[0] = new Vector2f(uvleft, uvbottom); uv[1] = new Vector2f(uvright, uvbottom); uv[2] = new Vector2f(uvright, uvtop); uv[3] = new Vector2f(uvleft, uvtop); if (Clockwise == true) { triangles.Set(0, 0, 1, 2); triangles.Set(1, 0, 2, 3); } else { triangles.Set(0, 0, 2, 1); triangles.Set(1, 0, 3, 2); } }
override public MeshGenerator Generate() { if (Polygon == null) { Polygon = Polygon2d.MakeCircle(1.0f, 8); } int NV = Vertices.Count; int Slices = Polygon.VertexCount; int nRings = (ClosedLoop && NoSharedVertices) ? NV + 1 : NV; int nRingSize = (NoSharedVertices) ? Slices + 1 : Slices; int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1; if (Capped == false || ClosedLoop == true) { nCapVertices = 0; } vertices = new VectorArray3d(nRings * nRingSize + 2 * nCapVertices); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); int quad_strips = (ClosedLoop) ? NV : NV - 1; int nSpanTris = quad_strips * (2 * Slices); int nCapTris = (Capped && ClosedLoop == false) ? 2 * Slices : 0; triangles = new IndexArray3i(nSpanTris + nCapTris); Frame3f fCur = new Frame3f(Frame); Vector3d dv = CurveUtils.GetTangent(Vertices, 0, ClosedLoop); fCur.Origin = (Vector3f)Vertices[0]; fCur.AlignAxis(2, (Vector3f)dv); Frame3f fStart = new Frame3f(fCur); double circumference = Polygon.ArcLength; double pathLength = CurveUtils.ArcLength(Vertices, ClosedLoop); double accum_path_u = 0; // generate tube for (int ri = 0; ri < nRings; ++ri) { int vi = ri % NV; // propagate frame Vector3d tangent = CurveUtils.GetTangent(Vertices, vi, ClosedLoop); fCur.Origin = (Vector3f)Vertices[vi]; fCur.AlignAxis(2, (Vector3f)tangent); // generate vertices int nStartR = ri * nRingSize; double accum_ring_v = 0; for (int j = 0; j < nRingSize; ++j) { int k = nStartR + j; Vector2d pv = Polygon.Vertices[j % Slices]; Vector2d pvNext = Polygon.Vertices[(j + 1) % Slices]; Vector3d v = fCur.FromPlaneUV((Vector2f)pv, 2); vertices[k] = v; uv[k] = new Vector2f(accum_path_u, accum_ring_v); accum_ring_v += (pv.Distance(pvNext) / circumference); Vector3f n = (Vector3f)(v - fCur.Origin).Normalized; normals[k] = n; } int viNext = (ri + 1) % NV; double d = Vertices[vi].Distance(Vertices[viNext]); accum_path_u += d / pathLength; } // generate triangles int ti = 0; int nStop = (ClosedLoop && NoSharedVertices == false) ? nRings : (nRings - 1); for (int ri = 0; ri < nStop; ++ri) { int r0 = ri * nRingSize; int r1 = r0 + nRingSize; if (ClosedLoop && ri == nStop - 1 && NoSharedVertices == false) { r1 = 0; } for (int k = 0; k < nRingSize - 1; ++k) { triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise); triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise); } if (NoSharedVertices == false) // last quad if we aren't sharing vertices { int M = nRingSize - 1; triangles.Set(ti++, r0 + M, r0, r1, Clockwise); triangles.Set(ti++, r0 + M, r1, r1 + M, Clockwise); } } if (Capped && ClosedLoop == false) { Vector2d c = (OverrideCapCenter) ? CapCenter : Polygon.Bounds.Center; // add endcap verts int nBottomC = nRings * nRingSize; vertices[nBottomC] = fStart.FromPlaneUV((Vector2f)c, 2); uv[nBottomC] = new Vector2f(0.5f, 0.5f); normals[nBottomC] = -fStart.Z; startCapCenterIndex = nBottomC; int nTopC = nBottomC + 1; vertices[nTopC] = fCur.FromPlaneUV((Vector2f)c, 2); uv[nTopC] = new Vector2f(0.5f, 0.5f); normals[nTopC] = fCur.Z; endCapCenterIndex = nTopC; if (NoSharedVertices) { // duplicate first loop and make a fan w/ bottom-center int nExistingB = 0; int nStartB = nTopC + 1; for (int k = 0; k < Slices; ++k) { vertices[nStartB + k] = vertices[nExistingB + k]; Vector2d vuv = ((Polygon[k] - c).Normalized + Vector2d.One) * 0.5; uv[nStartB + k] = (Vector2f)vuv; normals[nStartB + k] = normals[nBottomC]; } append_disc(Slices, nBottomC, nStartB, true, Clockwise, ref ti); // duplicate second loop and make fan int nExistingT = nRingSize * (nRings - 1); int nStartT = nStartB + Slices; for (int k = 0; k < Slices; ++k) { vertices[nStartT + k] = vertices[nExistingT + k]; uv[nStartT + k] = uv[nStartB + k]; normals[nStartT + k] = normals[nTopC]; } append_disc(Slices, nTopC, nStartT, true, !Clockwise, ref ti); } else { append_disc(Slices, nBottomC, 0, true, Clockwise, ref ti); append_disc(Slices, nTopC, nRingSize * (nRings - 1), true, !Clockwise, ref ti); } } return(this); }
override public void Generate() { int nRings = (NoSharedVertices) ? 2 * (Sections.Length - 1) : Sections.Length; int nRingSize = (NoSharedVertices) ? Slices + 1 : Slices; int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1; if (Capped == false) { nCapVertices = 0; } vertices = new VectorArray3d(nRings * nRingSize + 2 * nCapVertices); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); int nSpanTris = (Sections.Length - 1) * (2 * Slices); int nCapTris = (Capped) ? 2 * Slices : 0; triangles = new IndexArray3i(nSpanTris + nCapTris); float fDelta = (float)((Math.PI * 2.0) / Slices); float fYSpan = Sections.Last().SectionY - Sections[0].SectionY; if (fYSpan == 0) { fYSpan = 1.0f; } // generate top and bottom rings for cylinder int ri = 0; for (int si = 0; si < Sections.Length; ++si) { int nStartR = ri * nRingSize; float y = Sections[si].SectionY; float yt = (y - Sections[0].SectionY) / fYSpan; for (int j = 0; j < nRingSize; ++j) { int k = nStartR + j; float angle = (float)j * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); vertices[k] = new Vector3d(Sections[si].Radius * cosa, y, Sections[si].Radius * sina); float t = (float)j / (float)(Slices - 1); uv[k] = new Vector2f(t, yt); Vector3f n = new Vector3f((float)cosa, 0, (float)sina); n.Normalize(); normals[k] = n; } ri++; if (NoSharedVertices && si != 0 && si != Sections.Length - 1) { duplicate_vertex_span(nStartR, nRingSize); ri++; } } // generate triangles int ti = 0; ri = 0; for (int si = 0; si < Sections.Length - 1; ++si) { int r0 = ri * nRingSize; int r1 = r0 + nRingSize; ri += (NoSharedVertices) ? 2 : 1; for (int k = 0; k < nRingSize - 1; ++k) { triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise); triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise); } if (NoSharedVertices == false) // close disc if we went all the way { triangles.Set(ti++, r1 - 1, r0, r1, Clockwise); triangles.Set(ti++, r1 - 1, r1, r1 + nRingSize - 1, Clockwise); } } if (Capped) { // add endcap verts var s0 = Sections[0]; var sN = Sections.Last(); int nBottomC = nRings * nRingSize; vertices[nBottomC] = new Vector3d(0, s0.SectionY, 0); uv[nBottomC] = new Vector2f(0.5f, 0.5f); normals[nBottomC] = new Vector3f(0, -1, 0); startCapCenterIndex = nBottomC; int nTopC = nBottomC + 1; vertices[nTopC] = new Vector3d(0, sN.SectionY, 0); uv[nTopC] = new Vector2f(0.5f, 0.5f); normals[nTopC] = new Vector3f(0, 1, 0); endCapCenterIndex = nTopC; if (NoSharedVertices) { int nStartB = nTopC + 1; for (int k = 0; k < Slices; ++k) { float a = (float)k * fDelta; double cosa = Math.Cos(a), sina = Math.Sin(a); vertices[nStartB + k] = new Vector3d(s0.Radius * cosa, s0.SectionY, s0.Radius * sina); uv[nStartB + k] = new Vector2f(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartB + k] = -Vector3f.AxisY; } append_disc(Slices, nBottomC, nStartB, true, Clockwise, ref ti); int nStartT = nStartB + Slices; for (int k = 0; k < Slices; ++k) { float a = (float)k * fDelta; double cosa = Math.Cos(a), sina = Math.Sin(a); vertices[nStartT + k] = new Vector3d(sN.Radius * cosa, sN.SectionY, sN.Radius * sina); uv[nStartT + k] = new Vector2f(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartT + k] = Vector3f.AxisY; } append_disc(Slices, nTopC, nStartT, true, !Clockwise, ref ti); } else { append_disc(Slices, nBottomC, 0, true, Clockwise, ref ti); append_disc(Slices, nTopC, nRingSize * (Sections.Length - 1), true, !Clockwise, ref ti); } } }
override public void Generate() { bool bClosed = ((EndAngleDeg - StartAngleDeg) > 359.99f); int nRingSize = (NoSharedVertices && bClosed) ? Slices + 1 : Slices; int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1; int nFaceVertices = (NoSharedVertices && bClosed == false) ? 8 : 0; vertices = new VectorArray3d(2 * nRingSize + 2 * nCapVertices + nFaceVertices); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); int nCylTris = 2 * Slices; int nCapTris = 2 * Slices; int nFaceTris = (bClosed == false) ? 4 : 0; triangles = new IndexArray3i(nCylTris + nCapTris + nFaceTris); groups = new int[triangles.Count]; float fTotalRange = (EndAngleDeg - StartAngleDeg) * MathUtil.Deg2Radf; float fStartRad = StartAngleDeg * MathUtil.Deg2Radf; float fDelta = (bClosed) ? fTotalRange / Slices : fTotalRange / (Slices - 1); // generate top and bottom rings for cylinder for (int k = 0; k < nRingSize; ++k) { float angle = fStartRad + (float)k * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); vertices[k] = new Vector3d(BaseRadius * cosa, 0, BaseRadius * sina); vertices[nRingSize + k] = new Vector3d(TopRadius * cosa, Height, TopRadius * sina); float t = (float)k / (float)Slices; uv[k] = new Vector2f(t, 0.0f); uv[nRingSize + k] = new Vector2f(t, 1.0f); Vector3f n = new Vector3f((float)cosa, 0, (float)sina); n.Normalize(); normals[k] = normals[nRingSize + k] = n; } // generate cylinder panels int ti = 0; for (int k = 0; k < nRingSize - 1; ++k) { groups[ti] = 1; triangles.Set(ti++, k, k + 1, nRingSize + k + 1, Clockwise); groups[ti] = 1; triangles.Set(ti++, k, nRingSize + k + 1, nRingSize + k, Clockwise); } if (bClosed && NoSharedVertices == false) // close disc if we went all the way { groups[ti] = 1; triangles.Set(ti++, nRingSize - 1, 0, nRingSize, Clockwise); groups[ti] = 1; triangles.Set(ti++, nRingSize - 1, nRingSize, 2 * nRingSize - 1, Clockwise); } int nBottomC = 2 * nRingSize; vertices[nBottomC] = new Vector3d(0, 0, 0); uv[nBottomC] = new Vector2f(0.5f, 0.5f); normals[nBottomC] = new Vector3f(0, -1, 0); int nTopC = 2 * nRingSize + 1; vertices[nTopC] = new Vector3d(0, Height, 0); uv[nTopC] = new Vector2f(0.5f, 0.5f); normals[nTopC] = new Vector3f(0, 1, 0); if (NoSharedVertices) { int nStartB = 2 * nRingSize + 2; for (int k = 0; k < Slices; ++k) { float a = fStartRad + (float)k * fDelta; double cosa = Math.Cos(a), sina = Math.Sin(a); vertices[nStartB + k] = new Vector3d(BaseRadius * cosa, 0, BaseRadius * sina); uv[nStartB + k] = new Vector2f(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartB + k] = -Vector3f.AxisY; } append_disc(Slices, nBottomC, nStartB, bClosed, Clockwise, ref ti, 2); int nStartT = 2 * nRingSize + 2 + Slices; for (int k = 0; k < Slices; ++k) { float a = fStartRad + (float)k * fDelta; double cosa = Math.Cos(a), sina = Math.Sin(a); vertices[nStartT + k] = new Vector3d(TopRadius * cosa, Height, TopRadius * sina); uv[nStartT + k] = new Vector2f(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartT + k] = Vector3f.AxisY; } append_disc(Slices, nTopC, nStartT, bClosed, !Clockwise, ref ti, 3); // ugh this is very ugly but hard to see the pattern... if (bClosed == false) { int nStartF = 2 * nRingSize + 2 + 2 * Slices; vertices[nStartF] = vertices[nStartF + 5] = vertices[nBottomC]; vertices[nStartF + 1] = vertices[nStartF + 4] = vertices[nTopC]; vertices[nStartF + 2] = vertices[nRingSize]; vertices[nStartF + 3] = vertices[0]; vertices[nStartF + 6] = vertices[nRingSize - 1]; vertices[nStartF + 7] = vertices[2 * nRingSize - 1]; normals[nStartF] = normals[nStartF + 1] = normals[nStartF + 2] = normals[nStartF + 3] = estimate_normal(nStartF, nStartF + 1, nStartF + 2); normals[nStartF + 4] = normals[nStartF + 5] = normals[nStartF + 6] = normals[nStartF + 7] = estimate_normal(nStartF + 4, nStartF + 5, nStartF + 6); uv[nStartF] = uv[nStartF + 5] = new Vector2f(0, 0); uv[nStartF + 1] = uv[nStartF + 4] = new Vector2f(0, 1); uv[nStartF + 2] = uv[nStartF + 7] = new Vector2f(1, 1); uv[nStartF + 3] = uv[nStartF + 6] = new Vector2f(1, 0); append_rectangle(nStartF + 0, nStartF + 1, nStartF + 2, nStartF + 3, !Clockwise, ref ti, 4); append_rectangle(nStartF + 4, nStartF + 5, nStartF + 6, nStartF + 7, !Clockwise, ref ti, 5); } } else { append_disc(Slices, nBottomC, 0, bClosed, Clockwise, ref ti, 2); append_disc(Slices, nTopC, nRingSize, bClosed, !Clockwise, ref ti, 3); if (bClosed == false) { append_rectangle(nBottomC, 0, nRingSize, nTopC, Clockwise, ref ti, 4); append_rectangle(nRingSize - 1, nBottomC, nTopC, 2 * nRingSize - 1, Clockwise, ref ti, 5); } } }
override public void Generate() { bool bClosed = ((EndAngleDeg - StartAngleDeg) > 359.99f); int nRingSize = (NoSharedVertices && bClosed) ? Slices + 1 : Slices; int nTipVertices = (NoSharedVertices) ? nRingSize : 1; int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1; int nFaceVertices = (NoSharedVertices && bClosed == false) ? 6 : 0; vertices = new VectorArray3d(nRingSize + nTipVertices + nCapVertices + nFaceVertices); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); int nConeTris = (NoSharedVertices) ? 2 * Slices : Slices; int nCapTris = Slices; int nFaceTris = (bClosed == false) ? 2 : 0; triangles = new IndexArray3i(nConeTris + nCapTris + nFaceTris); float fTotalRange = (EndAngleDeg - StartAngleDeg) * MathUtil.Deg2Radf; float fStartRad = StartAngleDeg * MathUtil.Deg2Radf; float fDelta = (bClosed) ? fTotalRange / Slices : fTotalRange / (Slices - 1); // generate rings for (int k = 0; k < nRingSize; ++k) { float angle = fStartRad + (float)k * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); vertices[k] = new Vector3d(BaseRadius * cosa, 0, BaseRadius * sina); uv[k] = new Vector2f(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); Vector3f n = new Vector3f(cosa * Height, BaseRadius / Height, sina * Height); n.Normalize(); normals[k] = n; if (NoSharedVertices) { vertices[nRingSize + k] = new Vector3d(0, Height, 0); uv[nRingSize + k] = new Vector2f(0.5f, 0.5f); normals[nRingSize + k] = n; } } if (NoSharedVertices == false) { vertices[nRingSize] = new Vector3d(0, Height, 0); normals[nRingSize] = Vector3f.AxisY; uv[nRingSize] = new Vector2f(0.5f, 0.5f); } // generate cylinder panels int ti = 0; if (NoSharedVertices) { for (int k = 0; k < nRingSize - 1; ++k) { triangles.Set(ti++, k, k + 1, nRingSize + k + 1, Clockwise); triangles.Set(ti++, k, nRingSize + k + 1, nRingSize + k, Clockwise); } } else { append_disc(Slices, nRingSize, 0, bClosed, !Clockwise, ref ti); } int nBottomC = nRingSize + nTipVertices; vertices[nBottomC] = new Vector3d(0, 0, 0); uv[nBottomC] = new Vector2f(0.5f, 0.5f); normals[nBottomC] = new Vector3f(0, -1, 0); if (NoSharedVertices) { int nStartB = nBottomC + 1; for (int k = 0; k < Slices; ++k) { float a = fStartRad + (float)k * fDelta; double cosa = Math.Cos(a), sina = Math.Sin(a); vertices[nStartB + k] = new Vector3d(BaseRadius * cosa, 0, BaseRadius * sina); uv[nStartB + k] = new Vector2f(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartB + k] = -Vector3f.AxisY; } append_disc(Slices, nBottomC, nStartB, bClosed, Clockwise, ref ti); // ugh this is very ugly but hard to see the pattern... if (bClosed == false) { int nStartF = nStartB + Slices; vertices[nStartF] = vertices[nStartF + 4] = vertices[nBottomC]; vertices[nStartF + 1] = vertices[nStartF + 3] = new Vector3d(0, Height, 0);; vertices[nStartF + 2] = vertices[0];; vertices[nStartF + 5] = vertices[nRingSize - 1]; normals[nStartF] = normals[nStartF + 1] = normals[nStartF + 2] = estimate_normal(nStartF, nStartF + 1, nStartF + 2); normals[nStartF + 3] = normals[nStartF + 4] = normals[nStartF + 5] = estimate_normal(nStartF + 3, nStartF + 4, nStartF + 5); uv[nStartF] = uv[nStartF + 4] = new Vector2f(0, 0); uv[nStartF + 1] = uv[nStartF + 3] = new Vector2f(0, 1); uv[nStartF + 2] = uv[nStartF + 5] = new Vector2f(1, 0); triangles.Set(ti++, nStartF + 0, nStartF + 1, nStartF + 2, !Clockwise); triangles.Set(ti++, nStartF + 3, nStartF + 4, nStartF + 5, !Clockwise); } } else { append_disc(Slices, nBottomC, 0, bClosed, Clockwise, ref ti); if (bClosed == false) { triangles.Set(ti++, nBottomC, nRingSize, 0, !Clockwise); triangles.Set(ti++, nBottomC, nRingSize, nRingSize - 1, Clockwise); } } }
override public MeshGenerator Generate() { if (MathUtil.InRange(IndicesMap.a, 1, 3) == false || MathUtil.InRange(IndicesMap.b, 1, 3) == false) { throw new Exception("TrivialRectGenerator: Invalid IndicesMap!"); } vertices = new VectorArray3d(4); uv = new VectorArray2f(4); normals = new VectorArray3f(4); triangles = new IndexArray3i(2); vertices[0] = make_vertex(-Width / 2.0f, -Height / 2.0f); vertices[1] = make_vertex(Width / 2.0f, -Height / 2.0f); vertices[2] = make_vertex(Width / 2.0f, Height / 2.0f); vertices[3] = make_vertex(-Width / 2.0f, Height / 2.0f); normals[0] = normals[1] = normals[2] = normals[3] = Normal; float uvleft = 0.0f, uvright = 1.0f, uvbottom = 0.0f, uvtop = 1.0f; // if we want the UV subregion, we assume it is if (UVMode != UVModes.FullUVSquare) { if (Width > Height) { float a = Height / Width; if (UVMode == UVModes.CenteredUVRectangle) { uvbottom = 0.5f - a / 2.0f; uvtop = 0.5f + a / 2.0f; } else { uvtop = a; } } else if (Height > Width) { float a = Width / Height; if (UVMode == UVModes.CenteredUVRectangle) { uvleft = 0.5f - a / 2.0f; uvright = 0.5f + a / 2.0f; } else { uvright = a; } } } uv[0] = new Vector2f(uvleft, uvbottom); uv[1] = new Vector2f(uvright, uvbottom); uv[2] = new Vector2f(uvright, uvtop); uv[3] = new Vector2f(uvleft, uvtop); if (Clockwise == true) { triangles.Set(0, 0, 1, 2); triangles.Set(1, 0, 2, 3); } else { triangles.Set(0, 0, 2, 1); triangles.Set(1, 0, 3, 2); } return(this); }
override public MeshGenerator Generate() { int corner_v = 0, corner_t = 0; for (int k = 0; k < 4; ++k) { if (((int)SharpCorners & (1 << k)) != 0) { corner_v += 1; corner_t += 2; } else { corner_v += CornerSteps; corner_t += (CornerSteps + 1); } } vertices = new VectorArray3d(12 + corner_v); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); triangles = new IndexArray3i(10 + corner_t); float innerW = Width - 2 * Radius; float innerH = Height - 2 * Radius; // make vertices for inner "cross" (ie 5 squares) vertices[0] = new Vector3d(-innerW / 2.0f, 0, -innerH / 2.0f); vertices[1] = new Vector3d(innerW / 2.0f, 0, -innerH / 2.0f); vertices[2] = new Vector3d(innerW / 2.0f, 0, innerH / 2.0f); vertices[3] = new Vector3d(-innerW / 2.0f, 0, innerH / 2.0f); vertices[4] = new Vector3d(-innerW / 2, 0, -Height / 2); vertices[5] = new Vector3d(innerW / 2, 0, -Height / 2); vertices[6] = new Vector3d(Width / 2, 0, -innerH / 2); vertices[7] = new Vector3d(Width / 2, 0, innerH / 2); vertices[8] = new Vector3d(innerW / 2, 0, Height / 2); vertices[9] = new Vector3d(-innerW / 2, 0, Height / 2); vertices[10] = new Vector3d(-Width / 2, 0, innerH / 2); vertices[11] = new Vector3d(-Width / 2, 0, -innerH / 2); // make triangles for inner cross bool cycle = (Clockwise == false); int ti = 0; append_rectangle(0, 1, 2, 3, cycle, ref ti); append_rectangle(4, 5, 1, 0, cycle, ref ti); append_rectangle(1, 6, 7, 2, cycle, ref ti); append_rectangle(3, 2, 8, 9, cycle, ref ti); append_rectangle(11, 0, 3, 10, cycle, ref ti); int vi = 12; for (int j = 0; j < 4; ++j) { bool sharp = ((int)SharpCorners & (1 << j)) > 0; if (sharp) { append_2d_disc_segment(corner_spans[3 * j], corner_spans[3 * j + 1], corner_spans[3 * j + 2], 1, cycle, ref vi, ref ti, -1, MathUtil.SqrtTwo * Radius); } else { append_2d_disc_segment(corner_spans[3 * j], corner_spans[3 * j + 1], corner_spans[3 * j + 2], CornerSteps, cycle, ref vi, ref ti); } } for (int k = 0; k < vertices.Count; ++k) { normals[k] = Vector3f.AxisY; } float uvleft = 0.0f, uvright = 1.0f, uvbottom = 0.0f, uvtop = 1.0f; // if we want the UV subregion, we assume it is if (UVMode != UVModes.FullUVSquare) { if (Width > Height) { float a = Height / Width; if (UVMode == UVModes.CenteredUVRectangle) { uvbottom = 0.5f - a / 2.0f; uvtop = 0.5f + a / 2.0f; } else { uvtop = a; } } else if (Height > Width) { float a = Width / Height; if (UVMode == UVModes.CenteredUVRectangle) { uvleft = 0.5f - a / 2.0f; uvright = 0.5f + a / 2.0f; } else { uvright = a; } } } Vector3d c = new Vector3d(-Width / 2, 0, -Height / 2); for (int k = 0; k < vertices.Count; ++k) { Vector3d v = vertices[k]; double tx = (v.x - c.x) / Width; double ty = (v.y - c.y) / Height; uv[k] = new Vector2f((1 - tx) * uvleft + (tx) * uvright, (1 - ty) * uvbottom + (ty) * uvtop); } return(this); }
override public MeshGenerator Generate() { if (MathUtil.InRange(IndicesMap.a, 1, 3) == false || MathUtil.InRange(IndicesMap.b, 1, 3) == false) { throw new Exception("GriddedRectGenerator: Invalid IndicesMap!"); } int N = (EdgeVertices > 1) ? EdgeVertices : 2; int NT = N - 1, N2 = N * N; vertices = new VectorArray3d(N2); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); triangles = new IndexArray3i(2 * NT * NT); groups = new int[triangles.Count]; // corner vertices Vector3d v00 = make_vertex(-Width / 2.0f, -Height / 2.0f); Vector3d v01 = make_vertex(Width / 2.0f, -Height / 2.0f); Vector3d v11 = make_vertex(Width / 2.0f, Height / 2.0f); Vector3d v10 = make_vertex(-Width / 2.0f, Height / 2.0f); // corner UVs float uvleft = 0.0f, uvright = 1.0f, uvbottom = 0.0f, uvtop = 1.0f; if (UVMode != UVModes.FullUVSquare) { if (Width > Height) { float a = Height / Width; if (UVMode == UVModes.CenteredUVRectangle) { uvbottom = 0.5f - a / 2.0f; uvtop = 0.5f + a / 2.0f; } else { uvtop = a; } } else if (Height > Width) { float a = Width / Height; if (UVMode == UVModes.CenteredUVRectangle) { uvleft = 0.5f - a / 2.0f; uvright = 0.5f + a / 2.0f; } else { uvright = a; } } } Vector2f uv00 = new Vector2f(uvleft, uvbottom); Vector2f uv01 = new Vector2f(uvright, uvbottom); Vector2f uv11 = new Vector2f(uvright, uvtop); Vector2f uv10 = new Vector2f(uvleft, uvtop); int vi = 0; int ti = 0; // add vertex rows int start_vi = vi; for (int yi = 0; yi < N; ++yi) { double ty = (double)yi / (double)(N - 1); for (int xi = 0; xi < N; ++xi) { double tx = (double)xi / (double)(N - 1); normals[vi] = Normal; uv[vi] = bilerp(ref uv00, ref uv01, ref uv11, ref uv10, (float)tx, (float)ty); vertices[vi++] = bilerp(ref v00, ref v01, ref v11, ref v10, tx, ty); } } // add faces for (int y0 = 0; y0 < NT; ++y0) { for (int x0 = 0; x0 < NT; ++x0) { int i00 = start_vi + y0 * N + x0; int i10 = start_vi + (y0 + 1) * N + x0; int i01 = i00 + 1, i11 = i10 + 1; groups[ti] = 0; triangles.Set(ti++, i00, i11, i01, Clockwise); groups[ti] = 0; triangles.Set(ti++, i00, i10, i11, Clockwise); } } return(this); }
public override void Generate() { int nRings = Curve.Length; int nRingSize = (NoSharedVertices) ? Slices + 1 : Slices; int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1; if (Capped == false) { nCapVertices = 0; } vertices = new VectorArray3d(nRingSize * nRings + 2 * nCapVertices); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); int nSpanTris = (nRings - 1) * (2 * Slices); int nCapTris = (Capped) ? 2 * Slices : 0; triangles = new IndexArray3i(nSpanTris + nCapTris); float fDelta = (float)((Math.PI * 2.0) / Slices); Frame3f f = Axis; // generate tube for (int ri = 0; ri < nRings; ++ri) { Vector3d v_along = Curve[ri]; Vector3f v_frame = f.ToFrameP((Vector3f)v_along); float uv_along = (float)ri / (float)(nRings - 1); // generate vertices int nStartR = ri * nRingSize; for (int j = 0; j < nRingSize; ++j) { float angle = (float)j * fDelta; // [TODO] this is not efficient...use Matrix3f? Vector3f v_rot = Quaternionf.AxisAngleR(Vector3f.AxisY, angle) * v_frame; Vector3d v_new = f.FromFrameP(v_rot); int k = nStartR + j; vertices[k] = v_new; float uv_around = (float)j / (float)(nRingSize); uv[k] = new Vector2f(uv_along, uv_around); // [TODO] proper normal Vector3f n = (Vector3f)(v_new - f.Origin).Normalized; normals[k] = n; } } // generate triangles int ti = 0; for (int ri = 0; ri < nRings - 1; ++ri) { int r0 = ri * nRingSize; int r1 = r0 + nRingSize; for (int k = 0; k < nRingSize - 1; ++k) { triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise); triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise); } if (NoSharedVertices == false) // close disc if we went all the way { triangles.Set(ti++, r1 - 1, r0, r1, Clockwise); triangles.Set(ti++, r1 - 1, r1, r1 + nRingSize - 1, Clockwise); } } if (Capped) { // find avg start loop size Vector3d vAvgStart = Vector3d.Zero, vAvgEnd = Vector3d.Zero; for (int k = 0; k < Slices; ++k) { vAvgStart += vertices[k]; vAvgEnd += vertices[(nRings - 1) * nRingSize + k]; } vAvgStart /= (double)Slices; vAvgEnd /= (double)Slices; Frame3f fStart = f; fStart.Origin = (Vector3f)vAvgStart; Frame3f fEnd = f; fEnd.Origin = (Vector3f)vAvgEnd; // add endcap verts int nBottomC = nRings * nRingSize; vertices[nBottomC] = fStart.Origin; uv[nBottomC] = new Vector2f(0.5f, 0.5f); normals[nBottomC] = -fStart.Z; startCapCenterIndex = nBottomC; int nTopC = nBottomC + 1; vertices[nTopC] = fEnd.Origin; uv[nTopC] = new Vector2f(0.5f, 0.5f); normals[nTopC] = fEnd.Z; endCapCenterIndex = nTopC; if (NoSharedVertices) { // duplicate first loop and make a fan w/ bottom-center int nExistingB = 0; int nStartB = nTopC + 1; for (int k = 0; k < Slices; ++k) { vertices[nStartB + k] = vertices[nExistingB + k]; //uv[nStartB + k] = (Vector2f)Polygon.Vertices[k].Normalized; float angle = (float)k * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); uv[nStartB + k] = new Vector2f(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartB + k] = normals[nBottomC]; } append_disc(Slices, nBottomC, nStartB, true, Clockwise, ref ti); // duplicate second loop and make fan int nExistingT = nRingSize * (nRings - 1); int nStartT = nStartB + Slices; for (int k = 0; k < Slices; ++k) { vertices[nStartT + k] = vertices[nExistingT + k]; //uv[nStartT + k] = (Vector2f)Polygon.Vertices[k].Normalized; float angle = (float)k * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); uv[nStartT + k] = new Vector2f(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartT + k] = normals[nTopC]; } append_disc(Slices, nTopC, nStartT, true, !Clockwise, ref ti); } else { append_disc(Slices, nBottomC, 0, true, Clockwise, ref ti); append_disc(Slices, nTopC, nRingSize * (nRings - 1), true, !Clockwise, ref ti); } } }