diff options
author | Teravus Ovares | 2008-05-29 20:20:50 +0000 |
---|---|---|
committer | Teravus Ovares | 2008-05-29 20:20:50 +0000 |
commit | 918f887c0c10fda33633548f3601bdf07d74edfd (patch) | |
tree | 2db5459288f52117a071fcc51c7f2d1d7a19a3b3 /OpenSim/Region/Physics/Meshing | |
parent | Mantis#1416. Thank you very much, Melanie for a patch that: (diff) | |
download | opensim-SC-918f887c0c10fda33633548f3601bdf07d74edfd.zip opensim-SC-918f887c0c10fda33633548f3601bdf07d74edfd.tar.gz opensim-SC-918f887c0c10fda33633548f3601bdf07d74edfd.tar.bz2 opensim-SC-918f887c0c10fda33633548f3601bdf07d74edfd.tar.xz |
* Applying Dahlia's interim path curve patch. it adds initial support for some tori/ring parameters. Thanks Dahlia!
* Some situations do not match the client's render of the tori, we know and are working on it. This is an initial support patch, so expect it to not be exact.
* Some tapers are acting slightly odd. Will fix.
Diffstat (limited to 'OpenSim/Region/Physics/Meshing')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Extruder.cs | 211 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/HelperTypes.cs | 36 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 450 |
3 files changed, 650 insertions, 47 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Extruder.cs b/OpenSim/Region/Physics/Meshing/Extruder.cs index c7dcf33..480ffda 100644 --- a/OpenSim/Region/Physics/Meshing/Extruder.cs +++ b/OpenSim/Region/Physics/Meshing/Extruder.cs | |||
@@ -47,6 +47,21 @@ namespace OpenSim.Region.Physics.Meshing | |||
47 | public float twistTop = 0; | 47 | public float twistTop = 0; |
48 | public float twistBot = 0; | 48 | public float twistBot = 0; |
49 | public float twistMid = 0; | 49 | public float twistMid = 0; |
50 | public float pathScaleX = 1.0f; | ||
51 | public float pathScaleY = 0.5f; | ||
52 | public float skew = 0.0f; | ||
53 | public float radius = 0.0f; | ||
54 | public float revolutions = 1.0f; | ||
55 | |||
56 | public float pathCutBegin = 0.0f; | ||
57 | public float pathCutEnd = 1.0f; | ||
58 | |||
59 | public ushort pathBegin = 0; | ||
60 | public ushort pathEnd = 0; | ||
61 | |||
62 | public float pathTaperX = 0.0f; | ||
63 | public float pathTaperY = 0.0f; | ||
64 | |||
50 | 65 | ||
51 | public Mesh Extrude(Mesh m) | 66 | public Mesh Extrude(Mesh m) |
52 | { | 67 | { |
@@ -230,5 +245,201 @@ namespace OpenSim.Region.Physics.Meshing | |||
230 | } | 245 | } |
231 | return result; | 246 | return result; |
232 | } | 247 | } |
248 | public Mesh ExtrudeCircularPath(Mesh m) | ||
249 | { | ||
250 | //startParameter = float.MinValue; | ||
251 | //stopParameter = float.MaxValue; | ||
252 | // Currently only works for iSteps=1; | ||
253 | Mesh result = new Mesh(); | ||
254 | |||
255 | Quaternion tt = new Quaternion(); | ||
256 | Vertex v2 = new Vertex(0, 0, 0); | ||
257 | |||
258 | Mesh newLayer; | ||
259 | Mesh lastLayer = null; | ||
260 | |||
261 | int start = 0; | ||
262 | int step; | ||
263 | int steps = 24; | ||
264 | |||
265 | float twistTotal = twistTop - twistBot; | ||
266 | if (System.Math.Abs(twistTotal) > (float)System.Math.PI * 1.5) steps *= 2; | ||
267 | if (System.Math.Abs(twistTotal) > (float)System.Math.PI * 3.0) steps *= 2; | ||
268 | |||
269 | double percentOfPathMultiplier = 1.0 / steps; | ||
270 | double angleStepMultiplier = System.Math.PI * 2.0 / steps; | ||
271 | |||
272 | //System.Console.WriteLine("twistTop: " + twistTop.ToString() + " twistbot: " + twistBot.ToString() + " twisttotal: " + twistTotal.ToString()); | ||
273 | |||
274 | float yPathScale = pathScaleY * 0.5f; | ||
275 | float skewStart = -skew; | ||
276 | float skewOffset = 0.0f; | ||
277 | float totalSkew = skew * 2.0f; | ||
278 | |||
279 | |||
280 | float startAngle = (float)(System.Math.PI * 2.0 * pathCutBegin * revolutions); | ||
281 | float endAngle = (float)(System.Math.PI * 2.0 * pathCutEnd * revolutions); | ||
282 | float stepSize = (float)0.2617993878; // 2*PI / 24 segments | ||
283 | step = (int)(startAngle / stepSize); | ||
284 | float angle = startAngle; | ||
285 | |||
286 | float xProfileScale = 1.0f; | ||
287 | float yProfileScale = 1.0f; | ||
288 | |||
289 | //System.Console.WriteLine("startAngle: " + startAngle.ToString() + " endAngle: " + endAngle.ToString() + " step: " + step.ToString()); | ||
290 | bool done = false; | ||
291 | |||
292 | //System.Console.WriteLine(" PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString()); | ||
293 | |||
294 | //System.Console.WriteLine("taperBotFactorX: " + taperBotFactorX.ToString() + " taperBotFactorY: " + taperBotFactorY.ToString() | ||
295 | // + " taperTopFactorX: " + taperTopFactorX.ToString() + " taperTopFactorY: " + taperTopFactorY.ToString()); | ||
296 | |||
297 | |||
298 | |||
299 | do | ||
300 | { | ||
301 | float percentOfPath = 1.0f; | ||
302 | |||
303 | percentOfPath = (angle - startAngle) / (endAngle - startAngle); // endAngle should always be larger than startAngle | ||
304 | |||
305 | // System.Console.WriteLine("angle: " + angle.ToString() + " percentOfPath: " + percentOfPath.ToString()); | ||
306 | |||
307 | if (pathTaperX > 0.001f) // can't really compare to 0.0f as the value passed is never exactly zero | ||
308 | xProfileScale = 1.0f - percentOfPath * pathTaperX; | ||
309 | else if (pathTaperX < -0.001f) | ||
310 | xProfileScale = 1.0f + (1.0f - percentOfPath) * pathTaperX; | ||
311 | else xProfileScale = 1.0f; | ||
312 | |||
313 | if (pathTaperY > 0.001f) | ||
314 | yProfileScale = 1.0f - percentOfPath * pathTaperY; | ||
315 | else if (pathTaperY < -0.001f) | ||
316 | yProfileScale = 1.0f + (1.0f - percentOfPath) * pathTaperY; | ||
317 | else yProfileScale = 1.0f; | ||
318 | |||
319 | float radiusScale; | ||
320 | |||
321 | if (radius > 0.001f) | ||
322 | radiusScale = 1.0f - radius * percentOfPath; | ||
323 | else if (radius < 0.001f) | ||
324 | radiusScale = 1.0f + radius * (1.0f - percentOfPath); | ||
325 | else radiusScale = 1.0f; | ||
326 | |||
327 | //radiusScale = 1.0f; | ||
328 | |||
329 | //System.Console.WriteLine("Extruder: radius: " + radius.ToString() + " radiusScale: " + radiusScale.ToString()); | ||
330 | |||
331 | |||
332 | |||
333 | |||
334 | |||
335 | float twist = twistBot + (twistTotal * (float)percentOfPath); | ||
336 | |||
337 | float zOffset = (float)(System.Math.Sin(angle) * (0.5f - yPathScale)) * radiusScale; | ||
338 | float yOffset = (float)(System.Math.Cos(angle) * (0.5f - yPathScale)) * radiusScale; | ||
339 | float xOffset = 0.5f * (skewStart + totalSkew * (float)percentOfPath); | ||
340 | |||
341 | newLayer = m.Clone(); | ||
342 | |||
343 | Vertex vTemp = new Vertex(0.0f, 0.0f, 0.0f); | ||
344 | |||
345 | if (twistTotal != 0.0f || twistBot != 0.0f) | ||
346 | { | ||
347 | Quaternion profileRot = new Quaternion(new Vertex(0.0f, 0.0f, -1.0f), twist); | ||
348 | foreach (Vertex v in newLayer.vertices) | ||
349 | { | ||
350 | if (v != null) | ||
351 | { | ||
352 | vTemp = v * profileRot; | ||
353 | v.X = vTemp.X; | ||
354 | v.Y = vTemp.Y; | ||
355 | v.Z = vTemp.Z; | ||
356 | } | ||
357 | } | ||
358 | } | ||
359 | |||
360 | Quaternion layerRot = new Quaternion(new Vertex(-1.0f, 0.0f, 0.0f), (float)angle); | ||
361 | foreach (Vertex v in newLayer.vertices) | ||
362 | { | ||
363 | if (v != null) | ||
364 | { | ||
365 | vTemp = v * layerRot; | ||
366 | v.X = xProfileScale * vTemp.X + xOffset; | ||
367 | v.Y = yProfileScale * vTemp.Y + yOffset; | ||
368 | v.Z = vTemp.Z + zOffset; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | if (angle == startAngle) // last layer, invert normals | ||
373 | foreach (Triangle t in newLayer.triangles) | ||
374 | { | ||
375 | t.invertNormal(); | ||
376 | } | ||
377 | |||
378 | result.Append(newLayer); | ||
379 | |||
380 | int iLastNull = 0; | ||
381 | |||
382 | if (lastLayer != null) | ||
383 | { | ||
384 | int i, count = newLayer.vertices.Count; | ||
385 | |||
386 | for (i = 0; i < count; i++) | ||
387 | { | ||
388 | int iNext = (i + 1); | ||
389 | |||
390 | if (lastLayer.vertices[i] == null) // cant make a simplex here | ||
391 | iLastNull = i + 1; | ||
392 | else | ||
393 | { | ||
394 | if (i == count - 1) // End of list | ||
395 | iNext = iLastNull; | ||
396 | |||
397 | if (lastLayer.vertices[iNext] == null) // Null means wrap to begin of last segment | ||
398 | iNext = iLastNull; | ||
399 | |||
400 | result.Add(new Triangle(newLayer.vertices[i], lastLayer.vertices[i], newLayer.vertices[iNext])); | ||
401 | result.Add(new Triangle(newLayer.vertices[iNext], lastLayer.vertices[i], lastLayer.vertices[iNext])); | ||
402 | } | ||
403 | } | ||
404 | } | ||
405 | lastLayer = newLayer; | ||
406 | |||
407 | |||
408 | |||
409 | |||
410 | |||
411 | |||
412 | |||
413 | |||
414 | // calc next angle | ||
415 | |||
416 | if (angle >= endAngle) | ||
417 | done = true; | ||
418 | else | ||
419 | { | ||
420 | angle = stepSize * ++step; | ||
421 | if (angle > endAngle) | ||
422 | angle = endAngle; | ||
423 | } | ||
424 | } | ||
425 | while (!done); | ||
426 | |||
427 | |||
428 | |||
429 | // scale the mesh to the desired size | ||
430 | float xScale = size.X; | ||
431 | float yScale = size.Y; | ||
432 | float zScale = size.Z; | ||
433 | |||
434 | foreach (Vertex v in result.vertices) | ||
435 | if (v != null) | ||
436 | { | ||
437 | v.X *= xScale; | ||
438 | v.Y *= yScale; | ||
439 | v.Z *= zScale; | ||
440 | } | ||
441 | |||
442 | return result; | ||
443 | } | ||
233 | } | 444 | } |
234 | } | 445 | } |
diff --git a/OpenSim/Region/Physics/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/Meshing/HelperTypes.cs index 584133c..f031fb6 100644 --- a/OpenSim/Region/Physics/Meshing/HelperTypes.cs +++ b/OpenSim/Region/Physics/Meshing/HelperTypes.cs | |||
@@ -51,9 +51,13 @@ public class Quaternion | |||
51 | { | 51 | { |
52 | // using (* 0.5) instead of (/2) | 52 | // using (* 0.5) instead of (/2) |
53 | w = (float)Math.Cos(angle * 0.5f); | 53 | w = (float)Math.Cos(angle * 0.5f); |
54 | x = axis.X * (float)Math.Sin(angle * 0.5f); | 54 | float sin = (float)Math.Sin(angle * 0.5f); |
55 | y = axis.Y * (float)Math.Sin(angle * 0.5f); | 55 | //x = axis.X * (float)Math.Sin(angle * 0.5f); |
56 | z = axis.Z * (float)Math.Sin(angle * 0.5f); | 56 | //y = axis.Y * (float)Math.Sin(angle * 0.5f); |
57 | //z = axis.Z * (float)Math.Sin(angle * 0.5f); | ||
58 | x = axis.X * sin; | ||
59 | y = axis.Y * sin; | ||
60 | z = axis.Z * sin; | ||
57 | normalize(); | 61 | normalize(); |
58 | } | 62 | } |
59 | public static Quaternion operator *(Quaternion a, Quaternion b) | 63 | public static Quaternion operator *(Quaternion a, Quaternion b) |
@@ -73,12 +77,18 @@ public class Quaternion | |||
73 | } | 77 | } |
74 | public void normalize() | 78 | public void normalize() |
75 | { | 79 | { |
76 | float mag = length(); | 80 | //float mag = length(); |
77 | 81 | ||
78 | w /= mag; | 82 | //w /= mag; |
79 | x /= mag; | 83 | //x /= mag; |
80 | y /= mag; | 84 | //y /= mag; |
81 | z /= mag; | 85 | //z /= mag; |
86 | float iMag = 1.0f / length(); | ||
87 | |||
88 | w *= iMag; | ||
89 | x *= iMag; | ||
90 | y *= iMag; | ||
91 | z *= iMag; | ||
82 | } | 92 | } |
83 | public float length() | 93 | public float length() |
84 | { | 94 | { |
@@ -169,7 +179,8 @@ public class Vertex : PhysicsVector, IComparable<Vertex> | |||
169 | float tlength = length(); | 179 | float tlength = length(); |
170 | if (tlength != 0) | 180 | if (tlength != 0) |
171 | { | 181 | { |
172 | return new Vertex(X / tlength, Y / tlength, Z / tlength); | 182 | float mul = 1.0f / tlength; |
183 | return new Vertex(X * mul, Y * mul, Z * mul); | ||
173 | } | 184 | } |
174 | else | 185 | else |
175 | { | 186 | { |
@@ -230,9 +241,10 @@ public class Vertex : PhysicsVector, IComparable<Vertex> | |||
230 | { | 241 | { |
231 | return new Vertex(0f,0f,0f); | 242 | return new Vertex(0f,0f,0f); |
232 | } | 243 | } |
233 | v1.X /= am; | 244 | float mul = 1.0f / am; |
234 | v1.Y /= am; | 245 | v1.X *= mul; |
235 | v1.Z /= am; | 246 | v1.Y *= mul; |
247 | v1.Z *= mul; | ||
236 | return v1; | 248 | return v1; |
237 | } | 249 | } |
238 | 250 | ||
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index ba4f941..5ef392c 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -29,6 +29,7 @@ using System; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using OpenSim.Framework; | 30 | using OpenSim.Framework; |
31 | using OpenSim.Region.Physics.Manager; | 31 | using OpenSim.Region.Physics.Manager; |
32 | using libsecondlife; | ||
32 | 33 | ||
33 | namespace OpenSim.Region.Physics.Meshing | 34 | namespace OpenSim.Region.Physics.Meshing |
34 | { | 35 | { |
@@ -253,7 +254,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
253 | holeHull.AddVertex(IPP); | 254 | holeHull.AddVertex(IPP); |
254 | holeHull.AddVertex(IPM); | 255 | holeHull.AddVertex(IPM); |
255 | } | 256 | } |
256 | if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) | 257 | //if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) |
258 | if ( hshape == HollowShape.Circle ) | ||
257 | { | 259 | { |
258 | float hollowFactorF = (float)fhollowFactor / (float)50000; | 260 | float hollowFactorF = (float)fhollowFactor / (float)50000; |
259 | 261 | ||
@@ -576,7 +578,6 @@ namespace OpenSim.Region.Physics.Meshing | |||
576 | } | 578 | } |
577 | } | 579 | } |
578 | 580 | ||
579 | |||
580 | if (pathShearX != 0) | 581 | if (pathShearX != 0) |
581 | { | 582 | { |
582 | if (pathShearX > 50) | 583 | if (pathShearX > 50) |
@@ -647,7 +648,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
647 | return result; | 648 | return result; |
648 | } | 649 | } |
649 | 650 | ||
650 | private static Mesh CreateCyllinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | 651 | private static Mesh CreateCylinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) |
651 | // Builds the z (+ and -) surfaces of a box shaped prim | 652 | // Builds the z (+ and -) surfaces of a box shaped prim |
652 | { | 653 | { |
653 | 654 | ||
@@ -1318,6 +1319,317 @@ namespace OpenSim.Region.Physics.Meshing | |||
1318 | return sm; | 1319 | return sm; |
1319 | 1320 | ||
1320 | } | 1321 | } |
1322 | |||
1323 | private static Mesh CreateCircularProfileMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | ||
1324 | { | ||
1325 | |||
1326 | UInt16 hollowFactor = primShape.ProfileHollow; | ||
1327 | UInt16 profileBegin = primShape.ProfileBegin; | ||
1328 | UInt16 profileEnd = primShape.ProfileEnd; | ||
1329 | UInt16 taperX = primShape.PathScaleX; | ||
1330 | UInt16 taperY = primShape.PathScaleY; | ||
1331 | UInt16 pathShearX = primShape.PathShearX; | ||
1332 | UInt16 pathShearY = primShape.PathShearY; | ||
1333 | Int16 twistBot = primShape.PathTwist; | ||
1334 | Int16 twistTop = primShape.PathTwistBegin; | ||
1335 | HollowShape hollowShape = primShape.HollowShape; | ||
1336 | |||
1337 | //Console.WriteLine("pathTwist: " + primShape.PathTwist.ToString() + " pathTwistBegin: " + primShape.PathTwistBegin.ToString()); | ||
1338 | |||
1339 | SimpleHull outerHull = new SimpleHull(); | ||
1340 | |||
1341 | //Console.WriteLine("primShape.ProfileCurve & 0x07: " + Convert.ToString(primShape.ProfileCurve & 0x07)); | ||
1342 | |||
1343 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
1344 | |||
1345 | //if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle | ||
1346 | // || (primShape.ProfileCurve & 0x07) == (byte) ProfileShape.Square) | ||
1347 | { | ||
1348 | //Console.WriteLine("Meshmerizer thinks " + primName + " is a TORUS"); | ||
1349 | if ( hollowShape == HollowShape.Same ) | ||
1350 | hollowShape = HollowShape.Circle; | ||
1351 | |||
1352 | // build the profile shape | ||
1353 | // counter-clockwise around the quadrants, start at 45 degrees | ||
1354 | |||
1355 | outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees | ||
1356 | outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees | ||
1357 | outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees | ||
1358 | outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees | ||
1359 | outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees | ||
1360 | outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees | ||
1361 | outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees | ||
1362 | outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees | ||
1363 | outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees | ||
1364 | outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees | ||
1365 | outerHull.AddVertex(new Vertex(-0.482963f, -0.129410f, 0.0f)); // 195 degrees | ||
1366 | outerHull.AddVertex(new Vertex(-0.433013f, -0.250000f, 0.0f)); // 210 degrees | ||
1367 | outerHull.AddVertex(new Vertex(-0.353553f, -0.353553f, 0.0f)); // 225 degrees | ||
1368 | outerHull.AddVertex(new Vertex(-0.250000f, -0.433013f, 0.0f)); // 240 degrees | ||
1369 | outerHull.AddVertex(new Vertex(-0.129410f, -0.482963f, 0.0f)); // 255 degrees | ||
1370 | outerHull.AddVertex(new Vertex(0.000000f, -0.500000f, 0.0f)); // 270 degrees | ||
1371 | outerHull.AddVertex(new Vertex(0.129410f, -0.482963f, 0.0f)); // 285 degrees | ||
1372 | outerHull.AddVertex(new Vertex(0.250000f, -0.433013f, 0.0f)); // 300 degrees | ||
1373 | outerHull.AddVertex(new Vertex(0.353553f, -0.353553f, 0.0f)); // 315 degrees | ||
1374 | outerHull.AddVertex(new Vertex(0.433013f, -0.250000f, 0.0f)); // 330 degrees | ||
1375 | outerHull.AddVertex(new Vertex(0.482963f, -0.129410f, 0.0f)); // 345 degrees | ||
1376 | outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees | ||
1377 | outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees | ||
1378 | outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees | ||
1379 | } | ||
1380 | |||
1381 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) // a ring | ||
1382 | { | ||
1383 | //Console.WriteLine("Meshmerizer thinks " + primName + " is a TUBE"); | ||
1384 | if ( hollowShape == HollowShape.Same ) | ||
1385 | hollowShape = HollowShape.Square; | ||
1386 | |||
1387 | outerHull.AddVertex(new Vertex(+0.5f, +0.5f, 0.0f)); | ||
1388 | outerHull.AddVertex(new Vertex(-0.5f, +0.5f, 0.0f)); | ||
1389 | outerHull.AddVertex(new Vertex(-0.5f, -0.5f, 0.0f)); | ||
1390 | outerHull.AddVertex(new Vertex(+0.5f, -0.5f, 0.0f)); | ||
1391 | } | ||
1392 | |||
1393 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
1394 | { | ||
1395 | //Console.WriteLine("Meshmerizer thinks " + primName + " is a RING"); | ||
1396 | if ( hollowShape == HollowShape.Same ) | ||
1397 | hollowShape = HollowShape.Triangle; | ||
1398 | |||
1399 | outerHull.AddVertex(new Vertex(+0.255f, -0.375f, 0.0f)); | ||
1400 | outerHull.AddVertex(new Vertex(+0.25f, +0.375f, 0.0f)); | ||
1401 | outerHull.AddVertex(new Vertex(-0.5f, +0.0f, 0.0f)); | ||
1402 | |||
1403 | } | ||
1404 | |||
1405 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
1406 | { | ||
1407 | //Console.WriteLine("Meshmerizer thinks " + primName + " is a SPHERE"); | ||
1408 | if (hollowShape == HollowShape.Same) | ||
1409 | hollowShape = HollowShape.Circle; | ||
1410 | |||
1411 | // not implemented here, use old routine | ||
1412 | return CreateSphereMesh(primName, primShape, size); | ||
1413 | } | ||
1414 | |||
1415 | // Deal with cuts now | ||
1416 | if ((profileBegin != 0) || (profileEnd != 0)) | ||
1417 | { | ||
1418 | double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; | ||
1419 | // In degree, for easier debugging and understanding | ||
1420 | //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y | ||
1421 | double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 | ||
1422 | //fProfileEndAngle -= (90.0 + 45.0); | ||
1423 | if (fProfileBeginAngle < fProfileEndAngle) | ||
1424 | fProfileEndAngle -= 360.0; | ||
1425 | |||
1426 | // Note, that we don't want to cut out a triangle, even if this is a | ||
1427 | // good approximation for small cuts. Indeed we want to cut out an arc | ||
1428 | // and we approximate this arc by a polygon chain | ||
1429 | // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space | ||
1430 | // So it can easily be subtracted from the outer hull | ||
1431 | int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); | ||
1432 | // how many steps do we need with approximately 45 degree | ||
1433 | double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps; | ||
1434 | |||
1435 | Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); | ||
1436 | |||
1437 | // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull | ||
1438 | SimpleHull cutHull = new SimpleHull(); | ||
1439 | cutHull.AddVertex(origin); | ||
1440 | for (int i = 0; i < iSteps; i++) | ||
1441 | { | ||
1442 | double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!! | ||
1443 | Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); | ||
1444 | cutHull.AddVertex(v); | ||
1445 | } | ||
1446 | Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); | ||
1447 | // Calculated separately to avoid errors | ||
1448 | cutHull.AddVertex(legEnd); | ||
1449 | |||
1450 | // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); | ||
1451 | SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); | ||
1452 | |||
1453 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
1454 | { | ||
1455 | Quaternion zFlip = new Quaternion(new Vertex(0.0f, 0.0f, 1.0f), (float)Math.PI); | ||
1456 | Vertex vTmp = new Vertex(0.0f, 0.0f, 0.0f); | ||
1457 | foreach (Vertex v in cuttedHull.getVertices()) | ||
1458 | if (v != null) | ||
1459 | { | ||
1460 | vTmp = v * zFlip; | ||
1461 | v.X = vTmp.X; | ||
1462 | v.Y = vTmp.Y; | ||
1463 | v.Z = vTmp.Z; | ||
1464 | } | ||
1465 | } | ||
1466 | |||
1467 | outerHull = cuttedHull; | ||
1468 | } | ||
1469 | |||
1470 | // Deal with the hole here | ||
1471 | if (hollowFactor > 0) | ||
1472 | { | ||
1473 | SimpleHull holeHull; | ||
1474 | |||
1475 | if (hollowShape == HollowShape.Triangle) | ||
1476 | { | ||
1477 | holeHull = new SimpleHull(); | ||
1478 | |||
1479 | float hollowFactorF = (float) hollowFactor / 50000.0f; | ||
1480 | |||
1481 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
1482 | { | ||
1483 | holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, -0.1875f * hollowFactorF, 0.0f)); | ||
1484 | holeHull.AddVertex(new Vertex(-0.25f * hollowFactorF, -0f * hollowFactorF, 0.0f)); | ||
1485 | holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, +0.1875f * hollowFactorF, 0.0f)); | ||
1486 | } | ||
1487 | else | ||
1488 | { | ||
1489 | holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f)); | ||
1490 | holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, -0f * hollowFactorF, 0.0f)); | ||
1491 | holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f)); | ||
1492 | |||
1493 | ////holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, -0f * hollowFactorF, 0.0f)); | ||
1494 | |||
1495 | ////holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f)); | ||
1496 | |||
1497 | ////holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f)); | ||
1498 | |||
1499 | //holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f)); | ||
1500 | //holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f)); | ||
1501 | //holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f)); | ||
1502 | ////holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f)); | ||
1503 | } | ||
1504 | } | ||
1505 | else | ||
1506 | { | ||
1507 | holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor); | ||
1508 | } | ||
1509 | |||
1510 | if (holeHull != null) | ||
1511 | { | ||
1512 | SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); | ||
1513 | |||
1514 | outerHull = hollowedHull; | ||
1515 | } | ||
1516 | } | ||
1517 | |||
1518 | Mesh m = new Mesh(); | ||
1519 | |||
1520 | Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); | ||
1521 | Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); | ||
1522 | Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); | ||
1523 | |||
1524 | m.Add(Seed1); | ||
1525 | m.Add(Seed2); | ||
1526 | m.Add(Seed3); | ||
1527 | |||
1528 | m.Add(new Triangle(Seed1, Seed2, Seed3)); | ||
1529 | m.Add(outerHull.getVertices()); | ||
1530 | |||
1531 | InsertVertices(m.vertices, 3, m.triangles); | ||
1532 | m.DumpRaw(baseDir, primName, "Proto first Mesh"); | ||
1533 | |||
1534 | m.Remove(Seed1); | ||
1535 | m.Remove(Seed2); | ||
1536 | m.Remove(Seed3); | ||
1537 | m.DumpRaw(baseDir, primName, "Proto seeds removed"); | ||
1538 | |||
1539 | m.RemoveTrianglesOutside(outerHull); | ||
1540 | m.DumpRaw(baseDir, primName, "Proto outsides removed"); | ||
1541 | |||
1542 | foreach (Triangle t in m.triangles) | ||
1543 | t.invertNormal(); | ||
1544 | |||
1545 | Vertex vTemp = new Vertex(0.0f, 0.0f, 0.0f); | ||
1546 | |||
1547 | //Console.WriteLine("primShape.PathScaleX: " + primShape.PathScaleX.ToString() + " primShape.PathScaleY: " + primShape.PathScaleY.ToString()); | ||
1548 | //Console.WriteLine("primShape.PathSkew: " + primShape.PathSkew.ToString() + " primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString() + " primShape.pathRevolutions: " + primShape.PathRevolutions.ToString()); | ||
1549 | |||
1550 | float skew = primShape.PathSkew * 0.01f; | ||
1551 | float pathScaleX = (float)(200 - primShape.PathScaleX) * 0.01f; | ||
1552 | float pathScaleY = (float)(200 - primShape.PathScaleY) * 0.01f; | ||
1553 | //Console.WriteLine("PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString()); | ||
1554 | |||
1555 | float profileXComp = pathScaleX * (1.0f - Math.Abs(skew)); | ||
1556 | foreach (Vertex v in m.vertices) | ||
1557 | if (v != null) | ||
1558 | { | ||
1559 | v.X *= profileXComp; | ||
1560 | v.Y *= pathScaleY; | ||
1561 | //v.Y *= 0.5f; // torus profile is scaled in y axis | ||
1562 | } | ||
1563 | |||
1564 | Extruder extr = new Extruder(); | ||
1565 | |||
1566 | extr.size = size; | ||
1567 | extr.pathScaleX = pathScaleX; | ||
1568 | extr.pathScaleY = pathScaleY; | ||
1569 | extr.pathCutBegin = 0.00002f * primShape.PathBegin; | ||
1570 | extr.pathCutEnd = 0.00002f * (50000 - primShape.PathEnd); | ||
1571 | extr.pathBegin = primShape.PathBegin; | ||
1572 | extr.pathEnd = primShape.PathEnd; | ||
1573 | extr.skew = skew; | ||
1574 | extr.revolutions = 1.0f + (float)primShape.PathRevolutions * 3.0f / 200.0f; | ||
1575 | |||
1576 | //System.Console.WriteLine("primShape.PathBegin: " + primShape.PathBegin.ToString() + " primShape.PathEnd: " + primShape.PathEnd.ToString()); | ||
1577 | //System.Console.WriteLine("extr.pathCutBegin: " + extr.pathCutBegin.ToString() + " extr.pathCutEnd: " + extr.pathCutEnd.ToString()); | ||
1578 | //System.Console.WriteLine("extr.revolutions: " + extr.revolutions.ToString()); | ||
1579 | |||
1580 | //System.Console.WriteLine("primShape.PathTaperX: " + primShape.PathTaperX.ToString()); | ||
1581 | //System.Console.WriteLine("primShape.PathTaperY: " + primShape.PathTaperY.ToString()); | ||
1582 | |||
1583 | extr.pathTaperX = 0.01f * (float)primShape.PathTaperX; | ||
1584 | extr.pathTaperY = 0.01f * (float)primShape.PathTaperY; | ||
1585 | |||
1586 | extr.radius = 0.01f * (float)primShape.PathRadiusOffset; | ||
1587 | //System.Console.WriteLine("primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString()); | ||
1588 | |||
1589 | |||
1590 | |||
1591 | |||
1592 | |||
1593 | if (pathShearX != 0) | ||
1594 | { | ||
1595 | if (pathShearX > 50) | ||
1596 | { | ||
1597 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
1598 | extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); | ||
1599 | //m_log.Warn("pushX: " + extr.pushX); | ||
1600 | } | ||
1601 | else | ||
1602 | { | ||
1603 | extr.pushX = (float)pathShearX / 100; | ||
1604 | //m_log.Warn("pushX: " + extr.pushX); | ||
1605 | } | ||
1606 | } | ||
1607 | |||
1608 | if (pathShearY != 0) | ||
1609 | { | ||
1610 | if (pathShearY > 50) | ||
1611 | { | ||
1612 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
1613 | extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); | ||
1614 | //m_log.Warn("pushY: " + extr.pushY); | ||
1615 | } | ||
1616 | else | ||
1617 | { | ||
1618 | extr.pushY = (float)pathShearY / 100; | ||
1619 | //m_log.Warn("pushY: " + extr.pushY); | ||
1620 | } | ||
1621 | |||
1622 | } | ||
1623 | |||
1624 | extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.02f; | ||
1625 | extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.02f; | ||
1626 | |||
1627 | //System.Console.WriteLine("[MESH]: twistTop = " + twistTop.ToString() + "|" + extr.twistTop.ToString() + ", twistMid = " + twistMid.ToString() + "|" + extr.twistMid.ToString() + ", twistbot = " + twistBot.ToString() + "|" + extr.twistBot.ToString()); | ||
1628 | Mesh result = extr.ExtrudeCircularPath(m); | ||
1629 | result.DumpRaw(baseDir, primName, "Z extruded"); | ||
1630 | return result; | ||
1631 | } | ||
1632 | |||
1321 | public static void CalcNormals(Mesh mesh) | 1633 | public static void CalcNormals(Mesh mesh) |
1322 | { | 1634 | { |
1323 | int iTriangles = mesh.triangles.Count; | 1635 | int iTriangles = mesh.triangles.Count; |
@@ -1432,43 +1744,111 @@ namespace OpenSim.Region.Physics.Meshing | |||
1432 | mesh = (Mesh)smesh; | 1744 | mesh = (Mesh)smesh; |
1433 | CalcNormals(mesh); | 1745 | CalcNormals(mesh); |
1434 | } | 1746 | } |
1435 | else | 1747 | else if ((primShape.ProfileCurve & (byte)ProfileShape.Square) == (byte)ProfileShape.Square) |
1748 | { | ||
1749 | if (primShape.PathCurve == (byte)LLObject.PathCurve.Line) | ||
1750 | { // its a box | ||
1751 | mesh = CreateBoxMesh(primName, primShape, size); | ||
1752 | CalcNormals(mesh); | ||
1753 | } | ||
1754 | else if (primShape.PathCurve == (byte)LLObject.PathCurve.Circle) | ||
1755 | { // tube | ||
1756 | // do a cylinder for now | ||
1757 | //mesh = CreateCylinderMesh(primName, primShape, size); | ||
1758 | mesh = CreateCircularProfileMesh(primName, primShape, size); | ||
1759 | CalcNormals(mesh); | ||
1760 | } | ||
1761 | } | ||
1762 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
1436 | { | 1763 | { |
1437 | switch (primShape.ProfileShape) | 1764 | if (primShape.PathCurve == (byte)Extrusion.Straight) |
1438 | { | 1765 | { |
1439 | case ProfileShape.Square: | 1766 | mesh = CreateCylinderMesh(primName, primShape, size); |
1440 | mesh = CreateBoxMesh(primName, primShape, size); | 1767 | CalcNormals(mesh); |
1441 | CalcNormals(mesh); | 1768 | } |
1442 | break; | ||
1443 | case ProfileShape.Circle: | ||
1444 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
1445 | { | ||
1446 | mesh = CreateCyllinderMesh(primName, primShape, size); | ||
1447 | CalcNormals(mesh); | ||
1448 | } | ||
1449 | break; | ||
1450 | case ProfileShape.HalfCircle: | ||
1451 | if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
1452 | { | ||
1453 | mesh = CreateSphereMesh(primName, primShape, size); | ||
1454 | CalcNormals(mesh); | ||
1455 | } | ||
1456 | break; | ||
1457 | |||
1458 | case ProfileShape.EquilateralTriangle: | ||
1459 | mesh = CreatePrismMesh(primName, primShape, size); | ||
1460 | CalcNormals(mesh); | ||
1461 | break; | ||
1462 | 1769 | ||
1463 | default: | 1770 | // look at LLObject.cs in libsecondlife for how to know the prim type |
1464 | mesh = CreateBoxMesh(primName, primShape, size); | 1771 | // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits |
1465 | CalcNormals(mesh); | 1772 | else if (primShape.PathCurve == (byte) Extrusion.Curve1 && LLObject.UnpackPathScale(primShape.PathScaleY) <= 0.75f) |
1466 | //Set default mesh to cube otherwise it'll return | 1773 | { // dahlia's favorite, a torus :) |
1467 | // null and crash on the 'setMesh' method in the physics plugins. | 1774 | mesh = CreateCircularProfileMesh(primName, primShape, size); |
1468 | //mesh = null; | 1775 | CalcNormals(mesh); |
1469 | break; | ||
1470 | } | 1776 | } |
1471 | } | 1777 | } |
1778 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
1779 | { | ||
1780 | if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte) Extrusion.Curve2) | ||
1781 | { | ||
1782 | mesh = CreateSphereMesh(primName, primShape, size); | ||
1783 | CalcNormals(mesh); | ||
1784 | } | ||
1785 | } | ||
1786 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
1787 | { | ||
1788 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
1789 | { | ||
1790 | mesh = CreatePrismMesh(primName, primShape, size); | ||
1791 | CalcNormals(mesh); | ||
1792 | } | ||
1793 | else if (primShape.PathCurve == (byte) Extrusion.Curve1) | ||
1794 | { // a ring - do a cylinder for now | ||
1795 | //mesh = CreateCylinderMesh(primName, primShape, size); | ||
1796 | mesh = CreateCircularProfileMesh(primName, primShape, size); | ||
1797 | CalcNormals(mesh); | ||
1798 | } | ||
1799 | } | ||
1800 | else // just do a box | ||
1801 | { | ||
1802 | mesh = CreateBoxMesh(primName, primShape, size); | ||
1803 | CalcNormals(mesh); | ||
1804 | } | ||
1805 | |||
1806 | //else | ||
1807 | //{ | ||
1808 | // switch (primShape.ProfileShape) | ||
1809 | // { | ||
1810 | // case ProfileShape.Square: | ||
1811 | // mesh = CreateBoxMesh(primName, primShape, size); | ||
1812 | // CalcNormals(mesh); | ||
1813 | // break; | ||
1814 | // case ProfileShape.Circle: | ||
1815 | // if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
1816 | // { | ||
1817 | // mesh = CreateCylinderMesh(primName, primShape, size); | ||
1818 | // CalcNormals(mesh); | ||
1819 | // } | ||
1820 | |||
1821 | // // look at LLObject.cs in libsecondlife for how to know the prim type | ||
1822 | // // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits | ||
1823 | // else if ((primShape.ProfileCurve & 0x07) == (byte)LLObject.ProfileCurve.Circle && LLObject.UnpackPathScale(primShape.PathScaleY) <= 0.75f) | ||
1824 | // { // dahlia's favorite, a torus :) | ||
1825 | // mesh = CreateCylinderMesh(primName, primShape, size); | ||
1826 | // CalcNormals(mesh); | ||
1827 | // } | ||
1828 | |||
1829 | // break; | ||
1830 | // case ProfileShape.HalfCircle: | ||
1831 | // if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
1832 | // { | ||
1833 | // mesh = CreateSphereMesh(primName, primShape, size); | ||
1834 | // CalcNormals(mesh); | ||
1835 | // } | ||
1836 | // break; | ||
1837 | |||
1838 | // case ProfileShape.EquilateralTriangle: | ||
1839 | // mesh = CreatePrismMesh(primName, primShape, size); | ||
1840 | // CalcNormals(mesh); | ||
1841 | // break; | ||
1842 | |||
1843 | // default: | ||
1844 | // mesh = CreateBoxMesh(primName, primShape, size); | ||
1845 | // CalcNormals(mesh); | ||
1846 | // //Set default mesh to cube otherwise it'll return | ||
1847 | // // null and crash on the 'setMesh' method in the physics plugins. | ||
1848 | // //mesh = null; | ||
1849 | // break; | ||
1850 | // } | ||
1851 | //} | ||
1472 | 1852 | ||
1473 | return mesh; | 1853 | return mesh; |
1474 | } | 1854 | } |