diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs (renamed from OpenSim/Region/Physics/Meshing/Meshmerizer.cs) | 389 |
1 files changed, 319 insertions, 70 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs index 8145d61..4d25bf3 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs | |||
@@ -28,8 +28,12 @@ | |||
28 | 28 | ||
29 | using System; | 29 | using System; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Reflection; | ||
32 | using System.IO; | ||
31 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
32 | using OpenSim.Region.Physics.Manager; | 34 | using OpenSim.Region.Framework.Scenes; |
35 | using OpenSim.Region.Framework.Interfaces; | ||
36 | using OpenSim.Region.PhysicsModules.SharedBase; | ||
33 | using OpenMetaverse; | 37 | using OpenMetaverse; |
34 | using OpenMetaverse.StructuredData; | 38 | using OpenMetaverse.StructuredData; |
35 | using System.Drawing; | 39 | using System.Drawing; |
@@ -38,32 +42,15 @@ using System.IO.Compression; | |||
38 | using PrimMesher; | 42 | using PrimMesher; |
39 | using log4net; | 43 | using log4net; |
40 | using Nini.Config; | 44 | using Nini.Config; |
41 | using System.Reflection; | 45 | using Mono.Addins; |
42 | using System.IO; | ||
43 | using ComponentAce.Compression.Libs.zlib; | ||
44 | 46 | ||
45 | namespace OpenSim.Region.Physics.Meshing | 47 | namespace OpenSim.Region.PhysicsModules.Meshing |
46 | { | 48 | { |
47 | public class MeshmerizerPlugin : IMeshingPlugin | 49 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Meshmerizer")] |
48 | { | 50 | public class Meshmerizer : IMesher, INonSharedRegionModule |
49 | public MeshmerizerPlugin() | ||
50 | { | ||
51 | } | ||
52 | |||
53 | public string GetName() | ||
54 | { | ||
55 | return "Meshmerizer"; | ||
56 | } | ||
57 | |||
58 | public IMesher GetMesher(IConfigSource config) | ||
59 | { | ||
60 | return new Meshmerizer(config); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | public class Meshmerizer : IMesher | ||
65 | { | 51 | { |
66 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
53 | private static string LogHeader = "[MESH]"; | ||
67 | 54 | ||
68 | // Setting baseDir to a path will enable the dumping of raw files | 55 | // 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 | 56 | // raw files can be imported by blender so a visual inspection of the results can be done |
@@ -72,6 +59,10 @@ namespace OpenSim.Region.Physics.Meshing | |||
72 | #else | 59 | #else |
73 | private const string baseDir = null; //"rawFiles"; | 60 | private const string baseDir = null; //"rawFiles"; |
74 | #endif | 61 | #endif |
62 | private bool m_Enabled = false; | ||
63 | |||
64 | // If 'true', lots of DEBUG logging of asset parsing details | ||
65 | private bool debugDetail = false; | ||
75 | 66 | ||
76 | private bool cacheSculptMaps = true; | 67 | private bool cacheSculptMaps = true; |
77 | private string decodedSculptMapPath = null; | 68 | private string decodedSculptMapPath = null; |
@@ -79,29 +70,85 @@ namespace OpenSim.Region.Physics.Meshing | |||
79 | 70 | ||
80 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh | 71 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh |
81 | 72 | ||
82 | private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); | 73 | private List<List<Vector3>> mConvexHulls = null; |
74 | private List<Vector3> mBoundingHull = null; | ||
75 | |||
76 | // Mesh cache. Static so it can be shared across instances of this class | ||
77 | private static Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); | ||
83 | 78 | ||
84 | public Meshmerizer(IConfigSource config) | 79 | #region INonSharedRegionModule |
80 | public string Name | ||
85 | { | 81 | { |
86 | IConfig start_config = config.Configs["Startup"]; | 82 | get { return "Meshmerizer"; } |
87 | IConfig mesh_config = config.Configs["Mesh"]; | 83 | } |
88 | 84 | ||
89 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); | 85 | public Type ReplaceableInterface |
90 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | 86 | { |
91 | if(mesh_config != null) | 87 | get { return null; } |
92 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | 88 | } |
93 | 89 | ||
94 | try | 90 | public void Initialise(IConfigSource source) |
95 | { | 91 | { |
96 | if (!Directory.Exists(decodedSculptMapPath)) | 92 | IConfig config = source.Configs["Startup"]; |
97 | Directory.CreateDirectory(decodedSculptMapPath); | 93 | if (config != null) |
98 | } | ||
99 | catch (Exception e) | ||
100 | { | 94 | { |
101 | m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message); | 95 | string mesher = config.GetString("meshing", string.Empty); |
96 | if (mesher == Name) | ||
97 | { | ||
98 | m_Enabled = true; | ||
99 | |||
100 | IConfig mesh_config = source.Configs["Mesh"]; | ||
101 | |||
102 | decodedSculptMapPath = config.GetString("DecodedSculptMapPath", "j2kDecodeCache"); | ||
103 | cacheSculptMaps = config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | ||
104 | if (mesh_config != null) | ||
105 | { | ||
106 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | ||
107 | debugDetail = mesh_config.GetBoolean("LogMeshDetails", debugDetail); | ||
108 | } | ||
109 | |||
110 | try | ||
111 | { | ||
112 | if (!Directory.Exists(decodedSculptMapPath)) | ||
113 | Directory.CreateDirectory(decodedSculptMapPath); | ||
114 | } | ||
115 | catch (Exception e) | ||
116 | { | ||
117 | m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message); | ||
118 | } | ||
119 | |||
120 | } | ||
102 | } | 121 | } |
103 | } | 122 | } |
104 | 123 | ||
124 | public void Close() | ||
125 | { | ||
126 | } | ||
127 | |||
128 | public void AddRegion(Scene scene) | ||
129 | { | ||
130 | if (!m_Enabled) | ||
131 | return; | ||
132 | |||
133 | scene.RegisterModuleInterface<IMesher>(this); | ||
134 | } | ||
135 | |||
136 | public void RemoveRegion(Scene scene) | ||
137 | { | ||
138 | if (!m_Enabled) | ||
139 | return; | ||
140 | |||
141 | scene.UnregisterModuleInterface<IMesher>(this); | ||
142 | } | ||
143 | |||
144 | public void RegionLoaded(Scene scene) | ||
145 | { | ||
146 | if (!m_Enabled) | ||
147 | return; | ||
148 | } | ||
149 | #endregion | ||
150 | |||
151 | |||
105 | /// <summary> | 152 | /// <summary> |
106 | /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may | 153 | /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may |
107 | /// be useful as a backup proxy when level of detail is not needed or when more complex meshes fail | 154 | /// be useful as a backup proxy when level of detail is not needed or when more complex meshes fail |
@@ -319,6 +366,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
319 | faces = new List<Face>(); | 366 | faces = new List<Face>(); |
320 | OSD meshOsd = null; | 367 | OSD meshOsd = null; |
321 | 368 | ||
369 | mConvexHulls = null; | ||
370 | mBoundingHull = null; | ||
371 | |||
322 | if (primShape.SculptData.Length <= 0) | 372 | if (primShape.SculptData.Length <= 0) |
323 | { | 373 | { |
324 | // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this | 374 | // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this |
@@ -355,9 +405,139 @@ namespace OpenSim.Region.Physics.Meshing | |||
355 | OSDMap physicsParms = null; | 405 | OSDMap physicsParms = null; |
356 | OSDMap map = (OSDMap)meshOsd; | 406 | OSDMap map = (OSDMap)meshOsd; |
357 | if (map.ContainsKey("physics_shape")) | 407 | if (map.ContainsKey("physics_shape")) |
408 | { | ||
358 | physicsParms = (OSDMap)map["physics_shape"]; // old asset format | 409 | physicsParms = (OSDMap)map["physics_shape"]; // old asset format |
410 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}': using 'physics_shape' mesh data", LogHeader, primName); | ||
411 | } | ||
359 | else if (map.ContainsKey("physics_mesh")) | 412 | else if (map.ContainsKey("physics_mesh")) |
413 | { | ||
360 | physicsParms = (OSDMap)map["physics_mesh"]; // new asset format | 414 | physicsParms = (OSDMap)map["physics_mesh"]; // new asset format |
415 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'physics_mesh' mesh data", LogHeader, primName); | ||
416 | } | ||
417 | else if (map.ContainsKey("medium_lod")) | ||
418 | { | ||
419 | physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh | ||
420 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'medium_lod' mesh data", LogHeader, primName); | ||
421 | } | ||
422 | else if (map.ContainsKey("high_lod")) | ||
423 | { | ||
424 | physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :) | ||
425 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'high_lod' mesh data", LogHeader, primName); | ||
426 | } | ||
427 | |||
428 | if (map.ContainsKey("physics_convex")) | ||
429 | { // pull this out also in case physics engine can use it | ||
430 | OSD convexBlockOsd = null; | ||
431 | try | ||
432 | { | ||
433 | OSDMap convexBlock = (OSDMap)map["physics_convex"]; | ||
434 | { | ||
435 | int convexOffset = convexBlock["offset"].AsInteger() + (int)start; | ||
436 | int convexSize = convexBlock["size"].AsInteger(); | ||
437 | |||
438 | byte[] convexBytes = new byte[convexSize]; | ||
439 | |||
440 | System.Buffer.BlockCopy(primShape.SculptData, convexOffset, convexBytes, 0, convexSize); | ||
441 | |||
442 | try | ||
443 | { | ||
444 | convexBlockOsd = DecompressOsd(convexBytes); | ||
445 | } | ||
446 | catch (Exception e) | ||
447 | { | ||
448 | m_log.ErrorFormat("{0} prim='{1}': exception decoding convex block: {2}", LogHeader, primName, e); | ||
449 | //return false; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | if (convexBlockOsd != null && convexBlockOsd is OSDMap) | ||
454 | { | ||
455 | convexBlock = convexBlockOsd as OSDMap; | ||
456 | |||
457 | if (debugDetail) | ||
458 | { | ||
459 | string keys = LogHeader + " keys found in convexBlock: "; | ||
460 | foreach (KeyValuePair<string, OSD> kvp in convexBlock) | ||
461 | keys += "'" + kvp.Key + "' "; | ||
462 | m_log.Debug(keys); | ||
463 | } | ||
464 | |||
465 | Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f); | ||
466 | if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3(); | ||
467 | Vector3 max = new Vector3(0.5f, 0.5f, 0.5f); | ||
468 | if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3(); | ||
469 | |||
470 | List<Vector3> boundingHull = null; | ||
471 | |||
472 | if (convexBlock.ContainsKey("BoundingVerts")) | ||
473 | { | ||
474 | byte[] boundingVertsBytes = convexBlock["BoundingVerts"].AsBinary(); | ||
475 | boundingHull = new List<Vector3>(); | ||
476 | for (int i = 0; i < boundingVertsBytes.Length; ) | ||
477 | { | ||
478 | ushort uX = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2; | ||
479 | ushort uY = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2; | ||
480 | ushort uZ = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2; | ||
481 | |||
482 | Vector3 pos = new Vector3( | ||
483 | Utils.UInt16ToFloat(uX, min.X, max.X), | ||
484 | Utils.UInt16ToFloat(uY, min.Y, max.Y), | ||
485 | Utils.UInt16ToFloat(uZ, min.Z, max.Z) | ||
486 | ); | ||
487 | |||
488 | boundingHull.Add(pos); | ||
489 | } | ||
490 | |||
491 | mBoundingHull = boundingHull; | ||
492 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed bounding hull. nVerts={2}", LogHeader, primName, mBoundingHull.Count); | ||
493 | } | ||
494 | |||
495 | if (convexBlock.ContainsKey("HullList")) | ||
496 | { | ||
497 | byte[] hullList = convexBlock["HullList"].AsBinary(); | ||
498 | |||
499 | byte[] posBytes = convexBlock["Positions"].AsBinary(); | ||
500 | |||
501 | List<List<Vector3>> hulls = new List<List<Vector3>>(); | ||
502 | int posNdx = 0; | ||
503 | |||
504 | foreach (byte cnt in hullList) | ||
505 | { | ||
506 | int count = cnt == 0 ? 256 : cnt; | ||
507 | List<Vector3> hull = new List<Vector3>(); | ||
508 | |||
509 | for (int i = 0; i < count; i++) | ||
510 | { | ||
511 | ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
512 | ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
513 | ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; | ||
514 | |||
515 | Vector3 pos = new Vector3( | ||
516 | Utils.UInt16ToFloat(uX, min.X, max.X), | ||
517 | Utils.UInt16ToFloat(uY, min.Y, max.Y), | ||
518 | Utils.UInt16ToFloat(uZ, min.Z, max.Z) | ||
519 | ); | ||
520 | |||
521 | hull.Add(pos); | ||
522 | } | ||
523 | |||
524 | hulls.Add(hull); | ||
525 | } | ||
526 | |||
527 | mConvexHulls = hulls; | ||
528 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed hulls. nHulls={2}", LogHeader, primName, mConvexHulls.Count); | ||
529 | } | ||
530 | else | ||
531 | { | ||
532 | if (debugDetail) m_log.DebugFormat("{0} prim='{1}' has physics_convex but no HullList", LogHeader, primName); | ||
533 | } | ||
534 | } | ||
535 | } | ||
536 | catch (Exception e) | ||
537 | { | ||
538 | m_log.WarnFormat("{0} exception decoding convex block: {1}", LogHeader, e); | ||
539 | } | ||
540 | } | ||
361 | 541 | ||
362 | if (physicsParms == null) | 542 | if (physicsParms == null) |
363 | { | 543 | { |
@@ -374,34 +554,14 @@ namespace OpenSim.Region.Physics.Meshing | |||
374 | OSD decodedMeshOsd = new OSD(); | 554 | OSD decodedMeshOsd = new OSD(); |
375 | byte[] meshBytes = new byte[physSize]; | 555 | byte[] meshBytes = new byte[physSize]; |
376 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); | 556 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); |
377 | // byte[] decompressed = new byte[physSize * 5]; | 557 | // byte[] decompressed = new byte[physSize * 5]; |
378 | try | 558 | try |
379 | { | 559 | { |
380 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | 560 | 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 | } | 561 | } |
402 | catch (Exception e) | 562 | catch (Exception e) |
403 | { | 563 | { |
404 | m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); | 564 | m_log.ErrorFormat("{0} prim='{1}': exception decoding physical mesh: {2}", LogHeader, primName, e); |
405 | return false; | 565 | return false; |
406 | } | 566 | } |
407 | 567 | ||
@@ -410,7 +570,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
410 | // physics_shape is an array of OSDMaps, one for each submesh | 570 | // physics_shape is an array of OSDMaps, one for each submesh |
411 | if (decodedMeshOsd is OSDArray) | 571 | if (decodedMeshOsd is OSDArray) |
412 | { | 572 | { |
413 | // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); | 573 | // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); |
414 | 574 | ||
415 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; | 575 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; |
416 | foreach (OSD subMeshOsd in decodedMeshOsdArray) | 576 | foreach (OSD subMeshOsd in decodedMeshOsdArray) |
@@ -418,6 +578,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
418 | if (subMeshOsd is OSDMap) | 578 | if (subMeshOsd is OSDMap) |
419 | AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); | 579 | AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); |
420 | } | 580 | } |
581 | if (debugDetail) | ||
582 | m_log.DebugFormat("{0} {1}: mesh decoded. offset={2}, size={3}, nCoords={4}, nFaces={5}", | ||
583 | LogHeader, primName, physOffset, physSize, coords.Count, faces.Count); | ||
421 | } | 584 | } |
422 | } | 585 | } |
423 | 586 | ||
@@ -425,6 +588,42 @@ namespace OpenSim.Region.Physics.Meshing | |||
425 | } | 588 | } |
426 | 589 | ||
427 | /// <summary> | 590 | /// <summary> |
591 | /// decompresses a gzipped OSD object | ||
592 | /// </summary> | ||
593 | /// <param name="decodedOsd"></param> the OSD object | ||
594 | /// <param name="meshBytes"></param> | ||
595 | /// <returns></returns> | ||
596 | private static OSD DecompressOsd(byte[] meshBytes) | ||
597 | { | ||
598 | OSD decodedOsd = null; | ||
599 | |||
600 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | ||
601 | { | ||
602 | using (MemoryStream outMs = new MemoryStream()) | ||
603 | { | ||
604 | using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress)) | ||
605 | { | ||
606 | byte[] readBuffer = new byte[2048]; | ||
607 | inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header | ||
608 | int readLen = 0; | ||
609 | |||
610 | while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0) | ||
611 | outMs.Write(readBuffer, 0, readLen); | ||
612 | |||
613 | outMs.Flush(); | ||
614 | |||
615 | outMs.Seek(0, SeekOrigin.Begin); | ||
616 | |||
617 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
618 | |||
619 | decodedOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
620 | } | ||
621 | } | ||
622 | } | ||
623 | return decodedOsd; | ||
624 | } | ||
625 | |||
626 | /// <summary> | ||
428 | /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. | 627 | /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. |
429 | /// </summary> | 628 | /// </summary> |
430 | /// <param name="primName"></param> | 629 | /// <param name="primName"></param> |
@@ -469,10 +668,11 @@ namespace OpenSim.Region.Physics.Meshing | |||
469 | 668 | ||
470 | try | 669 | try |
471 | { | 670 | { |
472 | OpenMetaverse.Imaging.ManagedImage unusedData; | 671 | OpenMetaverse.Imaging.ManagedImage managedImage; |
473 | OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata); | 672 | |
673 | OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out managedImage); | ||
474 | 674 | ||
475 | if (idata == null) | 675 | if (managedImage == null) |
476 | { | 676 | { |
477 | // In some cases it seems that the decode can return a null bitmap without throwing | 677 | // In some cases it seems that the decode can return a null bitmap without throwing |
478 | // an exception | 678 | // an exception |
@@ -481,9 +681,12 @@ namespace OpenSim.Region.Physics.Meshing | |||
481 | return false; | 681 | return false; |
482 | } | 682 | } |
483 | 683 | ||
484 | unusedData = null; | 684 | if ((managedImage.Channels & OpenMetaverse.Imaging.ManagedImage.ImageChannels.Alpha) != 0) |
685 | managedImage.ConvertChannels(managedImage.Channels & ~OpenMetaverse.Imaging.ManagedImage.ImageChannels.Alpha); | ||
485 | 686 | ||
486 | //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); | 687 | Bitmap imgData = OpenMetaverse.Imaging.LoadTGAClass.LoadTGA(new MemoryStream(managedImage.ExportTGA())); |
688 | idata = (Image)imgData; | ||
689 | managedImage = null; | ||
487 | 690 | ||
488 | if (cacheSculptMaps) | 691 | if (cacheSculptMaps) |
489 | { | 692 | { |
@@ -700,6 +903,45 @@ namespace OpenSim.Region.Physics.Meshing | |||
700 | return true; | 903 | return true; |
701 | } | 904 | } |
702 | 905 | ||
906 | /// <summary> | ||
907 | /// temporary prototype code - please do not use until the interface has been finalized! | ||
908 | /// </summary> | ||
909 | /// <param name="size">value to scale the hull points by</param> | ||
910 | /// <returns>a list of vertices in the bounding hull if it exists and has been successfully decoded, otherwise null</returns> | ||
911 | public List<Vector3> GetBoundingHull(Vector3 size) | ||
912 | { | ||
913 | if (mBoundingHull == null) | ||
914 | return null; | ||
915 | |||
916 | List<Vector3> verts = new List<Vector3>(); | ||
917 | foreach (var vert in mBoundingHull) | ||
918 | verts.Add(vert * size); | ||
919 | |||
920 | return verts; | ||
921 | } | ||
922 | |||
923 | /// <summary> | ||
924 | /// temporary prototype code - please do not use until the interface has been finalized! | ||
925 | /// </summary> | ||
926 | /// <param name="size">value to scale the hull points by</param> | ||
927 | /// <returns>a list of hulls if they exist and have been successfully decoded, otherwise null</returns> | ||
928 | public List<List<Vector3>> GetConvexHulls(Vector3 size) | ||
929 | { | ||
930 | if (mConvexHulls == null) | ||
931 | return null; | ||
932 | |||
933 | List<List<Vector3>> hulls = new List<List<Vector3>>(); | ||
934 | foreach (var hull in mConvexHulls) | ||
935 | { | ||
936 | List<Vector3> verts = new List<Vector3>(); | ||
937 | foreach (var vert in hull) | ||
938 | verts.Add(vert * size); | ||
939 | hulls.Add(verts); | ||
940 | } | ||
941 | |||
942 | return hulls; | ||
943 | } | ||
944 | |||
703 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) | 945 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) |
704 | { | 946 | { |
705 | return CreateMesh(primName, primShape, size, lod, false, true); | 947 | return CreateMesh(primName, primShape, size, lod, false, true); |
@@ -724,8 +966,11 @@ namespace OpenSim.Region.Physics.Meshing | |||
724 | if (shouldCache) | 966 | if (shouldCache) |
725 | { | 967 | { |
726 | key = primShape.GetMeshKey(size, lod); | 968 | key = primShape.GetMeshKey(size, lod); |
727 | if (m_uniqueMeshes.TryGetValue(key, out mesh)) | 969 | lock (m_uniqueMeshes) |
728 | return mesh; | 970 | { |
971 | if (m_uniqueMeshes.TryGetValue(key, out mesh)) | ||
972 | return mesh; | ||
973 | } | ||
729 | } | 974 | } |
730 | 975 | ||
731 | if (size.X < 0.01f) size.X = 0.01f; | 976 | if (size.X < 0.01f) size.X = 0.01f; |
@@ -751,11 +996,15 @@ namespace OpenSim.Region.Physics.Meshing | |||
751 | 996 | ||
752 | if (shouldCache) | 997 | if (shouldCache) |
753 | { | 998 | { |
754 | m_uniqueMeshes.Add(key, mesh); | 999 | lock (m_uniqueMeshes) |
1000 | { | ||
1001 | m_uniqueMeshes.Add(key, mesh); | ||
1002 | } | ||
755 | } | 1003 | } |
756 | } | 1004 | } |
757 | 1005 | ||
758 | return mesh; | 1006 | return mesh; |
759 | } | 1007 | } |
1008 | |||
760 | } | 1009 | } |
761 | } | 1010 | } |