Пример #1
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);
        }
Пример #2
0
        public override void Generate()
        {
            double tCurveLen            = CurveUtils.ArcLength(Curve);
            SampledArcLengthParam pAxis = new SampledArcLengthParam(Axis, Axis.Length);
            double tAxisLen             = pAxis.ArcLength;
            double tScale = tAxisLen / tCurveLen;

            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);

            double      tCur = 0;
            CurveSample s    = pAxis.Sample(tCur);
            Frame3f     f0   = new Frame3f((Vector3f)s.position, (Vector3f)s.tangent, 1);
            Frame3f     fCur = f0;

            // generate tube
            for (int ri = 0; ri < nRings; ++ri)
            {
                if (ri > 0)
                {
                    tCur       += (Curve[ri] - Curve[ri - 1]).Length;
                    s           = pAxis.Sample(tCur * tScale);
                    fCur.Origin = (Vector3f)s.position;
                    fCur.AlignAxis(1, (Vector3f)s.tangent);
                }

                Vector3d v_along  = Curve[ri];
                Vector3f v_frame  = fCur.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 = fCur.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 - 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)
            {
                // 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 = f0;
                fStart.Origin = (Vector3f)vAvgStart;
                Frame3f fEnd = fCur;
                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);
                }
            }
        }