aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Meshmerizer.cs')
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs641
1 files changed, 360 insertions, 281 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 5413aa8..e81b982 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -301,20 +301,22 @@ namespace OpenSim.Region.Physics.Meshing
301 } 301 }
302 } 302 }
303 303
304 /// <summary>
305 /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type.
306 /// </summary>
307 /// <param name="primName"></param>
308 /// <param name="primShape"></param>
309 /// <param name="size"></param>
310 /// <param name="lod"></param>
311 /// <returns></returns>
304 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 312 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
305 { 313 {
306// m_log.DebugFormat( 314// m_log.DebugFormat(
307// "[MESH]: Creating physics proxy for {0}, shape {1}", 315// "[MESH]: Creating physics proxy for {0}, shape {1}",
308// primName, (OpenMetaverse.SculptType)primShape.SculptType); 316// primName, (OpenMetaverse.SculptType)primShape.SculptType);
309 317
310 PrimMesh primMesh; 318 List<Coord> coords;
311 PrimMesher.SculptMesh sculptMesh; 319 List<Face> faces;
312
313 List<Coord> coords = new List<Coord>();
314 List<Face> faces = new List<Face>();
315
316 Image idata = null;
317 string decodedSculptFileName = "";
318 320
319 if (primShape.SculptEntry) 321 if (primShape.SculptEntry)
320 { 322 {
@@ -323,337 +325,414 @@ namespace OpenSim.Region.Physics.Meshing
323 if (!useMeshiesPhysicsMesh) 325 if (!useMeshiesPhysicsMesh)
324 return null; 326 return null;
325 327
326 m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); 328 if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces))
329 return null;
330 }
331 else
332 {
333 if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
334 return null;
335 }
336 }
337 else
338 {
339 if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, out coords, out faces))
340 return null;
341 }
327 342
328 OSD meshOsd = null; 343 // Remove the reference to any JPEG2000 sculpt data so it can be GCed
344 primShape.SculptData = Utils.EmptyBytes;
329 345
330 if (primShape.SculptData.Length <= 0) 346 int numCoords = coords.Count;
331 { 347 int numFaces = faces.Count;
332 m_log.Error("[MESH]: asset data is zero length");
333 return null;
334 }
335 348
336 long start = 0; 349 // Create the list of vertices
337 using (MemoryStream data = new MemoryStream(primShape.SculptData)) 350 List<Vertex> vertices = new List<Vertex>();
338 { 351 for (int i = 0; i < numCoords; i++)
339 try 352 {
340 { 353 Coord c = coords[i];
341 OSD osd = OSDParser.DeserializeLLSDBinary(data); 354 vertices.Add(new Vertex(c.X, c.Y, c.Z));
342 if (osd is OSDMap) 355 }
343 meshOsd = (OSDMap)osd;
344 else
345 {
346 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
347 return null;
348 }
349 }
350 catch (Exception e)
351 {
352 m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString());
353 }
354 356
355 start = data.Position; 357 Mesh mesh = new Mesh();
356 } 358 // Add the corresponding triangles to the mesh
359 for (int i = 0; i < numFaces; i++)
360 {
361 Face f = faces[i];
362 mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3]));
363 }
364
365 return mesh;
366 }
357 367
358 if (meshOsd is OSDMap) 368 /// <summary>
369 /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim.
370 /// </summary>
371 /// <param name="primName"></param>
372 /// <param name="primShape"></param>
373 /// <param name="size"></param>
374 /// <param name="coords">Coords are added to this list by the method.</param>
375 /// <param name="faces">Faces are added to this list by the method.</param>
376 /// <returns>true if coords and faces were successfully generated, false if not</returns>
377 private bool GenerateCoordsAndFacesFromPrimMeshData(
378 string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces)
379 {
380 m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
381
382 coords = new List<Coord>();
383 faces = new List<Face>();
384 OSD meshOsd = null;
385
386 if (primShape.SculptData.Length <= 0)
387 {
388 m_log.Error("[MESH]: asset data is zero length");
389 return false;
390 }
391
392 long start = 0;
393 using (MemoryStream data = new MemoryStream(primShape.SculptData))
394 {
395 try
396 {
397 OSD osd = OSDParser.DeserializeLLSDBinary(data);
398 if (osd is OSDMap)
399 meshOsd = (OSDMap)osd;
400 else
359 { 401 {
360 OSDMap physicsParms = null; 402 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
361 OSDMap map = (OSDMap)meshOsd; 403 return false;
362 if (map.ContainsKey("physics_shape")) 404 }
363 physicsParms = (OSDMap)map["physics_shape"]; // old asset format 405 }
364 else if (map.ContainsKey("physics_mesh")) 406 catch (Exception e)
365 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format 407 {
366 408 m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString());
367 if (physicsParms == null) 409 }
368 { 410
369 m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset"); 411 start = data.Position;
370 return null; 412 }
371 }
372 413
373 int physOffset = physicsParms["offset"].AsInteger() + (int)start; 414 if (meshOsd is OSDMap)
374 int physSize = physicsParms["size"].AsInteger(); 415 {
416 OSDMap physicsParms = null;
417 OSDMap map = (OSDMap)meshOsd;
418 if (map.ContainsKey("physics_shape"))
419 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
420 else if (map.ContainsKey("physics_mesh"))
421 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
422
423 if (physicsParms == null)
424 {
425 m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset");
426 return false;
427 }
375 428
376 if (physOffset < 0 || physSize == 0) 429 int physOffset = physicsParms["offset"].AsInteger() + (int)start;
377 return null; // no mesh data in asset 430 int physSize = physicsParms["size"].AsInteger();
378 431
379 OSD decodedMeshOsd = new OSD(); 432 if (physOffset < 0 || physSize == 0)
380 byte[] meshBytes = new byte[physSize]; 433 return false; // no mesh data in asset
381 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); 434
435 OSD decodedMeshOsd = new OSD();
436 byte[] meshBytes = new byte[physSize];
437 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
382// byte[] decompressed = new byte[physSize * 5]; 438// byte[] decompressed = new byte[physSize * 5];
383 try 439 try
440 {
441 using (MemoryStream inMs = new MemoryStream(meshBytes))
442 {
443 using (MemoryStream outMs = new MemoryStream())
384 { 444 {
385 using (MemoryStream inMs = new MemoryStream(meshBytes)) 445 using (ZOutputStream zOut = new ZOutputStream(outMs))
386 { 446 {
387 using (MemoryStream outMs = new MemoryStream()) 447 byte[] readBuffer = new byte[2048];
448 int readLen = 0;
449 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
388 { 450 {
389 using (ZOutputStream zOut = new ZOutputStream(outMs)) 451 zOut.Write(readBuffer, 0, readLen);
390 {
391 byte[] readBuffer = new byte[2048];
392 int readLen = 0;
393 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
394 {
395 zOut.Write(readBuffer, 0, readLen);
396 }
397 zOut.Flush();
398 outMs.Seek(0, SeekOrigin.Begin);
399
400 byte[] decompressedBuf = outMs.GetBuffer();
401
402 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
403 }
404 } 452 }
453 zOut.Flush();
454 outMs.Seek(0, SeekOrigin.Begin);
455
456 byte[] decompressedBuf = outMs.GetBuffer();
457
458 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
405 } 459 }
406 } 460 }
407 catch (Exception e) 461 }
408 { 462 }
409 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); 463 catch (Exception e)
410 return null; 464 {
411 } 465 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString());
466 return false;
467 }
412 468
413 OSDArray decodedMeshOsdArray = null; 469 OSDArray decodedMeshOsdArray = null;
414 470
415 // physics_shape is an array of OSDMaps, one for each submesh 471 // physics_shape is an array of OSDMaps, one for each submesh
416 if (decodedMeshOsd is OSDArray) 472 if (decodedMeshOsd is OSDArray)
417 { 473 {
418// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); 474// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
419 475
420 decodedMeshOsdArray = (OSDArray)decodedMeshOsd; 476 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
421 foreach (OSD subMeshOsd in decodedMeshOsdArray) 477 foreach (OSD subMeshOsd in decodedMeshOsdArray)
422 { 478 {
423 if (subMeshOsd is OSDMap) 479 if (subMeshOsd is OSDMap)
424 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); 480 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
425 }
426 }
427 } 481 }
428 } 482 }
429 else 483 }
484
485 return true;
486 }
487
488 /// <summary>
489 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim.
490 /// </summary>
491 /// <param name="primName"></param>
492 /// <param name="primShape"></param>
493 /// <param name="size"></param>
494 /// <param name="lod"></param>
495 /// <param name="coords">Coords are added to this list by the method.</param>
496 /// <param name="faces">Faces are added to this list by the method.</param>
497 /// <returns>true if coords and faces were successfully generated, false if not</returns>
498 private bool GenerateCoordsAndFacesFromPrimSculptData(
499 string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces)
500 {
501 coords = new List<Coord>();
502 faces = new List<Face>();
503 PrimMesher.SculptMesh sculptMesh;
504 Image idata = null;
505 string decodedSculptFileName = "";
506
507 if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero)
508 {
509 decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString());
510 try
430 { 511 {
431 if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero) 512 if (File.Exists(decodedSculptFileName))
432 { 513 {
433 decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString()); 514 idata = Image.FromFile(decodedSculptFileName);
434 try
435 {
436 if (File.Exists(decodedSculptFileName))
437 {
438 idata = Image.FromFile(decodedSculptFileName);
439 }
440 }
441 catch (Exception e)
442 {
443 m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
444
445 }
446 //if (idata != null)
447 // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
448 } 515 }
516 }
517 catch (Exception e)
518 {
519 m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
520
521 }
522 //if (idata != null)
523 // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
524 }
525
526 if (idata == null)
527 {
528 if (primShape.SculptData == null || primShape.SculptData.Length == 0)
529 return false;
530
531 try
532 {
533 OpenMetaverse.Imaging.ManagedImage unusedData;
534 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
449 535
450 if (idata == null) 536 if (idata == null)
451 { 537 {
452 if (primShape.SculptData == null || primShape.SculptData.Length == 0) 538 // In some cases it seems that the decode can return a null bitmap without throwing
453 return null; 539 // an exception
540 m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
454 541
455 try 542 return false;
456 { 543 }
457 OpenMetaverse.Imaging.ManagedImage unusedData;
458 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
459 unusedData = null;
460 544
461 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); 545 unusedData = null;
462 546
463 if (cacheSculptMaps && idata != null) 547 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
464 {
465 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
466 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
467 }
468 }
469 catch (DllNotFoundException)
470 {
471 m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed. Often times this is because of an old version of GLIBC. You must have version 2.4 or above!");
472 return null;
473 }
474 catch (IndexOutOfRangeException)
475 {
476 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
477 return null;
478 }
479 catch (Exception ex)
480 {
481 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
482 return null;
483 }
484 }
485 548
486 PrimMesher.SculptMesh.SculptType sculptType; 549 if (cacheSculptMaps)
487 switch ((OpenMetaverse.SculptType)primShape.SculptType)
488 { 550 {
489 case OpenMetaverse.SculptType.Cylinder: 551 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
490 sculptType = PrimMesher.SculptMesh.SculptType.cylinder; 552 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
491 break;
492 case OpenMetaverse.SculptType.Plane:
493 sculptType = PrimMesher.SculptMesh.SculptType.plane;
494 break;
495 case OpenMetaverse.SculptType.Torus:
496 sculptType = PrimMesher.SculptMesh.SculptType.torus;
497 break;
498 case OpenMetaverse.SculptType.Sphere:
499 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
500 break;
501 default:
502 sculptType = PrimMesher.SculptMesh.SculptType.plane;
503 break;
504 } 553 }
554 }
555 catch (DllNotFoundException)
556 {
557 m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed. Often times this is because of an old version of GLIBC. You must have version 2.4 or above!");
558 return false;
559 }
560 catch (IndexOutOfRangeException)
561 {
562 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
563 return false;
564 }
565 catch (Exception ex)
566 {
567 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
568 return false;
569 }
570 }
571
572 PrimMesher.SculptMesh.SculptType sculptType;
573 switch ((OpenMetaverse.SculptType)primShape.SculptType)
574 {
575 case OpenMetaverse.SculptType.Cylinder:
576 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
577 break;
578 case OpenMetaverse.SculptType.Plane:
579 sculptType = PrimMesher.SculptMesh.SculptType.plane;
580 break;
581 case OpenMetaverse.SculptType.Torus:
582 sculptType = PrimMesher.SculptMesh.SculptType.torus;
583 break;
584 case OpenMetaverse.SculptType.Sphere:
585 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
586 break;
587 default:
588 sculptType = PrimMesher.SculptMesh.SculptType.plane;
589 break;
590 }
505 591
506 bool mirror = ((primShape.SculptType & 128) != 0); 592 bool mirror = ((primShape.SculptType & 128) != 0);
507 bool invert = ((primShape.SculptType & 64) != 0); 593 bool invert = ((primShape.SculptType & 64) != 0);
508 594
509 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); 595 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert);
510
511 idata.Dispose();
512 596
513 sculptMesh.DumpRaw(baseDir, primName, "primMesh"); 597 idata.Dispose();
514 598
515 sculptMesh.Scale(size.X, size.Y, size.Z); 599 sculptMesh.DumpRaw(baseDir, primName, "primMesh");
516 600
517 coords = sculptMesh.coords; 601 sculptMesh.Scale(size.X, size.Y, size.Z);
518 faces = sculptMesh.faces; 602
519 } 603 coords = sculptMesh.coords;
604 faces = sculptMesh.faces;
605
606 return true;
607 }
608
609 /// <summary>
610 /// Generate the co-ords and faces necessary to construct a mesh from the shape data the accompanies a prim.
611 /// </summary>
612 /// <param name="primName"></param>
613 /// <param name="primShape"></param>
614 /// <param name="size"></param>
615 /// <param name="coords">Coords are added to this list by the method.</param>
616 /// <param name="faces">Faces are added to this list by the method.</param>
617 /// <returns>true if coords and faces were successfully generated, false if not</returns>
618 private bool GenerateCoordsAndFacesFromPrimShapeData(
619 string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces)
620 {
621 PrimMesh primMesh;
622 coords = new List<Coord>();
623 faces = new List<Face>();
624
625 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
626 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
627 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
628 float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
629 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
630 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
631
632 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
633 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
634 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
635 if (profileHollow > 0.95f)
636 profileHollow = 0.95f;
637
638 int sides = 4;
639 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
640 sides = 3;
641 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
642 sides = 24;
643 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
644 { // half circle, prim is a sphere
645 sides = 24;
646
647 profileBegin = 0.5f * profileBegin + 0.5f;
648 profileEnd = 0.5f * profileEnd + 0.5f;
520 } 649 }
521 else
522 {
523 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
524 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
525 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
526 float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
527 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
528 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
529
530 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
531 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
532 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
533 if (profileHollow > 0.95f)
534 profileHollow = 0.95f;
535
536 int sides = 4;
537 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
538 sides = 3;
539 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
540 sides = 24;
541 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
542 { // half circle, prim is a sphere
543 sides = 24;
544
545 profileBegin = 0.5f * profileBegin + 0.5f;
546 profileEnd = 0.5f * profileEnd + 0.5f;
547 }
548 650
549 int hollowSides = sides; 651 int hollowSides = sides;
550 if (primShape.HollowShape == HollowShape.Circle) 652 if (primShape.HollowShape == HollowShape.Circle)
551 hollowSides = 24; 653 hollowSides = 24;
552 else if (primShape.HollowShape == HollowShape.Square) 654 else if (primShape.HollowShape == HollowShape.Square)
553 hollowSides = 4; 655 hollowSides = 4;
554 else if (primShape.HollowShape == HollowShape.Triangle) 656 else if (primShape.HollowShape == HollowShape.Triangle)
555 hollowSides = 3; 657 hollowSides = 3;
556 658
557 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides); 659 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
558 660
559 if (primMesh.errorMessage != null) 661 if (primMesh.errorMessage != null)
560 if (primMesh.errorMessage.Length > 0) 662 if (primMesh.errorMessage.Length > 0)
561 m_log.Error("[ERROR] " + primMesh.errorMessage); 663 m_log.Error("[ERROR] " + primMesh.errorMessage);
562 664
563 primMesh.topShearX = pathShearX; 665 primMesh.topShearX = pathShearX;
564 primMesh.topShearY = pathShearY; 666 primMesh.topShearY = pathShearY;
565 primMesh.pathCutBegin = pathBegin; 667 primMesh.pathCutBegin = pathBegin;
566 primMesh.pathCutEnd = pathEnd; 668 primMesh.pathCutEnd = pathEnd;
567 669
568 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible) 670 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible)
569 { 671 {
570 primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10; 672 primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10;
571 primMesh.twistEnd = primShape.PathTwist * 18 / 10; 673 primMesh.twistEnd = primShape.PathTwist * 18 / 10;
572 primMesh.taperX = pathScaleX; 674 primMesh.taperX = pathScaleX;
573 primMesh.taperY = pathScaleY; 675 primMesh.taperY = pathScaleY;
574 676
575 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) 677 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
576 { 678 {
577 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); 679 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
578 if (profileBegin < 0.0f) profileBegin = 0.0f; 680 if (profileBegin < 0.0f) profileBegin = 0.0f;
579 if (profileEnd > 1.0f) profileEnd = 1.0f; 681 if (profileEnd > 1.0f) profileEnd = 1.0f;
580 } 682 }
581#if SPAM 683#if SPAM
582 m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString()); 684 m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
583#endif 685#endif
584 try 686 try
585 { 687 {
586 primMesh.ExtrudeLinear(); 688 primMesh.ExtrudeLinear();
587 }
588 catch (Exception ex)
589 {
590 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
591 return null;
592 }
593 } 689 }
594 else 690 catch (Exception ex)
595 { 691 {
596 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f; 692 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
597 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f; 693 return false;
598 primMesh.radius = 0.01f * primShape.PathRadiusOffset; 694 }
599 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions; 695 }
600 primMesh.skew = 0.01f * primShape.PathSkew; 696 else
601 primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10; 697 {
602 primMesh.twistEnd = primShape.PathTwist * 36 / 10; 698 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f;
603 primMesh.taperX = primShape.PathTaperX * 0.01f; 699 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f;
604 primMesh.taperY = primShape.PathTaperY * 0.01f; 700 primMesh.radius = 0.01f * primShape.PathRadiusOffset;
605 701 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions;
606 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) 702 primMesh.skew = 0.01f * primShape.PathSkew;
607 { 703 primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10;
608 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); 704 primMesh.twistEnd = primShape.PathTwist * 36 / 10;
609 if (profileBegin < 0.0f) profileBegin = 0.0f; 705 primMesh.taperX = primShape.PathTaperX * 0.01f;
610 if (profileEnd > 1.0f) profileEnd = 1.0f; 706 primMesh.taperY = primShape.PathTaperY * 0.01f;
611 } 707
708 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
709 {
710 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
711 if (profileBegin < 0.0f) profileBegin = 0.0f;
712 if (profileEnd > 1.0f) profileEnd = 1.0f;
713 }
612#if SPAM 714#if SPAM
613 m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString()); 715 m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString());
614#endif 716#endif
615 try 717 try
616 { 718 {
617 primMesh.ExtrudeCircular(); 719 primMesh.ExtrudeCircular();
618 } 720 }
619 catch (Exception ex) 721 catch (Exception ex)
620 { 722 {
621 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); 723 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
622 return null; 724 return false;
623 }
624 } 725 }
625
626 primMesh.DumpRaw(baseDir, primName, "primMesh");
627
628 primMesh.Scale(size.X, size.Y, size.Z);
629
630 coords = primMesh.coords;
631 faces = primMesh.faces;
632 } 726 }
633 727
634 // Remove the reference to any JPEG2000 sculpt data so it can be GCed 728 primMesh.DumpRaw(baseDir, primName, "primMesh");
635 primShape.SculptData = Utils.EmptyBytes;
636 729
637 int numCoords = coords.Count; 730 primMesh.Scale(size.X, size.Y, size.Z);
638 int numFaces = faces.Count;
639 731
640 // Create the list of vertices 732 coords = primMesh.coords;
641 List<Vertex> vertices = new List<Vertex>(); 733 faces = primMesh.faces;
642 for (int i = 0; i < numCoords; i++)
643 {
644 Coord c = coords[i];
645 vertices.Add(new Vertex(c.X, c.Y, c.Z));
646 }
647
648 Mesh mesh = new Mesh();
649 // Add the corresponding triangles to the mesh
650 for (int i = 0; i < numFaces; i++)
651 {
652 Face f = faces[i];
653 mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3]));
654 }
655 734
656 return mesh; 735 return true;
657 } 736 }
658 737
659 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 738 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)