aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
diff options
context:
space:
mode:
authorDahlia Trimble2008-11-29 11:02:14 +0000
committerDahlia Trimble2008-11-29 11:02:14 +0000
commitfdd238833163eb947986bfcdd09da82f6949a5f2 (patch)
tree6b90177758405f6106f4f5d4d75e3b98bf08053c /OpenSim/Region/Physics/Meshing/Meshmerizer.cs
parentComment the ScriptSponsor and restore the indefinite lifetime for (diff)
downloadopensim-SC_OLD-fdd238833163eb947986bfcdd09da82f6949a5f2.zip
opensim-SC_OLD-fdd238833163eb947986bfcdd09da82f6949a5f2.tar.gz
opensim-SC_OLD-fdd238833163eb947986bfcdd09da82f6949a5f2.tar.bz2
opensim-SC_OLD-fdd238833163eb947986bfcdd09da82f6949a5f2.tar.xz
Update meshing code to sync with current PrimMesher.cs on forge.
Migrate sculpt meshing code to primMesher version. This should result in more accurate physical sculpted prim proxies. Remove much obsolete code from Region/Physics/Meshing
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Meshmerizer.cs')
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs1761
1 files changed, 131 insertions, 1630 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 6955aa0..a65d0f4 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -31,6 +31,9 @@ using System.Collections.Generic;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager; 32using OpenSim.Region.Physics.Manager;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Imaging;
35using System.Drawing;
36using System.Drawing.Imaging;
34using PrimMesher; 37using PrimMesher;
35 38
36namespace OpenSim.Region.Physics.Meshing 39namespace OpenSim.Region.Physics.Meshing
@@ -54,8 +57,6 @@ namespace OpenSim.Region.Physics.Meshing
54 57
55 public class Meshmerizer : IMesher 58 public class Meshmerizer : IMesher
56 { 59 {
57 private bool usePrimMesher = true;
58
59 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 60 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
60 61
61 // Setting baseDir to a path will enable the dumping of raw files 62 // Setting baseDir to a path will enable the dumping of raw files
@@ -65,277 +66,9 @@ namespace OpenSim.Region.Physics.Meshing
65#else 66#else
66 private const string baseDir = null; //"rawFiles"; 67 private const string baseDir = null; //"rawFiles";
67#endif 68#endif
68 private const float DEG_TO_RAD = 0.01745329238f;
69 69
70 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh 70 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
71 71
72// private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2,
73// PhysicsVector r2, ref float lambda, ref float mu)
74// {
75 // p1, p2, points on the straight
76 // r1, r2, directional vectors of the straight. Not necessarily of length 1!
77 // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
78 // thus allowing to decide whether an intersection is between two points
79
80// float r1x = r1.X;
81// float r1y = r1.Y;
82// float r2x = r2.X;
83// float r2y = r2.Y;
84//
85// float denom = r1y * r2x - r1x * r2y;
86//
87// if (denom == 0.0)
88// {
89// lambda = Single.NaN;
90// mu = Single.NaN;
91// return;
92// }
93//
94// float p1x = p1.X;
95// float p1y = p1.Y;
96// float p2x = p2.X;
97// float p2y = p2.Y;
98// lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom;
99// mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom;
100// }
101
102 private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
103 {
104 List<Triangle> influenced = new List<Triangle>();
105 foreach (Triangle t in triangles)
106 {
107 if (t.isInCircle(v.X, v.Y))
108 {
109 influenced.Add(t);
110 }
111 }
112 return influenced;
113 }
114
115 private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
116 {
117 // This is a variant of the delaunay algorithm
118 // each time a new vertex is inserted, all triangles that are influenced by it are deleted
119 // and replaced by new ones including the new vertex
120 // It is not very time efficient but easy to implement.
121
122 int iCurrentVertex;
123 int iMaxVertex = vertices.Count;
124 for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
125 {
126 // Background: A triangle mesh fulfills the delaunay condition if (iff!)
127 // each circumlocutory circle (i.e. the circle that touches all three corners)
128 // of each triangle is empty of other vertices.
129 // Obviously a single (seeding) triangle fulfills this condition.
130 // If we now add one vertex, we need to reconstruct all triangles, that
131 // do not fulfill this condition with respect to the new triangle
132
133 // Find the triangles that are influenced by the new vertex
134 Vertex v = vertices[iCurrentVertex];
135 if (v == null)
136 continue; // Null is polygon stop marker. Ignore it
137 List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v);
138
139 List<Simplex> simplices = new List<Simplex>();
140
141 // Reconstruction phase. First step, dissolve each triangle into it's simplices,
142 // i.e. it's "border lines"
143 // Goal is to find "inner" borders and delete them, while the hull gets conserved.
144 // Inner borders are special in the way that they always come twice, which is how we detect them
145 foreach (Triangle t in influencedTriangles)
146 {
147 List<Simplex> newSimplices = t.GetSimplices();
148 simplices.AddRange(newSimplices);
149 triangles.Remove(t);
150 }
151 // Now sort the simplices. That will make identical ones reside side by side in the list
152 simplices.Sort();
153
154 // Look for duplicate simplices here.
155 // Remember, they are directly side by side in the list right now,
156 // So we only check directly neighbours
157 int iSimplex;
158 List<Simplex> innerSimplices = new List<Simplex>();
159 for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
160 {
161 if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0)
162 {
163 innerSimplices.Add(simplices[iSimplex - 1]);
164 innerSimplices.Add(simplices[iSimplex]);
165 }
166 }
167
168 foreach (Simplex s in innerSimplices)
169 {
170 simplices.Remove(s);
171 }
172
173 // each simplex still in the list belongs to the hull of the region in question
174 // The new vertex (yes, we still deal with verices here :-)) forms a triangle
175 // with each of these simplices. Build the new triangles and add them to the list
176 foreach (Simplex s in simplices)
177 {
178 Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
179 if (!t.isDegraded())
180 {
181 triangles.Add(t);
182 }
183 }
184 }
185 }
186
187 private static SimpleHull BuildHoleHull(PrimitiveBaseShape pbs, ProfileShape pshape, HollowShape hshape, UInt16 hollowFactor)
188 {
189 // Tackle HollowShape.Same
190 float fhollowFactor = (float)hollowFactor;
191
192 switch (pshape)
193 {
194 case ProfileShape.Square:
195 if (hshape == HollowShape.Same)
196 hshape= HollowShape.Square;
197 break;
198 case ProfileShape.EquilateralTriangle:
199 fhollowFactor = ((float)hollowFactor / 1.9f);
200 if (hshape == HollowShape.Same)
201 {
202 hshape = HollowShape.Triangle;
203 }
204
205 break;
206
207 case ProfileShape.HalfCircle:
208 case ProfileShape.Circle:
209 if (pbs.PathCurve == (byte)Extrusion.Straight)
210 {
211 if (hshape == HollowShape.Same)
212 {
213 hshape = HollowShape.Circle;
214 }
215 }
216 break;
217
218
219 default:
220 if (hshape == HollowShape.Same)
221 hshape= HollowShape.Square;
222 break;
223 }
224
225
226 SimpleHull holeHull = null;
227
228 if (hshape == HollowShape.Square)
229 {
230 float hollowFactorF = (float)fhollowFactor / (float)50000;
231 Vertex IMM;
232 Vertex IPM;
233 Vertex IPP;
234 Vertex IMP;
235
236 if (pshape == ProfileShape.Circle)
237 { // square cutout in cylinder is 45 degress rotated
238 IMM = new Vertex(0.0f, -0.707f * hollowFactorF, 0.0f);
239 IPM = new Vertex(0.707f * hollowFactorF, 0.0f, 0.0f);
240 IPP = new Vertex(0.0f, 0.707f * hollowFactorF, 0.0f);
241 IMP = new Vertex(-0.707f * hollowFactorF, 0.0f, 0.0f);
242 }
243 else if (pshape == ProfileShape.EquilateralTriangle)
244 {
245 IMM = new Vertex(0.0f, -0.667f * hollowFactorF, 0.0f);
246 IPM = new Vertex(0.667f * hollowFactorF, 0.0f, 0.0f);
247 IPP = new Vertex(0.0f, 0.667f * hollowFactorF, 0.0f);
248 IMP = new Vertex(-0.667f * hollowFactorF, 0.0f, 0.0f);
249 }
250 else
251 {
252 IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
253 IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
254 IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
255 IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
256 }
257
258 holeHull = new SimpleHull();
259
260 holeHull.AddVertex(IMM);
261 holeHull.AddVertex(IMP);
262 holeHull.AddVertex(IPP);
263 holeHull.AddVertex(IPM);
264 }
265 //if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
266 if (hshape == HollowShape.Circle)
267 {
268 float hollowFactorF = (float)fhollowFactor / (float)50000;
269
270 //Counter clockwise around the quadrants
271 holeHull = new SimpleHull();
272
273 holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 45 degrees
274 holeHull.AddVertex(new Vertex(0.433013f * hollowFactorF, 0.250000f * hollowFactorF, 0.0f)); // 30 degrees
275 holeHull.AddVertex(new Vertex(0.482963f * hollowFactorF, 0.129410f * hollowFactorF, 0.0f)); // 15 degrees
276 holeHull.AddVertex(new Vertex(0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 0 degrees
277 holeHull.AddVertex(new Vertex(0.482963f * hollowFactorF, -0.129410f * hollowFactorF, 0.0f)); // 345 degrees
278 holeHull.AddVertex(new Vertex(0.433013f * hollowFactorF, -0.250000f * hollowFactorF, 0.0f)); // 330 degrees
279 holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, -0.353553f * hollowFactorF, 0.0f)); // 315 degrees
280 holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, -0.433013f * hollowFactorF, 0.0f)); // 300 degrees
281 holeHull.AddVertex(new Vertex(0.129410f * hollowFactorF, -0.482963f * hollowFactorF, 0.0f)); // 285 degrees
282 holeHull.AddVertex(new Vertex(0.000000f * hollowFactorF, -0.500000f * hollowFactorF, 0.0f)); // 270 degrees
283 holeHull.AddVertex(new Vertex(-0.129410f * hollowFactorF, -0.482963f * hollowFactorF, 0.0f)); // 255 degrees
284 holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, -0.433013f * hollowFactorF, 0.0f)); // 240 degrees
285 holeHull.AddVertex(new Vertex(-0.353553f * hollowFactorF, -0.353553f * hollowFactorF, 0.0f)); // 225 degrees
286 holeHull.AddVertex(new Vertex(-0.433013f * hollowFactorF, -0.250000f * hollowFactorF, 0.0f)); // 210 degrees
287 holeHull.AddVertex(new Vertex(-0.482963f * hollowFactorF, -0.129410f * hollowFactorF, 0.0f)); // 195 degrees
288 holeHull.AddVertex(new Vertex(-0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 180 degrees
289 holeHull.AddVertex(new Vertex(-0.482963f * hollowFactorF, 0.129410f * hollowFactorF, 0.0f)); // 165 degrees
290 holeHull.AddVertex(new Vertex(-0.433013f * hollowFactorF, 0.250000f * hollowFactorF, 0.0f)); // 150 degrees
291 holeHull.AddVertex(new Vertex(-0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 135 degrees
292 holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 120 degrees
293 holeHull.AddVertex(new Vertex(-0.129410f * hollowFactorF, 0.482963f * hollowFactorF, 0.0f)); // 105 degrees
294 holeHull.AddVertex(new Vertex(0.000000f * hollowFactorF, 0.500000f * hollowFactorF, 0.0f)); // 90 degrees
295 holeHull.AddVertex(new Vertex(0.129410f * hollowFactorF, 0.482963f * hollowFactorF, 0.0f)); // 75 degrees
296 holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 60 degrees
297 holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 45 degrees
298
299 }
300 if (hshape == HollowShape.Triangle)
301 {
302 float hollowFactorF = (float)fhollowFactor / (float)50000;
303 Vertex IMM;
304 Vertex IPM;
305 Vertex IPP;
306
307 if (pshape == ProfileShape.Square)
308 {
309 // corner points are at 345, 105, and 225 degrees for the triangle within a box
310
311 //IMM = new Vertex(((float)Math.Cos(345.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(345.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f);
312 //IPM = new Vertex(((float)Math.Cos(105.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(105.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f);
313 //IPP = new Vertex(((float)Math.Cos(225.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(225.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f);
314
315 // hard coded here for speed, the equations are in the commented out lines above
316 IMM = new Vertex(0.48296f * hollowFactorF, -0.12941f * hollowFactorF, 0.0f);
317 IPM = new Vertex(-0.12941f * hollowFactorF, 0.48296f * hollowFactorF, 0.0f);
318 IPP = new Vertex(-0.35355f * hollowFactorF, -0.35355f * hollowFactorF, 0.0f);
319 }
320 else
321 {
322 IMM = new Vertex(-0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f);
323 IPM = new Vertex(+0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f);
324 IPP = new Vertex(-0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f);
325 }
326
327 holeHull = new SimpleHull();
328
329 holeHull.AddVertex(IMM);
330 holeHull.AddVertex(IPP);
331 holeHull.AddVertex(IPM);
332
333 }
334
335 return holeHull;
336
337
338 }
339 72
340 /// <summary> 73 /// <summary>
341 /// creates a simple box mesh of the specified size 74 /// creates a simple box mesh of the specified size
@@ -420,1364 +153,197 @@ namespace OpenSim.Region.Physics.Meshing
420 return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ); 153 return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ);
421 } 154 }
422 155
423 156 private void ReportPrimError(string message, string primName, PrimMesh primMesh)
424 private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
425 // Builds the z (+ and -) surfaces of a box shaped prim
426 {
427 UInt16 hollowFactor = primShape.ProfileHollow;
428 UInt16 profileBegin = primShape.ProfileBegin;
429 UInt16 profileEnd = primShape.ProfileEnd;
430 UInt16 taperX = primShape.PathScaleX;
431 UInt16 taperY = primShape.PathScaleY;
432 UInt16 pathShearX = primShape.PathShearX;
433 UInt16 pathShearY = primShape.PathShearY;
434
435#if SPAM
436 reportPrimParams("[BOX] " + primName, primShape);
437#endif
438
439 // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
440 // of a block are basically the same
441 // They may be warped differently but the shape is identical
442 // So we only create one surface as a model and derive both plus and minus surface of the block from it
443 // This is done in a model space where the block spans from -.5 to +.5 in X and Y
444 // The mapping to Scene space is done later during the "extrusion" phase
445
446 // Base
447 Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
448 Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
449 Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
450 Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
451
452 SimpleHull outerHull = new SimpleHull();
453
454 outerHull.AddVertex(PP);
455 outerHull.AddVertex(MP);
456 outerHull.AddVertex(MM);
457 outerHull.AddVertex(PM);
458
459 // Deal with cuts now
460 if ((profileBegin != 0) || (profileEnd != 0))
461 {
462 double fProfileBeginAngle = profileBegin / 50000.0*360.0;
463 // In degree, for easier debugging and understanding
464 fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
465 double fProfileEndAngle = 360.0 - profileEnd / 50000.0*360.0; // Pathend comes as complement to 1.0
466 fProfileEndAngle -= (90.0 + 45.0);
467
468 // avoid some problem angles until the hull subtraction routine is fixed
469 if ((fProfileBeginAngle + 45.0f) % 90.0f == 0.0f)
470 fProfileBeginAngle += 5.0f;
471 if ((fProfileEndAngle + 45.0f) % 90.0f == 0.0f)
472 fProfileEndAngle -= 5.0f;
473 if (fProfileBeginAngle % 90.0f == 0.0f)
474 fProfileBeginAngle += 1.0f;
475 if (fProfileEndAngle % 90.0f == 0.0f)
476 fProfileEndAngle -= 1.0f;
477
478 if (fProfileBeginAngle < fProfileEndAngle)
479 fProfileEndAngle -= 360.0;
480
481#if SPAM
482 Console.WriteLine("Meshmerizer: fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString());
483#endif
484
485 // Note, that we don't want to cut out a triangle, even if this is a
486 // good approximation for small cuts. Indeed we want to cut out an arc
487 // and we approximate this arc by a polygon chain
488 // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
489 // So it can easily be subtracted from the outer hull
490 int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5);
491 // how many steps do we need with approximately 45 degree
492 double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps;
493
494 Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
495
496 // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
497 SimpleHull cutHull = new SimpleHull();
498 cutHull.AddVertex(origin);
499 for (int i = 0; i < iSteps; i++)
500 {
501 double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!!
502 Vertex v = Vertex.FromAngle(angle*Math.PI/180.0);
503 cutHull.AddVertex(v);
504 }
505 Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0);
506 // Calculated separately to avoid errors
507 cutHull.AddVertex(legEnd);
508
509 //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
510 SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
511
512 outerHull = cuttedHull;
513 }
514
515 // Deal with the hole here
516 if (hollowFactor > 0)
517 {
518 if (hollowFactor < 1000)
519 hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines
520
521 SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
522 if (holeHull != null)
523 {
524 SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
525
526 outerHull = hollowedHull;
527 }
528 }
529
530 Mesh m = new Mesh();
531
532 Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
533 Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
534 Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
535
536 m.Add(Seed1);
537 m.Add(Seed2);
538 m.Add(Seed3);
539
540 m.Add(new Triangle(Seed1, Seed2, Seed3));
541 m.Add(outerHull.getVertices());
542
543 InsertVertices(m.vertices, 3, m.triangles);
544 m.DumpRaw(baseDir, primName, "Proto first Mesh");
545
546 m.Remove(Seed1);
547 m.Remove(Seed2);
548 m.Remove(Seed3);
549 m.DumpRaw(baseDir, primName, "Proto seeds removed");
550
551 m.RemoveTrianglesOutside(outerHull);
552 m.DumpRaw(baseDir, primName, "Proto outsides removed");
553
554 foreach (Triangle t in m.triangles)
555 {
556 PhysicsVector n = t.getNormal();
557 if (n.Z < 0.0)
558 t.invertNormal();
559 }
560
561 Extruder extr = new Extruder();
562
563 extr.size = size;
564
565 if (taperX != 100)
566 {
567 if (taperX > 100)
568 {
569 extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100);
570 }
571 else
572 {
573 extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
574 }
575
576 }
577
578 if (taperY != 100)
579 {
580 if (taperY > 100)
581 {
582 extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100);
583 }
584 else
585 {
586 extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
587 }
588 }
589
590 if (pathShearX != 0)
591 {
592 if (pathShearX > 50)
593 {
594 // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
595 extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
596 }
597 else
598 {
599 extr.pushX = (float)pathShearX / 100;
600 }
601 }
602
603 if (pathShearY != 0)
604 {
605 if (pathShearY > 50)
606 {
607 // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
608 extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
609 }
610 else
611 {
612 extr.pushY = (float)pathShearY / 100;
613 }
614 }
615
616 extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f;
617 extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f;
618 extr.pathBegin = primShape.PathBegin;
619 extr.pathEnd = primShape.PathEnd;
620
621 Mesh result = extr.ExtrudeLinearPath(m);
622 result.DumpRaw(baseDir, primName, "Z extruded");
623#if SPAM
624 int vCount = 0;
625
626 foreach (Vertex v in result.vertices)
627 if (v != null)
628 vCount++;
629 System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
630#endif
631 return result;
632 }
633
634 private static Mesh CreateCylinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
635 // Builds the z (+ and -) surfaces of a box shaped prim
636 { 157 {
158 Console.WriteLine(message);
159 Console.WriteLine("\nPrim Name: " + primName);
160 Console.WriteLine("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString());
637 161
638 UInt16 hollowFactor = primShape.ProfileHollow;
639 UInt16 profileBegin = primShape.ProfileBegin;
640 UInt16 profileEnd = primShape.ProfileEnd;
641 UInt16 taperX = primShape.PathScaleX;
642 UInt16 taperY = primShape.PathScaleY;
643 UInt16 pathShearX = primShape.PathShearX;
644 UInt16 pathShearY = primShape.PathShearY;
645
646#if SPAM
647 reportPrimParams("[CYLINDER] " + primName, primShape);
648#endif
649
650
651 // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
652 // of a block are basically the same
653 // They may be warped differently but the shape is identical
654 // So we only create one surface as a model and derive both plus and minus surface of the block from it
655 // This is done in a model space where the block spans from -.5 to +.5 in X and Y
656 // The mapping to Scene space is done later during the "extrusion" phase
657
658 // Base
659
660 SimpleHull outerHull = new SimpleHull();
661
662 // counter-clockwise around the quadrants, start at 45 degrees
663
664 outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees
665 outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees
666 outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees
667 outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees
668 outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees
669 outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees
670 outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees
671 outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees
672 outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees
673 outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees
674 outerHull.AddVertex(new Vertex(-0.482963f, -0.129410f, 0.0f)); // 195 degrees
675 outerHull.AddVertex(new Vertex(-0.433013f, -0.250000f, 0.0f)); // 210 degrees
676 outerHull.AddVertex(new Vertex(-0.353553f, -0.353553f, 0.0f)); // 225 degrees
677 outerHull.AddVertex(new Vertex(-0.250000f, -0.433013f, 0.0f)); // 240 degrees
678 outerHull.AddVertex(new Vertex(-0.129410f, -0.482963f, 0.0f)); // 255 degrees
679 outerHull.AddVertex(new Vertex(0.000000f, -0.500000f, 0.0f)); // 270 degrees
680 outerHull.AddVertex(new Vertex(0.129410f, -0.482963f, 0.0f)); // 285 degrees
681 outerHull.AddVertex(new Vertex(0.250000f, -0.433013f, 0.0f)); // 300 degrees
682 outerHull.AddVertex(new Vertex(0.353553f, -0.353553f, 0.0f)); // 315 degrees
683 outerHull.AddVertex(new Vertex(0.433013f, -0.250000f, 0.0f)); // 330 degrees
684 outerHull.AddVertex(new Vertex(0.482963f, -0.129410f, 0.0f)); // 345 degrees
685 outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees
686 outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees
687 outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees
688
689
690
691 // Deal with cuts now
692 if ((profileBegin != 0) || (profileEnd != 0))
693 {
694 double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
695 // In degree, for easier debugging and understanding
696 double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
697
698#if SPAM
699 Console.WriteLine("Extruder: Cylinder fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString());
700#endif
701 if (fProfileBeginAngle > 270.0f && fProfileBeginAngle < 271.8f) // a problem angle for the hull subtract routine :(
702 fProfileBeginAngle = 271.8f; // workaround - use the smaller slice
703
704 if (fProfileBeginAngle < fProfileEndAngle)
705 fProfileEndAngle -= 360.0;
706#if SPAM
707 Console.WriteLine("Extruder: Cylinder fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString());
708#endif
709
710 // Note, that we don't want to cut out a triangle, even if this is a
711 // good approximation for small cuts. Indeed we want to cut out an arc
712 // and we approximate this arc by a polygon chain
713 // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
714 // So it can easily be subtracted from the outer hull
715 int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
716 // how many steps do we need with approximately 45 degree
717 double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
718
719 Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
720
721 // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
722 SimpleHull cutHull = new SimpleHull();
723 cutHull.AddVertex(origin);
724 for (int i = 0; i < iSteps; i++)
725 {
726 double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
727 Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
728 cutHull.AddVertex(v);
729 }
730 Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
731 // Calculated separately to avoid errors
732 cutHull.AddVertex(legEnd);
733
734 SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
735
736 outerHull = cuttedHull;
737 }
738
739 // Deal with the hole here
740 if (hollowFactor > 0)
741 {
742 if (hollowFactor < 1000)
743 hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines
744
745 SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
746 if (holeHull != null)
747 {
748 SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
749
750 outerHull = hollowedHull;
751 }
752 }
753
754 Mesh m = new Mesh();
755
756 Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
757 Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
758 Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
759
760 m.Add(Seed1);
761 m.Add(Seed2);
762 m.Add(Seed3);
763
764 m.Add(new Triangle(Seed1, Seed2, Seed3));
765 m.Add(outerHull.getVertices());
766
767 InsertVertices(m.vertices, 3, m.triangles);
768 m.DumpRaw(baseDir, primName, "Proto first Mesh");
769
770 m.Remove(Seed1);
771 m.Remove(Seed2);
772 m.Remove(Seed3);
773 m.DumpRaw(baseDir, primName, "Proto seeds removed");
774
775 m.RemoveTrianglesOutside(outerHull);
776 m.DumpRaw(baseDir, primName, "Proto outsides removed");
777
778 foreach (Triangle t in m.triangles)
779 {
780 PhysicsVector n = t.getNormal();
781 if (n.Z < 0.0)
782 t.invertNormal();
783 }
784
785 Extruder extr = new Extruder();
786
787 extr.size = size;
788
789 if (taperX != 100)
790 {
791 if (taperX > 100)
792 {
793 extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100); }
794 else
795 {
796 extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
797 }
798
799 }
800
801 if (taperY != 100)
802 {
803 if (taperY > 100)
804 {
805 extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100);
806 }
807 else
808 {
809 extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
810 }
811 }
812
813 if (pathShearX != 0)
814 {
815 if (pathShearX > 50)
816 {
817 // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
818 extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
819 }
820 else
821 {
822 extr.pushX = (float)pathShearX / 100;
823 }
824 }
825
826 if (pathShearY != 0)
827 {
828 if (pathShearY > 50)
829 {
830 // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
831 extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
832 }
833 else
834 {
835 extr.pushY = (float)pathShearY / 100;
836 }
837
838 }
839
840 extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f;
841 extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f;
842 extr.pathBegin = primShape.PathBegin;
843 extr.pathEnd = primShape.PathEnd;
844
845 Mesh result = extr.ExtrudeLinearPath(m);
846 result.DumpRaw(baseDir, primName, "Z extruded");
847#if SPAM
848 int vCount = 0;
849
850 foreach (Vertex v in result.vertices)
851 if (v != null)
852 vCount++;
853 System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
854#endif
855 return result;
856 } 162 }
857 163
858 private static Mesh CreatePrismMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) 164 public Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod)
859 // Builds the z (+ and -) surfaces of a box shaped prim
860 { 165 {
861 UInt16 hollowFactor = primShape.ProfileHollow; 166 Mesh mesh = new Mesh();
862 UInt16 profileBegin = primShape.ProfileBegin; 167 PrimMesh primMesh;
863 UInt16 profileEnd = primShape.ProfileEnd; 168 PrimMesher.SculptMesh sculptMesh;
864 UInt16 taperX = primShape.PathScaleX;
865 UInt16 taperY = primShape.PathScaleY;
866 UInt16 pathShearX = primShape.PathShearX;
867 UInt16 pathShearY = primShape.PathShearY;
868
869
870#if SPAM
871 reportPrimParams("[PRISM] " + primName, primShape);
872#endif
873 // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
874 // of a block are basically the same
875 // They may be warped differently but the shape is identical
876 // So we only create one surface as a model and derive both plus and minus surface of the block from it
877 // This is done in a model space where the block spans from -.5 to +.5 in X and Y
878 // The mapping to Scene space is done later during the "extrusion" phase
879
880 // Base
881 Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
882 Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
883 Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
884
885
886 SimpleHull outerHull = new SimpleHull();
887
888 outerHull.AddVertex(PP);
889 outerHull.AddVertex(MM);
890 outerHull.AddVertex(PM);
891
892 // Deal with cuts now
893 if ((profileBegin != 0) || (profileEnd != 0))
894 {
895 double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
896 // In degree, for easier debugging and understanding
897 double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
898
899 if (fProfileBeginAngle < fProfileEndAngle)
900 fProfileEndAngle -= 360.0;
901
902 // Note, that we don't want to cut out a triangle, even if this is a
903 // good approximation for small cuts. Indeed we want to cut out an arc
904 // and we approximate this arc by a polygon chain
905 // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
906 // So it can easily be subtracted from the outer hull
907 int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
908 // how many steps do we need with approximately 45 degree
909 double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
910
911 Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
912
913 // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
914 SimpleHull cutHull = new SimpleHull();
915 cutHull.AddVertex(origin);
916 for (int i = 0; i < iSteps; i++)
917 {
918 double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
919 Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
920 cutHull.AddVertex(v);
921 }
922 Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
923 // Calculated separately to avoid errors
924 cutHull.AddVertex(legEnd);
925
926 SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
927
928 outerHull = cuttedHull;
929 }
930
931 // Deal with the hole here
932 if (hollowFactor > 0)
933 {
934 if (hollowFactor < 1000)
935 hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines
936
937 SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
938 if (holeHull != null)
939 {
940 SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
941
942 outerHull = hollowedHull;
943 }
944 }
945
946 Mesh m = new Mesh();
947
948 Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
949 Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
950 Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
951
952 m.Add(Seed1);
953 m.Add(Seed2);
954 m.Add(Seed3);
955
956 m.Add(new Triangle(Seed1, Seed2, Seed3));
957 m.Add(outerHull.getVertices());
958
959 InsertVertices(m.vertices, 3, m.triangles);
960 m.DumpRaw(baseDir, primName, "Proto first Mesh");
961
962 m.Remove(Seed1);
963 m.Remove(Seed2);
964 m.Remove(Seed3);
965 m.DumpRaw(baseDir, primName, "Proto seeds removed");
966
967 m.RemoveTrianglesOutside(outerHull);
968 m.DumpRaw(baseDir, primName, "Proto outsides removed");
969
970 foreach (Triangle t in m.triangles)
971 {
972 PhysicsVector n = t.getNormal();
973 if (n.Z < 0.0)
974 t.invertNormal();
975 }
976 169
977 Extruder extr = new Extruder(); 170 List<Coord> coords;
171 List<Face> faces;
978 172
979 extr.size = size; 173 Image idata = null;
980 174
981 if (taperX != 100) 175 if (primShape.SculptEntry)
982 { 176 {
983 if (taperX > 100) 177 if (primShape.SculptData.Length == 0)
984 { 178 return null;
985 extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100);
986 }
987 else
988 {
989 extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
990 }
991
992 }
993 179
994 if (taperY != 100) 180 try
995 {
996 if (taperY > 100)
997 { 181 {
998 extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100); 182 ManagedImage managedImage; // we never use this
183 OpenJPEG.DecodeToImage(primShape.SculptData, out managedImage, out idata);
999 } 184 }
1000 else 185 catch (Exception)
1001 { 186 {
1002 extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); 187 System.Console.WriteLine("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed!");
188 return null;
1003 } 189 }
1004 }
1005 190
1006 if (pathShearX != 0)
1007 {
1008 if (pathShearX > 50)
1009 {
1010 // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
1011 extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
1012 }
1013 else
1014 {
1015 extr.pushX = (float)pathShearX / 100;
1016 }
1017 }
1018 191
1019 if (pathShearY != 0) 192 PrimMesher.SculptMesh.SculptType sculptType;
1020 { 193 switch ((OpenMetaverse.SculptType)primShape.SculptType)
1021 if (pathShearY > 50)
1022 {
1023 // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
1024 extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
1025 }
1026 else
1027 { 194 {
1028 extr.pushY = (float)pathShearY / 100; 195 case OpenMetaverse.SculptType.Cylinder:
196 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
197 break;
198 case OpenMetaverse.SculptType.Plane:
199 sculptType = PrimMesher.SculptMesh.SculptType.plane;
200 break;
201 case OpenMetaverse.SculptType.Torus:
202 sculptType = PrimMesher.SculptMesh.SculptType.torus;
203 break;
204 case OpenMetaverse.SculptType.Sphere:
205 default:
206 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
207 break;
1029 } 208 }
1030 } 209 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false);
1031
1032 extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f;
1033 extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f;
1034 extr.pathBegin = primShape.PathBegin;
1035 extr.pathEnd = primShape.PathEnd;
1036
1037 Mesh result = extr.ExtrudeLinearPath(m);
1038 result.DumpRaw(baseDir, primName, "Z extruded");
1039#if SPAM
1040 int vCount = 0;
1041
1042 foreach (Vertex v in result.vertices)
1043 if (v != null)
1044 vCount++;
1045 System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
1046#endif
1047 return result;
1048 }
1049
1050 /// <summary>
1051 /// builds an icosahedral geodesic sphere - used as default in place of problem meshes
1052 /// </summary>
1053 /// <param name="primName"></param>
1054 /// <param name="primShape"></param>
1055 /// <param name="size"></param>
1056 /// <returns></returns>
1057 private static Mesh CreateSphereMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
1058 {
1059 // Builds an icosahedral geodesic sphere
1060 // based on an article by Paul Bourke
1061 // http://local.wasp.uwa.edu.au/~pbourke/
1062 // articles:
1063 // http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonmesh/
1064 // and
1065 // http://local.wasp.uwa.edu.au/~pbourke/geometry/polyhedra/index.html
1066
1067 // Still have more to do here.
1068
1069 Mesh m = new Mesh();
1070
1071#if SPAM
1072 reportPrimParams("[SPHERE] " + primName, primShape);
1073#endif
1074
1075 float LOD = 0.2f;
1076 float diameter = 0.5f;// Our object will result in -0.5 to 0.5
1077 float sq5 = (float) Math.Sqrt(5.0);
1078 float phi = (1 + sq5) * 0.5f;
1079 float rat = (float) Math.Sqrt(10f + (2f * sq5)) / (4f * phi);
1080 float a = (diameter / rat) * 0.5f;
1081 float b = (diameter / rat) / (2.0f * phi);
1082
1083
1084 // 12 Icosahedron vertexes
1085 Vertex v1 = new Vertex(0f, b, -a);
1086 Vertex v2 = new Vertex(b, a, 0f);
1087 Vertex v3 = new Vertex(-b, a, 0f);
1088 Vertex v4 = new Vertex(0f, b, a);
1089 Vertex v5 = new Vertex(0f, -b, a);
1090 Vertex v6 = new Vertex(-a, 0f, b);
1091 Vertex v7 = new Vertex(0f, -b, -a);
1092 Vertex v8 = new Vertex(a, 0f, -b);
1093 Vertex v9 = new Vertex(a, 0f, b);
1094 Vertex v10 = new Vertex(-a, 0f, -b);
1095 Vertex v11 = new Vertex(b, -a, 0);
1096 Vertex v12 = new Vertex(-b, -a, 0);
1097
1098
1099
1100 // Base Faces of the Icosahedron (20)
1101 SphereLODTriangle(v1, v2, v3, diameter, LOD, m);
1102 SphereLODTriangle(v4, v3, v2, diameter, LOD, m);
1103 SphereLODTriangle(v4, v5, v6, diameter, LOD, m);
1104 SphereLODTriangle(v4, v9, v5, diameter, LOD, m);
1105 SphereLODTriangle(v1, v7, v8, diameter, LOD, m);
1106 SphereLODTriangle(v1, v10, v7, diameter, LOD, m);
1107 SphereLODTriangle(v5, v11, v12, diameter, LOD, m);
1108 SphereLODTriangle(v7, v12, v11, diameter, LOD, m);
1109 SphereLODTriangle(v3, v6, v10, diameter, LOD, m);
1110 SphereLODTriangle(v12, v10, v6, diameter, LOD, m);
1111 SphereLODTriangle(v2, v8, v9, diameter, LOD, m);
1112 SphereLODTriangle(v11, v9, v8, diameter, LOD, m);
1113 SphereLODTriangle(v4, v6, v3, diameter, LOD, m);
1114 SphereLODTriangle(v4, v2, v9, diameter, LOD, m);
1115 SphereLODTriangle(v1, v3, v10, diameter, LOD, m);
1116 SphereLODTriangle(v1, v8, v2, diameter, LOD, m);
1117 SphereLODTriangle(v7, v10, v12, diameter, LOD, m);
1118 SphereLODTriangle(v7, v11, v8, diameter, LOD, m);
1119 SphereLODTriangle(v5, v12, v6, diameter, LOD, m);
1120 SphereLODTriangle(v5, v9, v11, diameter, LOD, m);
1121
1122 // Scale the mesh based on our prim scale
1123 foreach (Vertex v in m.vertices)
1124 {
1125 v.X *= size.X;
1126 v.Y *= size.Y;
1127 v.Z *= size.Z;
1128 }
1129
1130 // This was built with the normals pointing inside..
1131 // therefore we have to invert the normals
1132 foreach (Triangle t in m.triangles)
1133 {
1134 t.invertNormal();
1135 }
1136 // Dump the faces for visualization in blender.
1137 m.DumpRaw(baseDir, primName, "Icosahedron");
1138#if SPAM
1139 int vCount = 0;
1140
1141 foreach (Vertex v in m.vertices)
1142 if (v != null)
1143 vCount++;
1144 System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
1145#endif
1146
1147 return m;
1148 }
1149 private SculptMesh CreateSculptMesh(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod)
1150 {
1151
1152#if SPAM
1153 reportPrimParams("[SCULPT] " + primName, primShape);
1154#endif
1155
1156 SculptMesh sm = new SculptMesh(primShape.SculptData, lod);
1157 // Scale the mesh based on our prim scale
1158 foreach (Vertex v in sm.vertices)
1159 {
1160 v.X *= 0.5f;
1161 v.Y *= 0.5f;
1162 v.Z *= 0.5f;
1163 v.X *= size.X;
1164 v.Y *= size.Y;
1165 v.Z *= size.Z;
1166 }
1167 // This was built with the normals pointing inside..
1168 // therefore we have to invert the normals
1169 foreach (Triangle t in sm.triangles)
1170 {
1171 t.invertNormal();
1172 }
1173 sm.DumpRaw(baseDir, primName, "Sculpt");
1174 return sm;
1175
1176 }
1177
1178 /// <summary>
1179 /// Creates a mesh for prim types torus, ring, tube, and sphere
1180 /// </summary>
1181 /// <param name="primName"></param>
1182 /// <param name="primShape"></param>
1183 /// <param name="size"></param>
1184 /// <returns></returns>
1185 private static Mesh CreateCircularPathMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
1186 {
1187
1188 UInt16 hollowFactor = primShape.ProfileHollow;
1189 UInt16 profileBegin = primShape.ProfileBegin;
1190 UInt16 profileEnd = primShape.ProfileEnd;
1191 UInt16 pathShearX = primShape.PathShearX;
1192 UInt16 pathShearY = primShape.PathShearY;
1193 HollowShape hollowShape = primShape.HollowShape;
1194
1195#if SPAM
1196 reportPrimParams("[CIRCULAR PATH PRIM] " + primName, primShape);
1197 Console.WriteLine("pathTwist: " + primShape.PathTwist.ToString() + " pathTwistBegin: " + primShape.PathTwistBegin.ToString());
1198 Console.WriteLine("primShape.ProfileCurve & 0x07: " + Convert.ToString(primShape.ProfileCurve & 0x07));
1199
1200#endif
1201
1202 SimpleHull outerHull = new SimpleHull();
1203
1204 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
1205 {
1206#if SPAM
1207 Console.WriteLine("Meshmerizer thinks " + primName + " is a TORUS");
1208#endif
1209 if (hollowShape == HollowShape.Same)
1210 hollowShape = HollowShape.Circle;
1211
1212 // build the profile shape
1213 // counter-clockwise around the quadrants, start at 45 degrees
1214
1215 outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees
1216 outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees
1217 outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees
1218 outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees
1219 outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees
1220 outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees
1221 outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees
1222 outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees
1223 outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees
1224 outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees
1225 outerHull.AddVertex(new Vertex(-0.482963f, -0.129410f, 0.0f)); // 195 degrees
1226 outerHull.AddVertex(new Vertex(-0.433013f, -0.250000f, 0.0f)); // 210 degrees
1227 outerHull.AddVertex(new Vertex(-0.353553f, -0.353553f, 0.0f)); // 225 degrees
1228 outerHull.AddVertex(new Vertex(-0.250000f, -0.433013f, 0.0f)); // 240 degrees
1229 outerHull.AddVertex(new Vertex(-0.129410f, -0.482963f, 0.0f)); // 255 degrees
1230 outerHull.AddVertex(new Vertex(0.000000f, -0.500000f, 0.0f)); // 270 degrees
1231 outerHull.AddVertex(new Vertex(0.129410f, -0.482963f, 0.0f)); // 285 degrees
1232 outerHull.AddVertex(new Vertex(0.250000f, -0.433013f, 0.0f)); // 300 degrees
1233 outerHull.AddVertex(new Vertex(0.353553f, -0.353553f, 0.0f)); // 315 degrees
1234 outerHull.AddVertex(new Vertex(0.433013f, -0.250000f, 0.0f)); // 330 degrees
1235 outerHull.AddVertex(new Vertex(0.482963f, -0.129410f, 0.0f)); // 345 degrees
1236 outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees
1237 outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees
1238 outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees
1239 }
1240
1241 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) // a ring
1242 {
1243#if SPAM
1244 Console.WriteLine("Meshmerizer thinks " + primName + " is a TUBE");
1245#endif
1246 if (hollowShape == HollowShape.Same)
1247 hollowShape = HollowShape.Square;
1248 210
1249 outerHull.AddVertex(new Vertex(+0.5f, +0.5f, 0.0f)); 211 idata.Dispose();
1250 outerHull.AddVertex(new Vertex(-0.5f, +0.5f, 0.0f));
1251 outerHull.AddVertex(new Vertex(-0.5f, -0.5f, 0.0f));
1252 outerHull.AddVertex(new Vertex(+0.5f, -0.5f, 0.0f));
1253 }
1254 212
1255 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) 213 sculptMesh.DumpRaw(baseDir, primName, "primMesh");
1256 {
1257#if SPAM
1258 Console.WriteLine("Meshmerizer thinks " + primName + " is a RING");
1259#endif
1260 if (hollowShape == HollowShape.Same)
1261 hollowShape = HollowShape.Triangle;
1262 214
1263 outerHull.AddVertex(new Vertex(+0.255f, -0.375f, 0.0f)); 215 sculptMesh.Scale(size.X, size.Y, size.Z);
1264 outerHull.AddVertex(new Vertex(+0.25f, +0.375f, 0.0f));
1265 outerHull.AddVertex(new Vertex(-0.5f, +0.0f, 0.0f));
1266 216
217 coords = sculptMesh.coords;
218 faces = sculptMesh.faces;
1267 } 219 }
1268 220
1269 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) 221 else
1270 { 222 {
1271#if SPAM 223 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
1272 Console.WriteLine("Meshmerizer thinks " + primName + " is a SPHERE"); 224 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
1273#endif 225 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
1274 226 float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
1275 // sanity check here... some spheres have inverted normals which can trap avatars 227 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
1276 // so for now if the shape parameters are such that this may happen, revert to the 228 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
1277 // geodesic sphere mesh.. the threshold is arbitrary as it seems any twist on a sphere
1278 // will create some inverted normals
1279 if (
1280 (System.Math.Abs(primShape.PathTwist - primShape.PathTwistBegin) > 65)
1281 || (primShape.PathBegin == 0
1282 && primShape.PathEnd == 0
1283 && primShape.PathTwist == 0
1284 && primShape.PathTwistBegin == 0
1285 && primShape.ProfileBegin == 0
1286 && primShape.ProfileEnd == 0
1287 && hollowFactor == 0
1288 ) // simple sphere, revert to geodesic shape
1289
1290 )
1291 {
1292#if SPAM
1293 System.Console.WriteLine("reverting to geodesic sphere for prim: " + primName);
1294#endif
1295 return CreateSphereMesh(primName, primShape, size);
1296 }
1297 229
1298 if (hollowFactor == 0) 230 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
1299 { 231 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
1300 // the hull triangulator is happier with a minimal hollow 232 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
1301 hollowFactor = 2000;
1302 }
1303 233
1304 if (hollowShape == HollowShape.Same) 234 int sides = 4;
1305 hollowShape = HollowShape.Circle; 235 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
1306 236 sides = 3;
1307 outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees 237 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
1308 outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees 238 sides = 24;
1309 outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees 239 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
1310 outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees 240 { // half circle, prim is a sphere
1311 outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees 241 sides = 24;
1312 outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees
1313 outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees
1314 outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees
1315 outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees
1316
1317 outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees
1318 outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees
1319 outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees
1320 outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees
1321 }
1322 242
1323 // Deal with cuts now 243 profileBegin = 0.5f * profileBegin + 0.5f;
1324 if ((profileBegin != 0) || (profileEnd != 0)) 244 profileEnd = 0.5f * profileEnd + 0.5f;
1325 {
1326 double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
1327 // In degree, for easier debugging and understanding
1328 double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
1329
1330 if (fProfileBeginAngle < fProfileEndAngle)
1331 fProfileEndAngle -= 360.0;
1332
1333 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
1334 { // dimpled sphere uses profile cut but since it's a half circle the angles are smaller
1335 fProfileBeginAngle = 0.0036f * (float)primShape.ProfileBegin;
1336 fProfileEndAngle = 180.0f - 0.0036f * (float)primShape.ProfileEnd;
1337 if (fProfileBeginAngle < fProfileEndAngle)
1338 fProfileEndAngle -= 360.0f;
1339 // a cut starting at 0 degrees with a hollow causes an infinite loop so move the start angle
1340 // past it into the empty part of the circle to avoid this condition
1341 if (fProfileBeginAngle == 0.0f) fProfileBeginAngle = -10.0f;
1342 245
1343#if SPAM
1344 Console.WriteLine("Sphere dimple: fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString());
1345#endif
1346 }
1347 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
1348 { // tube profile cut is offset 45 degrees from other prim types
1349 fProfileBeginAngle += 45.0f;
1350 fProfileEndAngle += 45.0f;
1351 if (fProfileBeginAngle < fProfileEndAngle)
1352 fProfileEndAngle -= 360.0;
1353 }
1354 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
1355 { // ring profile cut is offset 180 degrees from other prim types
1356 fProfileBeginAngle += 180.0f;
1357 fProfileEndAngle += 180.0f;
1358 if (fProfileBeginAngle < fProfileEndAngle)
1359 fProfileEndAngle -= 360.0;
1360 } 246 }
1361 247
1362 // Note, that we don't want to cut out a triangle, even if this is a 248 int hollowSides = sides;
1363 // good approximation for small cuts. Indeed we want to cut out an arc 249 if (primShape.HollowShape == HollowShape.Circle)
1364 // and we approximate this arc by a polygon chain 250 hollowSides = 24;
1365 // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space 251 else if (primShape.HollowShape == HollowShape.Square)
1366 // So it can easily be subtracted from the outer hull 252 hollowSides = 4;
1367 int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); 253 else if (primShape.HollowShape == HollowShape.Triangle)
1368 // how many steps do we need with approximately 45 degree 254 hollowSides = 3;
1369 double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
1370
1371 Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
1372
1373 // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
1374 SimpleHull cutHull = new SimpleHull();
1375 cutHull.AddVertex(origin);
1376 for (int i = 0; i < iSteps; i++)
1377 {
1378 double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
1379 Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
1380 cutHull.AddVertex(v);
1381 }
1382 Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
1383 // Calculated separately to avoid errors
1384 cutHull.AddVertex(legEnd);
1385 255
1386 // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); 256 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
1387 SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
1388 257
1389 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) 258 primMesh.topShearX = pathShearX;
1390 { 259 primMesh.topShearY = pathShearY;
1391 Quaternion zFlip = Quaternion.CreateFromAxisAngle(new Vector3(0.0f, 0.0f, 1.0f), (float)Math.PI); 260 primMesh.pathCutBegin = pathBegin;
1392 Vertex vTmp = new Vertex(0.0f, 0.0f, 0.0f); 261 primMesh.pathCutEnd = pathEnd;
1393 foreach (Vertex v in cuttedHull.getVertices())
1394 if (v != null)
1395 {
1396 vTmp = v * zFlip;
1397 v.X = vTmp.X;
1398 v.Y = vTmp.Y;
1399 v.Z = vTmp.Z;
1400 }
1401 }
1402
1403 outerHull = cuttedHull;
1404 }
1405 262
1406 // Deal with the hole here 263 if (primShape.PathCurve == (byte)Extrusion.Straight)
1407 if (hollowFactor > 0)
1408 {
1409 SimpleHull holeHull;
1410
1411 if (hollowShape == HollowShape.Triangle)
1412 { 264 {
1413 holeHull = new SimpleHull(); 265 primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10;
266 primMesh.twistEnd = primShape.PathTwist * 18 / 10;
267 primMesh.taperX = pathScaleX;
268 primMesh.taperY = pathScaleY;
1414 269
1415 float hollowFactorF = (float)hollowFactor * 2.0e-5f; 270 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
1416
1417 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
1418 { 271 {
1419 holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, -0.1875f * hollowFactorF, 0.0f)); 272 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
1420 holeHull.AddVertex(new Vertex(-0.25f * hollowFactorF, -0f * hollowFactorF, 0.0f)); 273 if (profileBegin < 0.0f) profileBegin = 0.0f;
1421 holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, +0.1875f * hollowFactorF, 0.0f)); 274 if (profileEnd > 1.0f) profileEnd = 1.0f;
1422 } 275 }
1423 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) 276#if SPAM
277 Console.WriteLine("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
278#endif
279 try
1424 { 280 {
1425 holeHull.AddVertex(new Vertex(-0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 180 degrees 281 primMesh.ExtrudeLinear();
1426 holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 120 degrees
1427 holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 60 degrees
1428 holeHull.AddVertex(new Vertex(0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 0 degrees
1429 } 282 }
1430 else 283 catch (Exception ex)
1431 { 284 {
1432 holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f)); 285 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
1433 holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, -0f * hollowFactorF, 0.0f)); 286 return null;
1434 holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f));
1435 } 287 }
1436 } 288 }
1437 else if (hollowShape == HollowShape.Square && (primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
1438 {
1439 holeHull = new SimpleHull();
1440
1441 float hollowFactorF = (float)hollowFactor * 2.0e-5f;
1442
1443 holeHull.AddVertex(new Vertex(-0.707f * hollowFactorF, 0.0f, 0.0f)); // 180 degrees
1444 holeHull.AddVertex(new Vertex(0.0f, 0.707f * hollowFactorF, 0.0f)); // 120 degrees
1445 holeHull.AddVertex(new Vertex(0.707f * hollowFactorF, 0.0f, 0.0f)); // 60 degrees
1446 }
1447 else 289 else
1448 { 290 {
1449 holeHull = BuildHoleHull(primShape, primShape.ProfileShape, hollowShape, hollowFactor); 291 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f;
1450 } 292 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f;
1451 293 primMesh.radius = 0.01f * primShape.PathRadiusOffset;
1452 if (holeHull != null) 294 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions;
1453 { 295 primMesh.skew = 0.01f * primShape.PathSkew;
1454 SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); 296 primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10;
1455 297 primMesh.twistEnd = primShape.PathTwist * 36 / 10;
1456 outerHull = hollowedHull; 298 primMesh.taperX = primShape.PathTaperX * 0.01f;
1457 } 299 primMesh.taperY = primShape.PathTaperY * 0.01f;
1458 } 300
1459 301 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
1460 Mesh m = new Mesh(); 302 {
1461 303 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
1462 Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); 304 if (profileBegin < 0.0f) profileBegin = 0.0f;
1463 Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); 305 if (profileEnd > 1.0f) profileEnd = 1.0f;
1464 Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); 306 }
1465
1466 m.Add(Seed1);
1467 m.Add(Seed2);
1468 m.Add(Seed3);
1469
1470 m.Add(new Triangle(Seed1, Seed2, Seed3));
1471 m.Add(outerHull.getVertices());
1472
1473 InsertVertices(m.vertices, 3, m.triangles);
1474 m.DumpRaw(baseDir, primName, "Proto first Mesh");
1475
1476 m.Remove(Seed1);
1477 m.Remove(Seed2);
1478 m.Remove(Seed3);
1479 m.DumpRaw(baseDir, primName, "Proto seeds removed");
1480
1481 m.RemoveTrianglesOutside(outerHull);
1482 m.DumpRaw(baseDir, primName, "Proto outsides removed");
1483
1484 foreach (Triangle t in m.triangles)
1485 t.invertNormal();
1486
1487
1488 float skew = primShape.PathSkew * 0.01f;
1489 float pathScaleX = (float)(200 - primShape.PathScaleX) * 0.01f;
1490 float pathScaleY = (float)(200 - primShape.PathScaleY) * 0.01f;
1491 float profileXComp = pathScaleX * (1.0f - Math.Abs(skew));
1492
1493#if SPAM
1494 //Console.WriteLine("primShape.PathScaleX: " + primShape.PathScaleX.ToString() + " primShape.PathScaleY: " + primShape.PathScaleY.ToString());
1495 //Console.WriteLine("primShape.PathSkew: " + primShape.PathSkew.ToString() + " primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString() + " primShape.pathRevolutions: " + primShape.PathRevolutions.ToString());
1496 Console.WriteLine("PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString());
1497 Console.WriteLine("skew: " + skew.ToString() + " profileXComp: " + profileXComp.ToString());
1498#endif
1499
1500 foreach (Vertex v in m.vertices)
1501 if (v != null)
1502 {
1503 v.X *= profileXComp;
1504 v.Y *= pathScaleY;
1505 }
1506
1507 Extruder extr = new Extruder();
1508
1509 extr.size = size;
1510 extr.pathScaleX = pathScaleX;
1511 extr.pathScaleY = pathScaleY;
1512 extr.pathCutBegin = 0.00002f * primShape.PathBegin;
1513 extr.pathCutEnd = 0.00002f * (50000 - primShape.PathEnd);
1514 extr.pathBegin = primShape.PathBegin;
1515 extr.pathEnd = primShape.PathEnd;
1516 extr.skew = skew;
1517 extr.revolutions = 1.0f + (float)primShape.PathRevolutions * 3.0f / 200.0f;
1518 extr.pathTaperX = 0.01f * (float)primShape.PathTaperX;
1519 extr.pathTaperY = 0.01f * (float)primShape.PathTaperY;
1520
1521 extr.radius = 0.01f * (float)primShape.PathRadiusOffset;
1522
1523#if SPAM 307#if SPAM
1524 //System.Console.WriteLine("primShape.PathBegin: " + primShape.PathBegin.ToString() + " primShape.PathEnd: " + primShape.PathEnd.ToString()); 308 Console.WriteLine("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString());
1525 System.Console.WriteLine("extr.pathCutBegin: " + extr.pathCutBegin.ToString() + " extr.pathCutEnd: " + extr.pathCutEnd.ToString());
1526 System.Console.WriteLine("extr.revolutions: " + extr.revolutions.ToString());
1527
1528 //System.Console.WriteLine("primShape.PathTaperX: " + primShape.PathTaperX.ToString());
1529 //System.Console.WriteLine("primShape.PathTaperY: " + primShape.PathTaperY.ToString());
1530
1531
1532 //System.Console.WriteLine("primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString());
1533#endif 309#endif
1534 310 try
1535 311 {
1536 312 primMesh.ExtrudeCircular();
1537 313 }
1538 if (pathShearX != 0) 314 catch (Exception ex)
1539 { 315 {
1540 if (pathShearX > 50) 316 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
1541 { 317 return null;
1542 // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 318 }
1543 extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
1544 }
1545 else
1546 {
1547 extr.pushX = (float)pathShearX / 100;
1548 }
1549 }
1550
1551 if (pathShearY != 0)
1552 {
1553 if (pathShearY > 50)
1554 {
1555 // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
1556 extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
1557 }
1558 else
1559 {
1560 extr.pushY = (float)pathShearY / 100;
1561 } 319 }
1562 320
1563 } 321 primMesh.DumpRaw(baseDir, primName, "primMesh");
1564
1565 extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.02f;
1566 extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.02f;
1567
1568 Mesh result = extr.ExtrudeCircularPath(m);
1569 result.DumpRaw(baseDir, primName, "Z extruded");
1570
1571#if SPAM
1572 int vCount = 0;
1573
1574 foreach (Vertex v in result.vertices)
1575 {
1576 if (v != null)
1577 vCount++;
1578 }
1579
1580 System.Console.WriteLine("Mesh vertex count: " + vCount.ToString());
1581#endif
1582
1583 return result;
1584 }
1585
1586 public static Vertex midUnitRadialPoint(Vertex a, Vertex b, float radius)
1587 {
1588 Vertex midpoint = new Vertex(a + b) * 0.5f;
1589 return (midpoint.normalize() * radius);
1590 }
1591
1592 public static void SphereLODTriangle(Vertex a, Vertex b, Vertex c, float diameter, float LOD, Mesh m)
1593 {
1594 Vertex aa = a - b;
1595 Vertex ba = b - c;
1596 Vertex da = c - a;
1597
1598 if (((aa.length() < LOD) && (ba.length() < LOD) && (da.length() < LOD)))
1599 {
1600 // We don't want duplicate verticies. Duplicates cause the scale algorithm to produce a spikeball
1601 // spikes are novel, but we want ellipsoids.
1602
1603 if (!m.vertices.Contains(a))
1604 m.Add(a);
1605 if (!m.vertices.Contains(b))
1606 m.Add(b);
1607 if (!m.vertices.Contains(c))
1608 m.Add(c);
1609
1610 // Add the triangle to the mesh
1611 Triangle t = new Triangle(a, b, c);
1612 m.Add(t);
1613 }
1614 else
1615 {
1616 Vertex ab = midUnitRadialPoint(a, b, diameter);
1617 Vertex bc = midUnitRadialPoint(b, c, diameter);
1618 Vertex ca = midUnitRadialPoint(c, a, diameter);
1619
1620 // Recursive! Splits the triangle up into 4 smaller triangles
1621 SphereLODTriangle(a, ab, ca, diameter, LOD, m);
1622 SphereLODTriangle(ab, b, bc, diameter, LOD, m);
1623 SphereLODTriangle(ca, bc, c, diameter, LOD, m);
1624 SphereLODTriangle(ab, bc, ca, diameter, LOD, m);
1625
1626 }
1627 }
1628
1629 private void ReportPrimError(string message, string primName, PrimMesh primMesh)
1630 {
1631 Console.WriteLine(message);
1632 Console.WriteLine("\nPrim Name: " + primName);
1633 Console.WriteLine("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
1634
1635 }
1636
1637 public Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod)
1638 {
1639 Mesh mesh = new Mesh();
1640
1641 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
1642 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
1643 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
1644 float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
1645 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
1646 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
1647
1648 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
1649 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
1650 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
1651
1652 int sides = 4;
1653 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
1654 sides = 3;
1655 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
1656 sides = 24;
1657 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
1658 { // half circle, prim is a sphere
1659 sides = 24;
1660
1661 profileBegin = 0.5f * profileBegin + 0.5f;
1662 profileEnd = 0.5f * profileEnd + 0.5f;
1663
1664 }
1665
1666 int hollowSides = sides;
1667 if (primShape.HollowShape == HollowShape.Circle)
1668 hollowSides = 24;
1669 else if (primShape.HollowShape == HollowShape.Square)
1670 hollowSides = 4;
1671 else if (primShape.HollowShape == HollowShape.Triangle)
1672 hollowSides = 3;
1673 322
1674 PrimMesh primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides); 323 primMesh.Scale(size.X, size.Y, size.Z);
1675 324
1676 primMesh.topShearX = pathShearX; 325 coords = primMesh.coords;
1677 primMesh.topShearY = pathShearY; 326 faces = primMesh.faces;
1678 primMesh.pathCutBegin = pathBegin;
1679 primMesh.pathCutEnd = pathEnd;
1680 327
1681 if (primShape.PathCurve == (byte)Extrusion.Straight)
1682 {
1683 primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10;
1684 primMesh.twistEnd = primShape.PathTwist * 18 / 10;
1685 primMesh.taperX = pathScaleX;
1686 primMesh.taperY = pathScaleY;
1687
1688 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
1689 {
1690 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
1691 if (profileBegin < 0.0f) profileBegin = 0.0f;
1692 if (profileEnd > 1.0f) profileEnd = 1.0f;
1693 }
1694#if SPAM
1695 Console.WriteLine("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
1696#endif
1697 try
1698 {
1699 primMesh.ExtrudeLinear();
1700 }
1701 catch (Exception ex)
1702 {
1703 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
1704 return null;
1705 }
1706 } 328 }
1707 else
1708 {
1709 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f;
1710 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f;
1711 primMesh.radius = 0.01f * primShape.PathRadiusOffset;
1712 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions;
1713 primMesh.skew = 0.01f * primShape.PathSkew;
1714 primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10;
1715 primMesh.twistEnd = primShape.PathTwist * 36 / 10;
1716 primMesh.taperX = primShape.PathTaperX * 0.01f;
1717 primMesh.taperY = primShape.PathTaperY * 0.01f;
1718
1719 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
1720 {
1721 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
1722 if (profileBegin < 0.0f) profileBegin = 0.0f;
1723 if (profileEnd > 1.0f) profileEnd = 1.0f;
1724 }
1725#if SPAM
1726 Console.WriteLine("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString());
1727#endif
1728 try
1729 {
1730 primMesh.ExtrudeCircular();
1731 }
1732 catch (Exception ex)
1733 {
1734 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
1735 return null;
1736 }
1737 }
1738
1739 primMesh.DumpRaw(baseDir, primName, "primMesh");
1740 329
1741 primMesh.Scale(size.X, size.Y, size.Z);
1742 330
1743 int numCoords = primMesh.coords.Count; 331 int numCoords = coords.Count;
1744 int numFaces = primMesh.faces.Count; 332 int numFaces = faces.Count;
1745 333
1746 List<Coord> coords = primMesh.coords;
1747 for (int i = 0; i < numCoords; i++) 334 for (int i = 0; i < numCoords; i++)
1748 { 335 {
1749 Coord c = coords[i]; 336 Coord c = coords[i];
1750 mesh.vertices.Add(new Vertex(c.X, c.Y, c.Z)); 337 mesh.vertices.Add(new Vertex(c.X, c.Y, c.Z));
1751 } 338 }
1752 339
1753 List<Face> faces = primMesh.faces;
1754 List<Vertex> vertices = mesh.vertices; 340 List<Vertex> vertices = mesh.vertices;
1755
1756 for (int i = 0; i < numFaces; i++) 341 for (int i = 0; i < numFaces; i++)
1757 { 342 {
1758 Face f = faces[i]; 343 Face f = faces[i];
1759 mesh.triangles.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); 344 mesh.triangles.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3]));
1760 } 345 }
1761 346
1762 //for (int i = 0; i < numFaces; i++)
1763 //{
1764 // Face f = primMesh.faces[i];
1765 // Coord vert = primMesh.coords[f.v1];
1766 // Vertex v1 = new Vertex(vert.X, vert.Y, vert.Z);
1767 // mesh.vertices.Add(v1);
1768 // vert = primMesh.coords[f.v2];
1769 // Vertex v2 = new Vertex(vert.X, vert.Y, vert.Z);
1770 // mesh.vertices.Add(v2);
1771 // vert = primMesh.coords[f.v3];
1772 // Vertex v3 = new Vertex(vert.X, vert.Y, vert.Z);
1773 // mesh.vertices.Add(v3);
1774 // mesh.triangles.Add(new Triangle(v1, v2, v3));
1775 //}
1776
1777 //mesh.DumpRaw(baseDir, primName, "Mesh");
1778
1779 //mesh.primMesh = primMesh;
1780
1781 return mesh; 347 return mesh;
1782 } 348 }
1783 349
@@ -1794,83 +360,16 @@ namespace OpenSim.Region.Physics.Meshing
1794 if (size.Y < 0.01f) size.Y = 0.01f; 360 if (size.Y < 0.01f) size.Y = 0.01f;
1795 if (size.Z < 0.01f) size.Z = 0.01f; 361 if (size.Z < 0.01f) size.Z = 0.01f;
1796 362
1797#if SPAM 363 mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
1798 reportPrimParams(primName, primShape);
1799#endif
1800
1801 if (primShape.SculptEntry && primShape.SculptType != (byte)0 && primShape.SculptData.Length > 0)
1802 {
1803 SculptMesh smesh = CreateSculptMesh(primName, primShape, size, lod);
1804 mesh = (Mesh)smesh;
1805 }
1806
1807 else if (usePrimMesher)
1808 {
1809 mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
1810 }
1811 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
1812 {
1813 if (primShape.PathCurve == (byte)Extrusion.Straight)
1814 { // its a box
1815 mesh = CreateBoxMesh(primName, primShape, size);
1816 //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
1817 }
1818 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
1819 { // tube
1820 // do a cylinder for now
1821 mesh = CreateCylinderMesh(primName, primShape, size);
1822 //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
1823 }
1824 }
1825 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
1826 {
1827 if (primShape.PathCurve == (byte)Extrusion.Straight)
1828 {
1829 mesh = CreateCylinderMesh(primName, primShape, size);
1830 //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
1831 }
1832
1833 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
1834 else if (primShape.PathCurve == (byte) Extrusion.Curve1)
1835 { // dahlia's favorite, a torus :)
1836 mesh = CreateCircularPathMesh(primName, primShape, size);
1837 //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);\
1838 }
1839 }
1840 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
1841 {
1842 if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte) Extrusion.Curve2)
1843 {
1844 //mesh = CreateSphereMesh(primName, primShape, size);
1845 mesh = CreateCircularPathMesh(primName, primShape, size);
1846 //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
1847 }
1848 }
1849 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
1850 {
1851 if (primShape.PathCurve == (byte)Extrusion.Straight)
1852 {
1853 mesh = CreatePrismMesh(primName, primShape, size);
1854 //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
1855 }
1856 else if (primShape.PathCurve == (byte) Extrusion.Curve1)
1857 { // a ring - do a cylinder for now
1858 //mesh = CreateCylinderMesh(primName, primShape, size);
1859 mesh = CreateCircularPathMesh(primName, primShape, size);
1860 //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
1861 }
1862 }
1863 else // just do a box
1864 {
1865 mesh = CreateBoxMesh(primName, primShape, size);
1866 }
1867 364
1868 if (mesh != null) 365 if (mesh != null)
1869 { 366 {
1870 if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh) 367 if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh)
1871 { 368 {
1872#if SPAM 369#if SPAM
1873 Console.WriteLine("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " + minSizeForComplexMesh.ToString() + " - creating simple bounding box" ); 370 Console.WriteLine("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " +
371
372minSizeForComplexMesh.ToString() + " - creating simple bounding box" );
1874#endif 373#endif
1875 mesh = CreateBoundingBoxMesh(mesh); 374 mesh = CreateBoundingBoxMesh(mesh);
1876 mesh.DumpRaw(baseDir, primName, "Z extruded"); 375 mesh.DumpRaw(baseDir, primName, "Z extruded");
@@ -1884,6 +383,8 @@ namespace OpenSim.Region.Physics.Meshing
1884 return mesh; 383 return mesh;
1885 } 384 }
1886 385
386
387
1887#if SPAM 388#if SPAM
1888 // please dont comment this out until I'm done with this module - dahlia 389 // please dont comment this out until I'm done with this module - dahlia
1889 private static void reportPrimParams(string name, PrimitiveBaseShape primShape) 390 private static void reportPrimParams(string name, PrimitiveBaseShape primShape)