diff options
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Meshmerizer.cs')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 135 |
1 files changed, 114 insertions, 21 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 8145d61..79edc12 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -79,6 +79,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
79 | 79 | ||
80 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh | 80 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh |
81 | 81 | ||
82 | private List<List<Vector3>> mConvexHulls = null; | ||
83 | |||
82 | private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); | 84 | private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); |
83 | 85 | ||
84 | public Meshmerizer(IConfigSource config) | 86 | public Meshmerizer(IConfigSource config) |
@@ -358,6 +360,61 @@ namespace OpenSim.Region.Physics.Meshing | |||
358 | physicsParms = (OSDMap)map["physics_shape"]; // old asset format | 360 | physicsParms = (OSDMap)map["physics_shape"]; // old asset format |
359 | else if (map.ContainsKey("physics_mesh")) | 361 | else if (map.ContainsKey("physics_mesh")) |
360 | physicsParms = (OSDMap)map["physics_mesh"]; // new asset format | 362 | physicsParms = (OSDMap)map["physics_mesh"]; // new asset format |
363 | else if (map.ContainsKey("medium_lod")) | ||
364 | physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh | ||
365 | else if (map.ContainsKey("high_lod")) | ||
366 | physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :) | ||
367 | |||
368 | if (map.ContainsKey("physics_convex")) | ||
369 | { // pull this out also in case physics engine can use it | ||
370 | try | ||
371 | { | ||
372 | OSDMap convexBlock = (OSDMap)map["physics_convex"]; | ||
373 | if (convexBlock.ContainsKey("HullList")) | ||
374 | { | ||
375 | byte[] hullList = convexBlock["HullList"].AsBinary(); | ||
376 | Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f); | ||
377 | if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3(); | ||
378 | Vector3 max = new Vector3(0.5f, 0.5f, 0.5f); | ||
379 | if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3(); | ||
380 | |||
381 | // decompress and decode hull points | ||
382 | byte[] posBytes = DecompressOsd(convexBlock["Positions"].AsBinary()).AsBinary(); | ||
383 | |||
384 | List<List<Vector3>> hulls = new List<List<Vector3>>(); | ||
385 | int posNdx = 0; | ||
386 | |||
387 | foreach (byte cnt in hullList) | ||
388 | { | ||
389 | int count = cnt == 0 ? 256 : cnt; | ||
390 | List<Vector3> hull = new List<Vector3>(); | ||
391 | |||
392 | for (int i = 0; i < count; i++) | ||
393 | { | ||
394 | ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
395 | ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
396 | ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
397 | |||
398 | Vector3 pos = new Vector3( | ||
399 | Utils.UInt16ToFloat(uX, min.X, max.X), | ||
400 | Utils.UInt16ToFloat(uY, min.Y, max.Y), | ||
401 | Utils.UInt16ToFloat(uZ, min.Z, max.Z) | ||
402 | ); | ||
403 | |||
404 | hull.Add(pos); | ||
405 | } | ||
406 | |||
407 | hulls.Add(hull); | ||
408 | } | ||
409 | |||
410 | mConvexHulls = hulls; | ||
411 | } | ||
412 | } | ||
413 | catch (Exception e) | ||
414 | { | ||
415 | m_log.WarnFormat("[MESH]: exception decoding convex block: {0}", e.Message); | ||
416 | } | ||
417 | } | ||
361 | 418 | ||
362 | if (physicsParms == null) | 419 | if (physicsParms == null) |
363 | { | 420 | { |
@@ -377,27 +434,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
377 | // byte[] decompressed = new byte[physSize * 5]; | 434 | // byte[] decompressed = new byte[physSize * 5]; |
378 | try | 435 | try |
379 | { | 436 | { |
380 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | 437 | decodedMeshOsd = DecompressOsd(meshBytes); |
381 | { | ||
382 | using (MemoryStream outMs = new MemoryStream()) | ||
383 | { | ||
384 | using (ZOutputStream zOut = new ZOutputStream(outMs)) | ||
385 | { | ||
386 | byte[] readBuffer = new byte[2048]; | ||
387 | int readLen = 0; | ||
388 | while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) | ||
389 | { | ||
390 | zOut.Write(readBuffer, 0, readLen); | ||
391 | } | ||
392 | zOut.Flush(); | ||
393 | outMs.Seek(0, SeekOrigin.Begin); | ||
394 | |||
395 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
396 | |||
397 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
398 | } | ||
399 | } | ||
400 | } | ||
401 | } | 438 | } |
402 | catch (Exception e) | 439 | catch (Exception e) |
403 | { | 440 | { |
@@ -424,6 +461,41 @@ namespace OpenSim.Region.Physics.Meshing | |||
424 | return true; | 461 | return true; |
425 | } | 462 | } |
426 | 463 | ||
464 | |||
465 | /// <summary> | ||
466 | /// decompresses a gzipped OSD object | ||
467 | /// </summary> | ||
468 | /// <param name="decodedOsd"></param> the OSD object | ||
469 | /// <param name="meshBytes"></param> | ||
470 | /// <returns></returns> | ||
471 | private static OSD DecompressOsd(byte[] meshBytes) | ||
472 | { | ||
473 | OSD decodedOsd = null; | ||
474 | |||
475 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | ||
476 | { | ||
477 | using (MemoryStream outMs = new MemoryStream()) | ||
478 | { | ||
479 | using (ZOutputStream zOut = new ZOutputStream(outMs)) | ||
480 | { | ||
481 | byte[] readBuffer = new byte[2048]; | ||
482 | int readLen = 0; | ||
483 | while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) | ||
484 | { | ||
485 | zOut.Write(readBuffer, 0, readLen); | ||
486 | } | ||
487 | zOut.Flush(); | ||
488 | outMs.Seek(0, SeekOrigin.Begin); | ||
489 | |||
490 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
491 | |||
492 | decodedOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
493 | } | ||
494 | } | ||
495 | } | ||
496 | return decodedOsd; | ||
497 | } | ||
498 | |||
427 | /// <summary> | 499 | /// <summary> |
428 | /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. | 500 | /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. |
429 | /// </summary> | 501 | /// </summary> |
@@ -700,6 +772,27 @@ namespace OpenSim.Region.Physics.Meshing | |||
700 | return true; | 772 | return true; |
701 | } | 773 | } |
702 | 774 | ||
775 | /// <summary> | ||
776 | /// temporary prototype code - please do not use until the interface has been finalized! | ||
777 | /// </summary> | ||
778 | /// <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> | ||
780 | public List<List<Vector3>> GetConvexHulls(Vector3 size) | ||
781 | { | ||
782 | if (mConvexHulls == null) | ||
783 | return null; | ||
784 | |||
785 | List<List<Vector3>> hulls = new List<List<Vector3>>(); | ||
786 | foreach (var hull in mConvexHulls) | ||
787 | { | ||
788 | List<Vector3> verts = new List<Vector3>(); | ||
789 | foreach (var vert in hull) | ||
790 | verts.Add(vert * size); | ||
791 | } | ||
792 | |||
793 | return hulls; | ||
794 | } | ||
795 | |||
703 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) | 796 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) |
704 | { | 797 | { |
705 | return CreateMesh(primName, primShape, size, lod, false, true); | 798 | return CreateMesh(primName, primShape, size, lod, false, true); |