aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing/PrimMesher.cs
diff options
context:
space:
mode:
authorMelanie2009-10-12 15:12:15 +0100
committerMelanie2009-10-12 15:12:15 +0100
commit70553a979e551efc47f56930282c6b01ff4277e1 (patch)
tree347632a3f51e7eace08e383f17b7f3e5ad218610 /OpenSim/Region/Physics/Meshing/PrimMesher.cs
parentMerge branch 'master' into vehicles (diff)
parentOptimize ODE mesh by removing sleep. On a region with 100,000 prims and ODE e... (diff)
downloadopensim-SC-70553a979e551efc47f56930282c6b01ff4277e1.zip
opensim-SC-70553a979e551efc47f56930282c6b01ff4277e1.tar.gz
opensim-SC-70553a979e551efc47f56930282c6b01ff4277e1.tar.bz2
opensim-SC-70553a979e551efc47f56930282c6b01ff4277e1.tar.xz
Merge branch 'master' into vehicles
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/Meshing/PrimMesher.cs787
1 files changed, 771 insertions, 16 deletions
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
index abfd400..a283840 100644
--- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
@@ -67,6 +67,11 @@ namespace PrimMesher
67 Normalize(); 67 Normalize();
68 } 68 }
69 69
70 public Quat Identity()
71 {
72 return new Quat(0.0f, 0.0f, 0.0f, 1.1f);
73 }
74
70 public float Length() 75 public float Length()
71 { 76 {
72 return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W); 77 return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
@@ -97,6 +102,15 @@ namespace PrimMesher
97 return this; 102 return this;
98 } 103 }
99 104
105 public static Quat operator *(Quat q1, Quat q2)
106 {
107 float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y;
108 float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X;
109 float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W;
110 float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z;
111 return new Quat(x, y, z, w);
112 }
113
100 public override string ToString() 114 public override string ToString()
101 { 115 {
102 return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">"; 116 return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">";
@@ -305,6 +319,10 @@ namespace PrimMesher
305 public Coord v2; 319 public Coord v2;
306 public Coord v3; 320 public Coord v3;
307 321
322 public int coordIndex1;
323 public int coordIndex2;
324 public int coordIndex3;
325
308 public Coord n1; 326 public Coord n1;
309 public Coord n2; 327 public Coord n2;
310 public Coord n3; 328 public Coord n3;
@@ -321,6 +339,8 @@ namespace PrimMesher
321 this.v2 = new Coord(); 339 this.v2 = new Coord();
322 this.v3 = new Coord(); 340 this.v3 = new Coord();
323 341
342 this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet
343
324 this.n1 = new Coord(); 344 this.n1 = new Coord();
325 this.n2 = new Coord(); 345 this.n2 = new Coord();
326 this.n3 = new Coord(); 346 this.n3 = new Coord();
@@ -602,6 +622,12 @@ namespace PrimMesher
602 internal List<UVCoord> faceUVs; 622 internal List<UVCoord> faceUVs;
603 internal List<int> faceNumbers; 623 internal List<int> faceNumbers;
604 624
625 // use these for making individual meshes for each prim face
626 internal List<int> outerCoordIndices = null;
627 internal List<int> hollowCoordIndices = null;
628 internal List<int> cut1CoordIndices = null;
629 internal List<int> cut2CoordIndices = null;
630
605 internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); 631 internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f);
606 internal Coord cutNormal1 = new Coord(); 632 internal Coord cutNormal1 = new Coord();
607 internal Coord cutNormal2 = new Coord(); 633 internal Coord cutNormal2 = new Coord();
@@ -634,11 +660,20 @@ namespace PrimMesher
634 this.faceNumbers = new List<int>(); 660 this.faceNumbers = new List<int>();
635 661
636 Coord center = new Coord(0.0f, 0.0f, 0.0f); 662 Coord center = new Coord(0.0f, 0.0f, 0.0f);
663 bool hasCenter = false;
637 664
638 List<Coord> hollowCoords = new List<Coord>(); 665 List<Coord> hollowCoords = new List<Coord>();
639 List<Coord> hollowNormals = new List<Coord>(); 666 List<Coord> hollowNormals = new List<Coord>();
640 List<float> hollowUs = new List<float>(); 667 List<float> hollowUs = new List<float>();
641 668
669 if (calcVertexNormals)
670 {
671 this.outerCoordIndices = new List<int>();
672 this.hollowCoordIndices = new List<int>();
673 this.cut1CoordIndices = new List<int>();
674 this.cut2CoordIndices = new List<int>();
675 }
676
642 bool hasHollow = (hollow > 0.0f); 677 bool hasHollow = (hollow > 0.0f);
643 678
644 bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f); 679 bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f);
@@ -692,6 +727,7 @@ namespace PrimMesher
692 else if (!simpleFace) 727 else if (!simpleFace)
693 { 728 {
694 this.coords.Add(center); 729 this.coords.Add(center);
730 hasCenter = true;
695 if (this.calcVertexNormals) 731 if (this.calcVertexNormals)
696 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); 732 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f));
697 this.us.Add(0.0f); 733 this.us.Add(0.0f);
@@ -736,6 +772,8 @@ namespace PrimMesher
736 this.coords.Add(newVert); 772 this.coords.Add(newVert);
737 if (this.calcVertexNormals) 773 if (this.calcVertexNormals)
738 { 774 {
775 this.outerCoordIndices.Add(this.coords.Count - 1);
776
739 if (sides < 5) 777 if (sides < 5)
740 { 778 {
741 this.vertexNormals.Add(angles.normals[i]); 779 this.vertexNormals.Add(angles.normals[i]);
@@ -870,7 +908,16 @@ namespace PrimMesher
870 } 908 }
871 } 909 }
872 910
873 this.coords.AddRange(hollowCoords); 911 if (calcVertexNormals)
912 {
913 foreach (Coord hc in hollowCoords)
914 {
915 this.coords.Add(hc);
916 hollowCoordIndices.Add(this.coords.Count - 1);
917 }
918 }
919 else
920 this.coords.AddRange(hollowCoords);
874 921
875 if (this.calcVertexNormals) 922 if (this.calcVertexNormals)
876 { 923 {
@@ -897,6 +944,12 @@ namespace PrimMesher
897 { 944 {
898 int lastOuterVertIndex = this.numOuterVerts - 1; 945 int lastOuterVertIndex = this.numOuterVerts - 1;
899 946
947 this.cut1CoordIndices.Add(0);
948 this.cut1CoordIndices.Add(this.coords.Count - 1);
949
950 this.cut2CoordIndices.Add(lastOuterVertIndex + 1);
951 this.cut2CoordIndices.Add(lastOuterVertIndex);
952
900 this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y; 953 this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y;
901 this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X); 954 this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X);
902 955
@@ -935,9 +988,15 @@ namespace PrimMesher
935 this.faceNumbers.Add(-1); 988 this.faceNumbers.Add(-1);
936 for (int i = 0; i < numOuterVerts - 1; i++) 989 for (int i = 0; i < numOuterVerts - 1; i++)
937 this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum); 990 this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum);
991
992 //if (!hasHollow && !hasProfileCut)
993 // this.bottomFaceNumber = faceNum++;
994
938 this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++); 995 this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++);
939 if (sides > 4) 996
997 if (sides > 4 && (hasHollow || hasProfileCut))
940 faceNum++; 998 faceNum++;
999
941 if (hasHollow) 1000 if (hasHollow)
942 { 1001 {
943 for (int i = 0; i < numHollowVerts; i++) 1002 for (int i = 0; i < numHollowVerts; i++)
@@ -945,13 +1004,17 @@ namespace PrimMesher
945 1004
946 faceNum++; 1005 faceNum++;
947 } 1006 }
1007 //if (hasProfileCut || hasHollow)
1008 // this.bottomFaceNumber = faceNum++;
948 this.bottomFaceNumber = faceNum++; 1009 this.bottomFaceNumber = faceNum++;
1010
949 if (hasHollow && hasProfileCut) 1011 if (hasHollow && hasProfileCut)
950 this.faceNumbers.Add(faceNum++); 1012 this.faceNumbers.Add(faceNum++);
951 for (int i = 0; i < this.faceNumbers.Count; i++) 1013 for (int i = 0; i < this.faceNumbers.Count; i++)
952 if (this.faceNumbers[i] == -1) 1014 if (this.faceNumbers[i] == -1)
953 this.faceNumbers[i] = faceNum++; 1015 this.faceNumbers[i] = faceNum++;
954 1016
1017
955 this.numPrimFaces = faceNum; 1018 this.numPrimFaces = faceNum;
956 } 1019 }
957 1020
@@ -986,6 +1049,11 @@ namespace PrimMesher
986 copy.cutNormal2 = this.cutNormal2; 1049 copy.cutNormal2 = this.cutNormal2;
987 copy.us.AddRange(this.us); 1050 copy.us.AddRange(this.us);
988 copy.faceNumbers.AddRange(this.faceNumbers); 1051 copy.faceNumbers.AddRange(this.faceNumbers);
1052
1053 copy.cut1CoordIndices = new List<int>(this.cut1CoordIndices);
1054 copy.cut2CoordIndices = new List<int>(this.cut2CoordIndices);
1055 copy.hollowCoordIndices = new List<int>(this.hollowCoordIndices);
1056 copy.outerCoordIndices = new List<int>(this.outerCoordIndices);
989 } 1057 }
990 copy.numOuterVerts = this.numOuterVerts; 1058 copy.numOuterVerts = this.numOuterVerts;
991 copy.numHollowVerts = this.numHollowVerts; 1059 copy.numHollowVerts = this.numHollowVerts;
@@ -1149,17 +1217,213 @@ namespace PrimMesher
1149 1217
1150 public struct PathNode 1218 public struct PathNode
1151 { 1219 {
1152 public float position; 1220 public Coord position;
1153 public Quat rotation; 1221 public Quat rotation;
1154 public float xScale; 1222 public float xScale;
1155 public float yScale; 1223 public float yScale;
1224 public float percentOfPath;
1225 }
1156 1226
1157 public PathNode(float position, Quat rotation, float xScale, float yScale) 1227 public enum PathType { Linear = 0, Circular = 1, Flexible = 2 }
1228
1229 public class Path
1230 {
1231 public List<PathNode> pathNodes = new List<PathNode>();
1232
1233 public float twistBegin = 0.0f;
1234 public float twistEnd = 0.0f;
1235 public float topShearX = 0.0f;
1236 public float topShearY = 0.0f;
1237 public float pathCutBegin = 0.0f;
1238 public float pathCutEnd = 1.0f;
1239 public float dimpleBegin = 0.0f;
1240 public float dimpleEnd = 1.0f;
1241 public float skew = 0.0f;
1242 public float holeSizeX = 1.0f; // called pathScaleX in pbs
1243 public float holeSizeY = 0.25f;
1244 public float taperX = 0.0f;
1245 public float taperY = 0.0f;
1246 public float radius = 0.0f;
1247 public float revolutions = 1.0f;
1248 public int stepsPerRevolution = 24;
1249
1250 private const float twoPi = 2.0f * (float)Math.PI;
1251
1252 public void Create(PathType pathType, int steps)
1158 { 1253 {
1159 this.position = position; 1254 if (pathType == PathType.Linear || pathType == PathType.Flexible)
1160 this.rotation = rotation; 1255 {
1161 this.xScale = xScale; 1256 int step = 0;
1162 this.yScale = yScale; 1257
1258 float length = this.pathCutEnd - this.pathCutBegin;
1259 float twistTotal = twistEnd - twistBegin;
1260 float twistTotalAbs = Math.Abs(twistTotal);
1261 if (twistTotalAbs > 0.01f)
1262 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
1263
1264 float start = -0.5f;
1265 float stepSize = length / (float)steps;
1266 float percentOfPathMultiplier = stepSize;
1267 float xOffset = 0.0f;
1268 float yOffset = 0.0f;
1269 float zOffset = start;
1270 float xOffsetStepIncrement = this.topShearX / steps;
1271 float yOffsetStepIncrement = this.topShearY / steps;
1272
1273 float percentOfPath = this.pathCutBegin;
1274 zOffset += percentOfPath;
1275
1276 // sanity checks
1277
1278 bool done = false;
1279
1280 while (!done)
1281 {
1282 PathNode newNode = new PathNode();
1283
1284 newNode.xScale = 1.0f;
1285 if (this.taperX == 0.0f)
1286 newNode.xScale = 1.0f;
1287 else if (this.taperX > 0.0f)
1288 newNode.xScale = 1.0f - percentOfPath * this.taperX;
1289 else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX;
1290
1291 newNode.yScale = 1.0f;
1292 if (this.taperY == 0.0f)
1293 newNode.yScale = 1.0f;
1294 else if (this.taperY > 0.0f)
1295 newNode.yScale = 1.0f - percentOfPath * this.taperY;
1296 else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY;
1297
1298 float twist = twistBegin + twistTotal * percentOfPath;
1299
1300 newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
1301 newNode.position = new Coord(xOffset, yOffset, zOffset);
1302 newNode.percentOfPath = percentOfPath;
1303
1304 pathNodes.Add(newNode);
1305
1306 if (step < steps)
1307 {
1308 step += 1;
1309 percentOfPath += percentOfPathMultiplier;
1310 xOffset += xOffsetStepIncrement;
1311 yOffset += yOffsetStepIncrement;
1312 zOffset += stepSize;
1313 if (percentOfPath > this.pathCutEnd)
1314 done = true;
1315 }
1316 else done = true;
1317 }
1318 } // end of linear path code
1319
1320 else // pathType == Circular
1321 {
1322 float twistTotal = twistEnd - twistBegin;
1323
1324 // if the profile has a lot of twist, add more layers otherwise the layers may overlap
1325 // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't
1326 // accurately match the viewer
1327 float twistTotalAbs = Math.Abs(twistTotal);
1328 if (twistTotalAbs > 0.01f)
1329 {
1330 if (twistTotalAbs > Math.PI * 1.5f)
1331 steps *= 2;
1332 if (twistTotalAbs > Math.PI * 3.0f)
1333 steps *= 2;
1334 }
1335
1336 float yPathScale = this.holeSizeY * 0.5f;
1337 float pathLength = this.pathCutEnd - this.pathCutBegin;
1338 float totalSkew = this.skew * 2.0f * pathLength;
1339 float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew;
1340 float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY));
1341 float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f;
1342
1343 // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end
1344 // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used
1345 // to calculate the sine for generating the path radius appears to approximate it's effects there
1346 // too, but there are some subtle differences in the radius which are noticeable as the prim size
1347 // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on
1348 // the meshes generated with this technique appear nearly identical in shape to the same prims when
1349 // displayed by the viewer.
1350
1351 float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f;
1352 float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f;
1353 float stepSize = twoPi / this.stepsPerRevolution;
1354
1355 int step = (int)(startAngle / stepSize);
1356 int firstStep = step;
1357 float angle = startAngle;
1358
1359 bool done = false;
1360 while (!done) // loop through the length of the path and add the layers
1361 {
1362 PathNode newNode = new PathNode();
1363
1364 float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX;
1365 float yProfileScale = this.holeSizeY;
1366
1367 float percentOfPath = angle / (twoPi * this.revolutions);
1368 float percentOfAngles = (angle - startAngle) / (endAngle - startAngle);
1369
1370 if (this.taperX > 0.01f)
1371 xProfileScale *= 1.0f - percentOfPath * this.taperX;
1372 else if (this.taperX < -0.01f)
1373 xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX;
1374
1375 if (this.taperY > 0.01f)
1376 yProfileScale *= 1.0f - percentOfPath * this.taperY;
1377 else if (this.taperY < -0.01f)
1378 yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY;
1379
1380 newNode.xScale = xProfileScale;
1381 newNode.yScale = yProfileScale;
1382
1383 float radiusScale = 1.0f;
1384 if (this.radius > 0.001f)
1385 radiusScale = 1.0f - this.radius * percentOfPath;
1386 else if (this.radius < 0.001f)
1387 radiusScale = 1.0f + this.radius * (1.0f - percentOfPath);
1388
1389 float twist = twistBegin + twistTotal * percentOfPath;
1390
1391 float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
1392 xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
1393
1394 float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
1395
1396 float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale;
1397
1398 newNode.position = new Coord(xOffset, yOffset, zOffset);
1399
1400 // now orient the rotation of the profile layer relative to it's position on the path
1401 // adding taperY to the angle used to generate the quat appears to approximate the viewer
1402
1403 newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY);
1404
1405 // next apply twist rotation to the profile layer
1406 if (twistTotal != 0.0f || twistBegin != 0.0f)
1407 newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
1408
1409 newNode.percentOfPath = percentOfPath;
1410
1411 pathNodes.Add(newNode);
1412
1413 // calculate terms for next iteration
1414 // calculate the angle for the next iteration of the loop
1415
1416 if (angle >= endAngle - 0.01)
1417 done = true;
1418 else
1419 {
1420 step += 1;
1421 angle = stepSize * step;
1422 if (angle > endAngle)
1423 angle = endAngle;
1424 }
1425 }
1426 }
1163 } 1427 }
1164 } 1428 }
1165 1429
@@ -1279,6 +1543,447 @@ namespace PrimMesher
1279 /// <summary> 1543 /// <summary>
1280 /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. 1544 /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism.
1281 /// </summary> 1545 /// </summary>
1546 public void Extrude(PathType pathType)
1547 {
1548 this.coords = new List<Coord>();
1549 this.faces = new List<Face>();
1550
1551 if (this.viewerMode)
1552 {
1553 this.viewerFaces = new List<ViewerFace>();
1554 this.calcVertexNormals = true;
1555 }
1556
1557 if (this.calcVertexNormals)
1558 this.normals = new List<Coord>();
1559
1560 //int step = 0;
1561 int steps = 1;
1562
1563 float length = this.pathCutEnd - this.pathCutBegin;
1564 normalsProcessed = false;
1565
1566 if (this.viewerMode && this.sides == 3)
1567 {
1568 // prisms don't taper well so add some vertical resolution
1569 // other prims may benefit from this but just do prisms for now
1570 if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01)
1571 steps = (int)(steps * 4.5 * length);
1572 }
1573
1574
1575 float twistBegin = this.twistBegin / 360.0f * twoPi;
1576 float twistEnd = this.twistEnd / 360.0f * twoPi;
1577 float twistTotal = twistEnd - twistBegin;
1578 float twistTotalAbs = Math.Abs(twistTotal);
1579 if (twistTotalAbs > 0.01f)
1580 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
1581
1582 //float start = -0.5f;
1583 //float stepSize = length / (float)steps;
1584 //float percentOfPathMultiplier = stepSize;
1585 //float xProfileScale = 1.0f;
1586 //float yProfileScale = 1.0f;
1587 //float xOffset = 0.0f;
1588 //float yOffset = 0.0f;
1589 //float zOffset = start;
1590 //float xOffsetStepIncrement = this.topShearX / steps;
1591 //float yOffsetStepIncrement = this.topShearY / steps;
1592
1593 //float percentOfPath = this.pathCutBegin;
1594 //zOffset += percentOfPath;
1595
1596 float hollow = this.hollow;
1597
1598 // sanity checks
1599 float initialProfileRot = 0.0f;
1600 if (pathType == PathType.Circular)
1601 {
1602 if (this.sides == 3)
1603 {
1604 initialProfileRot = (float)Math.PI;
1605 if (this.hollowSides == 4)
1606 {
1607 if (hollow > 0.7f)
1608 hollow = 0.7f;
1609 hollow *= 0.707f;
1610 }
1611 else hollow *= 0.5f;
1612 }
1613 else if (this.sides == 4)
1614 {
1615 initialProfileRot = 0.25f * (float)Math.PI;
1616 if (this.hollowSides != 4)
1617 hollow *= 0.707f;
1618 }
1619 else if (this.sides > 4)
1620 {
1621 initialProfileRot = (float)Math.PI;
1622 if (this.hollowSides == 4)
1623 {
1624 if (hollow > 0.7f)
1625 hollow = 0.7f;
1626 hollow /= 0.7f;
1627 }
1628 }
1629 }
1630 else
1631 {
1632 if (this.sides == 3)
1633 {
1634 if (this.hollowSides == 4)
1635 {
1636 if (hollow > 0.7f)
1637 hollow = 0.7f;
1638 hollow *= 0.707f;
1639 }
1640 else hollow *= 0.5f;
1641 }
1642 else if (this.sides == 4)
1643 {
1644 initialProfileRot = 1.25f * (float)Math.PI;
1645 if (this.hollowSides != 4)
1646 hollow *= 0.707f;
1647 }
1648 else if (this.sides == 24 && this.hollowSides == 4)
1649 hollow *= 1.414f;
1650 }
1651
1652 Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals);
1653 this.errorMessage = profile.errorMessage;
1654
1655 this.numPrimFaces = profile.numPrimFaces;
1656
1657 int cut1Vert = -1;
1658 int cut2Vert = -1;
1659 if (hasProfileCut)
1660 {
1661 cut1Vert = hasHollow ? profile.coords.Count - 1 : 0;
1662 cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
1663 }
1664
1665
1666 if (initialProfileRot != 0.0f)
1667 {
1668 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
1669 if (viewerMode)
1670 profile.MakeFaceUVs();
1671 }
1672
1673 Coord lastCutNormal1 = new Coord();
1674 Coord lastCutNormal2 = new Coord();
1675 float lastV = 1.0f;
1676
1677 Path path = new Path();
1678 path.twistBegin = twistBegin;
1679 path.twistEnd = twistEnd;
1680 path.topShearX = topShearX;
1681 path.topShearY = topShearY;
1682 path.pathCutBegin = pathCutBegin;
1683 path.pathCutEnd = pathCutEnd;
1684 path.dimpleBegin = dimpleBegin;
1685 path.dimpleEnd = dimpleEnd;
1686 path.skew = skew;
1687 path.holeSizeX = holeSizeX;
1688 path.holeSizeY = holeSizeY;
1689 path.taperX = taperX;
1690 path.taperY = taperY;
1691 path.radius = radius;
1692 path.revolutions = revolutions;
1693 path.stepsPerRevolution = stepsPerRevolution;
1694
1695 path.Create(pathType, steps);
1696 /*
1697 public int twistBegin = 0;
1698 public int twistEnd = 0;
1699 public float topShearX = 0.0f;
1700 public float topShearY = 0.0f;
1701 public float pathCutBegin = 0.0f;
1702 public float pathCutEnd = 1.0f;
1703 public float dimpleBegin = 0.0f;
1704 public float dimpleEnd = 1.0f;
1705 public float skew = 0.0f;
1706 public float holeSizeX = 1.0f; // called pathScaleX in pbs
1707 public float holeSizeY = 0.25f;
1708 public float taperX = 0.0f;
1709 public float taperY = 0.0f;
1710 public float radius = 0.0f;
1711 public float revolutions = 1.0f;
1712 public int stepsPerRevolution = 24;
1713 */
1714
1715 bool needEndFaces = false;
1716 if (pathType == PathType.Circular)
1717 {
1718 needEndFaces = false;
1719 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
1720 needEndFaces = true;
1721 else if (this.taperX != 0.0f || this.taperY != 0.0f)
1722 needEndFaces = true;
1723 else if (this.skew != 0.0f)
1724 needEndFaces = true;
1725 else if (twistTotal != 0.0f)
1726 needEndFaces = true;
1727 else if (this.radius != 0.0f)
1728 needEndFaces = true;
1729 }
1730 else needEndFaces = true;
1731
1732 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1733 {
1734 PathNode node = path.pathNodes[nodeIndex];
1735 Profile newLayer = profile.Copy();
1736 newLayer.Scale(node.xScale, node.yScale);
1737
1738 newLayer.AddRot(node.rotation);
1739 newLayer.AddPos(node.position);
1740
1741 if (needEndFaces && nodeIndex == 0)
1742 {
1743 newLayer.FlipNormals();
1744
1745 // add the top faces to the viewerFaces list here
1746 if (this.viewerMode)
1747 {
1748 Coord faceNormal = newLayer.faceNormal;
1749 ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber);
1750 int numFaces = newLayer.faces.Count;
1751 List<Face> faces = newLayer.faces;
1752
1753 for (int i = 0; i < numFaces; i++)
1754 {
1755 Face face = faces[i];
1756 newViewerFace.v1 = newLayer.coords[face.v1];
1757 newViewerFace.v2 = newLayer.coords[face.v2];
1758 newViewerFace.v3 = newLayer.coords[face.v3];
1759
1760 newViewerFace.coordIndex1 = face.v1;
1761 newViewerFace.coordIndex2 = face.v2;
1762 newViewerFace.coordIndex3 = face.v3;
1763
1764 newViewerFace.n1 = faceNormal;
1765 newViewerFace.n2 = faceNormal;
1766 newViewerFace.n3 = faceNormal;
1767
1768 newViewerFace.uv1 = newLayer.faceUVs[face.v1];
1769 newViewerFace.uv2 = newLayer.faceUVs[face.v2];
1770 newViewerFace.uv3 = newLayer.faceUVs[face.v3];
1771
1772 this.viewerFaces.Add(newViewerFace);
1773 }
1774 }
1775 } // if (nodeIndex == 0)
1776
1777 // append this layer
1778
1779 int coordsLen = this.coords.Count;
1780 int lastCoordsLen = coordsLen;
1781 newLayer.AddValue2FaceVertexIndices(coordsLen);
1782
1783 this.coords.AddRange(newLayer.coords);
1784
1785 if (this.calcVertexNormals)
1786 {
1787 newLayer.AddValue2FaceNormalIndices(this.normals.Count);
1788 this.normals.AddRange(newLayer.vertexNormals);
1789 }
1790
1791 if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f)
1792 this.faces.AddRange(newLayer.faces);
1793
1794 // fill faces between layers
1795
1796 int numVerts = newLayer.coords.Count;
1797 Face newFace = new Face();
1798
1799 //if (step > 0)
1800 if (nodeIndex > 0)
1801 {
1802 int startVert = coordsLen + 1;
1803 int endVert = this.coords.Count;
1804
1805 if (sides < 5 || this.hasProfileCut || hollow > 0.0f)
1806 startVert--;
1807
1808 for (int i = startVert; i < endVert; i++)
1809 {
1810 int iNext = i + 1;
1811 if (i == endVert - 1)
1812 iNext = startVert;
1813
1814 int whichVert = i - startVert;
1815 //int whichVert2 = i - lastCoordsLen;
1816
1817 newFace.v1 = i;
1818 newFace.v2 = i - numVerts;
1819 newFace.v3 = iNext - numVerts;
1820 this.faces.Add(newFace);
1821
1822 newFace.v2 = iNext - numVerts;
1823 newFace.v3 = iNext;
1824 this.faces.Add(newFace);
1825
1826 if (this.viewerMode)
1827 {
1828 // add the side faces to the list of viewerFaces here
1829
1830 int primFaceNum = profile.faceNumbers[whichVert];
1831 if (!needEndFaces)
1832 primFaceNum -= 1;
1833
1834 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum);
1835 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum);
1836
1837 float u1 = newLayer.us[whichVert];
1838 float u2 = 1.0f;
1839 if (whichVert < newLayer.us.Count - 1)
1840 u2 = newLayer.us[whichVert + 1];
1841
1842 if (whichVert == cut1Vert || whichVert == cut2Vert)
1843 {
1844 u1 = 0.0f;
1845 u2 = 1.0f;
1846 }
1847 else if (sides < 5)
1848 {
1849 if (whichVert < profile.numOuterVerts)
1850 { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled
1851 // to reflect the entire texture width
1852 u1 *= sides;
1853 u2 *= sides;
1854 u2 -= (int)u1;
1855 u1 -= (int)u1;
1856 if (u2 < 0.1f)
1857 u2 = 1.0f;
1858 }
1859 else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1)
1860 {
1861 u1 *= 2.0f;
1862 u2 *= 2.0f;
1863 }
1864 }
1865
1866 newViewerFace1.uv1.U = u1;
1867 newViewerFace1.uv2.U = u1;
1868 newViewerFace1.uv3.U = u2;
1869
1870 newViewerFace1.uv1.V = 1.0f - node.percentOfPath;
1871 newViewerFace1.uv2.V = lastV;
1872 newViewerFace1.uv3.V = lastV;
1873
1874 newViewerFace2.uv1.U = u1;
1875 newViewerFace2.uv2.U = u2;
1876 newViewerFace2.uv3.U = u2;
1877
1878 newViewerFace2.uv1.V = 1.0f - node.percentOfPath;
1879 newViewerFace2.uv2.V = lastV;
1880 newViewerFace2.uv3.V = 1.0f - node.percentOfPath;
1881
1882 newViewerFace1.v1 = this.coords[i];
1883 newViewerFace1.v2 = this.coords[i - numVerts];
1884 newViewerFace1.v3 = this.coords[iNext - numVerts];
1885
1886 newViewerFace2.v1 = this.coords[i];
1887 newViewerFace2.v2 = this.coords[iNext - numVerts];
1888 newViewerFace2.v3 = this.coords[iNext];
1889
1890 newViewerFace1.coordIndex1 = i;
1891 newViewerFace1.coordIndex2 = i - numVerts;
1892 newViewerFace1.coordIndex3 = iNext - numVerts;
1893
1894 newViewerFace2.coordIndex1 = i;
1895 newViewerFace2.coordIndex2 = iNext - numVerts;
1896 newViewerFace2.coordIndex3 = iNext;
1897
1898 // profile cut faces
1899 if (whichVert == cut1Vert)
1900 {
1901 newViewerFace1.n1 = newLayer.cutNormal1;
1902 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
1903
1904 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1;
1905 newViewerFace2.n2 = lastCutNormal1;
1906 }
1907 else if (whichVert == cut2Vert)
1908 {
1909 newViewerFace1.n1 = newLayer.cutNormal2;
1910 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2;
1911
1912 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2;
1913 newViewerFace2.n2 = lastCutNormal2;
1914 }
1915
1916 else // outer and hollow faces
1917 {
1918 if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts))
1919 { // looks terrible when path is twisted... need vertex normals here
1920 newViewerFace1.CalcSurfaceNormal();
1921 newViewerFace2.CalcSurfaceNormal();
1922 }
1923 else
1924 {
1925 newViewerFace1.n1 = this.normals[i];
1926 newViewerFace1.n2 = this.normals[i - numVerts];
1927 newViewerFace1.n3 = this.normals[iNext - numVerts];
1928
1929 newViewerFace2.n1 = this.normals[i];
1930 newViewerFace2.n2 = this.normals[iNext - numVerts];
1931 newViewerFace2.n3 = this.normals[iNext];
1932 }
1933 }
1934
1935 this.viewerFaces.Add(newViewerFace1);
1936 this.viewerFaces.Add(newViewerFace2);
1937
1938 }
1939 }
1940 }
1941
1942 lastCutNormal1 = newLayer.cutNormal1;
1943 lastCutNormal2 = newLayer.cutNormal2;
1944 lastV = 1.0f - node.percentOfPath;
1945
1946 if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode)
1947 {
1948 // add the top faces to the viewerFaces list here
1949 Coord faceNormal = newLayer.faceNormal;
1950 ViewerFace newViewerFace = new ViewerFace();
1951 newViewerFace.primFaceNumber = 0;
1952 int numFaces = newLayer.faces.Count;
1953 List<Face> faces = newLayer.faces;
1954
1955 for (int i = 0; i < numFaces; i++)
1956 {
1957 Face face = faces[i];
1958 newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen];
1959 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen];
1960 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen];
1961
1962 newViewerFace.coordIndex1 = face.v1 - coordsLen;
1963 newViewerFace.coordIndex2 = face.v2 - coordsLen;
1964 newViewerFace.coordIndex3 = face.v3 - coordsLen;
1965
1966 newViewerFace.n1 = faceNormal;
1967 newViewerFace.n2 = faceNormal;
1968 newViewerFace.n3 = faceNormal;
1969
1970 newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen];
1971 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen];
1972 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen];
1973
1974 this.viewerFaces.Add(newViewerFace);
1975 }
1976 }
1977
1978
1979 } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1980
1981 }
1982
1983
1984 /// <summary>
1985 /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism.
1986 /// </summary>
1282 public void ExtrudeLinear() 1987 public void ExtrudeLinear()
1283 { 1988 {
1284 this.coords = new List<Coord>(); 1989 this.coords = new List<Coord>();
@@ -1421,6 +2126,10 @@ namespace PrimMesher
1421 newViewerFace.v2 = newLayer.coords[face.v2]; 2126 newViewerFace.v2 = newLayer.coords[face.v2];
1422 newViewerFace.v3 = newLayer.coords[face.v3]; 2127 newViewerFace.v3 = newLayer.coords[face.v3];
1423 2128
2129 newViewerFace.coordIndex1 = face.v1;
2130 newViewerFace.coordIndex2 = face.v2;
2131 newViewerFace.coordIndex3 = face.v3;
2132
1424 newViewerFace.n1 = faceNormal; 2133 newViewerFace.n1 = faceNormal;
1425 newViewerFace.n2 = faceNormal; 2134 newViewerFace.n2 = faceNormal;
1426 newViewerFace.n3 = faceNormal; 2135 newViewerFace.n3 = faceNormal;
@@ -1437,6 +2146,7 @@ namespace PrimMesher
1437 // append this layer 2146 // append this layer
1438 2147
1439 int coordsLen = this.coords.Count; 2148 int coordsLen = this.coords.Count;
2149 int lastCoordsLen = coordsLen;
1440 newLayer.AddValue2FaceVertexIndices(coordsLen); 2150 newLayer.AddValue2FaceVertexIndices(coordsLen);
1441 2151
1442 this.coords.AddRange(newLayer.coords); 2152 this.coords.AddRange(newLayer.coords);
@@ -1470,6 +2180,7 @@ namespace PrimMesher
1470 iNext = startVert; 2180 iNext = startVert;
1471 2181
1472 int whichVert = i - startVert; 2182 int whichVert = i - startVert;
2183 //int whichVert2 = i - lastCoordsLen;
1473 2184
1474 newFace.v1 = i; 2185 newFace.v1 = i;
1475 newFace.v2 = i - numVerts; 2186 newFace.v2 = i - numVerts;
@@ -1483,9 +2194,11 @@ namespace PrimMesher
1483 if (this.viewerMode) 2194 if (this.viewerMode)
1484 { 2195 {
1485 // add the side faces to the list of viewerFaces here 2196 // add the side faces to the list of viewerFaces here
1486 int primFaceNum = 1; 2197 //int primFaceNum = 1;
1487 if (whichVert >= sides) 2198 //if (whichVert >= sides)
1488 primFaceNum = 2; 2199 // primFaceNum = 2;
2200 int primFaceNum = profile.faceNumbers[whichVert];
2201
1489 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); 2202 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum);
1490 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); 2203 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum);
1491 2204
@@ -1536,6 +2249,14 @@ namespace PrimMesher
1536 newViewerFace2.v2 = this.coords[iNext - numVerts]; 2249 newViewerFace2.v2 = this.coords[iNext - numVerts];
1537 newViewerFace2.v3 = this.coords[iNext]; 2250 newViewerFace2.v3 = this.coords[iNext];
1538 2251
2252 newViewerFace1.coordIndex1 = i;
2253 newViewerFace1.coordIndex2 = i - numVerts;
2254 newViewerFace1.coordIndex3 = iNext - numVerts;
2255
2256 newViewerFace2.coordIndex1 = i;
2257 newViewerFace2.coordIndex2 = iNext - numVerts;
2258 newViewerFace2.coordIndex3 = iNext;
2259
1539 // profile cut faces 2260 // profile cut faces
1540 if (whichVert == cut1Vert) 2261 if (whichVert == cut1Vert)
1541 { 2262 {
@@ -1573,7 +2294,7 @@ namespace PrimMesher
1573 } 2294 }
1574 } 2295 }
1575 2296
1576 newViewerFace2.primFaceNumber = newViewerFace1.primFaceNumber = newLayer.faceNumbers[whichVert]; 2297 //newViewerFace2.primFaceNumber = newViewerFace1.primFaceNumber = newLayer.faceNumbers[whichVert];
1577 2298
1578 this.viewerFaces.Add(newViewerFace1); 2299 this.viewerFaces.Add(newViewerFace1);
1579 this.viewerFaces.Add(newViewerFace2); 2300 this.viewerFaces.Add(newViewerFace2);
@@ -1616,6 +2337,10 @@ namespace PrimMesher
1616 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; 2337 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen];
1617 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen]; 2338 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen];
1618 2339
2340 newViewerFace.coordIndex1 = face.v1 - coordsLen;
2341 newViewerFace.coordIndex2 = face.v2 - coordsLen;
2342 newViewerFace.coordIndex3 = face.v3 - coordsLen;
2343
1619 newViewerFace.n1 = faceNormal; 2344 newViewerFace.n1 = faceNormal;
1620 newViewerFace.n2 = faceNormal; 2345 newViewerFace.n2 = faceNormal;
1621 newViewerFace.n3 = faceNormal; 2346 newViewerFace.n3 = faceNormal;
@@ -1630,6 +2355,7 @@ namespace PrimMesher
1630 } 2355 }
1631 } 2356 }
1632 2357
2358
1633 /// <summary> 2359 /// <summary>
1634 /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring. 2360 /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring.
1635 /// </summary> 2361 /// </summary>
@@ -1826,6 +2552,10 @@ namespace PrimMesher
1826 newViewerFace.v2 = newLayer.coords[face.v2]; 2552 newViewerFace.v2 = newLayer.coords[face.v2];
1827 newViewerFace.v3 = newLayer.coords[face.v3]; 2553 newViewerFace.v3 = newLayer.coords[face.v3];
1828 2554
2555 newViewerFace.coordIndex1 = face.v1;
2556 newViewerFace.coordIndex2 = face.v2;
2557 newViewerFace.coordIndex3 = face.v3;
2558
1829 newViewerFace.n1 = faceNormal; 2559 newViewerFace.n1 = faceNormal;
1830 newViewerFace.n2 = faceNormal; 2560 newViewerFace.n2 = faceNormal;
1831 newViewerFace.n3 = faceNormal; 2561 newViewerFace.n3 = faceNormal;
@@ -1886,9 +2616,13 @@ namespace PrimMesher
1886 2616
1887 if (this.viewerMode) 2617 if (this.viewerMode)
1888 { 2618 {
2619 int primFaceNumber = profile.faceNumbers[whichVert];
2620 if (!needEndFaces)
2621 primFaceNumber -= 1;
2622
1889 // add the side faces to the list of viewerFaces here 2623 // add the side faces to the list of viewerFaces here
1890 ViewerFace newViewerFace1 = new ViewerFace(); 2624 ViewerFace newViewerFace1 = new ViewerFace(primFaceNumber);
1891 ViewerFace newViewerFace2 = new ViewerFace(); 2625 ViewerFace newViewerFace2 = new ViewerFace(primFaceNumber);
1892 float u1 = newLayer.us[whichVert]; 2626 float u1 = newLayer.us[whichVert];
1893 float u2 = 1.0f; 2627 float u2 = 1.0f;
1894 if (whichVert < newLayer.us.Count - 1) 2628 if (whichVert < newLayer.us.Count - 1)
@@ -1936,6 +2670,14 @@ namespace PrimMesher
1936 newViewerFace2.v2 = this.coords[iNext - numVerts]; 2670 newViewerFace2.v2 = this.coords[iNext - numVerts];
1937 newViewerFace2.v3 = this.coords[iNext]; 2671 newViewerFace2.v3 = this.coords[iNext];
1938 2672
2673 newViewerFace1.coordIndex1 = i;
2674 newViewerFace1.coordIndex2 = i - numVerts;
2675 newViewerFace1.coordIndex3 = iNext - numVerts;
2676
2677 newViewerFace2.coordIndex1 = i;
2678 newViewerFace2.coordIndex2 = iNext - numVerts;
2679 newViewerFace2.coordIndex3 = iNext;
2680
1939 // profile cut faces 2681 // profile cut faces
1940 if (whichVert == cut1Vert) 2682 if (whichVert == cut1Vert)
1941 { 2683 {
@@ -1987,7 +2729,7 @@ namespace PrimMesher
1987 } 2729 }
1988 } 2730 }
1989 2731
1990 newViewerFace1.primFaceNumber = newViewerFace2.primFaceNumber = newLayer.faceNumbers[whichVert]; 2732 //newViewerFace1.primFaceNumber = newViewerFace2.primFaceNumber = newLayer.faceNumbers[whichVert];
1991 this.viewerFaces.Add(newViewerFace1); 2733 this.viewerFaces.Add(newViewerFace1);
1992 this.viewerFaces.Add(newViewerFace2); 2734 this.viewerFaces.Add(newViewerFace2);
1993 2735
@@ -2002,7 +2744,7 @@ namespace PrimMesher
2002 // calculate terms for next iteration 2744 // calculate terms for next iteration
2003 // calculate the angle for the next iteration of the loop 2745 // calculate the angle for the next iteration of the loop
2004 2746
2005 if (angle >= endAngle) 2747 if (angle >= endAngle - 0.01)
2006 done = true; 2748 done = true;
2007 else 2749 else
2008 { 2750 {
@@ -2017,6 +2759,7 @@ namespace PrimMesher
2017 // add the bottom faces to the viewerFaces list here 2759 // add the bottom faces to the viewerFaces list here
2018 Coord faceNormal = newLayer.faceNormal; 2760 Coord faceNormal = newLayer.faceNormal;
2019 ViewerFace newViewerFace = new ViewerFace(); 2761 ViewerFace newViewerFace = new ViewerFace();
2762 //newViewerFace.primFaceNumber = newLayer.bottomFaceNumber + 1;
2020 newViewerFace.primFaceNumber = newLayer.bottomFaceNumber; 2763 newViewerFace.primFaceNumber = newLayer.bottomFaceNumber;
2021 foreach (Face face in newLayer.faces) 2764 foreach (Face face in newLayer.faces)
2022 { 2765 {
@@ -2024,6 +2767,10 @@ namespace PrimMesher
2024 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; 2767 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen];
2025 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen]; 2768 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen];
2026 2769
2770 newViewerFace.coordIndex1 = face.v1 - coordsLen;
2771 newViewerFace.coordIndex2 = face.v2 - coordsLen;
2772 newViewerFace.coordIndex3 = face.v3 - coordsLen;
2773
2027 newViewerFace.n1 = faceNormal; 2774 newViewerFace.n1 = faceNormal;
2028 newViewerFace.n2 = faceNormal; 2775 newViewerFace.n2 = faceNormal;
2029 newViewerFace.n3 = faceNormal; 2776 newViewerFace.n3 = faceNormal;
@@ -2206,8 +2953,16 @@ namespace PrimMesher
2206 this.viewerFaces[i] = v; 2953 this.viewerFaces[i] = v;
2207 } 2954 }
2208 } 2955 }
2956 }
2209 2957
2958#if VERTEX_INDEXER
2959 public VertexIndexer GetVertexIndexer()
2960 {
2961 if (this.viewerMode && this.viewerFaces.Count > 0)
2962 return new VertexIndexer(this);
2963 return null;
2210 } 2964 }
2965#endif
2211 2966
2212 /// <summary> 2967 /// <summary>
2213 /// Scales the mesh 2968 /// Scales the mesh