aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs460
1 files changed, 240 insertions, 220 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index b478a9c..9dfaaa2 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -302,123 +302,6 @@ namespace OpenSim.Region.Physics.Meshing
302 } 302 }
303 303
304 /// <summary> 304 /// <summary>
305 /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim.
306 /// </summary>
307 /// <param name="primName"></param>
308 /// <param name="primShape"></param>
309 /// <param name="size"></param>
310 /// <param name="coords">Coords are added to this list by the method.</param>
311 /// <param name="faces">Faces are added to this list by the method.</param>
312 /// <returns>true if coords and faces were successfully generated, false if not</returns>
313 private bool GenerateCoordsAndFacesFromPrimMeshData(string primName, PrimitiveBaseShape primShape, Vector3 size, List<Coord> coords, List<Face> faces)
314 {
315 m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
316
317 OSD meshOsd = null;
318
319 if (primShape.SculptData.Length <= 0)
320 {
321 m_log.Error("[MESH]: asset data is zero length");
322 return false;
323 }
324
325 long start = 0;
326 using (MemoryStream data = new MemoryStream(primShape.SculptData))
327 {
328 try
329 {
330 OSD osd = OSDParser.DeserializeLLSDBinary(data);
331 if (osd is OSDMap)
332 meshOsd = (OSDMap)osd;
333 else
334 {
335 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
336 return false;
337 }
338 }
339 catch (Exception e)
340 {
341 m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString());
342 }
343
344 start = data.Position;
345 }
346
347 if (meshOsd is OSDMap)
348 {
349 OSDMap physicsParms = null;
350 OSDMap map = (OSDMap)meshOsd;
351 if (map.ContainsKey("physics_shape"))
352 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
353 else if (map.ContainsKey("physics_mesh"))
354 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
355
356 if (physicsParms == null)
357 {
358 m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset");
359 return false;
360 }
361
362 int physOffset = physicsParms["offset"].AsInteger() + (int)start;
363 int physSize = physicsParms["size"].AsInteger();
364
365 if (physOffset < 0 || physSize == 0)
366 return false; // no mesh data in asset
367
368 OSD decodedMeshOsd = new OSD();
369 byte[] meshBytes = new byte[physSize];
370 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
371// byte[] decompressed = new byte[physSize * 5];
372 try
373 {
374 using (MemoryStream inMs = new MemoryStream(meshBytes))
375 {
376 using (MemoryStream outMs = new MemoryStream())
377 {
378 using (ZOutputStream zOut = new ZOutputStream(outMs))
379 {
380 byte[] readBuffer = new byte[2048];
381 int readLen = 0;
382 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
383 {
384 zOut.Write(readBuffer, 0, readLen);
385 }
386 zOut.Flush();
387 outMs.Seek(0, SeekOrigin.Begin);
388
389 byte[] decompressedBuf = outMs.GetBuffer();
390
391 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
392 }
393 }
394 }
395 }
396 catch (Exception e)
397 {
398 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString());
399 return false;
400 }
401
402 OSDArray decodedMeshOsdArray = null;
403
404 // physics_shape is an array of OSDMaps, one for each submesh
405 if (decodedMeshOsd is OSDArray)
406 {
407// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
408
409 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
410 foreach (OSD subMeshOsd in decodedMeshOsdArray)
411 {
412 if (subMeshOsd is OSDMap)
413 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
414 }
415 }
416 }
417
418 return true;
419 }
420
421 /// <summary>
422 /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type. 305 /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type.
423 /// </summary> 306 /// </summary>
424 /// <param name="primName"></param> 307 /// <param name="primName"></param>
@@ -433,14 +316,10 @@ namespace OpenSim.Region.Physics.Meshing
433// primName, (OpenMetaverse.SculptType)primShape.SculptType); 316// primName, (OpenMetaverse.SculptType)primShape.SculptType);
434 317
435 PrimMesh primMesh; 318 PrimMesh primMesh;
436 PrimMesher.SculptMesh sculptMesh;
437 319
438 List<Coord> coords = new List<Coord>(); 320 List<Coord> coords = new List<Coord>();
439 List<Face> faces = new List<Face>(); 321 List<Face> faces = new List<Face>();
440 322
441 Image idata = null;
442 string decodedSculptFileName = "";
443
444 if (primShape.SculptEntry) 323 if (primShape.SculptEntry)
445 { 324 {
446 if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) 325 if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh)
@@ -448,109 +327,13 @@ namespace OpenSim.Region.Physics.Meshing
448 if (!useMeshiesPhysicsMesh) 327 if (!useMeshiesPhysicsMesh)
449 return null; 328 return null;
450 329
451 if (!GeneratePointsAndFacesFromPrimMeshData(primName, primShape, size, coords, faces)) 330 if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, coords, faces))
452 return null; 331 return null;
453 } 332 }
454 else 333 else
455 { 334 {
456 if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero) 335 if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, coords, faces))
457 { 336 return null;
458 decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString());
459 try
460 {
461 if (File.Exists(decodedSculptFileName))
462 {
463 idata = Image.FromFile(decodedSculptFileName);
464 }
465 }
466 catch (Exception e)
467 {
468 m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
469
470 }
471 //if (idata != null)
472 // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
473 }
474
475 if (idata == null)
476 {
477 if (primShape.SculptData == null || primShape.SculptData.Length == 0)
478 return null;
479
480 try
481 {
482 OpenMetaverse.Imaging.ManagedImage unusedData;
483 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
484
485 if (idata == null)
486 {
487 // In some cases it seems that the decode can return a null bitmap without throwing
488 // an exception
489 m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
490
491 return null;
492 }
493
494 unusedData = null;
495
496 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
497
498 if (cacheSculptMaps)
499 {
500 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
501 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
502 }
503 }
504 catch (DllNotFoundException)
505 {
506 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!");
507 return null;
508 }
509 catch (IndexOutOfRangeException)
510 {
511 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
512 return null;
513 }
514 catch (Exception ex)
515 {
516 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
517 return null;
518 }
519 }
520
521 PrimMesher.SculptMesh.SculptType sculptType;
522 switch ((OpenMetaverse.SculptType)primShape.SculptType)
523 {
524 case OpenMetaverse.SculptType.Cylinder:
525 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
526 break;
527 case OpenMetaverse.SculptType.Plane:
528 sculptType = PrimMesher.SculptMesh.SculptType.plane;
529 break;
530 case OpenMetaverse.SculptType.Torus:
531 sculptType = PrimMesher.SculptMesh.SculptType.torus;
532 break;
533 case OpenMetaverse.SculptType.Sphere:
534 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
535 break;
536 default:
537 sculptType = PrimMesher.SculptMesh.SculptType.plane;
538 break;
539 }
540
541 bool mirror = ((primShape.SculptType & 128) != 0);
542 bool invert = ((primShape.SculptType & 64) != 0);
543
544 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert);
545
546 idata.Dispose();
547
548 sculptMesh.DumpRaw(baseDir, primName, "primMesh");
549
550 sculptMesh.Scale(size.X, size.Y, size.Z);
551
552 coords = sculptMesh.coords;
553 faces = sculptMesh.faces;
554 } 337 }
555 } 338 }
556 else 339 else
@@ -691,6 +474,243 @@ namespace OpenSim.Region.Physics.Meshing
691 return mesh; 474 return mesh;
692 } 475 }
693 476
477 /// <summary>
478 /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim.
479 /// </summary>
480 /// <param name="primName"></param>
481 /// <param name="primShape"></param>
482 /// <param name="size"></param>
483 /// <param name="coords">Coords are added to this list by the method.</param>
484 /// <param name="faces">Faces are added to this list by the method.</param>
485 /// <returns>true if coords and faces were successfully generated, false if not</returns>
486 private bool GenerateCoordsAndFacesFromPrimMeshData(
487 string primName, PrimitiveBaseShape primShape, Vector3 size, List<Coord> coords, List<Face> faces)
488 {
489 m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
490
491 OSD meshOsd = null;
492
493 if (primShape.SculptData.Length <= 0)
494 {
495 m_log.Error("[MESH]: asset data is zero length");
496 return false;
497 }
498
499 long start = 0;
500 using (MemoryStream data = new MemoryStream(primShape.SculptData))
501 {
502 try
503 {
504 OSD osd = OSDParser.DeserializeLLSDBinary(data);
505 if (osd is OSDMap)
506 meshOsd = (OSDMap)osd;
507 else
508 {
509 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
510 return false;
511 }
512 }
513 catch (Exception e)
514 {
515 m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString());
516 }
517
518 start = data.Position;
519 }
520
521 if (meshOsd is OSDMap)
522 {
523 OSDMap physicsParms = null;
524 OSDMap map = (OSDMap)meshOsd;
525 if (map.ContainsKey("physics_shape"))
526 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
527 else if (map.ContainsKey("physics_mesh"))
528 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
529
530 if (physicsParms == null)
531 {
532 m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset");
533 return false;
534 }
535
536 int physOffset = physicsParms["offset"].AsInteger() + (int)start;
537 int physSize = physicsParms["size"].AsInteger();
538
539 if (physOffset < 0 || physSize == 0)
540 return false; // no mesh data in asset
541
542 OSD decodedMeshOsd = new OSD();
543 byte[] meshBytes = new byte[physSize];
544 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
545// byte[] decompressed = new byte[physSize * 5];
546 try
547 {
548 using (MemoryStream inMs = new MemoryStream(meshBytes))
549 {
550 using (MemoryStream outMs = new MemoryStream())
551 {
552 using (ZOutputStream zOut = new ZOutputStream(outMs))
553 {
554 byte[] readBuffer = new byte[2048];
555 int readLen = 0;
556 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
557 {
558 zOut.Write(readBuffer, 0, readLen);
559 }
560 zOut.Flush();
561 outMs.Seek(0, SeekOrigin.Begin);
562
563 byte[] decompressedBuf = outMs.GetBuffer();
564
565 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
566 }
567 }
568 }
569 }
570 catch (Exception e)
571 {
572 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString());
573 return false;
574 }
575
576 OSDArray decodedMeshOsdArray = null;
577
578 // physics_shape is an array of OSDMaps, one for each submesh
579 if (decodedMeshOsd is OSDArray)
580 {
581// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
582
583 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
584 foreach (OSD subMeshOsd in decodedMeshOsdArray)
585 {
586 if (subMeshOsd is OSDMap)
587 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
588 }
589 }
590 }
591
592 return true;
593 }
594
595 /// <summary>
596 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim.
597 /// </summary>
598 /// <param name="primName"></param>
599 /// <param name="primShape"></param>
600 /// <param name="size"></param>
601 /// <param name="lod"></param>
602 /// <param name="coords">Coords are added to this list by the method.</param>
603 /// <param name="faces">Faces are added to this list by the method.</param>
604 /// <returns>true if coords and faces were successfully generated, false if not</returns>
605 private bool GenerateCoordsAndFacesFromPrimSculptData(
606 string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, List<Coord> coords, List<Face> faces)
607 {
608 PrimMesher.SculptMesh sculptMesh;
609 Image idata = null;
610 string decodedSculptFileName = "";
611
612 if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero)
613 {
614 decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString());
615 try
616 {
617 if (File.Exists(decodedSculptFileName))
618 {
619 idata = Image.FromFile(decodedSculptFileName);
620 }
621 }
622 catch (Exception e)
623 {
624 m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
625
626 }
627 //if (idata != null)
628 // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
629 }
630
631 if (idata == null)
632 {
633 if (primShape.SculptData == null || primShape.SculptData.Length == 0)
634 return false;
635
636 try
637 {
638 OpenMetaverse.Imaging.ManagedImage unusedData;
639 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
640
641 if (idata == null)
642 {
643 // In some cases it seems that the decode can return a null bitmap without throwing
644 // an exception
645 m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
646
647 return false;
648 }
649
650 unusedData = null;
651
652 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
653
654 if (cacheSculptMaps)
655 {
656 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
657 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
658 }
659 }
660 catch (DllNotFoundException)
661 {
662 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!");
663 return false;
664 }
665 catch (IndexOutOfRangeException)
666 {
667 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
668 return false;
669 }
670 catch (Exception ex)
671 {
672 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
673 return false;
674 }
675 }
676
677 PrimMesher.SculptMesh.SculptType sculptType;
678 switch ((OpenMetaverse.SculptType)primShape.SculptType)
679 {
680 case OpenMetaverse.SculptType.Cylinder:
681 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
682 break;
683 case OpenMetaverse.SculptType.Plane:
684 sculptType = PrimMesher.SculptMesh.SculptType.plane;
685 break;
686 case OpenMetaverse.SculptType.Torus:
687 sculptType = PrimMesher.SculptMesh.SculptType.torus;
688 break;
689 case OpenMetaverse.SculptType.Sphere:
690 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
691 break;
692 default:
693 sculptType = PrimMesher.SculptMesh.SculptType.plane;
694 break;
695 }
696
697 bool mirror = ((primShape.SculptType & 128) != 0);
698 bool invert = ((primShape.SculptType & 64) != 0);
699
700 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert);
701
702 idata.Dispose();
703
704 sculptMesh.DumpRaw(baseDir, primName, "primMesh");
705
706 sculptMesh.Scale(size.X, size.Y, size.Z);
707
708 coords = sculptMesh.coords;
709 faces = sculptMesh.faces;
710
711 return true;
712 }
713
694 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 714 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
695 { 715 {
696 return CreateMesh(primName, primShape, size, lod, false); 716 return CreateMesh(primName, primShape, size, lod, false);