Exemplo 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 = this.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;
        }
Exemplo 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
                this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
            this.hasHollow = (this.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 == 4)
                    hollow2 *= 1.414f;
            }

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

            numPrimFaces = profile.numPrimFaces;

            profileOuterFaceNumber = profile.outerFaceNumber;
            //this is always 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 lastV = 1.0f;

            Path path = new Path
                            {
                                twistBegin = twistBegin2,
                                twistEnd = twistEnd2,
                                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);

            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;

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

                            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;
                if (nodeIndex > 0)
                {
                    Face newFace = 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;

                        newFace.v1 = i;
                        newFace.v2 = i - numVerts;
                        newFace.v3 = iNext - numVerts;
                        faces.Add(newFace);

                        newFace.v2 = iNext - numVerts;
                        newFace.v3 = iNext;
                        faces.Add(newFace);

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

                            float u1 = newLayer.us[whichVert];
                            float u2 = 1.0f;
                            if (whichVert < newLayer.us.Count - 1)
                                u2 = newLayer.us[whichVert + 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 -= (int) u1;
                                    u1 -= (int) u1;
                                    if (u2 < 0.1f)
                                        u2 = 1.0f;
                                }
                                else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1)
                                {
                                    u1 *= 2.0f;
                                    u2 *= 2.0f;
                                    //this.profileHollowFaceNumber = primFaceNum;
                                }
                            }

                            if (this.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 = 1.0f - node.percentOfPath;
                            newViewerFace1.uv2.V = lastV;
                            newViewerFace1.uv3.V = lastV;

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

                            newViewerFace2.uv1.V = 1.0f - node.percentOfPath;
                            newViewerFace2.uv2.V = lastV;
                            newViewerFace2.uv3.V = 1.0f - node.percentOfPath;

                            newViewerFace1.v1 = coords[i];
                            newViewerFace1.v2 = coords[i - numVerts];
                            newViewerFace1.v3 = coords[iNext - numVerts];

                            newViewerFace2.v1 = coords[i];
                            newViewerFace2.v2 = coords[iNext - numVerts];
                            newViewerFace2.v3 = coords[iNext];

                            newViewerFace1.coordIndex1 = i;
                            newViewerFace1.coordIndex2 = i - numVerts;
                            newViewerFace1.coordIndex3 = iNext - numVerts;

                            newViewerFace2.coordIndex1 = i;
                            newViewerFace2.coordIndex2 = iNext - numVerts;
                            newViewerFace2.coordIndex3 = iNext;

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

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

                                newViewerFace2.n1 = 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[i];
                                    newViewerFace1.n2 = normals[i - numVerts];
                                    newViewerFace1.n3 = normals[iNext - numVerts];

                                    newViewerFace2.n1 = normals[i];
                                    newViewerFace2.n2 = normals[iNext - numVerts];
                                    newViewerFace2.n3 = normals[iNext];
                                }
                            }

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

                        viewerFaces.Add(newViewerFace);
                    }
                }
            } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
        }