diff options
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Meshmerizer.cs')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 152 |
1 files changed, 129 insertions, 23 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 79edc12..fc679e7 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -64,6 +64,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
64 | public class Meshmerizer : IMesher | 64 | public class Meshmerizer : IMesher |
65 | { | 65 | { |
66 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 66 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
67 | private static string LogHeader = "[MESH]"; | ||
67 | 68 | ||
68 | // Setting baseDir to a path will enable the dumping of raw files | 69 | // Setting baseDir to a path will enable the dumping of raw files |
69 | // raw files can be imported by blender so a visual inspection of the results can be done | 70 | // raw files can be imported by blender so a visual inspection of the results can be done |
@@ -72,6 +73,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
72 | #else | 73 | #else |
73 | private const string baseDir = null; //"rawFiles"; | 74 | private const string baseDir = null; //"rawFiles"; |
74 | #endif | 75 | #endif |
76 | // If 'true', lots of DEBUG logging of asset parsing details | ||
77 | private bool debugDetail = false; | ||
75 | 78 | ||
76 | private bool cacheSculptMaps = true; | 79 | private bool cacheSculptMaps = true; |
77 | private string decodedSculptMapPath = null; | 80 | private string decodedSculptMapPath = null; |
@@ -80,6 +83,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
80 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh | 83 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh |
81 | 84 | ||
82 | private List<List<Vector3>> mConvexHulls = null; | 85 | private List<List<Vector3>> mConvexHulls = null; |
86 | private List<Vector3> mBoundingHull = null; | ||
83 | 87 | ||
84 | private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); | 88 | private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); |
85 | 89 | ||
@@ -90,8 +94,11 @@ namespace OpenSim.Region.Physics.Meshing | |||
90 | 94 | ||
91 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); | 95 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); |
92 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | 96 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); |
93 | if(mesh_config != null) | 97 | if (mesh_config != null) |
98 | { | ||
94 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | 99 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); |
100 | debugDetail = mesh_config.GetBoolean("LogMeshDetails", debugDetail); | ||
101 | } | ||
95 | 102 | ||
96 | try | 103 | try |
97 | { | 104 | { |
@@ -321,6 +328,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
321 | faces = new List<Face>(); | 328 | faces = new List<Face>(); |
322 | OSD meshOsd = null; | 329 | OSD meshOsd = null; |
323 | 330 | ||
331 | mConvexHulls = null; | ||
332 | mBoundingHull = null; | ||
333 | |||
324 | if (primShape.SculptData.Length <= 0) | 334 | if (primShape.SculptData.Length <= 0) |
325 | { | 335 | { |
326 | // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this | 336 | // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this |
@@ -357,43 +367,79 @@ namespace OpenSim.Region.Physics.Meshing | |||
357 | OSDMap physicsParms = null; | 367 | OSDMap physicsParms = null; |
358 | OSDMap map = (OSDMap)meshOsd; | 368 | OSDMap map = (OSDMap)meshOsd; |
359 | if (map.ContainsKey("physics_shape")) | 369 | if (map.ContainsKey("physics_shape")) |
370 | { | ||
360 | physicsParms = (OSDMap)map["physics_shape"]; // old asset format | 371 | physicsParms = (OSDMap)map["physics_shape"]; // old asset format |
372 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}': using 'physics_shape' mesh data", LogHeader, primName); | ||
373 | } | ||
361 | else if (map.ContainsKey("physics_mesh")) | 374 | else if (map.ContainsKey("physics_mesh")) |
375 | { | ||
362 | physicsParms = (OSDMap)map["physics_mesh"]; // new asset format | 376 | physicsParms = (OSDMap)map["physics_mesh"]; // new asset format |
377 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'physics_mesh' mesh data", LogHeader, primName); | ||
378 | } | ||
363 | else if (map.ContainsKey("medium_lod")) | 379 | else if (map.ContainsKey("medium_lod")) |
380 | { | ||
364 | physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh | 381 | physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh |
382 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'medium_lod' mesh data", LogHeader, primName); | ||
383 | } | ||
365 | else if (map.ContainsKey("high_lod")) | 384 | else if (map.ContainsKey("high_lod")) |
385 | { | ||
366 | physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :) | 386 | physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :) |
387 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'high_lod' mesh data", LogHeader, primName); | ||
388 | } | ||
367 | 389 | ||
368 | if (map.ContainsKey("physics_convex")) | 390 | if (map.ContainsKey("physics_convex")) |
369 | { // pull this out also in case physics engine can use it | 391 | { // pull this out also in case physics engine can use it |
392 | OSD convexBlockOsd = null; | ||
370 | try | 393 | try |
371 | { | 394 | { |
372 | OSDMap convexBlock = (OSDMap)map["physics_convex"]; | 395 | OSDMap convexBlock = (OSDMap)map["physics_convex"]; |
373 | if (convexBlock.ContainsKey("HullList")) | ||
374 | { | 396 | { |
375 | byte[] hullList = convexBlock["HullList"].AsBinary(); | 397 | int convexOffset = convexBlock["offset"].AsInteger() + (int)start; |
398 | int convexSize = convexBlock["size"].AsInteger(); | ||
399 | |||
400 | byte[] convexBytes = new byte[convexSize]; | ||
401 | |||
402 | System.Buffer.BlockCopy(primShape.SculptData, convexOffset, convexBytes, 0, convexSize); | ||
403 | |||
404 | try | ||
405 | { | ||
406 | convexBlockOsd = DecompressOsd(convexBytes); | ||
407 | } | ||
408 | catch (Exception e) | ||
409 | { | ||
410 | m_log.ErrorFormat("{0} prim='{1}': exception decoding convex block: {2}", LogHeader, primName, e); | ||
411 | //return false; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | if (convexBlockOsd != null && convexBlockOsd is OSDMap) | ||
416 | { | ||
417 | convexBlock = convexBlockOsd as OSDMap; | ||
418 | |||
419 | if (debugDetail) | ||
420 | { | ||
421 | string keys = LogHeader + " keys found in convexBlock: "; | ||
422 | foreach (KeyValuePair<string, OSD> kvp in convexBlock) | ||
423 | keys += "'" + kvp.Key + "' "; | ||
424 | m_log.Debug(keys); | ||
425 | } | ||
426 | |||
376 | Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f); | 427 | Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f); |
377 | if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3(); | 428 | if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3(); |
378 | Vector3 max = new Vector3(0.5f, 0.5f, 0.5f); | 429 | Vector3 max = new Vector3(0.5f, 0.5f, 0.5f); |
379 | if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3(); | 430 | if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3(); |
380 | 431 | ||
381 | // decompress and decode hull points | 432 | List<Vector3> boundingHull = null; |
382 | byte[] posBytes = DecompressOsd(convexBlock["Positions"].AsBinary()).AsBinary(); | ||
383 | |||
384 | List<List<Vector3>> hulls = new List<List<Vector3>>(); | ||
385 | int posNdx = 0; | ||
386 | 433 | ||
387 | foreach (byte cnt in hullList) | 434 | if (convexBlock.ContainsKey("BoundingVerts")) |
388 | { | 435 | { |
389 | int count = cnt == 0 ? 256 : cnt; | 436 | byte[] boundingVertsBytes = convexBlock["BoundingVerts"].AsBinary(); |
390 | List<Vector3> hull = new List<Vector3>(); | 437 | boundingHull = new List<Vector3>(); |
391 | 438 | for (int i = 0; i < boundingVertsBytes.Length; ) | |
392 | for (int i = 0; i < count; i++) | ||
393 | { | 439 | { |
394 | ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | 440 | ushort uX = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2; |
395 | ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | 441 | ushort uY = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2; |
396 | ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | 442 | ushort uZ = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2; |
397 | 443 | ||
398 | Vector3 pos = new Vector3( | 444 | Vector3 pos = new Vector3( |
399 | Utils.UInt16ToFloat(uX, min.X, max.X), | 445 | Utils.UInt16ToFloat(uX, min.X, max.X), |
@@ -401,18 +447,57 @@ namespace OpenSim.Region.Physics.Meshing | |||
401 | Utils.UInt16ToFloat(uZ, min.Z, max.Z) | 447 | Utils.UInt16ToFloat(uZ, min.Z, max.Z) |
402 | ); | 448 | ); |
403 | 449 | ||
404 | hull.Add(pos); | 450 | boundingHull.Add(pos); |
405 | } | 451 | } |
406 | 452 | ||
407 | hulls.Add(hull); | 453 | mBoundingHull = boundingHull; |
454 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed bounding hull. nVerts={2}", LogHeader, primName, mBoundingHull.Count); | ||
408 | } | 455 | } |
409 | 456 | ||
410 | mConvexHulls = hulls; | 457 | if (convexBlock.ContainsKey("HullList")) |
458 | { | ||
459 | byte[] hullList = convexBlock["HullList"].AsBinary(); | ||
460 | |||
461 | byte[] posBytes = convexBlock["Positions"].AsBinary(); | ||
462 | |||
463 | List<List<Vector3>> hulls = new List<List<Vector3>>(); | ||
464 | int posNdx = 0; | ||
465 | |||
466 | foreach (byte cnt in hullList) | ||
467 | { | ||
468 | int count = cnt == 0 ? 256 : cnt; | ||
469 | List<Vector3> hull = new List<Vector3>(); | ||
470 | |||
471 | for (int i = 0; i < count; i++) | ||
472 | { | ||
473 | ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
474 | ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
475 | ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
476 | |||
477 | Vector3 pos = new Vector3( | ||
478 | Utils.UInt16ToFloat(uX, min.X, max.X), | ||
479 | Utils.UInt16ToFloat(uY, min.Y, max.Y), | ||
480 | Utils.UInt16ToFloat(uZ, min.Z, max.Z) | ||
481 | ); | ||
482 | |||
483 | hull.Add(pos); | ||
484 | } | ||
485 | |||
486 | hulls.Add(hull); | ||
487 | } | ||
488 | |||
489 | mConvexHulls = hulls; | ||
490 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed hulls. nHulls={2}", LogHeader, primName, mConvexHulls.Count); | ||
491 | } | ||
492 | else | ||
493 | { | ||
494 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}' has physics_convex but no HullList", LogHeader, primName); | ||
495 | } | ||
411 | } | 496 | } |
412 | } | 497 | } |
413 | catch (Exception e) | 498 | catch (Exception e) |
414 | { | 499 | { |
415 | m_log.WarnFormat("[MESH]: exception decoding convex block: {0}", e.Message); | 500 | m_log.WarnFormat("{0} exception decoding convex block: {1}", LogHeader, e); |
416 | } | 501 | } |
417 | } | 502 | } |
418 | 503 | ||
@@ -431,14 +516,14 @@ namespace OpenSim.Region.Physics.Meshing | |||
431 | OSD decodedMeshOsd = new OSD(); | 516 | OSD decodedMeshOsd = new OSD(); |
432 | byte[] meshBytes = new byte[physSize]; | 517 | byte[] meshBytes = new byte[physSize]; |
433 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); | 518 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); |
434 | // byte[] decompressed = new byte[physSize * 5]; | 519 | // byte[] decompressed = new byte[physSize * 5]; |
435 | try | 520 | try |
436 | { | 521 | { |
437 | decodedMeshOsd = DecompressOsd(meshBytes); | 522 | decodedMeshOsd = DecompressOsd(meshBytes); |
438 | } | 523 | } |
439 | catch (Exception e) | 524 | catch (Exception e) |
440 | { | 525 | { |
441 | m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); | 526 | m_log.ErrorFormat("{0} prim='{1}': exception decoding physical mesh: {2}", LogHeader, primName, e); |
442 | return false; | 527 | return false; |
443 | } | 528 | } |
444 | 529 | ||
@@ -447,7 +532,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
447 | // physics_shape is an array of OSDMaps, one for each submesh | 532 | // physics_shape is an array of OSDMaps, one for each submesh |
448 | if (decodedMeshOsd is OSDArray) | 533 | if (decodedMeshOsd is OSDArray) |
449 | { | 534 | { |
450 | // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); | 535 | // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); |
451 | 536 | ||
452 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; | 537 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; |
453 | foreach (OSD subMeshOsd in decodedMeshOsdArray) | 538 | foreach (OSD subMeshOsd in decodedMeshOsdArray) |
@@ -455,6 +540,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
455 | if (subMeshOsd is OSDMap) | 540 | if (subMeshOsd is OSDMap) |
456 | AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); | 541 | AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); |
457 | } | 542 | } |
543 | if (debugDetail) | ||
544 | m_log.DebugFormat("{0} {1}: mesh decoded. offset={2}, size={3}, nCoords={4}, nFaces={5}", | ||
545 | LogHeader, primName, physOffset, physSize, coords.Count, faces.Count); | ||
458 | } | 546 | } |
459 | } | 547 | } |
460 | 548 | ||
@@ -776,6 +864,23 @@ namespace OpenSim.Region.Physics.Meshing | |||
776 | /// temporary prototype code - please do not use until the interface has been finalized! | 864 | /// temporary prototype code - please do not use until the interface has been finalized! |
777 | /// </summary> | 865 | /// </summary> |
778 | /// <param name="size">value to scale the hull points by</param> | 866 | /// <param name="size">value to scale the hull points by</param> |
867 | /// <returns>a list of vertices in the bounding hull if it exists and has been successfully decoded, otherwise null</returns> | ||
868 | public List<Vector3> GetBoundingHull(Vector3 size) | ||
869 | { | ||
870 | if (mBoundingHull == null) | ||
871 | return null; | ||
872 | |||
873 | List<Vector3> verts = new List<Vector3>(); | ||
874 | foreach (var vert in mBoundingHull) | ||
875 | verts.Add(vert * size); | ||
876 | |||
877 | return verts; | ||
878 | } | ||
879 | |||
880 | /// <summary> | ||
881 | /// temporary prototype code - please do not use until the interface has been finalized! | ||
882 | /// </summary> | ||
883 | /// <param name="size">value to scale the hull points by</param> | ||
779 | /// <returns>a list of hulls if they exist and have been successfully decoded, otherwise null</returns> | 884 | /// <returns>a list of hulls if they exist and have been successfully decoded, otherwise null</returns> |
780 | public List<List<Vector3>> GetConvexHulls(Vector3 size) | 885 | public List<List<Vector3>> GetConvexHulls(Vector3 size) |
781 | { | 886 | { |
@@ -788,6 +893,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
788 | List<Vector3> verts = new List<Vector3>(); | 893 | List<Vector3> verts = new List<Vector3>(); |
789 | foreach (var vert in hull) | 894 | foreach (var vert in hull) |
790 | verts.Add(vert * size); | 895 | verts.Add(vert * size); |
896 | hulls.Add(verts); | ||
791 | } | 897 | } |
792 | 898 | ||
793 | return hulls; | 899 | return hulls; |