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

            Coord center = new Coord(0.0f, 0.0f, 0.0f);
            //bool hasCenter = false;

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

            if (calcVertexNormals)
            {
                this.outerCoordIndices = new List<int>();
                this.hollowCoordIndices = new List<int>();
                this.cut1CoordIndices = new List<int>();
                this.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.707f;
                yScale = 0.707f;
            }

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

            try { angles.makeAngles(sides, startAngle, stopAngle); }
            catch (Exception ex)
            {

                errorMessage = "makeAngles failed: Exception: " + ex.ToString()
                + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();

                return;
            }

            this.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.ToString()
                        + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();

                        return;
                    }
                }
                this.numHollowVerts = hollowAngles.angles.Count;
            }
            else if (!simpleFace)
            {
                this.coords.Add(center);
                //hasCenter = true;
                if (this.calcVertexNormals)
                    this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f));
                this.us.Add(0.0f);
            }

            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)
                    {
                        if (hollowSides < 5)
                            hollowNormals.Add(hollowAngles.normals[i].Invert());
                        else
                            hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));

                        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;
                this.coords.Add(newVert);
                if (this.calcVertexNormals)
                {
                    this.outerCoordIndices.Add(this.coords.Count - 1);

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

                if (hasHollow)
                {
                    if (hollowSides == sides)
                    {
                        newVert.X *= hollow;
                        newVert.Y *= hollow;
                        newVert.Z = z;
                        hollowCoords.Add(newVert);
                        if (this.calcVertexNormals)
                        {
                            if (sides < 5)
                            {
                                hollowNormals.Add(angles.normals[i].Invert());
                            }

                            else
                                hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));

                            hollowUs.Add(angle.angle * hollow);
                        }
                    }
                }
                else if (!simpleFace && createFaces && angle.angle > 0.0001f)
                {
                    Face newFace = new Face();
                    newFace.v1 = 0;
                    newFace.v2 = index;
                    newFace.v3 = index + 1;

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

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

                if (createFaces)
                {
                    //int numOuterVerts = this.coords.Count;
                    //numOuterVerts = this.coords.Count;
                    //int numHollowVerts = hollowCoords.Count;
                    int numTotalVerts = this.numOuterVerts + this.numHollowVerts;

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

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

                            newFace.v1 = coordIndex + 1;
                            newFace.v2 = numTotalVerts - coordIndex - 2;
                            newFace.v3 = numTotalVerts - coordIndex - 1;
                            this.faces.Add(newFace);
                        }
                    }
                    else
                    {
                        if (this.numOuterVerts < this.numHollowVerts)
                        {
                            Face newFace = new Face();
                            int j = 0; // j is the index for outer vertices
                            int maxJ = this.numOuterVerts - 1;
                            for (int i = 0; i < this.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;

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

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

                                this.faces.Add(newFace);
                            }
                        }
                        else // numHollowVerts < numOuterVerts
                        {
                            Face newFace = new Face();
                            int j = 0; // j is the index for inner vertices
                            int maxJ = this.numHollowVerts - 1;
                            for (int i = 0; i < this.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;

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

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

                                this.faces.Add(newFace);
                            }
                        }
                    }
                }

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

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

                }
            }

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

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

                    this.cut1CoordIndices.Add(0);
                    this.cut1CoordIndices.Add(this.coords.Count - 1);

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

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

                    this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y;
                    this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X);
                }

                else
                {
                    this.cutNormal1.X = this.vertexNormals[1].Y;
                    this.cutNormal1.Y = -this.vertexNormals[1].X;

                    this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y;
                    this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X;

                }
                this.cutNormal1.Normalize();
                this.cutNormal2.Normalize();
            }

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

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

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

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

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

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

                if (hasHollow && hasProfileCut)
                    this.faceNumbers.Add(faceNum++);
                for (int i = 0; i < this.faceNumbers.Count; i++)
                    if (this.faceNumbers[i] == -1)
                        this.faceNumbers[i] = faceNum++;


                this.numPrimFaces = faceNum;
            }

        }
