Beispiel #1
0
        internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides,
                         bool createFaces, bool calcVertexNormals)
        {
            this.calcVertexNormals = calcVertexNormals;
            coords = new List<Coord> ();
            faces = new List<Face> ();
            vertexNormals = new List<Coord> ();
            us = new List<float> ();
            faceUVs = new List<UVCoord> ();
            faceNumbers = new List<int> ();

            Coord center = new Coord (0.0f, 0.0f, 0.0f);

            List<Coord> hollowCoords = new List<Coord> ();
            List<Coord> hollowNormals = new List<Coord> ();
            List<float> hollowUs = new List<float> ();

            if (calcVertexNormals)
            {
                outerCoordIndices = new List<int> ();
                hollowCoordIndices = new List<int> ();
                cut1CoordIndices = new List<int> ();
                cut2CoordIndices = new List<int> ();
            }

            bool hasHollow = (hollow > 0.0f);

            bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f);

            AngleList angles = new AngleList ();
            AngleList hollowAngles = new AngleList ();

            float xScale = 0.5f;
            float yScale = 0.5f;
            if (sides == 4) // corners of a square are sqrt(2) from center
            {
                xScale = 0.707107f;
                yScale = 0.707107f;
            }

            float startAngle = profileStart * twoPi;
            float stopAngle = profileEnd * twoPi;

            try
            {
                angles.makeAngles (sides, startAngle, stopAngle);
            } catch (Exception ex)
            {
                errorMessage = "makeAngles failed: Exception: " + ex +
                    "\nsides: " + sides + " startAngle: " + startAngle + " stopAngle: " + stopAngle;

                return;
            }

            numOuterVerts = angles.angles.Count;

            // flag to create as few triangles as possible for 3 or 4 side profile
            bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);

            if (hasHollow)
            {
                if (sides == hollowSides)
                    hollowAngles = angles;
                else
                {
                    try
                    {
                        hollowAngles.makeAngles (hollowSides, startAngle, stopAngle);
                    } catch (Exception ex)
                    {
                        errorMessage = "makeAngles failed: Exception: " + ex +
                        "\nsides: " + sides + " startAngle: " + startAngle + " stopAngle: " + stopAngle;

                        return;
                    }
                }
                numHollowVerts = hollowAngles.angles.Count;
            } else if (!simpleFace)
            {
                coords.Add (center);

                if (this.calcVertexNormals)
                    vertexNormals.Add (new Coord (0.0f, 0.0f, 1.0f));
                us.Add (0.0f);
            }

            const float z = 0.0f;

            Angle angle;
            Coord newVert = new Coord ();
            if (hasHollow && hollowSides != sides)
            {
                int numHollowAngles = hollowAngles.angles.Count;
                for (int i = 0; i < numHollowAngles; i++)
                {
                    angle = hollowAngles.angles [i];
                    newVert.X = hollow * xScale * angle.X;
                    newVert.Y = hollow * yScale * angle.Y;
                    newVert.Z = z;

                    hollowCoords.Add (newVert);
                    if (this.calcVertexNormals)
                    {
                        hollowNormals.Add (hollowSides < 5
                                              ? hollowAngles.normals [i].Invert ()
                                              : new Coord (-angle.X, -angle.Y, 0.0f));

                        if (hollowSides == 4)
                            hollowUs.Add(angle.angle * hollow * 0.707107f);
                        else
                            hollowUs.Add(angle.angle * hollow);

                    }
                }
            }

            int index = 0;
            int numAngles = angles.angles.Count;

            for (int i = 0; i < numAngles; i++)
            {
                angle = angles.angles [i];
                newVert.X = angle.X * xScale;
                newVert.Y = angle.Y * yScale;
                newVert.Z = z;
                coords.Add (newVert);
                if (this.calcVertexNormals)
                {
                    outerCoordIndices.Add (coords.Count - 1);

                    if (sides < 5)
                    {
                        vertexNormals.Add (angles.normals [i]);
                        float u = angle.angle;
                        us.Add (u);
                    } else
                    {
                        vertexNormals.Add (new Coord (angle.X, angle.Y, 0.0f));
                        us.Add (angle.angle);
                    }
                }

                if (hasHollow)
                {
                    if (hollowSides == sides)
                    {
                        newVert.X *= hollow;
                        newVert.Y *= hollow;
                        newVert.Z = z;
                        hollowCoords.Add (newVert);
                        if (this.calcVertexNormals)
                        {
                            hollowNormals.Add (sides < 5
                                                  ? angles.normals [i].Invert ()
                                                  : new Coord (-angle.X, -angle.Y, 0.0f));

                            hollowUs.Add (angle.angle * hollow);  //20151106 - not used here??
                        }
                    }
                } else if (!simpleFace && createFaces && angle.angle > 0.0001f)
                {
                    Face newFace = new Face { v1 = 0, v2 = index, v3 = index + 1 };

                    faces.Add (newFace);
                }
                index += 1;
            }

            if (hasHollow)
            {
                hollowCoords.Reverse ();
                if (this.calcVertexNormals)
                {
                    hollowNormals.Reverse ();
                    hollowUs.Reverse ();
                }

                if (createFaces)
                {
                    int numTotalVerts = numOuterVerts + numHollowVerts;

                    if (numOuterVerts == numHollowVerts)
                    {
                        Face newFace = new Face ();

                        for (int coordIndex = 0; coordIndex < numOuterVerts - 1; coordIndex++)
                        {
                            newFace.v1 = coordIndex;
                            newFace.v2 = coordIndex + 1;
                            newFace.v3 = numTotalVerts - coordIndex - 1;
                            faces.Add (newFace);

                            newFace.v1 = coordIndex + 1;
                            newFace.v2 = numTotalVerts - coordIndex - 2;
                            newFace.v3 = numTotalVerts - coordIndex - 1;
                            faces.Add (newFace);
                        }
                    } else
                    {
                        if (numOuterVerts < numHollowVerts)
                        {
                            Face newFace = new Face ();
                            int j = 0; // j is the index for outer vertices
                            int maxJ = numOuterVerts - 1;
                            for (int i = 0; i < numHollowVerts; i++) // i is the index for inner vertices
                            {
                                if (j < maxJ)
                                if (angles.angles [j + 1].angle - hollowAngles.angles [i].angle <
                                        hollowAngles.angles [i].angle - angles.angles [j].angle + 0.000001f)
                                {
                                    newFace.v1 = numTotalVerts - i - 1;
                                    newFace.v2 = j;
                                    newFace.v3 = j + 1;

                                    faces.Add (newFace);
                                    j += 1;
                                }

                                newFace.v1 = j;
                                newFace.v2 = numTotalVerts - i - 2;
                                newFace.v3 = numTotalVerts - i - 1;

                                faces.Add (newFace);
                            }
                        } else // numHollowVerts < numOuterVerts
                        {
                            Face newFace = new Face ();
                            int j = 0; // j is the index for inner vertices
                            int maxJ = numHollowVerts - 1;
                            for (int i = 0; i < numOuterVerts; i++)
                            {
                                if (j < maxJ)
                                if (hollowAngles.angles [j + 1].angle - angles.angles [i].angle <
                                        angles.angles [i].angle - hollowAngles.angles [j].angle + 0.000001f)
                                {
                                    newFace.v1 = i;
                                    newFace.v2 = numTotalVerts - j - 2;
                                    newFace.v3 = numTotalVerts - j - 1;

                                    faces.Add (newFace);
                                    j += 1;
                                }

                                newFace.v1 = numTotalVerts - j - 1;
                                newFace.v2 = i;
                                newFace.v3 = i + 1;

                                faces.Add (newFace);
                            }
                        }
                    }
                }

                if (calcVertexNormals)
                {
                    foreach (Coord hc in hollowCoords)
                    {
                        coords.Add (hc);
                        hollowCoordIndices.Add (coords.Count - 1);
                    }
                } else
                    coords.AddRange (hollowCoords);

                if (this.calcVertexNormals)
                {
                    vertexNormals.AddRange (hollowNormals);
                    us.AddRange (hollowUs);
                }
            }

            if (simpleFace && createFaces)
            {
                if (sides == 3)
                    faces.Add (new Face (0, 1, 2));
                else if (sides == 4)
                {
                    faces.Add (new Face (0, 1, 2));
                    faces.Add (new Face (0, 2, 3));
                }
            }

            if (calcVertexNormals && hasProfileCut)
            {
                int lastOuterVertIndex = numOuterVerts - 1;

                if (hasHollow)
                {
                    cut1CoordIndices.Add (0);
                    cut1CoordIndices.Add (coords.Count - 1);

                    cut2CoordIndices.Add (lastOuterVertIndex + 1);
                    cut2CoordIndices.Add (lastOuterVertIndex);

                    cutNormal1.X = coords [0].Y - coords [coords.Count - 1].Y;
                    cutNormal1.Y = -(coords [0].X - coords [coords.Count - 1].X);

                    cutNormal2.X = coords [lastOuterVertIndex + 1].Y - coords [lastOuterVertIndex].Y;
                    cutNormal2.Y = -(coords [lastOuterVertIndex + 1].X - coords [lastOuterVertIndex].X);
                } else
                {
                    cut1CoordIndices.Add (0);
                    cut1CoordIndices.Add (1);

                    cut2CoordIndices.Add (lastOuterVertIndex);
                    cut2CoordIndices.Add (0);

                    cutNormal1.X = vertexNormals [1].Y;
                    cutNormal1.Y = -vertexNormals [1].X;

                    cutNormal2.X = -vertexNormals [vertexNormals.Count - 2].Y;
                    cutNormal2.Y = vertexNormals [vertexNormals.Count - 2].X;
                }
                cutNormal1.Normalize ();
                cutNormal2.Normalize ();
            }

            MakeFaceUVs ();

            hollowCoords = null;
            hollowNormals = null;
            hollowUs = null;

            if (calcVertexNormals)
            {
                // calculate prim face numbers

                // face number order is top, outer, hollow, bottom, start cut, end cut
                // I know it's ugly but so is the whole concept of prim face numbers

                int faceNum = 1; // start with outer faces
                outerFaceNumber = faceNum;

                int startVert = hasProfileCut && !hasHollow ? 1 : 0;
                if (startVert > 0)
                    faceNumbers.Add (-1);
                for (int i = 0; i < numOuterVerts - 1; i++)
                    faceNumbers.Add (sides < 5 && i <= sides ? faceNum++ : faceNum);

                //if (!hasHollow && !hasProfileCut)
                //    this.bottomFaceNumber = faceNum++;

                faceNumbers.Add (hasProfileCut ? -1 : faceNum++);

                if (sides > 4 && (hasHollow || hasProfileCut))
                    faceNum++;

                if (sides < 5 && (hasHollow || hasProfileCut) && numOuterVerts < sides)
                    faceNum++;

                if (hasHollow)
                {
                    for (int i = 0; i < numHollowVerts; i++)
                        faceNumbers.Add (faceNum);

                    hollowFaceNumber = faceNum++;
                }
                //if (hasProfileCut || hasHollow)
                //    this.bottomFaceNumber = faceNum++;
                bottomFaceNumber = faceNum++;

                if (hasHollow && hasProfileCut)
                    faceNumbers.Add (faceNum++);

                for (int i = 0; i < faceNumbers.Count; i++)
                    if (faceNumbers [i] == -1)
                        faceNumbers [i] = faceNum++;

                numPrimFaces = faceNum;
            }
        }
