Esempio n. 1
0
        CylinderMesh GenerateCylinder(TelescopeParameters tParams, float slope,
                                      bool innerGroove = false, bool outerGroove = false, bool overhang = true,
                                      int extraRings   = 0)
        {
            // We basically need to sweep a circular cross-section along a circular path.
            List <List <IndexedVertex> > circles = new List <List <IndexedVertex> >();

            float lengthStep = 1f / (Constants.CUTS_PER_CYLINDER - 1);

            float radiusLoss = 0;

            int numCircles = Constants.CUTS_PER_CYLINDER + (overhang ? Constants.OVERHANG_CUTS : 0) + extraRings;

            // Generate vertices
            for (int i = 0; i < numCircles; i++)
            {
                radiusLoss = i * lengthStep * slope * tParams.length;
                Vector3 centerPoint     = getLocalLocationAlongPath(i * lengthStep, tParams.curvature, tParams.torsion);
                Vector3 facingDirection = getDirectionAlongPath(i * lengthStep, tParams.curvature, tParams.torsion);
                Vector3 normalDirection = getNormalAlongPath(i * lengthStep, tParams.curvature, tParams.torsion);

                bool doInner = (innerGroove && i < Constants.CUTS_PER_CYLINDER + Constants.FIN_CUTS);
                bool doOuter = (outerGroove && i <= Constants.FIN_CUTS);

                List <IndexedVertex> circle = GenerateCircle(i, centerPoint, facingDirection, normalDirection,
                                                             tParams.radius - radiusLoss, addInnerGrooves: doInner, addOuterGroove: doOuter);
                circles.Add(circle);
            }

            // Now generate faces
            List <IndexTriangle> allIndices = new List <IndexTriangle>();

            for (int i = 0; i < numCircles - 1; i++)
            {
                List <IndexTriangle> tris = StitchCircles(circles[i], circles[i + 1]);
                allIndices.AddRange(tris);
            }

            CylinderMesh cm = new CylinderMesh(circles, allIndices);

            return(cm);
        }
Esempio n. 2
0
        public Mesh GenerateInnerVolume(TelescopeParameters nextParams, float arcOffset, int extraRings = 0)
        {
            currentIndex = 0;

            Mesh mesh = new Mesh();

            // Get the inner cylinder of the shell
            CylinderMesh inner = GenerateInnerCylinder(nextParams, HasOverhang, arcOffset, extraRings: extraRings);

            // Get the vertices
            List <IndexedVertex> verticesList = flattenList(inner.circleCuts);
            // Create the triangles for the two ends of the cylinder; this also
            // adds 2 vertices to the list.
            List <IndexTriangle> capTris = CloseCylinderCaps(inner, verticesList);
            // Get the positions out of the list
            List <Vector3> vertices = verticesList.ConvertAll(new
                                                              System.Converter <IndexedVertex, Vector3>(IndexedVertex.toVector3));
            List <int> indicesList = new List <int>();

            // Add triangles for the cylinder itself
            foreach (IndexTriangle tri in inner.triangles)
            {
                tri.addFrontFace(indicesList);
            }

            // Add triangles for the two ends
            foreach (IndexTriangle tri in capTris)
            {
                tri.addFrontFace(indicesList);
            }

            mesh.vertices  = vertices.ToArray();
            mesh.triangles = indicesList.ToArray();
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();

            return(mesh);
        }
