Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
                }
            }
        }
Esempio n. 3
0
        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);
            }
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
                }
            }
        }
Esempio n. 6
0
        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);
                }
            }
        }
Esempio n. 7
0
        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);
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        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);
                }
            }
        }