Beispiel #2
0
 Coord SurfaceNormal(Face face)
 {
     return SurfaceNormal (coords [face.v1], coords [face.v2], coords [face.v3]);
 }
Beispiel #3
0
        /// <summary>
        ///     ** Experimental ** May disappear from future versions ** not recommended for use in applications
        ///     Construct a sculpt mesh from a 2D array of floats
        /// </summary>
        /// <param name="zMap"></param>
        /// <param name="xBegin"></param>
        /// <param name="xEnd"></param>
        /// <param name="yBegin"></param>
        /// <param name="yEnd"></param>
        /// <param name="viewerMode"></param>
        public SculptMesh (float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode)
        {
            float xStep, yStep;
            float uStep, vStep;

            int numYElements = zMap.GetLength (0);
            int numXElements = zMap.GetLength (1);

            try
            {
                xStep = (xEnd - xBegin) / (numXElements - 1);
                yStep = (yEnd - yBegin) / (numYElements - 1);

                uStep = 1.0f / (numXElements - 1);
                vStep = 1.0f / (numYElements - 1);
            } catch (DivideByZeroException)
            {
                return;
            }

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

            viewerFaces = new List<ViewerFace> ();

            int p1, p2, p3, p4;

            int x, y;
            int xStart = 0, yStart = 0;

            for (y = yStart; y < numYElements; y++)
            {
                int rowOffset = y * numXElements;

                for (x = xStart; x < numXElements; x++)
                {
                    /*
                    *   p1-----p2
                    *   | \ f2 |
                    *   |   \  |
                    *   | f1  \|
                    *   p3-----p4
                    */

                    p4 = rowOffset + x;
                    p3 = p4 - 1;

                    p2 = p4 - numXElements;
                    p1 = p3 - numXElements;
                    Coord c = new Coord (xBegin + x * xStep, yBegin + y * yStep, zMap [y, x]);
                    this.coords.Add (c);
                    if (viewerMode)
                    {
                        this.normals.Add (new Coord ());
                        this.uvs.Add (new UVCoord (uStep * x, 1.0f - vStep * y));
                    }

                    if (y > 0 && x > 0)
                    {
                        Face f1, f2;

                        if (viewerMode)
                        {
                            f1 = new Face (p1, p4, p3, p1, p4, p3) { uv1 = p1, uv2 = p4, uv3 = p3 };

                            f2 = new Face (p1, p2, p4, p1, p2, p4) { uv1 = p1, uv2 = p2, uv3 = p4 };
                        } else
                        {
                            f1 = new Face (p1, p4, p3);
                            f2 = new Face (p1, p2, p4);
                        }

                        this.faces.Add (f1);
                        this.faces.Add (f2);
                    }
                }
            }

            if (viewerMode)
                calcVertexNormals (SculptType.plane, numXElements, numYElements);
        }