Esempio n. 3
0
        public void GenerateGeometry(TelescopeParameters theParams, TelescopeParameters nextParams,
                                     bool doOverhang = true, bool outerGroove = true)
        {
            HasOverhang = doOverhang;

            this.thickness      = theParams.thickness;
            this.length         = theParams.length;
            this.radius         = theParams.radius;
            this.curvature      = theParams.curvature;
            this.torsion        = theParams.torsion;
            this.twistAngle     = theParams.twistFromParent;
            this.nextTwistAngle = (nextParams != null) ? nextParams.twistFromParent : 0;

            // Reset the mesh.
            currentIndex = 0;
            mFilter.mesh.Clear();

            float slopeCosmetic = thickness * Constants.COSMETIC_TAPER_RATIO;

            TelescopeParameters outerParams = new TelescopeParameters(length, radius - Constants.SHELL_GAP,
                                                                      thickness, curvature, torsion, 0);

            CylinderMesh outerCyl = GenerateCylinder(outerParams,
                                                     slopeCosmetic + Constants.TAPER_SLOPE,
                                                     outerGroove: outerGroove, overhang: doOverhang);

            CylinderMesh innerCyl = GenerateInnerCylinder(nextParams, doOverhang, 0);

            // Flatten vertex list
            List <IndexedVertex> outerVerts = flattenList(outerCyl.circleCuts);
            List <IndexedVertex> innerVerts = flattenList(innerCyl.circleCuts);

            outerVerts.AddRange(innerVerts);

            // Get the triangles that join the inner and outer surfaces.
            List <IndexTriangle> edgeTriangles = stitchCylinderEnds(outerCyl, innerCyl);

            // Sort the vertices just to be safe
            outerVerts.Sort();

            // Make vertex buffer
            List <Vector3> vecs = outerVerts.ConvertAll(new System.Converter <IndexedVertex, Vector3>(IndexedVertex.toVector3));

            Vector3[] vertices = vecs.ToArray();

            // Make index buffer
            List <int> indicesList = new List <int>();

            foreach (IndexTriangle tri in outerCyl.triangles)
            {
                tri.addFrontFace(indicesList);
            }
            foreach (IndexTriangle tri in innerCyl.triangles)
            {
                tri.addBackFace(indicesList);
            }
            foreach (IndexTriangle tri in edgeTriangles)
            {
                tri.addFrontFace(indicesList);
            }

            mFilter.mesh.vertices  = vertices;
            mFilter.mesh.triangles = indicesList.ToArray();

            mFilter.mesh.RecalculateBounds();
            mFilter.mesh.RecalculateNormals();
        }
Esempio n. 4
0
        List <IndexTriangle> CloseCylinderCaps(CylinderMesh cylinder, List <IndexedVertex> verts)
        {
            List <IndexTriangle> triangles = new List <IndexTriangle>();

            List <IndexedVertex> bottomCircle = cylinder.circleCuts[0];
            List <IndexedVertex> topCircle    = cylinder.circleCuts[cylinder.circleCuts.Count - 1];

            // Compute center point of bottom circle.
            Vector3 bottomCenter = Vector3.zero;

            foreach (IndexedVertex v in bottomCircle)
            {
                bottomCenter += v.vertex;
            }
            bottomCenter /= bottomCircle.Count;

            // Compute center point of top circle.
            Vector3 topCenter = Vector3.zero;

            foreach (IndexedVertex v in topCircle)
            {
                topCenter += v.vertex;
            }
            topCenter /= topCircle.Count;

            // Add the two points to the mesh.
            IndexedVertex bottomCenterVert = new IndexedVertex(bottomCenter, currentIndex);

            currentIndex++;
            IndexedVertex topCenterVert = new IndexedVertex(topCenter, currentIndex);

            currentIndex++;

            verts.Add(bottomCenterVert);
            verts.Add(topCenterVert);

            // Add triangle fans.
            for (int i = 0; i < bottomCircle.Count; i++)
            {
                // Bottom circle gets CCW order
                int iPlus = (i + 1) % bottomCircle.Count;

                IndexedVertex i1 = bottomCenterVert;
                IndexedVertex i2 = bottomCircle[i];
                IndexedVertex i3 = bottomCircle[iPlus];

                IndexTriangle tri = new IndexTriangle(i1, i2, i3);
                triangles.Add(tri);
            }

            for (int i = 0; i < topCircle.Count; i++)
            {
                // Top circle gets CW order
                int iPlus = (i + 1) % topCircle.Count;

                IndexedVertex i1 = topCenterVert;
                IndexedVertex i2 = topCircle[iPlus];
                IndexedVertex i3 = topCircle[i];

                IndexTriangle tri = new IndexTriangle(i1, i2, i3);
                triangles.Add(tri);
            }

            return(triangles);
        }