Exemplo n.º 2
0
        public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool hasProfileCut, bool createFaces)
        {
            const float halfSqr2 = 0.7071067811866f;
            
            this.coords = new List<Coord>();
            this.faces = new List<Face>();

            List<Coord> hollowCoords = new List<Coord>();

            bool hasHollow = (hollow > 0.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 = halfSqr2;
                yScale = halfSqr2;
            }

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

            try { angles.makeAngles(sides, startAngle, stopAngle,hasProfileCut); }
            catch (Exception ex)
            {

                errorMessage = "makeAngles failed: Exception: " + ex.ToString()
                + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();

                return;
            }

            this.numOuterVerts = angles.angles.Count;

            Angle angle;
            Coord newVert = new Coord();

            // 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, hasProfileCut); }
                    catch (Exception ex)
                    {
                        errorMessage = "makeAngles failed: Exception: " + ex.ToString()
                        + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();

                        return;
                    }

                    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 = 0.0f;

                        hollowCoords.Add(newVert);
                    }
                }
                this.numHollowVerts = hollowAngles.angles.Count;
            }
            else if (!simpleFace)
            {
                Coord center = new Coord(0.0f, 0.0f, 0.0f);
                this.coords.Add(center);
            }

            int numAngles = angles.angles.Count;
            bool hollowsame = (hasHollow && hollowSides == sides);

            for (int i = 0; i < numAngles; i++)
            {
                angle = angles.angles[i];
                newVert.X = angle.X * xScale;
                newVert.Y = angle.Y * yScale;
                newVert.Z = 0.0f;
                this.coords.Add(newVert);
                if (hollowsame)
                {
                    newVert.X *= hollow;
                    newVert.Y *= hollow;
                    hollowCoords.Add(newVert);
                }
            }

            if (hasHollow)
            {
                hollowCoords.Reverse();
                this.coords.AddRange(hollowCoords);

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

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

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

                            newFace.v1 = coordIndex + 1;
                            newFace.v2 = numTotalVerts - coordIndex - 2;
                            newFace.v3 = numTotalVerts - coordIndex - 1;
                            this.faces.Add(newFace);
                        }
                        if (!hasProfileCut)
                        {
                            newFace.v1 = this.numOuterVerts - 1;
                            newFace.v2 = 0;
                            newFace.v3 = this.numOuterVerts;
                            this.faces.Add(newFace);

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

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

                            this.faces.Add(newFace);
                        }

                        if (!hasProfileCut)
                        {
                            if (i == this.numHollowVerts)
                            {
                                newFace.v1 = numTotalVerts - this.numHollowVerts;
                                newFace.v2 = maxJ;
                                newFace.v3 = 0;

                                this.faces.Add(newFace);
                            }
                            else
                            {
                                if (1.0f - curHollowAngle < curHollowAngle - angles.angles[maxJ].angle + 0.000001f)
                                {
                                    newFace.v1 = numTotalVerts - i - 1;
                                    newFace.v2 = maxJ;
                                    newFace.v3 = 0;

                                    this.faces.Add(newFace);
                                }

                                for (; i < this.numHollowVerts - 1; i++)
                                {
                                    newFace.v1 = 0;
                                    newFace.v2 = numTotalVerts - i - 2;
                                    newFace.v3 = numTotalVerts - i - 1;

                                    this.faces.Add(newFace);
                                }
                            }

                            newFace.v1 = 0;
                            newFace.v2 = numTotalVerts - this.numHollowVerts;
                            newFace.v3 = numTotalVerts - 1;
                            this.faces.Add(newFace);
                        }
                    }
                    else // numHollowVerts < numOuterVerts
                    {
                        Face newFace = new Face();
                        int j = 0; // j is the index for inner vertices
                        int maxJ = this.numHollowVerts - 1;
                        for (int i = 0; i < this.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;

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

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

                            this.faces.Add(newFace);
                        }

                        if (!hasProfileCut)
                        {
                            int i = this.numOuterVerts - 1;

                            if (hollowAngles.angles[0].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[maxJ].angle + 0.000001f)
                            {
                                newFace.v1 = 0;
                                newFace.v2 = numTotalVerts - maxJ - 1;
                                newFace.v3 = numTotalVerts - 1;

                                this.faces.Add(newFace);
                            }

                            newFace.v1 = numTotalVerts - maxJ - 1;
                            newFace.v2 = i;
                            newFace.v3 = 0;

                            this.faces.Add(newFace);
                        }
                    }
                }
                
            }

            else if (createFaces)
            {
                if (simpleFace)
                {
                    if (sides == 3)
                        this.faces.Add(new Face(0, 1, 2));
                    else if (sides == 4)
                    {
                        this.faces.Add(new Face(0, 1, 2));
                        this.faces.Add(new Face(0, 2, 3));
                    }
                }
                else
                {
                    for (int i = 1; i < numAngles ; i++)
                    {
                        Face newFace = new Face();
                        newFace.v1 = 0;
                        newFace.v2 = i;
                        newFace.v3 = i + 1;
                        this.faces.Add(newFace);
                    }
                    if (!hasProfileCut)
                    {
                        Face newFace = new Face();
                        newFace.v1 = 0;
                        newFace.v2 = numAngles;
                        newFace.v3 = 1;
                        this.faces.Add(newFace);
                    }
                }
            }


            hollowCoords = null;
        }