Beispiel #4
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++)
        }
Beispiel #5
0
        void _SculptMesh (List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror,
                          bool invert)
        {
            coords = new List<Coord> ();
            faces = new List<Face> ();
            normals = new List<Coord> ();
            uvs = new List<UVCoord> ();

            sculptType = (SculptType)(((int)sculptType) & 0x07);

            if (mirror)
                invert = !invert;

            viewerFaces = new List<ViewerFace> ();

            int width = rows [0].Count;

            int p1, p2, p3, p4;

            int imageX, imageY;

            if (sculptType != SculptType.plane)
            {
                if (rows.Count % 2 == 0)
                {
                    foreach (List<Coord> t in rows)
                        t.Add (t [0]);
                } else
                {
                    int lastIndex = rows [0].Count - 1;

                    foreach (List<Coord> t in rows)
                        t [0] = t [lastIndex];
                }
            }

            Coord topPole = rows [0] [width / 2];
            Coord bottomPole = rows [rows.Count - 1] [width / 2];

            if (sculptType == SculptType.sphere)
            {
                if (rows.Count % 2 == 0)
                {
                    int count = rows [0].Count;
                    List<Coord> topPoleRow = new List<Coord> (count);
                    List<Coord> bottomPoleRow = new List<Coord> (count);

                    for (int i = 0; i < count; i++)
                    {
                        topPoleRow.Add (topPole);
                        bottomPoleRow.Add (bottomPole);
                    }
                    rows.Insert (0, topPoleRow);
                    rows.Add (bottomPoleRow);
                } else
                {
                    int count = rows [0].Count;

                    List<Coord> topPoleRow = rows [0];
                    List<Coord> bottomPoleRow = rows [rows.Count - 1];

                    for (int i = 0; i < count; i++)
                    {
                        topPoleRow [i] = topPole;
                        bottomPoleRow [i] = bottomPole;
                    }
                }
            }

            if (sculptType == SculptType.torus)
                rows.Add (rows [0]);

            int coordsDown = rows.Count;
            int coordsAcross = rows [0].Count;

            float widthUnit = 1.0f / (coordsAcross - 1);
            float heightUnit = 1.0f / (coordsDown - 1);

            for (imageY = 0; imageY < coordsDown; imageY++)
            {
                int rowOffset = imageY * coordsAcross;

                for (imageX = 0; imageX < coordsAcross; imageX++)
                {
                    /*
                    *   p1-----p2
                    *   | \ f2 |
                    *   |   \  |
                    *   | f1  \|
                    *   p3-----p4
                    */

                    p4 = rowOffset + imageX;
                    p3 = p4 - 1;

                    p2 = p4 - coordsAcross;
                    p1 = p3 - coordsAcross;

                    coords.Add (rows [imageY] [imageX]);
                    if (viewerMode)
                    {
                        normals.Add (new Coord ());
                        uvs.Add (new UVCoord (widthUnit * imageX, heightUnit * imageY));
                    }

                    if (imageY > 0 && imageX > 0)
                    {
                        Face f1, f2;

                        if (viewerMode)
                        {
                            if (invert)
                            {
                                f1 = new Face (p1, p4, p3, p1, p4, p3) { uv1 = p1, uv2 = p4, uv3 = p3 };

                                f2 = new Face (p1, p2, p4, p1, p2, p4) { uv1 = p1, uv2 = p2, uv3 = p4 };
                            } else
                            {
                                f1 = new Face (p1, p3, p4, p1, p3, p4) { uv1 = p1, uv2 = p3, uv3 = p4 };

                                f2 = new Face (p1, p4, p2, p1, p4, p2) { uv1 = p1, uv2 = p4, uv3 = p2 };
                            }
                        } else
                        {
                            if (invert)
                            {
                                f1 = new Face (p1, p4, p3);
                                f2 = new Face (p1, p2, p4);
                            } else
                            {
                                f1 = new Face (p1, p3, p4);
                                f2 = new Face (p1, p4, p2);
                            }
                        }

                        faces.Add (f1);
                        faces.Add (f2);
                    }
                }
            }

            if (viewerMode)
                calcVertexNormals (sculptType, coordsAcross, coordsDown);
        }