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