diff options
author | dahlia | 2009-10-11 02:12:17 -0700 |
---|---|---|
committer | dahlia | 2009-10-11 02:12:17 -0700 |
commit | 7b4183d7a05079be975c954584ad6215e573755a (patch) | |
tree | 04576efc69a20ba6edb290e842795707e7afe2fa /OpenSim/Region | |
parent | disambiguate System.Path (preparation for new PrimMesher) (diff) | |
download | opensim-SC-7b4183d7a05079be975c954584ad6215e573755a.zip opensim-SC-7b4183d7a05079be975c954584ad6215e573755a.tar.gz opensim-SC-7b4183d7a05079be975c954584ad6215e573755a.tar.bz2 opensim-SC-7b4183d7a05079be975c954584ad6215e573755a.tar.xz |
sync PrimMesher with r46
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/PrimMesher.cs | 787 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/SculptMesh.cs | 14 |
2 files changed, 782 insertions, 19 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 |
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs index bd63aef..f1dd586 100644 --- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs +++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs | |||
@@ -436,9 +436,9 @@ namespace PrimMesher | |||
436 | { | 436 | { |
437 | Face face = this.faces[i]; | 437 | Face face = this.faces[i]; |
438 | Coord surfaceNormal = face.SurfaceNormal(this.coords); | 438 | Coord surfaceNormal = face.SurfaceNormal(this.coords); |
439 | this.normals[face.v1] += surfaceNormal; | 439 | this.normals[face.n1] += surfaceNormal; |
440 | this.normals[face.v2] += surfaceNormal; | 440 | this.normals[face.n2] += surfaceNormal; |
441 | this.normals[face.v3] += surfaceNormal; | 441 | this.normals[face.n3] += surfaceNormal; |
442 | } | 442 | } |
443 | 443 | ||
444 | int numNormals = this.normals.Count; | 444 | int numNormals = this.normals.Count; |
@@ -462,6 +462,10 @@ namespace PrimMesher | |||
462 | vf.v2 = this.coords[face.v2]; | 462 | vf.v2 = this.coords[face.v2]; |
463 | vf.v3 = this.coords[face.v3]; | 463 | vf.v3 = this.coords[face.v3]; |
464 | 464 | ||
465 | vf.coordIndex1 = face.v1; | ||
466 | vf.coordIndex2 = face.v2; | ||
467 | vf.coordIndex3 = face.v3; | ||
468 | |||
465 | vf.n1 = this.normals[face.n1]; | 469 | vf.n1 = this.normals[face.n1]; |
466 | vf.n2 = this.normals[face.n2]; | 470 | vf.n2 = this.normals[face.n2]; |
467 | vf.n3 = this.normals[face.n3]; | 471 | vf.n3 = this.normals[face.n3]; |
@@ -520,6 +524,10 @@ namespace PrimMesher | |||
520 | for (i = 0; i < numVerts; i++) | 524 | for (i = 0; i < numVerts; i++) |
521 | this.coords[i] *= q; | 525 | this.coords[i] *= q; |
522 | 526 | ||
527 | int numNormals = this.normals.Count; | ||
528 | for (i = 0; i < numNormals; i++) | ||
529 | this.normals[i] *= q; | ||
530 | |||
523 | if (this.viewerFaces != null) | 531 | if (this.viewerFaces != null) |
524 | { | 532 | { |
525 | int numViewerFaces = this.viewerFaces.Count; | 533 | int numViewerFaces = this.viewerFaces.Count; |