generates a profile for extrusion
Ejemplo n.º 1
0
        internal Profile Copy(bool needFaces)
        {
            Profile copy = new Profile ();

            copy.coords.AddRange (coords);
            copy.faceUVs.AddRange (faceUVs);

            if (needFaces)
                copy.faces.AddRange (faces);
            if ((copy.calcVertexNormals = calcVertexNormals))
            {
                copy.vertexNormals.AddRange (vertexNormals);
                copy.faceNormal = faceNormal;
                copy.cutNormal1 = cutNormal1;
                copy.cutNormal2 = cutNormal2;
                copy.us.AddRange (us);
                copy.faceNumbers.AddRange (faceNumbers);

                copy.cut1CoordIndices = new List<int> (cut1CoordIndices);
                copy.cut2CoordIndices = new List<int> (cut2CoordIndices);
                copy.hollowCoordIndices = new List<int> (hollowCoordIndices);
                copy.outerCoordIndices = new List<int> (outerCoordIndices);
            }
            copy.numOuterVerts = numOuterVerts;
            copy.numHollowVerts = numHollowVerts;

            return copy;
        }
Ejemplo n.º 2
0
        /// <summary>
        ///     Extrudes a profile along a path.
        /// </summary>
        public void Extrude(PathType pathType)
        {
            bool needEndFaces = false;

            coords = new List<Coord> ();
            faces = new List<Face> ();

            if (viewerMode)
            {
                viewerFaces = new List<ViewerFace> ();
                calcVertexNormals = true;
            }

            if (calcVertexNormals)
                normals = new List<Coord> ();

            int steps = 1;

            float length = pathCutEnd - pathCutBegin;
            normalsProcessed = false;

            if (viewerMode && sides == 3)
            {
                // prisms don't taper well so add some vertical resolution
                // other prims may benefit from this but just do prisms for now
                if (Math.Abs (taperX) > 0.01 || Math.Abs (taperY) > 0.01)
                    steps = (int)(steps * 4.5 * length);
            }

            if (sphereMode)
                hasProfileCut = profileEnd - profileStart < 0.4999f;
            else
                hasProfileCut = profileEnd - profileStart < 0.9999f;
            hasHollow = (hollow > 0.001f);

            float twistBegin2 = twistBegin / 360.0f * twoPi;
            float twistEnd2 = twistEnd / 360.0f * twoPi;
            float twistTotal = twistEnd2 - twistBegin2;
            float twistTotalAbs = Math.Abs (twistTotal);
            if (twistTotalAbs > 0.01f)
                steps += (int)(twistTotalAbs * 3.66); //  dahlia's magic number

            float hollow2 = hollow;

            // sanity checks
            float initialProfileRot = 0.0f;
            if (pathType == PathType.Circular)
            {
                if (sides == 3)
                {
                    initialProfileRot = (float)Math.PI;
                    if (hollowSides == 4)
                    {
                        if (hollow2 > 0.7f)
                            hollow2 = 0.7f;
                        hollow2 *= 0.707f;
                    } else
                        hollow2 *= 0.5f;
                } else if (sides == 4)
                {
                    initialProfileRot = 0.25f * (float)Math.PI;
                    if (hollowSides != 4)
                        hollow2 *= 0.707f;
                } else if (sides > 4)
                {
                    initialProfileRot = (float)Math.PI;
                    if (hollowSides == 4)
                    {
                        if (hollow2 > 0.7f)
                            hollow2 = 0.7f;
                        hollow2 /= 0.7f;
                    }
                }
            } else
            {
                if (sides == 3)
                {
                    if (hollowSides == 4)
                    {
                        if (hollow2 > 0.7f)
                            hollow2 = 0.7f;
                        hollow2 *= 0.707f;
                    } else
                        hollow2 *= 0.5f;
                } else if (sides == 4)
                {
                    initialProfileRot = 1.25f * (float)Math.PI;
                    if (hollowSides != 4)
                        hollow2 *= 0.707f;
                } else if (sides == 24 && hollowSides == 5)
                    hollow2 *= 1.414f;
            }

            Profile profile = new Profile (sides, profileStart, profileEnd, hollow2, hollowSides, true,
                                  calcVertexNormals);
            errorMessage = profile.errorMessage;

            numPrimFaces = profile.numPrimFaces;
            int cut1FaceNumber = profile.bottomFaceNumber + 1;
            int cut2FaceNumber = cut1FaceNumber + 1;
            if (!needEndFaces)
            {
                cut1FaceNumber -= 2;
                cut2FaceNumber -= 2;
            }

            profileOuterFaceNumber = profile.outerFaceNumber;

            if (pathType == PathType.Circular)
            {
                needEndFaces = false;
                if (pathCutBegin != 0.0f || pathCutEnd != 1.0f)
                    needEndFaces = true;
                else if (taperX != 0.0f || taperY != 0.0f)
                    needEndFaces = true;
                else if (skew != 0.0f)
                    needEndFaces = true;
                else if (twistTotal != 0.0f)
                    needEndFaces = true;
                else if (radius != 0.0f)
                    needEndFaces = true;
            }
            else needEndFaces = true;

            if (!needEndFaces)
                profileOuterFaceNumber--;

            if (hasHollow)
            {
                profileHollowFaceNumber = profile.hollowFaceNumber;
                if (!needEndFaces)
                    profileHollowFaceNumber--;
            }

            int cut1Vert = -1;
            int cut2Vert = -1;
            if (hasProfileCut)
            {
                cut1Vert = hasHollow ? profile.coords.Count - 1 : 0;
                cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
            }

            if (initialProfileRot != 0.0f)
            {
                profile.AddRot (new Quat (new Coord (0.0f, 0.0f, 1.0f), initialProfileRot));
                if (viewerMode)
                    profile.MakeFaceUVs ();
            }

            Coord lastCutNormal1 = new Coord ();
            Coord lastCutNormal2 = new Coord ();
            float thisV = 0.0f;
            float lastV = 0.0f;

            Path path = new Path {
                twistBegin = twistBegin2,			//20151106 - original was twistBegin
                twistEnd = twistEnd2,         //   ditto for twistEnd
                topShearX = topShearX,
                topShearY = topShearY,
                pathCutBegin = pathCutBegin,
                pathCutEnd = pathCutEnd,
                dimpleBegin = dimpleBegin,
                dimpleEnd = dimpleEnd,
                skew = skew,
                holeSizeX = holeSizeX,
                holeSizeY = holeSizeY,
                taperX = taperX,
                taperY = taperY,
                radius = radius,
                revolutions = revolutions,
                stepsPerRevolution = stepsPerRevolution
            };

            path.Create (pathType, steps);

            for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
            {
                PathNode node = path.pathNodes [nodeIndex];
                Profile newLayer = profile.Copy ();
                newLayer.Scale (node.xScale, node.yScale);

                newLayer.AddRot (node.rotation);
                newLayer.AddPos (node.position);

                if (needEndFaces && nodeIndex == 0)
                {
                    newLayer.FlipNormals ();

                    // add the top faces to the viewerFaces list here
                    if (viewerMode)
                    {
                        Coord faceNormal = newLayer.faceNormal;
                        ViewerFace newViewerFace = new ViewerFace (profile.bottomFaceNumber);
                        int numFaces = newLayer.faces.Count;
                        List<Face> faces2 = newLayer.faces;

                        for (int i = 0; i < numFaces; i++)
                        {
                            Face face = faces2 [i];
                            newViewerFace.v1 = newLayer.coords [face.v1];
                            newViewerFace.v2 = newLayer.coords [face.v2];
                            newViewerFace.v3 = newLayer.coords [face.v3];

                            newViewerFace.coordIndex1 = face.v1;
                            newViewerFace.coordIndex2 = face.v2;
                            newViewerFace.coordIndex3 = face.v3;

                            newViewerFace.n1 = faceNormal;
                            newViewerFace.n2 = faceNormal;
                            newViewerFace.n3 = faceNormal;

                            newViewerFace.uv1 = newLayer.faceUVs [face.v1];
                            newViewerFace.uv2 = newLayer.faceUVs [face.v2];
                            newViewerFace.uv3 = newLayer.faceUVs [face.v3];

                            if (pathType == PathType.Linear)
                            {
                                newViewerFace.uv1.Flip();
                                newViewerFace.uv2.Flip();
                                newViewerFace.uv3.Flip();
                            }
                            viewerFaces.Add (newViewerFace);
                        }
                    }
                } // if (nodeIndex == 0)

                // append this layer

                int coordsLen = coords.Count;
                newLayer.AddValue2FaceVertexIndices (coordsLen);

                coords.AddRange (newLayer.coords);

                if (calcVertexNormals)
                {
                    newLayer.AddValue2FaceNormalIndices (normals.Count);
                    normals.AddRange (newLayer.vertexNormals);
                }

                if (node.percentOfPath < pathCutBegin + 0.01f || node.percentOfPath > pathCutEnd - 0.01f)
                    faces.AddRange (newLayer.faces);

                // fill faces between layers

                int numVerts = newLayer.coords.Count;
                thisV = 1.0f - node.percentOfPath;
                if (nodeIndex > 0)
                {
                    Face newFace1 = new Face ();
                    Face newFace2 = new Face ();

                    int startVert = coordsLen + 1;
                    int endVert = coords.Count;

                    if (sides < 5 || hasProfileCut || hasHollow)
                        startVert--;

                    for (int i = startVert; i < endVert; i++)
                    {
                        int iNext = i + 1;
                        if (i == endVert - 1)
                            iNext = startVert;

                        int whichVert = i - startVert;

                        newFace1.v1 = i;
                        newFace1.v2 = i - numVerts;
                        newFace1.v3 = iNext;

                        newFace1.n1 = newFace1.v1;
                        newFace1.n2 = newFace1.v2;
                        newFace1.n3 = newFace1.v3;
                        faces.Add(newFace1);

                        newFace2.v1 = iNext;
                        newFace2.v2 = i - numVerts;
                        newFace2.v3 = iNext - numVerts;

                        newFace2.n1 = newFace2.v1;
                        newFace2.n2 = newFace2.v2;
                        newFace2.n3 = newFace2.v3;
                        faces.Add(newFace2);

                        if (viewerMode)
                        {
                            // add the side faces to the list of viewerFaces here

                            int primFaceNum = profile.faceNumbers [whichVert];
                            if (!needEndFaces)
                                primFaceNum -= 1;

                            ViewerFace newViewerFace1 = new ViewerFace (primFaceNum);
                            ViewerFace newViewerFace2 = new ViewerFace (primFaceNum);

                            int uIndex = whichVert;
                            if (!hasHollow && sides > 4 && uIndex < newLayer.us.Count - 1)
                            {
                                uIndex++;
                            }

                            float u1 = newLayer.us[uIndex];
                            float u2 = 1.0f;
                            if (uIndex < (int)newLayer.us.Count - 1)
                                u2 = newLayer.us[uIndex + 1];

                            if (whichVert == cut1Vert || whichVert == cut2Vert)
                            {
                                u1 = 0.0f;
                                u2 = 1.0f;
                                if (uIndex < (int) newLayer.us.Count - 1) u2 = newLayer.us[uIndex + 1];
                                if (whichVert == cut1Vert || whichVert == cut2Vert)
                                {
                                    u1 = 0.0f;
                                    u2 = 1.0f;
                                }
                            } else if (sides < 5)
                            {
                                if (whichVert < profile.numOuterVerts)
                                {
                                    // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled
                                    // to reflect the entire texture width
                                    u1 *= sides;
                                    u2 *= sides;
                                    u2 -= u1;
                                    u1 -= u1;
                                    if (u2 < 0.1f)
                                        u2 = 1.0f;
                                } else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1)
                                {
                                    u1 *= 2.0f;
                                    u2 *= 2.0f;
                                    //profileHollowFaceNumber = primFaceNum;
                                }
                            }

                            if (sphereMode)
                            {
                                if (whichVert != cut1Vert && whichVert != cut2Vert)
                                {
                                    u1 = u1 * 2.0f - 1.0f;
                                    u2 = u2 * 2.0f - 1.0f;

                                    if (whichVert >= newLayer.numOuterVerts)
                                    {
                                        u1 -= hollow;
                                        u2 -= hollow;
                                    }

                                }
                            }

                            newViewerFace1.uv1.U = u1;
                            newViewerFace1.uv2.U = u1;
                            newViewerFace1.uv3.U = u2;

                            newViewerFace1.uv1.V = thisV;
                            newViewerFace1.uv2.V = lastV;
                            newViewerFace1.uv3.V = thisV;

                            newViewerFace2.uv1.U = u2;
                            newViewerFace2.uv2.U = u1;
                            newViewerFace2.uv3.U = u2;

                            newViewerFace2.uv1.V = thisV;
                            newViewerFace2.uv2.V = lastV;
                            newViewerFace2.uv3.V = lastV;

                            newViewerFace1.v1 = coords[newFace1.v1];
                            newViewerFace1.v2 = coords[newFace1.v2];
                            newViewerFace1.v3 = coords[newFace1.v3];

                            newViewerFace2.v1 = coords[newFace2.v1];
                            newViewerFace2.v2 = coords[newFace2.v2];
                            newViewerFace2.v3 = coords[newFace2.v3];

                            newViewerFace1.coordIndex1 = newFace1.v1;
                            newViewerFace1.coordIndex2 = newFace1.v2;
                            newViewerFace1.coordIndex3 = newFace1.v3;

                            newViewerFace2.coordIndex1 = newFace2.v1;
                            newViewerFace2.coordIndex2 = newFace2.v2;
                            newViewerFace2.coordIndex3 = newFace2.v3;

                            // profile cut faces
                            if (whichVert == cut1Vert)
                            {
                                newViewerFace1.primFaceNumber = cut1FaceNumber;
                                newViewerFace2.primFaceNumber = cut1FaceNumber;
                                newViewerFace1.n1 = newLayer.cutNormal1;
                                newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;

                                newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1;
                                newViewerFace2.n2 = lastCutNormal1;
                            } else if (whichVert == cut2Vert)
                            {
                                newViewerFace1.primFaceNumber = cut2FaceNumber;
                                newViewerFace2.primFaceNumber = cut2FaceNumber;
                                newViewerFace1.n1 = newLayer.cutNormal2;
                                newViewerFace1.n2 = lastCutNormal2;
                                newViewerFace1.n3 = lastCutNormal2;

                                newViewerFace2.n1 = newLayer.cutNormal2;
                                newViewerFace2.n3 = newLayer.cutNormal2;
                                newViewerFace2.n2 = lastCutNormal2;
                            } else // outer and hollow faces
                            {
                                if ((sides < 5 && whichVert < newLayer.numOuterVerts) ||
                                    (hollowSides < 5 && whichVert >= newLayer.numOuterVerts))
                                {
                                    // looks terrible when path is twisted... need vertex normals here
                                    newViewerFace1.CalcSurfaceNormal ();
                                    newViewerFace2.CalcSurfaceNormal ();
                                } else
                                {
                                    newViewerFace1.n1 = normals[newFace1.n1];
                                    newViewerFace1.n2 = normals[newFace1.n2];
                                    newViewerFace1.n3 = normals[newFace1.n3];

                                    newViewerFace2.n1 = normals[newFace2.n1];
                                    newViewerFace2.n2 = normals[newFace2.n2];
                                    newViewerFace2.n3 = normals[newFace2.n3];
                                }
                            }
                            viewerFaces.Add (newViewerFace1);
                            viewerFaces.Add (newViewerFace2);

                        }
                    }
                }

                lastCutNormal1 = newLayer.cutNormal1;
                lastCutNormal2 = newLayer.cutNormal2;
                lastV = 1.0f - node.percentOfPath;

                if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode)
                {
                    // add the top faces to the viewerFaces list here
                    Coord faceNormal = newLayer.faceNormal;
                    ViewerFace newViewerFace = new ViewerFace { primFaceNumber = 0 };
                    int numFaces = newLayer.faces.Count;
                    List<Face> faces2 = newLayer.faces;

                    for (int i = 0; i < numFaces; i++)
                    {
                        Face face = faces2 [i];
                        newViewerFace.v1 = newLayer.coords [face.v1 - coordsLen];
                        newViewerFace.v2 = newLayer.coords [face.v2 - coordsLen];
                        newViewerFace.v3 = newLayer.coords [face.v3 - coordsLen];

                        newViewerFace.coordIndex1 = face.v1 - coordsLen;
                        newViewerFace.coordIndex2 = face.v2 - coordsLen;
                        newViewerFace.coordIndex3 = face.v3 - coordsLen;

                        newViewerFace.n1 = faceNormal;
                        newViewerFace.n2 = faceNormal;
                        newViewerFace.n3 = faceNormal;

                        newViewerFace.uv1 = newLayer.faceUVs [face.v1 - coordsLen];
                        newViewerFace.uv2 = newLayer.faceUVs [face.v2 - coordsLen];
                        newViewerFace.uv3 = newLayer.faceUVs [face.v3 - coordsLen];

                        if (pathType == PathType.Linear)
                        {
                            newViewerFace.uv1.Flip();
                            newViewerFace.uv2.Flip();
                            newViewerFace.uv3.Flip();
                        }
                        viewerFaces.Add (newViewerFace);
                    }
                }
            } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
        }