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
181 return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z);
186 return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z);
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 -
248 Coord c1 = coordList[this.v1];
249 Coord c2 = coordList[this.v2];
250 Coord c3 = coordList[this.v3];
252 Coord edge1 =
new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
253 Coord edge2 =
new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
255 return Coord.Cross(edge1, edge2).Normalize();
259 internal struct Angle
261 internal float angle;
265 internal Angle(
float angle,
float x,
float y)
273 internal class AngleList
275 private float iX, iY;
277 private static Angle[] angles3 =
279 new Angle(0.0f, 1.0f, 0.0f),
280 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
281 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
282 new Angle(1.0f, 1.0f, 0.0f)
285 private static Angle[] angles4 =
287 new Angle(0.0f, 1.0f, 0.0f),
288 new Angle(0.25f, 0.0f, 1.0f),
289 new Angle(0.5f, -1.0f, 0.0f),
290 new Angle(0.75f, 0.0f, -1.0f),
291 new Angle(1.0f, 1.0f, 0.0f)
294 private static Angle[] angles6 =
296 new Angle(0.0f, 1.0f, 0.0f),
297 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
298 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
299 new Angle(0.5f, -1.0f, 0.0f),
300 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
301 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
302 new Angle(1.0f, 1.0f, 0.0f)
305 private static Angle[] angles12 =
307 new Angle(0.0f, 1.0f, 0.0f),
308 new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
309 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
310 new Angle(0.25f, 0.0f, 1.0f),
311 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
312 new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
313 new Angle(0.5f, -1.0f, 0.0f),
314 new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
315 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
316 new Angle(0.75f, 0.0f, -1.0f),
317 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
318 new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
319 new Angle(1.0f, 1.0f, 0.0f)
322 private static Angle[] angles24 =
324 new Angle(0.0f, 1.0f, 0.0f),
325 new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f),
326 new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
327 new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f),
328 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
329 new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f),
330 new Angle(0.25f, 0.0f, 1.0f),
331 new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f),
332 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
333 new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f),
334 new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
335 new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f),
336 new Angle(0.5f, -1.0f, 0.0f),
337 new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f),
338 new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
339 new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f),
340 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
341 new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f),
342 new Angle(0.75f, 0.0f, -1.0f),
343 new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f),
344 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
345 new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f),
346 new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
347 new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f),
348 new Angle(1.0f, 1.0f, 0.0f)
351 private Angle interpolatePoints(
float newPoint, Angle p1, Angle p2)
353 float m = (newPoint - p1.angle) / (p2.angle - p1.angle);
354 return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y));
357 private void intersection(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
double x4,
double y4)
359 double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
360 double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
364 double ua = uaNumerator / denom;
365 iX = (float)(x1 + ua * (x2 - x1));
366 iY = (float)(y1 + ua * (y2 - y1));
370 internal List<Angle> angles;
372 internal void makeAngles(
int sides,
float startAngle,
float stopAngle,
bool hasCut)
374 angles =
new List<Angle>();
376 const double twoPi = System.Math.PI * 2.0;
377 const float twoPiInv = (float)(1.0d / twoPi);
380 throw new Exception(
"number of sides not greater than zero");
381 if (stopAngle <= startAngle)
382 throw new Exception(
"stopAngle not greater than startAngle");
384 if ((sides == 3 || sides == 4 || sides == 6 || sides == 12 || sides == 24))
386 startAngle *= twoPiInv;
387 stopAngle *= twoPiInv;
389 Angle[] sourceAngles;
393 sourceAngles = angles3;
396 sourceAngles = angles4;
399 sourceAngles = angles6;
402 sourceAngles = angles12;
405 sourceAngles = angles24;
409 int startAngleIndex = (int)(startAngle * sides);
410 int endAngleIndex = sourceAngles.Length - 1;
414 if (stopAngle < 1.0f)
415 endAngleIndex = (int)(stopAngle * sides) + 1;
416 if (endAngleIndex == startAngleIndex)
419 for (
int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++)
421 angles.Add(sourceAngles[angleIndex]);
424 if (startAngle > 0.0f)
425 angles[0] = interpolatePoints(startAngle, angles[0], angles[1]);
427 if (stopAngle < 1.0f)
429 int lastAngleIndex = angles.Count - 1;
430 angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]);
435 for (
int angleIndex = startAngleIndex; angleIndex < endAngleIndex; angleIndex++)
436 angles.Add(sourceAngles[angleIndex]);
441 double stepSize = twoPi / sides;
443 int startStep = (int)(startAngle / stepSize);
444 double angle = stepSize * startStep;
445 int step = startStep;
446 double stopAngleTest = stopAngle;
447 if (stopAngle < twoPi)
449 stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1);
450 if (stopAngleTest < stopAngle)
451 stopAngleTest += stepSize;
452 if (stopAngleTest > twoPi)
453 stopAngleTest = twoPi;
456 while (angle <= stopAngleTest)
459 newAngle.angle = (float)angle;
460 newAngle.X = (float)System.Math.Cos(angle);
461 newAngle.Y = (float)System.Math.Sin(angle);
462 angles.Add(newAngle);
464 angle = stepSize * step;
467 if (startAngle > angles[0].angle)
470 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));
471 newAngle.angle = startAngle;
474 angles[0] = newAngle;
477 int index = angles.Count - 1;
478 if (stopAngle < angles[index].angle)
481 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));
482 newAngle.angle = stopAngle;
485 angles[index] = newAngle;
496 private const float twoPi = 2.0f * (float)Math.PI;
500 public List<Coord>
coords;
501 public List<Face>
faces;
518 coords =
new List<Coord>();
519 faces =
new List<Face>();
522 public Profile(
int sides,
float profileStart,
float profileEnd,
float hollow,
int hollowSides,
bool hasProfileCut,
bool createFaces)
524 const float halfSqr2 = 0.7071067811866f;
526 coords =
new List<Coord>();
527 faces =
new List<Face>();
529 List<Coord> hollowCoords =
new List<Coord>();
531 bool hasHollow = (hollow > 0.0f);
533 AngleList angles =
new AngleList();
534 AngleList hollowAngles =
new AngleList();
544 float startAngle = profileStart * twoPi;
545 float stopAngle = profileEnd * twoPi;
547 try { angles.makeAngles(sides, startAngle, stopAngle,hasProfileCut); }
551 errorMessage =
"makeAngles failed: Exception: " + ex.ToString()
552 +
"\nsides: " + sides.ToString() +
" startAngle: " + startAngle.ToString() +
" stopAngle: " + stopAngle.ToString();
563 bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);
567 if (sides == hollowSides)
568 hollowAngles = angles;
571 try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle, hasProfileCut); }
574 errorMessage =
"makeAngles failed: Exception: " + ex.ToString()
575 +
"\nsides: " + sides.ToString() +
" startAngle: " + startAngle.ToString() +
" stopAngle: " + stopAngle.ToString();
580 int numHollowAngles = hollowAngles.angles.Count;
581 for (
int i = 0; i < numHollowAngles; i++)
583 angle = hollowAngles.angles[i];
584 newVert.X = hollow * xScale * angle.X;
585 newVert.Y = hollow * yScale * angle.Y;
588 hollowCoords.Add(newVert);
593 else if (!simpleFace)
596 this.coords.Add(center);
599 int numAngles = angles.angles.Count;
600 bool hollowsame = (hasHollow && hollowSides == sides);
602 for (
int i = 0; i < numAngles; i++)
604 angle = angles.angles[i];
605 newVert.X = angle.X * xScale;
606 newVert.Y = angle.Y * yScale;
613 hollowCoords.Add(newVert);
619 hollowCoords.Reverse();
620 coords.AddRange(hollowCoords);
630 for (
int coordIndex = 0; coordIndex <
numOuterVerts - 1; coordIndex++)
632 newFace.v1 = coordIndex;
633 newFace.v2 = coordIndex + 1;
634 newFace.v3 = numTotalVerts - coordIndex - 1;
637 newFace.v1 = coordIndex + 1;
638 newFace.v2 = numTotalVerts - coordIndex - 2;
639 newFace.v3 = numTotalVerts - coordIndex - 1;
644 newFace.v1 = numOuterVerts - 1;
650 newFace.v2 = numTotalVerts - 1;
661 float curHollowAngle = 0;
664 curHollowAngle = hollowAngles.angles[i].angle;
667 if (angles.angles[j + 1].angle - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f)
669 newFace.v1 = numTotalVerts - i - 1;
678 if (1.0f - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f)
683 newFace.v2 = numTotalVerts - i - 2;
684 newFace.v3 = numTotalVerts - i - 1;
691 if (i == numHollowVerts)
701 if (1.0f - curHollowAngle < curHollowAngle - angles.angles[maxJ].angle + 0.000001f)
703 newFace.v1 = numTotalVerts - i - 1;
710 for (; i < numHollowVerts - 1; i++)
713 newFace.v2 = numTotalVerts - i - 2;
714 newFace.v3 = numTotalVerts - i - 1;
722 newFace.v3 = numTotalVerts - 1;
730 int maxJ = numHollowVerts - 1;
734 if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f)
737 newFace.v2 = numTotalVerts - j - 2;
738 newFace.v3 = numTotalVerts - j - 1;
744 newFace.v1 = numTotalVerts - j - 1;
753 int i = numOuterVerts - 1;
755 if (hollowAngles.angles[0].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[maxJ].angle + 0.000001f)
758 newFace.v2 = numTotalVerts - maxJ - 1;
759 newFace.v3 = numTotalVerts - 1;
764 newFace.v1 = numTotalVerts - maxJ - 1;
775 else if (createFaces)
780 faces.Add(
new Face(0, 1, 2));
783 faces.Add(
new Face(0, 1, 2));
784 faces.Add(
new Face(0, 2, 3));
789 for (
int i = 1; i < numAngles ; i++)
801 newFace.v2 = numAngles;
822 copy.coords.AddRange(
coords);
825 copy.faces.AddRange(
faces);
835 this.AddPos(v.X, v.Y, v.Z);
838 public void AddPos(
float x,
float y,
float z)
841 int numVerts = coords.Count;
844 for (i = 0; i < numVerts; i++)
850 this.coords[i] = vert;
857 int numVerts = coords.Count;
859 for (i = 0; i < numVerts; i++)
866 int numVerts = coords.Count;
869 for (i = 0; i < numVerts; i++)
873 vert.X = (float)Math.Round(vert.X,5);
875 vert.Y = (float)Math.Round(vert.Y,5);
879 if(x == 0f || y == 0f)
880 faces =
new List<Face>();
888 int numFaces = faces.Count;
896 for (i = 0; i < numFaces; i++)
900 tmpFace.v3 = tmpFace.v1;
908 int numFaces = faces.Count;
914 for (
int i = 0; i < numFaces; i++)
925 public void DumpRaw(String path, String name, String title)
929 String fileName = name +
"_" + title +
".raw";
930 String completePath = System.IO.Path.Combine(path, fileName);
931 StreamWriter sw =
new StreamWriter(completePath);
933 for (
int i = 0; i < faces.Count; i++)
946 public struct PathNode
959 public List<PathNode>
pathNodes =
new List<PathNode>();
969 public float skew = 0.0f;
972 public float taperX = 0.0f;
973 public float taperY = 0.0f;
974 public float radius = 0.0f;
978 private const float twoPi = 2.0f * (float)Math.PI;
984 else if (
taperX < -.9999f)
988 else if (
taperY < -.9999f)
997 float twistTotalAbs = Math.Abs(twistTotal);
998 if (twistTotalAbs > 0.01f)
999 steps += (int)(twistTotalAbs * 3.66);
1001 float start = -0.5f;
1002 float stepSize = length / (float)steps;
1003 float percentOfPathMultiplier = stepSize * 0.999999f;
1006 float zOffset = start;
1007 float xOffsetStepIncrement =
topShearX * length / steps;
1008 float yOffsetStepIncrement =
topShearY * length / steps;
1011 zOffset += percentOfPath;
1021 newNode.xScale = 1.0f;
1023 newNode.xScale -= percentOfPath *
taperX;
1024 else if(taperX < 0.0f)
1025 newNode.xScale += (1.0f - percentOfPath) * taperX;
1027 newNode.yScale = 1.0f;
1029 newNode.yScale -= percentOfPath *
taperY;
1030 else if(taperY < 0.0f)
1031 newNode.yScale += (1.0f - percentOfPath) * taperY;
1033 float twist = twistBegin + twistTotal * percentOfPath;
1035 newNode.rotation =
new Quat(
new Coord(0.0f, 0.0f, 1.0f), twist);
1036 newNode.position =
new Coord(xOffset, yOffset, zOffset);
1037 newNode.percentOfPath = percentOfPath;
1039 pathNodes.Add(newNode);
1044 percentOfPath += percentOfPathMultiplier;
1045 xOffset += xOffsetStepIncrement;
1046 yOffset += yOffsetStepIncrement;
1047 zOffset += stepSize;
1062 float twistTotalAbs = Math.Abs(twistTotal);
1063 if (twistTotalAbs > 0.01f)
1065 if (twistTotalAbs > Math.PI * 1.5f)
1067 if (twistTotalAbs > Math.PI * 3.0f)
1073 float totalSkew =
skew * 2.0f * pathLength;
1074 float skewStart = pathCutBegin * 2.0f *
skew -
skew;
1076 float yShearCompensation = 1.0f + Math.Abs(
topShearY) * 0.25f;
1090 int step = (int)(startAngle / stepSize);
1091 float angle = startAngle;
1101 float percentOfPath = angle / (twoPi *
revolutions);
1102 float percentOfAngles = (angle - startAngle) / (endAngle - startAngle);
1105 xProfileScale *= 1.0f - percentOfPath *
taperX;
1106 else if (taperX < -0.01f)
1107 xProfileScale *= 1.0f + (1.0f - percentOfPath) * taperX;
1110 yProfileScale *= 1.0f - percentOfPath *
taperY;
1111 else if (taperY < -0.01f)
1112 yProfileScale *= 1.0f + (1.0f - percentOfPath) * taperY;
1114 newNode.xScale = xProfileScale;
1115 newNode.yScale = yProfileScale;
1117 float radiusScale = 1.0f;
1119 radiusScale = 1.0f -
radius * percentOfPath;
1120 else if (
radius < 0.001f)
1121 radiusScale = 1.0f +
radius * (1.0f - percentOfPath);
1123 float twist = twistBegin + twistTotal * percentOfPath;
1125 float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
1126 xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
1128 float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
1130 float zOffset = (float)Math.Sin(angle +
topShearY) * (0.5f - yPathScale) * radiusScale;
1132 newNode.position =
new Coord(xOffset, yOffset, zOffset);
1140 if (twistTotal != 0.0f || twistBegin != 0.0f)
1141 newNode.rotation *=
new Quat(
new Coord(0.0f, 0.0f, 1.0f), twist);
1143 newNode.percentOfPath = percentOfPath;
1145 pathNodes.Add(newNode);
1150 if (angle >= endAngle - 0.01)
1155 angle = stepSize * step;
1156 if (angle > endAngle)
1164 public class PrimMesh
1167 private const float twoPi = 2.0f * (float)Math.PI;
1169 public List<Coord>
coords;
1171 public List<Face>
faces;
1173 private int sides = 4;
1174 private int hollowSides = 4;
1175 private float profileStart = 0.0f;
1176 private float profileEnd = 1.0f;
1177 private float hollow = 0.0f;
1186 public float skew = 0.0f;
1189 public float taperX = 0.0f;
1190 public float taperY = 0.0f;
1191 public float radius = 0.0f;
1195 private bool hasProfileCut =
false;
1196 private bool hasHollow =
false;
1207 s +=
"sides..................: " + this.sides.ToString();
1208 s +=
"\nhollowSides..........: " + this.hollowSides.ToString();
1209 s +=
"\nprofileStart.........: " + this.profileStart.ToString();
1210 s +=
"\nprofileEnd...........: " + this.profileEnd.ToString();
1211 s +=
"\nhollow...............: " + this.hollow.ToString();
1212 s +=
"\ntwistBegin...........: " + this.twistBegin.ToString();
1213 s +=
"\ntwistEnd.............: " + this.twistEnd.ToString();
1214 s +=
"\ntopShearX............: " + this.topShearX.ToString();
1215 s +=
"\ntopShearY............: " + this.topShearY.ToString();
1216 s +=
"\npathCutBegin.........: " + this.pathCutBegin.ToString();
1217 s +=
"\npathCutEnd...........: " + this.pathCutEnd.ToString();
1218 s +=
"\ndimpleBegin..........: " + this.dimpleBegin.ToString();
1219 s +=
"\ndimpleEnd............: " + this.dimpleEnd.ToString();
1220 s +=
"\nskew.................: " + this.skew.ToString();
1221 s +=
"\nholeSizeX............: " + this.holeSizeX.ToString();
1222 s +=
"\nholeSizeY............: " + this.holeSizeY.ToString();
1223 s +=
"\ntaperX...............: " + this.taperX.ToString();
1224 s +=
"\ntaperY...............: " + this.taperY.ToString();
1225 s +=
"\nradius...............: " + this.radius.ToString();
1226 s +=
"\nrevolutions..........: " + this.revolutions.ToString();
1227 s +=
"\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString();
1228 s +=
"\nhasProfileCut........: " + this.hasProfileCut.ToString();
1229 s +=
"\nhasHollow............: " + this.hasHollow.ToString();
1236 get {
return hasProfileCut; }
1237 set { hasProfileCut = value; }
1242 get {
return hasHollow; }
1255 public PrimMesh(
int _sides,
float _profileStart,
float _profileEnd,
float _hollow,
int _hollowSides)
1257 coords =
new List<Coord>();
1258 faces =
new List<Face>();
1261 profileStart = _profileStart;
1262 profileEnd = _profileEnd;
1264 hollowSides = _hollowSides;
1268 if (hollowSides < 3)
1270 if (profileStart < 0.0f)
1271 profileStart = 0.0f;
1272 if (profileEnd > 1.0f)
1274 if (profileEnd < 0.02f)
1276 if (profileStart >= profileEnd)
1277 profileStart = profileEnd - 0.02f;
1289 bool needEndFaces =
false;
1291 coords =
new List<Coord>();
1292 faces =
new List<Face>();
1298 hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1300 hasHollow = (this.hollow > 0.001f);
1302 float twistBegin = this.twistBegin / 360.0f * twoPi;
1303 float twistEnd = this.twistEnd / 360.0f * twoPi;
1305 float twistTotalAbs = Math.Abs(twistTotal);
1306 if (twistTotalAbs > 0.01f)
1307 steps += (int)(twistTotalAbs * 3.66);
1309 float hollow = this.hollow;
1310 float initialProfileRot = 0.0f;
1314 needEndFaces =
false;
1315 if (pathCutBegin != 0.0f ||
pathCutEnd != 1.0f)
1316 needEndFaces =
true;
1318 needEndFaces =
true;
1319 else if (
skew != 0.0f)
1320 needEndFaces =
true;
1321 else if (twistTotal != 0.0f)
1322 needEndFaces =
true;
1324 needEndFaces =
true;
1326 else needEndFaces =
true;
1332 initialProfileRot = (float)Math.PI;
1333 if (hollowSides == 4)
1339 else hollow *= 0.5f;
1341 else if (sides == 4)
1343 initialProfileRot = 0.25f * (float)Math.PI;
1344 if (hollowSides != 4)
1349 initialProfileRot = (float)Math.PI;
1350 if (hollowSides == 4)
1362 if (hollowSides == 4)
1368 else hollow *= 0.5f;
1370 else if (sides == 4)
1372 initialProfileRot = 1.25f * (float)Math.PI;
1373 if (hollowSides != 4)
1376 else if (sides == 24 && hollowSides == 4)
1380 Profile profile =
new Profile(sides, profileStart, profileEnd, hollow, hollowSides,
1386 if (initialProfileRot != 0.0f)
1388 profile.AddRot(
new Quat(
new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
1409 path.Create(pathType, steps);
1411 int lastNode = path.pathNodes.Count - 1;
1413 for (
int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1415 PathNode node = path.pathNodes[nodeIndex];
1416 Profile newLayer = profile.Copy();
1418 newLayer.Scale(node.xScale, node.yScale);
1420 newLayer.AddPos(node.position);
1423 int coordsStart = coords.Count;
1424 coords.AddRange(newLayer.coords);
1426 if (needEndFaces && nodeIndex == 0 && newLayer.faces.Count > 0)
1428 newLayer.AddValue2FaceVertexIndices(coordsStart);
1429 newLayer.FlipNormals();
1430 faces.AddRange(newLayer.faces);
1435 List<Face> linkfaces =
new List<Face>();
1436 int numVerts = newLayer.coords.Count;
1442 int startVert = coordsStart;
1443 int endVert = coords.Count;
1446 if(numVerts > 5 && !hasHollow)
1449 for (
int l = 0; l < profile.numOuterVerts - 1; l++)
1452 newFace1.v2 = i - numVerts;
1453 newFace1.v3 = i + 1;
1454 linkfaces.Add(newFace1);
1456 newFace2.v1 = i + 1;
1457 newFace2.v2 = i - numVerts;
1458 newFace2.v3 = i + 1 - numVerts;
1459 linkfaces.Add(newFace2);
1464 newFace1.v2 = i - numVerts;
1465 newFace1.v3 = startVert;
1466 linkfaces.Add(newFace1);
1468 newFace2.v1 = startVert;
1469 newFace2.v2 = i - numVerts;
1470 newFace2.v3 = startVert - numVerts;
1471 linkfaces.Add(newFace2);
1476 for (
int l = 0; l < profile.numHollowVerts - 1; l++)
1479 newFace1.v2 = i - numVerts;
1480 newFace1.v3 = i + 1;
1481 linkfaces.Add(newFace1);
1483 newFace2.v1 = i + 1;
1484 newFace2.v2 = i - numVerts;
1485 newFace2.v3 = i + 1 - numVerts;
1486 linkfaces.Add(newFace2);
1491 newFace1.v2 = i - numVerts;
1492 newFace1.v3 = startVert;
1493 linkfaces.Add(newFace1);
1495 newFace2.v1 = startVert;
1496 newFace2.v2 = i - numVerts;
1497 newFace2.v3 = startVert - numVerts;
1498 linkfaces.Add(newFace2);
1503 for (
int i = startVert; i < endVert; i++)
1506 if (i == endVert - 1)
1510 newFace1.v2 = i - numVerts;
1511 newFace1.v3 = iNext;
1512 linkfaces.Add(newFace1);
1514 newFace2.v1 = iNext;
1515 newFace2.v2 = i - numVerts;
1516 newFace2.v3 = iNext - numVerts;
1517 linkfaces.Add(newFace2);
1522 if(linkfaces.Count > 0)
1523 faces.AddRange(linkfaces);
1525 if (needEndFaces && nodeIndex == lastNode && newLayer.faces.Count > 0)
1527 newLayer.AddValue2FaceVertexIndices(coordsStart);
1528 faces.AddRange(newLayer.faces);
1560 Coord edge1 =
new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
1561 Coord edge2 =
new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
1563 Coord normal = Coord.Cross(edge1, edge2);
1570 private Coord SurfaceNormal(Face face)
1572 return SurfaceNormal(this.
coords[face.v1],
this.coords[face.v2],
this.coords[face.v3]);
1582 int numFaces = this.faces.Count;
1583 if (faceIndex < 0 || faceIndex >= numFaces)
1584 throw new Exception(
"faceIndex out of range");
1586 return SurfaceNormal(this.
faces[faceIndex]);
1595 PrimMesh copy =
new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides);
1596 copy.twistBegin = this.twistBegin;
1597 copy.twistEnd = this.twistEnd;
1598 copy.topShearX = this.topShearX;
1599 copy.topShearY = this.topShearY;
1600 copy.pathCutBegin = this.pathCutBegin;
1601 copy.pathCutEnd = this.pathCutEnd;
1602 copy.dimpleBegin = this.dimpleBegin;
1603 copy.dimpleEnd = this.dimpleEnd;
1604 copy.skew = this.skew;
1605 copy.holeSizeX = this.holeSizeX;
1606 copy.holeSizeY = this.holeSizeY;
1607 copy.taperX = this.taperX;
1608 copy.taperY = this.taperY;
1609 copy.radius = this.radius;
1610 copy.revolutions = this.revolutions;
1611 copy.stepsPerRevolution = this.stepsPerRevolution;
1613 copy.numPrimFaces = this.numPrimFaces;
1614 copy.errorMessage = this.errorMessage;
1616 copy.coords =
new List<Coord>(this.coords);
1617 copy.faces =
new List<Face>(this.faces);
1628 public void AddPos(
float x,
float y,
float z)
1631 int numVerts = this.coords.Count;
1634 for (i = 0; i < numVerts; i++)
1636 vert = this.coords[i];
1640 this.coords[i] = vert;
1651 int numVerts = this.coords.Count;
1653 for (i = 0; i < numVerts; i++)
1658 public VertexIndexer GetVertexIndexer()
1670 public void Scale(
float x,
float y,
float z)
1673 int numVerts = this.coords.Count;
1677 for (i = 0; i < numVerts; i++)
1687 public void DumpRaw(String path, String name, String title)
1691 String fileName = name +
"_" + title +
".raw";
1692 String completePath = System.IO.Path.Combine(path, fileName);
1693 StreamWriter sw =
new StreamWriter(completePath);
1695 for (
int i = 0; i < this.faces.Count; i++)
1697 string s = this.coords[this.faces[i].v1].ToString();
1698 s +=
" " + this.coords[this.faces[i].v2].ToString();
1699 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 DumpRaw(String path, String name, String title)
Dumps the mesh to a Blender compatible "Raw" format file
void Create(PathType pathType, int steps)
Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool hasProfileCut, bool createFaces)
static Coord Cross(Coord c1, Coord c2)
override string ToString()
void ExtrudeLinear()
DEPRICATED - use Extrude(PathType.Linear) instead Extrudes a profile along a straight line path...
static Coord operator*(Coord v, Coord m)
List< int > hollowCoordIndices
generates a profile for extrusion
Profile Copy(bool needFaces)
PrimMesh(int _sides, float _profileStart, float _profileEnd, float _hollow, int _hollowSides)
Constructs a PrimMesh object and creates the profile for extrusion.
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...
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)
List< int > outerCoordIndices
void DumpRaw(String path, String name, String title)
void Scale(float x, float y)
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)
string ParamsToDisplayString()
Human readable string representation of the parameters used to create a mesh.
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.
static Coord operator+(Coord v, Coord a)
void AddPos(float x, float y, float z)