29 using System.Collections.Generic;
46 public Quat(
float x,
float y,
float z,
float w)
56 axis = axis.Normalize();
59 float c = (float)Math.Cos(angle);
60 float s = (float)Math.Sin(angle);
72 return (
float)Math.Sqrt(
X *
X +
Y *
Y +
Z *
Z +
W *
W);
77 const float MAG_THRESHOLD = 0.0000001f;
81 if (mag > MAG_THRESHOLD)
83 float oomag = 1f / mag;
102 float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y;
103 float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X;
104 float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W;
105 float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z;
106 return new Quat(x, y, z, w);
111 return "< X: " + this.X.ToString() +
", Y: " + this.
Y.ToString() +
", Z: " + this.Z.ToString() +
", W: " + this.
W.ToString() +
">";
121 public Coord(
float x,
float y,
float z)
130 return (
float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z);
144 const float MAG_THRESHOLD = 0.0000001f;
148 if (mag > MAG_THRESHOLD)
150 float oomag = 1.0f / mag;
167 return this.X.ToString() +
" " + this.
Y.ToString() +
" " + this.Z.ToString();
173 c1.
Y * c2.
Z - c2.
Y * c1.
Z,
174 c1.
Z * c2.
X - c2.
Z * c1.
X,
175 c1.
X * c2.
Y - c2.
X * c1.
Y
195 c2.X = q.W * q.W * v.X +
196 2f * q.Y * q.W * v.Z -
197 2f * q.Z * q.W * v.Y +
199 2f * q.Y * q.X * v.Y +
200 2f * q.Z * q.X * v.Z -
205 2f * q.X * q.Y * v.X +
207 2f * q.Z * q.Y * v.Z +
208 2f * q.W * q.Z * v.X -
211 2f * q.X * q.W * v.Z -
215 2f * q.X * q.Z * v.X +
216 2f * q.Y * q.Z * v.Y +
218 2f * q.W * q.Y * v.X -
220 2f * q.W * q.X * v.Y -
242 this.U = 1.0f - this.U;
243 this.V = 1.0f - this.V;
304 Coord c1 = coordList[this.v1];
305 Coord c2 = coordList[this.v2];
306 Coord c3 = coordList[this.v3];
311 return Coord.Cross(edge1, edge2).Normalize();
339 this.v1 =
new Coord();
340 this.v2 =
new Coord();
341 this.v3 =
new Coord();
343 this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1;
345 this.n1 =
new Coord();
346 this.n2 =
new Coord();
347 this.n3 =
new Coord();
354 public void Scale(
float x,
float y,
float z)
369 public void AddPos(
float x,
float y,
float z)
398 Coord edge1 =
new Coord(this.
v2.
X -
this.v1.X,
this.v2.Y -
this.v1.Y,
this.v2.Z -
this.v1.Z);
399 Coord edge2 =
new Coord(this.
v3.
X -
this.v1.X,
this.v3.Y -
this.v1.Y,
this.v3.Z -
this.v1.Z);
401 this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize();
405 internal struct Angle
407 internal float angle;
411 internal Angle(
float angle,
float x,
float y)
419 internal class AngleList
421 private float iX, iY;
423 private static Angle[] angles3 =
425 new Angle(0.0f, 1.0f, 0.0f),
426 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
427 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
428 new Angle(1.0f, 1.0f, 0.0f)
431 private static Coord[] normals3 =
433 new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(),
434 new Coord(-0.5f, 0.0f, 0.0f).Normalize(),
435 new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(),
436 new Coord(0.25f, 0.4330127019f, 0.0f).Normalize()
439 private static Angle[] angles4 =
441 new Angle(0.0f, 1.0f, 0.0f),
442 new Angle(0.25f, 0.0f, 1.0f),
443 new Angle(0.5f, -1.0f, 0.0f),
444 new Angle(0.75f, 0.0f, -1.0f),
445 new Angle(1.0f, 1.0f, 0.0f)
448 private static Coord[] normals4 =
450 new Coord(0.5f, 0.5f, 0.0f).Normalize(),
451 new Coord(-0.5f, 0.5f, 0.0f).Normalize(),
452 new Coord(-0.5f, -0.5f, 0.0f).Normalize(),
453 new Coord(0.5f, -0.5f, 0.0f).Normalize(),
454 new Coord(0.5f, 0.5f, 0.0f).Normalize()
457 private static Angle[] angles24 =
459 new Angle(0.0f, 1.0f, 0.0f),
460 new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f),
461 new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
462 new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f),
463 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
464 new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f),
465 new Angle(0.25f, 0.0f, 1.0f),
466 new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f),
467 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
468 new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f),
469 new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
470 new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f),
471 new Angle(0.5f, -1.0f, 0.0f),
472 new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f),
473 new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
474 new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f),
475 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
476 new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f),
477 new Angle(0.75f, 0.0f, -1.0f),
478 new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f),
479 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
480 new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f),
481 new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
482 new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f),
483 new Angle(1.0f, 1.0f, 0.0f)
486 private Angle interpolatePoints(
float newPoint, Angle p1, Angle p2)
488 float m = (newPoint - p1.angle) / (p2.angle - p1.angle);
489 return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y));
492 private void intersection(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
double x4,
double y4)
494 double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
495 double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
499 double ua = uaNumerator / denom;
500 iX = (float)(x1 + ua * (x2 - x1));
501 iY = (float)(y1 + ua * (y2 - y1));
505 internal List<Angle> angles;
506 internal List<Coord> normals;
508 internal void makeAngles(
int sides,
float startAngle,
float stopAngle)
510 angles =
new List<Angle>();
511 normals =
new List<Coord>();
513 double twoPi = System.Math.PI * 2.0;
514 float twoPiInv = 1.0f / (float)twoPi;
517 throw new Exception(
"number of sides not greater than zero");
518 if (stopAngle <= startAngle)
519 throw new Exception(
"stopAngle not greater than startAngle");
521 if ((sides == 3 || sides == 4 || sides == 24))
523 startAngle *= twoPiInv;
524 stopAngle *= twoPiInv;
526 Angle[] sourceAngles;
528 sourceAngles = angles3;
530 sourceAngles = angles4;
531 else sourceAngles = angles24;
533 int startAngleIndex = (int)(startAngle * sides);
534 int endAngleIndex = sourceAngles.Length - 1;
535 if (stopAngle < 1.0f)
536 endAngleIndex = (int)(stopAngle * sides) + 1;
537 if (endAngleIndex == startAngleIndex)
540 for (
int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++)
542 angles.Add(sourceAngles[angleIndex]);
544 normals.Add(normals3[angleIndex]);
546 normals.Add(normals4[angleIndex]);
549 if (startAngle > 0.0f)
550 angles[0] = interpolatePoints(startAngle, angles[0], angles[1]);
552 if (stopAngle < 1.0f)
554 int lastAngleIndex = angles.Count - 1;
555 angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]);
560 double stepSize = twoPi / sides;
562 int startStep = (int)(startAngle / stepSize);
563 double angle = stepSize * startStep;
564 int step = startStep;
565 double stopAngleTest = stopAngle;
566 if (stopAngle < twoPi)
568 stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1);
569 if (stopAngleTest < stopAngle)
570 stopAngleTest += stepSize;
571 if (stopAngleTest > twoPi)
572 stopAngleTest = twoPi;
575 while (angle <= stopAngleTest)
578 newAngle.angle = (float)angle;
579 newAngle.X = (float)System.Math.Cos(angle);
580 newAngle.Y = (float)System.Math.Sin(angle);
581 angles.Add(newAngle);
583 angle = stepSize * step;
586 if (startAngle > angles[0].angle)
589 intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (
float)Math.Cos(startAngle), (float)Math.Sin(startAngle));
590 newAngle.angle = startAngle;
593 angles[0] = newAngle;
596 int index = angles.Count - 1;
597 if (stopAngle < angles[index].angle)
600 intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (
float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle));
601 newAngle.angle = stopAngle;
604 angles[index] = newAngle;
615 private const float twoPi = 2.0f * (float)Math.PI;
617 public string errorMessage = null;
619 public List<Coord> coords;
620 public List<Face> faces;
621 public List<Coord> vertexNormals;
622 public List<float> us;
623 public List<UVCoord> faceUVs;
624 public List<int> faceNumbers;
627 public List<int> outerCoordIndices = null;
628 public List<int> hollowCoordIndices = null;
629 public List<int> cut1CoordIndices = null;
630 public List<int> cut2CoordIndices = null;
636 public int numOuterVerts = 0;
637 public int numHollowVerts = 0;
639 public int outerFaceNumber = -1;
640 public int hollowFaceNumber = -1;
642 public bool calcVertexNormals =
false;
643 public int bottomFaceNumber = 0;
644 public int numPrimFaces = 0;
648 this.coords =
new List<Coord>();
649 this.faces =
new List<Face>();
650 this.vertexNormals =
new List<Coord>();
651 this.us =
new List<float>();
652 this.faceUVs =
new List<UVCoord>();
653 this.faceNumbers =
new List<int>();
656 public Profile(
int sides,
float profileStart,
float profileEnd,
float hollow,
int hollowSides,
bool createFaces,
bool calcVertexNormals)
658 this.calcVertexNormals = calcVertexNormals;
659 this.coords =
new List<Coord>();
660 this.faces =
new List<Face>();
661 this.vertexNormals =
new List<Coord>();
662 this.us =
new List<float>();
663 this.faceUVs =
new List<UVCoord>();
664 this.faceNumbers =
new List<int>();
668 List<Coord> hollowCoords =
new List<Coord>();
669 List<Coord> hollowNormals =
new List<Coord>();
670 List<float> hollowUs =
new List<float>();
672 if (calcVertexNormals)
674 this.outerCoordIndices =
new List<int>();
675 this.hollowCoordIndices =
new List<int>();
676 this.cut1CoordIndices =
new List<int>();
677 this.cut2CoordIndices =
new List<int>();
680 bool hasHollow = (hollow > 0.0f);
682 bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f);
684 AngleList angles =
new AngleList();
685 AngleList hollowAngles =
new AngleList();
695 float startAngle = profileStart * twoPi;
696 float stopAngle = profileEnd * twoPi;
698 try { angles.makeAngles(sides, startAngle, stopAngle); }
702 errorMessage =
"makeAngles failed: Exception: " + ex.ToString()
703 +
"\nsides: " + sides.ToString() +
" startAngle: " + startAngle.ToString() +
" stopAngle: " + stopAngle.ToString();
708 this.numOuterVerts = angles.angles.Count;
711 bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);
715 if (sides == hollowSides)
716 hollowAngles = angles;
719 try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); }
722 errorMessage =
"makeAngles failed: Exception: " + ex.ToString()
723 +
"\nsides: " + sides.ToString() +
" startAngle: " + startAngle.ToString() +
" stopAngle: " + stopAngle.ToString();
728 this.numHollowVerts = hollowAngles.angles.Count;
730 else if (!simpleFace)
732 this.coords.Add(center);
733 if (this.calcVertexNormals)
734 this.vertexNormals.Add(
new Coord(0.0f, 0.0f, 1.0f));
742 if (hasHollow && hollowSides != sides)
744 int numHollowAngles = hollowAngles.angles.Count;
745 for (
int i = 0; i < numHollowAngles; i++)
747 angle = hollowAngles.angles[i];
748 newVert.X = hollow * xScale * angle.X;
749 newVert.Y = hollow * yScale * angle.Y;
752 hollowCoords.Add(newVert);
753 if (this.calcVertexNormals)
756 hollowNormals.Add(hollowAngles.normals[i].Invert());
758 hollowNormals.Add(
new Coord(-angle.X, -angle.Y, 0.0f));
760 if (hollowSides == 4)
761 hollowUs.Add(angle.angle * hollow * 0.707107f);
763 hollowUs.Add(angle.angle * hollow);
769 int numAngles = angles.angles.Count;
771 for (
int i = 0; i < numAngles; i++)
773 angle = angles.angles[i];
774 newVert.X = angle.X * xScale;
775 newVert.Y = angle.Y * yScale;
777 this.coords.Add(newVert);
778 if (this.calcVertexNormals)
780 this.outerCoordIndices.Add(this.coords.Count - 1);
784 this.vertexNormals.Add(angles.normals[i]);
785 float u = angle.angle;
790 this.vertexNormals.Add(
new Coord(angle.X, angle.Y, 0.0f));
791 this.us.Add(angle.angle);
797 if (hollowSides == sides)
802 hollowCoords.Add(newVert);
803 if (this.calcVertexNormals)
807 hollowNormals.Add(angles.normals[i].Invert());
811 hollowNormals.Add(
new Coord(-angle.X, -angle.Y, 0.0f));
813 hollowUs.Add(angle.angle * hollow);
817 else if (!simpleFace && createFaces && angle.angle > 0.0001f)
822 newFace.v3 = index + 1;
824 this.faces.Add(newFace);
831 hollowCoords.Reverse();
832 if (this.calcVertexNormals)
834 hollowNormals.Reverse();
840 int numTotalVerts = this.numOuterVerts + this.numHollowVerts;
842 if (this.numOuterVerts == this.numHollowVerts)
846 for (
int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++)
848 newFace.v1 = coordIndex;
849 newFace.v2 = coordIndex + 1;
850 newFace.v3 = numTotalVerts - coordIndex - 1;
851 this.faces.Add(newFace);
853 newFace.v1 = coordIndex + 1;
854 newFace.v2 = numTotalVerts - coordIndex - 2;
855 newFace.v3 = numTotalVerts - coordIndex - 1;
856 this.faces.Add(newFace);
861 if (this.numOuterVerts < this.numHollowVerts)
865 int maxJ = this.numOuterVerts - 1;
866 for (
int i = 0; i < this.numHollowVerts; i++)
869 if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f)
871 newFace.v1 = numTotalVerts - i - 1;
875 this.faces.Add(newFace);
880 newFace.v2 = numTotalVerts - i - 2;
881 newFace.v3 = numTotalVerts - i - 1;
883 this.faces.Add(newFace);
890 int maxJ = this.numHollowVerts - 1;
891 for (
int i = 0; i < this.numOuterVerts; i++)
894 if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f)
897 newFace.v2 = numTotalVerts - j - 2;
898 newFace.v3 = numTotalVerts - j - 1;
900 this.faces.Add(newFace);
904 newFace.v1 = numTotalVerts - j - 1;
908 this.faces.Add(newFace);
914 if (calcVertexNormals)
916 foreach (
Coord hc
in hollowCoords)
919 hollowCoordIndices.Add(this.coords.Count - 1);
923 this.coords.AddRange(hollowCoords);
925 if (this.calcVertexNormals)
927 this.vertexNormals.AddRange(hollowNormals);
928 this.us.AddRange(hollowUs);
933 if (simpleFace && createFaces)
936 this.faces.Add(
new Face(0, 1, 2));
939 this.faces.Add(
new Face(0, 1, 2));
940 this.faces.Add(
new Face(0, 2, 3));
944 if (calcVertexNormals && hasProfileCut)
946 int lastOuterVertIndex = this.numOuterVerts - 1;
950 this.cut1CoordIndices.Add(0);
951 this.cut1CoordIndices.Add(this.coords.Count - 1);
953 this.cut2CoordIndices.Add(lastOuterVertIndex + 1);
954 this.cut2CoordIndices.Add(lastOuterVertIndex);
956 this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y;
957 this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X);
959 this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y;
960 this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X);
965 this.cut1CoordIndices.Add(0);
966 this.cut1CoordIndices.Add(1);
968 this.cut2CoordIndices.Add(lastOuterVertIndex);
969 this.cut2CoordIndices.Add(0);
971 this.cutNormal1.X = this.vertexNormals[1].Y;
972 this.cutNormal1.Y = -this.vertexNormals[1].X;
974 this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y;
975 this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X;
978 this.cutNormal1.Normalize();
979 this.cutNormal2.Normalize();
985 hollowNormals = null;
988 if (calcVertexNormals)
995 this.outerFaceNumber = faceNum;
997 int startVert = hasProfileCut && !hasHollow ? 1 : 0;
999 this.faceNumbers.Add(-1);
1000 for (
int i = 0; i < this.numOuterVerts - 1; i++)
1001 this.faceNumbers.Add(sides < 5 && i <= sides ? faceNum++ : faceNum);
1003 this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++);
1005 if (sides > 4 && (hasHollow || hasProfileCut))
1008 if (sides < 5 && (hasHollow || hasProfileCut) && this.numOuterVerts < sides)
1013 for (
int i = 0; i < this.numHollowVerts; i++)
1014 this.faceNumbers.Add(faceNum);
1016 this.hollowFaceNumber = faceNum++;
1019 this.bottomFaceNumber = faceNum++;
1021 if (hasHollow && hasProfileCut)
1022 this.faceNumbers.Add(faceNum++);
1024 for (
int i = 0; i < this.faceNumbers.Count; i++)
1025 if (this.faceNumbers[i] == -1)
1026 this.faceNumbers[i] = faceNum++;
1028 this.numPrimFaces = faceNum;
1035 this.faceUVs =
new List<UVCoord>();
1036 foreach (
Coord c
in this.coords)
1037 this.faceUVs.Add(
new UVCoord(1.0f - (0.5f + c.
X), 1.0f - (0.5f - c.
Y)));
1042 return this.Copy(
true);
1049 copy.coords.AddRange(this.coords);
1050 copy.faceUVs.AddRange(this.faceUVs);
1053 copy.faces.AddRange(this.faces);
1056 copy.vertexNormals.AddRange(this.vertexNormals);
1057 copy.faceNormal = this.faceNormal;
1058 copy.cutNormal1 = this.cutNormal1;
1059 copy.cutNormal2 = this.cutNormal2;
1060 copy.us.AddRange(this.us);
1061 copy.faceNumbers.AddRange(this.faceNumbers);
1063 copy.cut1CoordIndices =
new List<int>(this.cut1CoordIndices);
1064 copy.cut2CoordIndices =
new List<int>(this.cut2CoordIndices);
1065 copy.hollowCoordIndices =
new List<int>(this.hollowCoordIndices);
1066 copy.outerCoordIndices =
new List<int>(this.outerCoordIndices);
1068 copy.numOuterVerts = this.numOuterVerts;
1069 copy.numHollowVerts = this.numHollowVerts;
1076 this.AddPos(v.X, v.Y, v.Z);
1079 public void AddPos(
float x,
float y,
float z)
1082 int numVerts = this.coords.Count;
1085 for (i = 0; i < numVerts; i++)
1087 vert = this.coords[i];
1091 this.coords[i] = vert;
1098 int numVerts = this.coords.Count;
1100 for (i = 0; i < numVerts; i++)
1101 this.coords[i] *= q;
1103 if (this.calcVertexNormals)
1105 int numNormals = this.vertexNormals.Count;
1106 for (i = 0; i < numNormals; i++)
1107 this.vertexNormals[i] *= q;
1109 this.faceNormal *= q;
1110 this.cutNormal1 *= q;
1111 this.cutNormal2 *= q;
1119 int numVerts = this.coords.Count;
1122 for (i = 0; i < numVerts; i++)
1124 vert = this.coords[i];
1127 this.coords[i] = vert;
1137 int numFaces = this.faces.Count;
1141 for (i = 0; i < numFaces; i++)
1143 tmpFace = this.faces[i];
1145 tmpFace.v3 = tmpFace.v1;
1147 this.faces[i] = tmpFace;
1150 if (this.calcVertexNormals)
1152 int normalCount = this.vertexNormals.Count;
1153 if (normalCount > 0)
1155 Coord n = this.vertexNormals[normalCount - 1];
1157 this.vertexNormals[normalCount - 1] = n;
1161 this.faceNormal.X = -this.faceNormal.X;
1162 this.faceNormal.Y = -this.faceNormal.Y;
1163 this.faceNormal.Z = -this.faceNormal.Z;
1165 int numfaceUVs = this.faceUVs.Count;
1166 for (i = 0; i < numfaceUVs; i++)
1170 this.faceUVs[i] = uv;
1176 int numFaces = this.faces.Count;
1178 for (
int i = 0; i < numFaces; i++)
1180 tmpFace = this.faces[i];
1185 this.faces[i] = tmpFace;
1191 if (this.calcVertexNormals)
1193 int numFaces = this.faces.Count;
1195 for (
int i = 0; i < numFaces; i++)
1197 tmpFace = this.faces[i];
1202 this.faces[i] = tmpFace;
1207 public void DumpRaw(String path, String name, String title)
1211 String fileName = name +
"_" + title +
".raw";
1212 String completePath = System.IO.Path.Combine(path, fileName);
1213 StreamWriter sw =
new StreamWriter(completePath);
1215 for (
int i = 0; i < this.faces.Count; i++)
1217 string s = this.coords[this.faces[i].v1].ToString();
1218 s +=
" " + this.coords[this.faces[i].v2].ToString();
1219 s +=
" " + this.coords[this.faces[i].v3].ToString();
1241 public List<PathNode> pathNodes =
new List<PathNode>();
1243 public float twistBegin = 0.0f;
1244 public float twistEnd = 0.0f;
1245 public float topShearX = 0.0f;
1246 public float topShearY = 0.0f;
1247 public float pathCutBegin = 0.0f;
1248 public float pathCutEnd = 1.0f;
1249 public float dimpleBegin = 0.0f;
1250 public float dimpleEnd = 1.0f;
1251 public float skew = 0.0f;
1252 public float holeSizeX = 1.0f;
1253 public float holeSizeY = 0.25f;
1254 public float taperX = 0.0f;
1255 public float taperY = 0.0f;
1256 public float radius = 0.0f;
1257 public float revolutions = 1.0f;
1258 public int stepsPerRevolution = 24;
1260 private const float twoPi = 2.0f * (float)Math.PI;
1264 if (this.taperX > 0.999f)
1265 this.taperX = 0.999f;
1266 if (this.taperX < -0.999f)
1267 this.taperX = -0.999f;
1268 if (this.taperY > 0.999f)
1269 this.taperY = 0.999f;
1270 if (this.taperY < -0.999f)
1271 this.taperY = -0.999f;
1277 float length = this.pathCutEnd - this.pathCutBegin;
1278 float twistTotal = twistEnd - twistBegin;
1279 float twistTotalAbs = Math.Abs(twistTotal);
1280 if (twistTotalAbs > 0.01f)
1281 steps += (int)(twistTotalAbs * 3.66);
1283 float start = -0.5f;
1284 float stepSize = length / (float)steps;
1285 float percentOfPathMultiplier = stepSize * 0.999999f;
1286 float xOffset = this.topShearX * this.pathCutBegin;
1287 float yOffset = this.topShearY * this.pathCutBegin;
1288 float zOffset = start;
1289 float xOffsetStepIncrement = this.topShearX * length / steps;
1290 float yOffsetStepIncrement = this.topShearY * length / steps;
1292 float percentOfPath = this.pathCutBegin;
1293 zOffset += percentOfPath;
1303 newNode.xScale = 1.0f;
1304 if (this.taperX == 0.0f)
1305 newNode.xScale = 1.0f;
1306 else if (this.taperX > 0.0f)
1307 newNode.xScale = 1.0f - percentOfPath * this.taperX;
1308 else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX;
1310 newNode.yScale = 1.0f;
1311 if (this.taperY == 0.0f)
1312 newNode.yScale = 1.0f;
1313 else if (this.taperY > 0.0f)
1314 newNode.yScale = 1.0f - percentOfPath * this.taperY;
1315 else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY;
1317 float twist = twistBegin + twistTotal * percentOfPath;
1319 newNode.rotation =
new Quat(
new Coord(0.0f, 0.0f, 1.0f), twist);
1320 newNode.position =
new Coord(xOffset, yOffset, zOffset);
1321 newNode.percentOfPath = percentOfPath;
1323 pathNodes.Add(newNode);
1328 percentOfPath += percentOfPathMultiplier;
1329 xOffset += xOffsetStepIncrement;
1330 yOffset += yOffsetStepIncrement;
1331 zOffset += stepSize;
1332 if (percentOfPath > this.pathCutEnd)
1341 float twistTotal = twistEnd - twistBegin;
1346 float twistTotalAbs = Math.Abs(twistTotal);
1347 if (twistTotalAbs > 0.01f)
1349 if (twistTotalAbs > Math.PI * 1.5f)
1351 if (twistTotalAbs > Math.PI * 3.0f)
1355 float yPathScale = this.holeSizeY * 0.5f;
1356 float pathLength = this.pathCutEnd - this.pathCutBegin;
1357 float totalSkew = this.skew * 2.0f * pathLength;
1358 float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew;
1359 float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY));
1360 float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f;
1370 float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f;
1371 float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f;
1372 float stepSize = twoPi / this.stepsPerRevolution;
1374 int step = (int)(startAngle / stepSize);
1375 float angle = startAngle;
1382 float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX;
1383 float yProfileScale = this.holeSizeY;
1385 float percentOfPath = angle / (twoPi * this.revolutions);
1386 float percentOfAngles = (angle - startAngle) / (endAngle - startAngle);
1388 if (this.taperX > 0.01f)
1389 xProfileScale *= 1.0f - percentOfPath * this.taperX;
1390 else if (this.taperX < -0.01f)
1391 xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX;
1393 if (this.taperY > 0.01f)
1394 yProfileScale *= 1.0f - percentOfPath * this.taperY;
1395 else if (this.taperY < -0.01f)
1396 yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY;
1398 newNode.xScale = xProfileScale;
1399 newNode.yScale = yProfileScale;
1401 float radiusScale = 1.0f;
1402 if (this.radius > 0.001f)
1403 radiusScale = 1.0f - this.radius * percentOfPath;
1404 else if (this.radius < 0.001f)
1405 radiusScale = 1.0f + this.radius * (1.0f - percentOfPath);
1407 float twist = twistBegin + twistTotal * percentOfPath;
1409 float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
1410 xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
1412 float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
1414 float zOffset = (float)Math.Sin(angle +
this.topShearY) * (0.5f - yPathScale) * radiusScale;
1416 newNode.position =
new Coord(xOffset, yOffset, zOffset);
1421 newNode.rotation =
new Quat(
new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY);
1424 if (twistTotal != 0.0f || twistBegin != 0.0f)
1425 newNode.rotation *=
new Quat(
new Coord(0.0f, 0.0f, 1.0f), twist);
1427 newNode.percentOfPath = percentOfPath;
1429 pathNodes.Add(newNode);
1434 if (angle >= endAngle - 0.01)
1439 angle = stepSize * step;
1440 if (angle > endAngle)
1450 public string errorMessage =
"";
1451 private const float twoPi = 2.0f * (float)Math.PI;
1453 public List<Coord> coords;
1454 public List<Coord> normals;
1455 public List<Face> faces;
1457 public List<ViewerFace> viewerFaces;
1459 private int sides = 4;
1460 private int hollowSides = 4;
1461 private float profileStart = 0.0f;
1462 private float profileEnd = 1.0f;
1463 private float hollow = 0.0f;
1464 public int twistBegin = 0;
1465 public int twistEnd = 0;
1466 public float topShearX = 0.0f;
1467 public float topShearY = 0.0f;
1468 public float pathCutBegin = 0.0f;
1469 public float pathCutEnd = 1.0f;
1470 public float dimpleBegin = 0.0f;
1471 public float dimpleEnd = 1.0f;
1472 public float skew = 0.0f;
1473 public float holeSizeX = 1.0f;
1474 public float holeSizeY = 0.25f;
1475 public float taperX = 0.0f;
1476 public float taperY = 0.0f;
1477 public float radius = 0.0f;
1478 public float revolutions = 1.0f;
1479 public int stepsPerRevolution = 24;
1481 private int profileOuterFaceNumber = -1;
1482 private int profileHollowFaceNumber = -1;
1484 private bool hasProfileCut =
false;
1485 private bool hasHollow =
false;
1486 public bool calcVertexNormals =
false;
1487 private bool normalsProcessed =
false;
1488 public bool viewerMode =
false;
1489 public bool sphereMode =
false;
1491 public int numPrimFaces = 0;
1497 public string ParamsToDisplayString()
1500 s +=
"sides..................: " + this.sides.ToString();
1501 s +=
"\nhollowSides..........: " + this.hollowSides.ToString();
1502 s +=
"\nprofileStart.........: " + this.profileStart.ToString();
1503 s +=
"\nprofileEnd...........: " + this.profileEnd.ToString();
1504 s +=
"\nhollow...............: " + this.hollow.ToString();
1505 s +=
"\ntwistBegin...........: " + this.twistBegin.ToString();
1506 s +=
"\ntwistEnd.............: " + this.twistEnd.ToString();
1507 s +=
"\ntopShearX............: " + this.topShearX.ToString();
1508 s +=
"\ntopShearY............: " + this.topShearY.ToString();
1509 s +=
"\npathCutBegin.........: " + this.pathCutBegin.ToString();
1510 s +=
"\npathCutEnd...........: " + this.pathCutEnd.ToString();
1511 s +=
"\ndimpleBegin..........: " + this.dimpleBegin.ToString();
1512 s +=
"\ndimpleEnd............: " + this.dimpleEnd.ToString();
1513 s +=
"\nskew.................: " + this.skew.ToString();
1514 s +=
"\nholeSizeX............: " + this.holeSizeX.ToString();
1515 s +=
"\nholeSizeY............: " + this.holeSizeY.ToString();
1516 s +=
"\ntaperX...............: " + this.taperX.ToString();
1517 s +=
"\ntaperY...............: " + this.taperY.ToString();
1518 s +=
"\nradius...............: " + this.radius.ToString();
1519 s +=
"\nrevolutions..........: " + this.revolutions.ToString();
1520 s +=
"\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString();
1521 s +=
"\nsphereMode...........: " + this.sphereMode.ToString();
1522 s +=
"\nhasProfileCut........: " + this.hasProfileCut.ToString();
1523 s +=
"\nhasHollow............: " + this.hasHollow.ToString();
1524 s +=
"\nviewerMode...........: " + this.viewerMode.ToString();
1529 public int ProfileOuterFaceNumber
1531 get {
return profileOuterFaceNumber; }
1534 public int ProfileHollowFaceNumber
1536 get {
return profileHollowFaceNumber; }
1539 public bool HasProfileCut
1541 get {
return hasProfileCut; }
1544 public bool HasHollow
1546 get {
return hasHollow; }
1558 public PrimMesh(
int sides,
float profileStart,
float profileEnd,
float hollow,
int hollowSides)
1560 this.coords =
new List<Coord>();
1561 this.faces =
new List<Face>();
1564 this.profileStart = profileStart;
1565 this.profileEnd = profileEnd;
1566 this.hollow = hollow;
1567 this.hollowSides = hollowSides;
1571 if (hollowSides < 3)
1572 this.hollowSides = 3;
1573 if (profileStart < 0.0f)
1574 this.profileStart = 0.0f;
1575 if (profileEnd > 1.0f)
1576 this.profileEnd = 1.0f;
1577 if (profileEnd < 0.02f)
1578 this.profileEnd = 0.02f;
1579 if (profileStart >= profileEnd)
1580 this.profileStart = profileEnd - 0.02f;
1582 this.hollow = 0.99f;
1592 bool needEndFaces =
false;
1594 this.coords =
new List<Coord>();
1595 this.faces =
new List<Face>();
1597 if (this.viewerMode)
1599 this.viewerFaces =
new List<ViewerFace>();
1600 this.calcVertexNormals =
true;
1603 if (this.calcVertexNormals)
1604 this.normals =
new List<Coord>();
1608 float length = this.pathCutEnd - this.pathCutBegin;
1609 normalsProcessed =
false;
1611 if (this.viewerMode && this.sides == 3)
1615 if (Math.Abs(
this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01)
1616 steps = (int)(steps * 4.5 * length);
1619 if (this.sphereMode)
1620 this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f;
1622 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1623 this.hasHollow = (this.hollow > 0.001f);
1625 float twistBegin = this.twistBegin / 360.0f * twoPi;
1626 float twistEnd = this.twistEnd / 360.0f * twoPi;
1627 float twistTotal = twistEnd - twistBegin;
1628 float twistTotalAbs = Math.Abs(twistTotal);
1629 if (twistTotalAbs > 0.01f)
1630 steps += (int)(twistTotalAbs * 3.66);
1632 float hollow = this.hollow;
1636 needEndFaces =
false;
1637 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
1638 needEndFaces =
true;
1639 else if (this.taperX != 0.0f || this.taperY != 0.0f)
1640 needEndFaces =
true;
1641 else if (this.skew != 0.0f)
1642 needEndFaces =
true;
1643 else if (twistTotal != 0.0f)
1644 needEndFaces =
true;
1645 else if (this.radius != 0.0f)
1646 needEndFaces =
true;
1648 else needEndFaces =
true;
1651 float initialProfileRot = 0.0f;
1654 if (this.sides == 3)
1656 initialProfileRot = (float)Math.PI;
1657 if (this.hollowSides == 4)
1663 else hollow *= 0.5f;
1665 else if (this.sides == 4)
1667 initialProfileRot = 0.25f * (float)Math.PI;
1668 if (this.hollowSides != 4)
1671 else if (this.sides > 4)
1673 initialProfileRot = (float)Math.PI;
1674 if (this.hollowSides == 4)
1684 if (this.sides == 3)
1686 if (this.hollowSides == 4)
1692 else hollow *= 0.5f;
1694 else if (this.sides == 4)
1696 initialProfileRot = 1.25f * (float)Math.PI;
1697 if (this.hollowSides != 4)
1700 else if (this.sides == 24 && this.hollowSides == 4)
1704 Profile profile =
new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides,
true, calcVertexNormals);
1705 this.errorMessage = profile.errorMessage;
1707 this.numPrimFaces = profile.numPrimFaces;
1709 int cut1FaceNumber = profile.bottomFaceNumber + 1;
1710 int cut2FaceNumber = cut1FaceNumber + 1;
1713 cut1FaceNumber -= 2;
1714 cut2FaceNumber -= 2;
1717 profileOuterFaceNumber = profile.outerFaceNumber;
1719 profileOuterFaceNumber--;
1723 profileHollowFaceNumber = profile.hollowFaceNumber;
1725 profileHollowFaceNumber--;
1732 cut1Vert = hasHollow ? profile.coords.Count - 1 : 0;
1733 cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
1736 if (initialProfileRot != 0.0f)
1738 profile.AddRot(
new Quat(
new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
1740 profile.MakeFaceUVs();
1749 path.twistBegin = twistBegin;
1750 path.twistEnd = twistEnd;
1751 path.topShearX = topShearX;
1752 path.topShearY = topShearY;
1753 path.pathCutBegin = pathCutBegin;
1754 path.pathCutEnd = pathCutEnd;
1755 path.dimpleBegin = dimpleBegin;
1756 path.dimpleEnd = dimpleEnd;
1758 path.holeSizeX = holeSizeX;
1759 path.holeSizeY = holeSizeY;
1760 path.taperX = taperX;
1761 path.taperY = taperY;
1762 path.radius = radius;
1763 path.revolutions = revolutions;
1764 path.stepsPerRevolution = stepsPerRevolution;
1766 path.Create(pathType, steps);
1768 for (
int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1770 PathNode node = path.pathNodes[nodeIndex];
1771 Profile newLayer = profile.Copy();
1772 newLayer.Scale(node.xScale, node.yScale);
1775 newLayer.AddPos(node.position);
1777 if (needEndFaces && nodeIndex == 0)
1779 newLayer.FlipNormals();
1782 if (this.viewerMode)
1784 Coord faceNormal = newLayer.faceNormal;
1786 int numFaces = newLayer.faces.Count;
1787 List<Face> faces = newLayer.faces;
1789 for (
int i = 0; i < numFaces; i++)
1791 Face face = faces[i];
1792 newViewerFace.v1 = newLayer.coords[face.v1];
1793 newViewerFace.v2 = newLayer.coords[face.v2];
1794 newViewerFace.v3 = newLayer.coords[face.v3];
1796 newViewerFace.coordIndex1 = face.v1;
1797 newViewerFace.coordIndex2 = face.v2;
1798 newViewerFace.coordIndex3 = face.v3;
1800 newViewerFace.n1 = faceNormal;
1801 newViewerFace.n2 = faceNormal;
1802 newViewerFace.n3 = faceNormal;
1804 newViewerFace.uv1 = newLayer.faceUVs[face.v1];
1805 newViewerFace.uv2 = newLayer.faceUVs[face.v2];
1806 newViewerFace.uv3 = newLayer.faceUVs[face.v3];
1810 newViewerFace.uv1.Flip();
1811 newViewerFace.uv2.Flip();
1812 newViewerFace.uv3.Flip();
1815 this.viewerFaces.Add(newViewerFace);
1822 int coordsLen = this.coords.Count;
1823 newLayer.AddValue2FaceVertexIndices(coordsLen);
1825 this.coords.AddRange(newLayer.coords);
1827 if (this.calcVertexNormals)
1829 newLayer.AddValue2FaceNormalIndices(this.normals.Count);
1830 this.normals.AddRange(newLayer.vertexNormals);
1834 this.faces.AddRange(newLayer.faces);
1838 int numVerts = newLayer.coords.Count;
1842 thisV = 1.0f - node.percentOfPath;
1846 int startVert = coordsLen + 1;
1847 int endVert = this.coords.Count;
1849 if (sides < 5 || this.hasProfileCut || this.hasHollow)
1852 for (
int i = startVert; i < endVert; i++)
1855 if (i == endVert - 1)
1858 int whichVert = i - startVert;
1861 newFace1.v2 = i - numVerts;
1862 newFace1.v3 = iNext;
1864 newFace1.n1 = newFace1.v1;
1865 newFace1.n2 = newFace1.v2;
1866 newFace1.n3 = newFace1.v3;
1867 this.faces.Add(newFace1);
1869 newFace2.v1 = iNext;
1870 newFace2.v2 = i - numVerts;
1871 newFace2.v3 = iNext - numVerts;
1873 newFace2.n1 = newFace2.v1;
1874 newFace2.n2 = newFace2.v2;
1875 newFace2.n3 = newFace2.v3;
1876 this.faces.Add(newFace2);
1878 if (this.viewerMode)
1882 int primFaceNum = profile.faceNumbers[whichVert];
1889 int uIndex = whichVert;
1890 if (!hasHollow && sides > 4 && uIndex < newLayer.
us.Count - 1)
1895 float u1 = newLayer.us[uIndex];
1897 if (uIndex < (
int)newLayer.
us.Count - 1)
1898 u2 = newLayer.us[uIndex + 1];
1900 if (whichVert == cut1Vert || whichVert == cut2Vert)
1919 if (this.sphereMode)
1921 if (whichVert != cut1Vert && whichVert != cut2Vert)
1923 u1 = u1 * 2.0f - 1.0f;
1924 u2 = u2 * 2.0f - 1.0f;
1935 newViewerFace1.uv1.U = u1;
1936 newViewerFace1.uv2.U = u1;
1937 newViewerFace1.uv3.U = u2;
1939 newViewerFace1.uv1.V = thisV;
1940 newViewerFace1.uv2.V = lastV;
1941 newViewerFace1.uv3.V = thisV;
1943 newViewerFace2.uv1.U = u2;
1944 newViewerFace2.uv2.U = u1;
1945 newViewerFace2.uv3.U = u2;
1947 newViewerFace2.uv1.V = thisV;
1948 newViewerFace2.uv2.V = lastV;
1949 newViewerFace2.uv3.V = lastV;
1951 newViewerFace1.v1 = this.coords[newFace1.v1];
1952 newViewerFace1.v2 = this.coords[newFace1.v2];
1953 newViewerFace1.v3 = this.coords[newFace1.v3];
1955 newViewerFace2.v1 = this.coords[newFace2.v1];
1956 newViewerFace2.v2 = this.coords[newFace2.v2];
1957 newViewerFace2.v3 = this.coords[newFace2.v3];
1959 newViewerFace1.coordIndex1 = newFace1.v1;
1960 newViewerFace1.coordIndex2 = newFace1.v2;
1961 newViewerFace1.coordIndex3 = newFace1.v3;
1963 newViewerFace2.coordIndex1 = newFace2.v1;
1964 newViewerFace2.coordIndex2 = newFace2.v2;
1965 newViewerFace2.coordIndex3 = newFace2.v3;
1968 if (whichVert == cut1Vert)
1970 newViewerFace1.primFaceNumber = cut1FaceNumber;
1971 newViewerFace2.primFaceNumber = cut1FaceNumber;
1972 newViewerFace1.n1 = newLayer.cutNormal1;
1973 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
1975 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1;
1976 newViewerFace2.n2 = lastCutNormal1;
1978 else if (whichVert == cut2Vert)
1980 newViewerFace1.primFaceNumber = cut2FaceNumber;
1981 newViewerFace2.primFaceNumber = cut2FaceNumber;
1982 newViewerFace1.n1 = newLayer.cutNormal2;
1983 newViewerFace1.n2 = lastCutNormal2;
1984 newViewerFace1.n3 = lastCutNormal2;
1986 newViewerFace2.n1 = newLayer.cutNormal2;
1987 newViewerFace2.n3 = newLayer.cutNormal2;
1988 newViewerFace2.n2 = lastCutNormal2;
1993 if ((sides < 5 && whichVert < newLayer.
numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts))
1995 newViewerFace1.CalcSurfaceNormal();
1996 newViewerFace2.CalcSurfaceNormal();
2000 newViewerFace1.n1 = this.normals[newFace1.n1];
2001 newViewerFace1.n2 = this.normals[newFace1.n2];
2002 newViewerFace1.n3 = this.normals[newFace1.n3];
2004 newViewerFace2.n1 = this.normals[newFace2.n1];
2005 newViewerFace2.n2 = this.normals[newFace2.n2];
2006 newViewerFace2.n3 = this.normals[newFace2.n3];
2010 this.viewerFaces.Add(newViewerFace1);
2011 this.viewerFaces.Add(newViewerFace2);
2017 lastCutNormal1 = newLayer.cutNormal1;
2018 lastCutNormal2 = newLayer.cutNormal2;
2021 if (needEndFaces && nodeIndex == path.
pathNodes.Count - 1 && viewerMode)
2024 Coord faceNormal = newLayer.faceNormal;
2026 int numFaces = newLayer.faces.Count;
2027 List<Face> faces = newLayer.faces;
2029 for (
int i = 0; i < numFaces; i++)
2031 Face face = faces[i];
2032 newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen];
2033 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen];
2034 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen];
2036 newViewerFace.coordIndex1 = face.v1 - coordsLen;
2037 newViewerFace.coordIndex2 = face.v2 - coordsLen;
2038 newViewerFace.coordIndex3 = face.v3 - coordsLen;
2040 newViewerFace.n1 = faceNormal;
2041 newViewerFace.n2 = faceNormal;
2042 newViewerFace.n3 = faceNormal;
2044 newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen];
2045 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen];
2046 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen];
2050 newViewerFace.uv1.Flip();
2051 newViewerFace.uv2.Flip();
2052 newViewerFace.uv3.Flip();
2055 this.viewerFaces.Add(newViewerFace);
2072 this.Extrude(PathType.Linear);
2083 this.Extrude(PathType.Circular);
2092 Coord normal = Coord.Cross(edge1, edge2);
2099 private Coord SurfaceNormal(Face face)
2101 return SurfaceNormal(this.coords[face.v1],
this.coords[face.v2],
this.coords[face.v3]);
2111 int numFaces = this.faces.Count;
2112 if (faceIndex < 0 || faceIndex >= numFaces)
2113 throw new Exception(
"faceIndex out of range");
2115 return SurfaceNormal(this.faces[faceIndex]);
2124 PrimMesh copy =
new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides);
2125 copy.twistBegin = this.twistBegin;
2126 copy.twistEnd = this.twistEnd;
2127 copy.topShearX = this.topShearX;
2128 copy.topShearY = this.topShearY;
2129 copy.pathCutBegin = this.pathCutBegin;
2130 copy.pathCutEnd = this.pathCutEnd;
2131 copy.dimpleBegin = this.dimpleBegin;
2132 copy.dimpleEnd = this.dimpleEnd;
2133 copy.skew = this.skew;
2134 copy.holeSizeX = this.holeSizeX;
2135 copy.holeSizeY = this.holeSizeY;
2136 copy.taperX = this.taperX;
2137 copy.taperY = this.taperY;
2138 copy.radius = this.radius;
2139 copy.revolutions = this.revolutions;
2140 copy.stepsPerRevolution = this.stepsPerRevolution;
2141 copy.calcVertexNormals = this.calcVertexNormals;
2142 copy.normalsProcessed = this.normalsProcessed;
2143 copy.viewerMode = this.viewerMode;
2144 copy.numPrimFaces = this.numPrimFaces;
2145 copy.errorMessage = this.errorMessage;
2147 copy.coords =
new List<Coord>(this.coords);
2148 copy.faces =
new List<Face>(this.faces);
2149 copy.viewerFaces =
new List<ViewerFace>(this.viewerFaces);
2150 copy.normals =
new List<Coord>(this.normals);
2160 if (normalsProcessed)
2163 normalsProcessed =
true;
2165 int numFaces = faces.Count;
2167 if (!this.calcVertexNormals)
2168 this.normals =
new List<Coord>();
2170 for (
int i = 0; i < numFaces; i++)
2172 Face face = faces[i];
2174 this.normals.Add(SurfaceNormal(i).Normalize());
2176 int normIndex = normals.Count - 1;
2177 face.n1 = normIndex;
2178 face.n2 = normIndex;
2179 face.n3 = normIndex;
2181 this.faces[i] = face;
2191 public void AddPos(
float x,
float y,
float z)
2194 int numVerts = this.coords.Count;
2197 for (i = 0; i < numVerts; i++)
2199 vert = this.coords[i];
2203 this.coords[i] = vert;
2206 if (this.viewerFaces != null)
2208 int numViewerFaces = this.viewerFaces.Count;
2210 for (i = 0; i < numViewerFaces; i++)
2214 this.viewerFaces[i] = v;
2226 int numVerts = this.coords.Count;
2228 for (i = 0; i < numVerts; i++)
2229 this.coords[i] *= q;
2231 if (this.normals != null)
2233 int numNormals = this.normals.Count;
2234 for (i = 0; i < numNormals; i++)
2235 this.normals[i] *= q;
2238 if (this.viewerFaces != null)
2240 int numViewerFaces = this.viewerFaces.Count;
2242 for (i = 0; i < numViewerFaces; i++)
2252 this.viewerFaces[i] = v;
2258 public VertexIndexer GetVertexIndexer()
2260 if (this.viewerMode && this.viewerFaces.Count > 0)
2261 return new VertexIndexer(
this);
2272 public void Scale(
float x,
float y,
float z)
2275 int numVerts = this.coords.Count;
2279 for (i = 0; i < numVerts; i++)
2280 this.coords[i] *= m;
2282 if (this.viewerFaces != null)
2284 int numViewerFaces = this.viewerFaces.Count;
2285 for (i = 0; i < numViewerFaces; i++)
2291 this.viewerFaces[i] = v;
2304 public void DumpRaw(String path, String name, String title)
2308 String fileName = name +
"_" + title +
".raw";
2309 String completePath = System.IO.Path.Combine(path, fileName);
2310 StreamWriter sw =
new StreamWriter(completePath);
2312 for (
int i = 0; i < this.faces.Count; i++)
2314 string s = this.coords[this.faces[i].v1].ToString();
2315 s +=
" " + this.coords[this.faces[i].v2].ToString();
2316 s +=
" " + this.coords[this.faces[i].v3].ToString();
override string ToString()
void AddValue2FaceVertexIndices(int num)
Quat(float x, float y, float z, float w)
void CalcNormals()
Calculate surface normals for all of the faces in the list of faces in this mesh
void DumpRaw(String path, String name, String title)
Dumps the mesh to a Blender compatible "Raw" format file
static Coord Cross(Coord c1, Coord c2)
override string ToString()
UVCoord(float u, float v)
void ExtrudeLinear()
DEPRICATED - use Extrude(PathType.Linear) instead Extrudes a profile along a straight line path...
Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals)
static Coord operator*(Coord v, Coord m)
void AddPos(float x, float y, float z)
generates a profile for extrusion
Profile Copy(bool needFaces)
void AddPos(float x, float y, float z)
Adds a value to each XYZ vertex coordinate in the mesh
PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides)
Constructs a PrimMesh object and creates the profile for extrusion.
void FlipNormals()
Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex norma...
void Scale(float x, float y, float z)
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
Coord SurfaceNormal(int faceIndex)
Calculate the surface normal for a face in the list of faces
Face(int v1, int v2, int v3)
void DumpRaw(String path, String name, String title)
void AddValue2FaceNormalIndices(int num)
void Scale(float x, float y)
Face(int v1, int v2, int v3, int n1, int n2, int n3)
Coord SurfaceNormal(List< Coord > coordList)
List< PathNode > pathNodes
Quat(Coord axis, float angle)
void Scale(float x, float y, float z)
Scales the mesh
Coord(float x, float y, float z)
void ExtrudeCircular()
DEPRICATED - use Extrude(PathType.Circular) instead Extrude a profile into a circular path prim mesh...
static Quat operator*(Quat q1, Quat q2)
void AddRot(Quat q)
Rotates the mesh
PrimMesh Copy()
Duplicates a PrimMesh object. All object properties are copied by value, including lists...
void Extrude(PathType pathType)
Extrudes a profile along a path.
ViewerFace(int primFaceNumber)
static Coord operator+(Coord v, Coord a)
void AddPos(float x, float y, float z)