Esempio n. 5
0
        List <IndexTriangle> stitchCylinderEnds(CylinderMesh outer, CylinderMesh inner)
        {
            if (outer.circleCuts.Count != inner.circleCuts.Count)
            {
                throw new System.Exception("Cylinders do not have same number of cuts.");
            }
            int numCuts = outer.circleCuts.Count;
            List <IndexTriangle> triangles = new List <IndexTriangle>();

            List <IndexedVertex> topOuter = outer.circleCuts[numCuts - 1];
            List <IndexedVertex> topInner = inner.circleCuts[numCuts - 1];

            topVerts = topOuter.ConvertAll <Vector3>(new Converter <IndexedVertex, Vector3>(IndexedVertex.toVector3));

            if (topOuter.Count != topInner.Count)
            {
                throw new System.Exception("Circles do not have same number of vertices.");
            }

            // Since the cuts are not necessarily aligned (in the case of curvature
            // or torsion changes), we want to stitch using the closest pairs of vertices.
            // Since we start with outer vertex i = 0, find the index of the inner vertex
            // closest to outer 0.
            Vector3 outer0top       = topOuter[0].vertex;
            int     topInnerOffset  = 0;
            float   closestDistance = Vector3.Distance(outer0top, topInner[0].vertex);

            for (int i = 0; i < topInner.Count; i++)
            {
                float dist = Vector3.Distance(topInner[i].vertex, outer0top);
                if (dist < closestDistance)
                {
                    closestDistance = dist;
                    topInnerOffset  = i;
                }
            }

            // To join the top rim, we need to add the triangles with
            // counterclockwise ordering, since the vertices are clockwise
            // when viewed from below (not above).
            for (int outerI = 0; outerI < topOuter.Count; outerI++)
            {
                int outerIPlus = (outerI + 1) % topOuter.Count;
                int innerI     = (outerI + topInnerOffset) % topInner.Count;
                int innerIPlus = (innerI + 1) % topInner.Count;

                // The triangles with two vertices in the outer circle have
                // the order outer[i], inner[i], outer[i+1].
                IndexedVertex iv1 = topOuter[outerI];
                IndexedVertex iv2 = topInner[innerI];
                IndexedVertex iv3 = topOuter[outerIPlus];
                IndexTriangle tri = new IndexTriangle(iv1, iv2, iv3);
                triangles.Add(tri);

                // The triangles with two vertices in the inner circle have
                // the order inner[i], inner[i+1], outer[i+1].
                iv1 = topInner[innerI];
                iv2 = topInner[innerIPlus];
                iv3 = topOuter[outerIPlus];
                tri = new IndexTriangle(iv1, iv2, iv3);
                triangles.Add(tri);
            }

            List <IndexedVertex> bottomOuter = outer.circleCuts[0];
            List <IndexedVertex> bottomInner = inner.circleCuts[0];

            bottomVerts = bottomOuter.ConvertAll <Vector3>(new Converter <IndexedVertex, Vector3>(IndexedVertex.toVector3));

            if (bottomOuter.Count != bottomInner.Count)
            {
                throw new System.Exception("Circles do not have same number of vertices.");
            }

            // Same procedure as top ring: find starting vertex closest to
            // vertex 0 of outer ring.
            Vector3 outer0bottom      = bottomOuter[0].vertex;
            int     bottomInnerOffset = 0;

            closestDistance = Vector3.Distance(outer0bottom, bottomInner[0].vertex);

            for (int i = 0; i < bottomInner.Count; i++)
            {
                float dist = Vector3.Distance(bottomInner[i].vertex, outer0bottom);
                if (dist < closestDistance)
                {
                    closestDistance   = dist;
                    bottomInnerOffset = i;
                }
            }

            // To join the bottom faces, we add triangles with vertices in clockwise order.
            for (int outerI = 0; outerI < bottomOuter.Count; outerI++)
            {
                int outerIPlus = (outerI + 1) % bottomOuter.Count;
                int innerI     = (outerI + bottomInnerOffset) % bottomInner.Count;
                int innerIPlus = (innerI + 1) % bottomInner.Count;

                // The triangles with two vertices in the outer circle have
                // the order outer[i], outer[i+1], inner[i].
                IndexedVertex iv1 = bottomOuter[outerI];
                IndexedVertex iv2 = bottomOuter[outerIPlus];
                IndexedVertex iv3 = bottomInner[innerI];
                IndexTriangle tri = new IndexTriangle(iv1, iv2, iv3);
                triangles.Add(tri);

                // The triangles with two vertices in the inner circle have
                // the order inner[i], outer[i+1], inner[i+1].
                iv1 = bottomInner[innerI];
                iv2 = bottomOuter[outerIPlus];
                iv3 = bottomInner[innerIPlus];
                tri = new IndexTriangle(iv1, iv2, iv3);
                triangles.Add(tri);
            }

            return(triangles);
        }