30 using System.Collections.Generic;
31 using System.Reflection;
33 using OpenSim.Framework;
34 using OpenSim.Region.Framework.Scenes;
35 using OpenSim.Region.Framework.Interfaces;
36 using OpenSim.Region.PhysicsModules.SharedBase;
38 using OpenMetaverse.StructuredData;
40 using System.Drawing.Imaging;
41 using System.IO.Compression;
47 namespace OpenSim.
Region.PhysicsModule.Meshing
49 [Extension(
Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"Meshmerizer")]
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 private static string LogHeader =
"[MESH]";
58 const string baseDir =
"rawFiles";
60 private const string baseDir = null;
62 private bool m_Enabled =
false;
65 private bool debugDetail =
false;
67 private bool cacheSculptMaps =
true;
68 private string decodedSculptMapPath = null;
69 private bool useMeshiesPhysicsMesh =
false;
71 private float minSizeForComplexMesh = 0.2f;
73 private List<List<Vector3>> mConvexHulls = null;
74 private List<Vector3> mBoundingHull = null;
77 private static Dictionary<ulong, Mesh> m_uniqueMeshes =
new Dictionary<ulong, Mesh>();
79 #region INonSharedRegionModule
82 get {
return "Meshmerizer"; }
85 public Type ReplaceableInterface
92 IConfig config = source.Configs[
"Startup"];
95 string mesher = config.GetString(
"meshing", string.Empty);
100 IConfig mesh_config = source.Configs[
"Mesh"];
102 decodedSculptMapPath = config.GetString(
"DecodedSculptMapPath",
"j2kDecodeCache");
103 cacheSculptMaps = config.GetBoolean(
"CacheSculptMaps", cacheSculptMaps);
104 if (mesh_config != null)
106 useMeshiesPhysicsMesh = mesh_config.GetBoolean(
"UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
107 debugDetail = mesh_config.GetBoolean(
"LogMeshDetails", debugDetail);
112 if (!Directory.Exists(decodedSculptMapPath))
113 Directory.CreateDirectory(decodedSculptMapPath);
117 m_log.WarnFormat(
"[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message);
133 scene.RegisterModuleInterface<
IMesher>(
this);
141 scene.UnregisterModuleInterface<
IMesher>(
this);
164 private static Mesh CreateSimpleBoxMesh(
float minX,
float maxX,
float minY,
float maxY,
float minZ,
float maxZ)
167 List<Vertex> vertices =
new List<Vertex>();
170 vertices.Add(
new Vertex(minX, maxY, minZ));
171 vertices.Add(
new Vertex(maxX, maxY, minZ));
172 vertices.Add(
new Vertex(maxX, minY, minZ));
173 vertices.Add(
new Vertex(minX, minY, minZ));
175 box.Add(
new Triangle(vertices[0], vertices[1], vertices[2]));
176 box.Add(
new Triangle(vertices[0], vertices[2], vertices[3]));
180 vertices.Add(
new Vertex(maxX, maxY, maxZ));
181 vertices.Add(
new Vertex(minX, maxY, maxZ));
182 vertices.Add(
new Vertex(minX, minY, maxZ));
183 vertices.Add(
new Vertex(maxX, minY, maxZ));
185 box.Add(
new Triangle(vertices[4], vertices[5], vertices[6]));
186 box.Add(
new Triangle(vertices[4], vertices[6], vertices[7]));
190 box.Add(
new Triangle(vertices[5], vertices[0], vertices[3]));
191 box.Add(
new Triangle(vertices[5], vertices[3], vertices[6]));
193 box.Add(
new Triangle(vertices[1], vertices[0], vertices[5]));
194 box.Add(
new Triangle(vertices[1], vertices[5], vertices[4]));
196 box.Add(
new Triangle(vertices[7], vertices[1], vertices[4]));
197 box.Add(
new Triangle(vertices[7], vertices[2], vertices[1]));
199 box.Add(
new Triangle(vertices[3], vertices[2], vertices[7]));
200 box.Add(
new Triangle(vertices[3], vertices[7], vertices[6]));
210 private static Mesh CreateBoundingBoxMesh(Mesh meshIn)
212 float minX = float.MaxValue;
213 float maxX = float.MinValue;
214 float minY = float.MaxValue;
215 float maxY = float.MinValue;
216 float minZ = float.MaxValue;
217 float maxZ = float.MinValue;
219 foreach (Vector3 v
in meshIn.getVertexList())
221 if (v.X < minX) minX = v.X;
222 if (v.Y < minY) minY = v.Y;
223 if (v.Z < minZ) minZ = v.Z;
225 if (v.X > maxX) maxX = v.X;
226 if (v.Y > maxY) maxY = v.Y;
227 if (v.Z > maxZ) maxZ = v.Z;
230 return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ);
233 private void ReportPrimError(
string message,
string primName,
PrimMesh primMesh)
235 m_log.Error(message);
236 m_log.Error(
"\nPrim Name: " + primName);
237 m_log.Error(
"****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString());
247 private void AddSubMesh(
OSDMap subMeshData, Vector3 size, List<Coord> coords, List<Face> faces)
254 if (subMeshData.ContainsKey(
"NoGeometry") && ((OSDBoolean)subMeshData[
"NoGeometry"]))
257 OpenMetaverse.Vector3 posMax = ((
OSDMap)subMeshData[
"PositionDomain"])[
"Max"].AsVector3();
258 OpenMetaverse.Vector3 posMin = ((
OSDMap)subMeshData[
"PositionDomain"])[
"Min"].AsVector3();
259 ushort faceIndexOffset = (ushort)coords.Count;
261 byte[] posBytes = subMeshData[
"Position"].AsBinary();
262 for (
int i = 0; i < posBytes.Length; i += 6)
264 ushort uX = Utils.BytesToUInt16(posBytes, i);
265 ushort uY = Utils.BytesToUInt16(posBytes, i + 2);
266 ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
269 Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X,
270 Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y,
271 Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z);
276 byte[] triangleBytes = subMeshData[
"TriangleList"].AsBinary();
277 for (
int i = 0; i < triangleBytes.Length; i += 6)
279 ushort v1 = (ushort)(
Utils.BytesToUInt16(triangleBytes, i) + faceIndexOffset);
280 ushort v2 = (ushort)(
Utils.BytesToUInt16(triangleBytes, i + 2) + faceIndexOffset);
281 ushort v3 = (ushort)(
Utils.BytesToUInt16(triangleBytes, i + 4) + faceIndexOffset);
295 private Mesh CreateMeshFromPrimMesher(
string primName,
PrimitiveBaseShape primShape, Vector3 size,
float lod)
308 if (!useMeshiesPhysicsMesh)
311 if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces))
316 if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
322 if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
327 primShape.SculptData = Utils.EmptyBytes;
329 int numCoords = coords.Count;
330 int numFaces = faces.Count;
333 List<Vertex> vertices =
new List<Vertex>();
334 for (
int i = 0; i < numCoords; i++)
340 Mesh mesh =
new Mesh();
342 for (
int i = 0; i < numFaces; i++)
345 mesh.Add(
new Triangle(vertices[f.
v1], vertices[f.
v2], vertices[f.
v3]));
360 private bool GenerateCoordsAndFacesFromPrimMeshData(
361 string primName,
PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces)
365 coords =
new List<Coord>();
366 faces =
new List<Face>();
370 mBoundingHull = null;
382 using (MemoryStream data =
new MemoryStream(primShape.
SculptData))
386 OSD osd = OSDParser.DeserializeLLSDBinary(data);
391 m_log.Warn(
"[Mesh}: unable to cast mesh asset to OSDMap");
397 m_log.Error(
"[MESH]: Exception deserializing mesh asset header:" + e.ToString());
400 start = data.Position;
405 OSDMap physicsParms = null;
406 OSDMap map = (
OSDMap)meshOsd;
407 if (map.ContainsKey(
"physics_shape"))
409 physicsParms = (
OSDMap)map[
"physics_shape"];
410 if (debugDetail) m_log.DebugFormat(
"{0} prim='{1}': using 'physics_shape' mesh data", LogHeader, primName);
412 else if (map.ContainsKey(
"physics_mesh"))
414 physicsParms = (
OSDMap)map[
"physics_mesh"];
415 if (debugDetail) m_log.DebugFormat(
"{0} prim='{1}':using 'physics_mesh' mesh data", LogHeader, primName);
417 else if (map.ContainsKey(
"medium_lod"))
419 physicsParms = (
OSDMap)map[
"medium_lod"];
420 if (debugDetail) m_log.DebugFormat(
"{0} prim='{1}':using 'medium_lod' mesh data", LogHeader, primName);
422 else if (map.ContainsKey(
"high_lod"))
424 physicsParms = (
OSDMap)map[
"high_lod"];
425 if (debugDetail) m_log.DebugFormat(
"{0} prim='{1}':using 'high_lod' mesh data", LogHeader, primName);
428 if (map.ContainsKey(
"physics_convex"))
430 OSD convexBlockOsd = null;
433 OSDMap convexBlock = (
OSDMap)map[
"physics_convex"];
435 int convexOffset = convexBlock[
"offset"].AsInteger() + (
int)start;
436 int convexSize = convexBlock["size"].AsInteger();
438 byte[] convexBytes = new byte[convexSize];
440 System.Buffer.BlockCopy(primShape.SculptData, convexOffset, convexBytes, 0, convexSize);
444 convexBlockOsd = DecompressOsd(convexBytes);
448 m_log.ErrorFormat(
"{0} prim='{1}': exception decoding convex block: {2}", LogHeader, primName, e);
453 if (convexBlockOsd != null && convexBlockOsd is OSDMap)
455 convexBlock = convexBlockOsd as
OSDMap;
459 string keys = LogHeader +
" keys found in convexBlock: ";
460 foreach (KeyValuePair<string, OSD> kvp
in convexBlock)
461 keys +=
"'" + kvp.Key +
"' ";
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();
470 List<Vector3> boundingHull = null;
472 if (convexBlock.ContainsKey(
"BoundingVerts"))
474 byte[] boundingVertsBytes = convexBlock[
"BoundingVerts"].AsBinary();
475 boundingHull =
new List<Vector3>();
476 for (
int i = 0; i < boundingVertsBytes.Length; )
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;
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)
488 boundingHull.Add(pos);
491 mBoundingHull = boundingHull;
492 if (debugDetail) m_log.DebugFormat(
"{0} prim='{1}': parsed bounding hull. nVerts={2}", LogHeader, primName, mBoundingHull.Count);
495 if (convexBlock.ContainsKey(
"HullList"))
497 byte[] hullList = convexBlock[
"HullList"].AsBinary();
499 byte[] posBytes = convexBlock[
"Positions"].AsBinary();
501 List<List<Vector3>> hulls =
new List<List<Vector3>>();
504 foreach (byte cnt
in hullList)
506 int count = cnt == 0 ? 256 : cnt;
507 List<Vector3> hull =
new List<Vector3>();
509 for (
int i = 0; i < count; i++)
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;
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)
527 mConvexHulls = hulls;
528 if (debugDetail) m_log.DebugFormat(
"{0} prim='{1}': parsed hulls. nHulls={2}", LogHeader, primName, mConvexHulls.Count);
532 if (debugDetail) m_log.DebugFormat(
"{0} prim='{1}' has physics_convex but no HullList", LogHeader, primName);
538 m_log.WarnFormat(
"{0} exception decoding convex block: {1}", LogHeader, e);
542 if (physicsParms == null)
544 m_log.WarnFormat(
"[MESH]: No recognized physics mesh found in mesh asset for {0}", primName);
548 int physOffset = physicsParms[
"offset"].AsInteger() + (
int)start;
549 int physSize = physicsParms["size"].AsInteger();
551 if (physOffset < 0 || physSize == 0)
554 OSD decodedMeshOsd = new
OSD();
555 byte[] meshBytes = new byte[physSize];
556 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
560 decodedMeshOsd = DecompressOsd(meshBytes);
564 m_log.ErrorFormat(
"{0} prim='{1}': exception decoding physical mesh: {2}", LogHeader, primName, e);
568 OSDArray decodedMeshOsdArray = null;
575 decodedMeshOsdArray = (
OSDArray)decodedMeshOsd;
576 foreach (
OSD subMeshOsd
in decodedMeshOsdArray)
578 if (subMeshOsd is OSDMap)
579 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
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);
596 private static OSD DecompressOsd(byte[] meshBytes)
598 OSD decodedOsd = null;
600 using (MemoryStream inMs =
new MemoryStream(meshBytes))
602 using (MemoryStream outMs =
new MemoryStream())
604 using (DeflateStream decompressionStream =
new DeflateStream(inMs,
CompressionMode.Decompress))
606 byte[] readBuffer =
new byte[2048];
607 inMs.Read(readBuffer, 0, 2);
610 while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
611 outMs.Write(readBuffer, 0, readLen);
615 outMs.Seek(0, SeekOrigin.Begin);
617 byte[] decompressedBuf = outMs.GetBuffer();
619 decodedOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
636 private bool GenerateCoordsAndFacesFromPrimSculptData(
637 string primName,
PrimitiveBaseShape primShape, Vector3 size,
float lod, out List<Coord> coords, out List<Face> faces)
639 coords =
new List<Coord>();
640 faces =
new List<Face>();
643 string decodedSculptFileName =
"";
647 decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath,
"smap_" + primShape.SculptTexture.ToString());
650 if (
File.Exists(decodedSculptFileName))
652 idata = Image.FromFile(decodedSculptFileName);
657 m_log.Error(
"[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName +
" " + e.Message);
671 OpenMetaverse.Imaging.ManagedImage managedImage;
673 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out managedImage);
675 if (managedImage == null)
679 m_log.WarnFormat(
"[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
684 if ((managedImage.Channels & OpenMetaverse.Imaging.ManagedImage.ImageChannels.Alpha) != 0)
685 managedImage.ConvertChannels(managedImage.Channels & ~OpenMetaverse.Imaging.ManagedImage.ImageChannels.Alpha);
687 Bitmap imgData = OpenMetaverse.Imaging.LoadTGAClass.LoadTGA(
new MemoryStream(managedImage.ExportTGA()));
688 idata = (Image)imgData;
693 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
694 catch (Exception e) { m_log.Error(
"[SCULPT]: unable to cache sculpt map " + decodedSculptFileName +
" " + e.Message); }
697 catch (DllNotFoundException)
699 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!");
702 catch (IndexOutOfRangeException)
704 m_log.Error(
"[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
709 m_log.Error(
"[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
717 case OpenMetaverse.SculptType.Cylinder:
718 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
720 case OpenMetaverse.SculptType.Plane:
721 sculptType = PrimMesher.SculptMesh.SculptType.plane;
723 case OpenMetaverse.SculptType.Torus:
724 sculptType = PrimMesher.SculptMesh.SculptType.torus;
726 case OpenMetaverse.SculptType.Sphere:
727 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
730 sculptType = PrimMesher.SculptMesh.SculptType.plane;
734 bool mirror = ((primShape.SculptType & 128) != 0);
735 bool invert = ((primShape.SculptType & 64) != 0);
741 sculptMesh.DumpRaw(baseDir, primName, "primMesh");
743 sculptMesh.Scale(size.X, size.Y, size.Z);
745 coords = sculptMesh.coords;
746 faces = sculptMesh.faces;
760 private
bool GenerateCoordsAndFacesFromPrimShapeData(
764 coords =
new List<Coord>();
765 faces =
new List<Face>();
767 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (
float)(primShape.PathShearX - 256) * 0.01f;
768 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (
float)(primShape.PathShearY - 256) * 0.01f;
769 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
770 float pathEnd = 1.0f - (
float)primShape.PathEnd * 2.0e-5f;
771 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
772 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
774 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
775 float profileEnd = 1.0f - (
float)primShape.ProfileEnd * 2.0e-5f;
776 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
777 if (profileHollow > 0.95f)
778 profileHollow = 0.95f;
782 if ((primShape.ProfileCurve & 0x07) == (byte)
ProfileShape.EquilateralTriangle)
784 else if ((primShape.ProfileCurve & 0x07) == (byte)
ProfileShape.Circle)
788 case LevelOfDetail.High: sides = 24;
break;
789 case LevelOfDetail.Medium: sides = 12;
break;
790 case LevelOfDetail.Low: sides = 6;
break;
791 case LevelOfDetail.VeryLow: sides = 3;
break;
792 default: sides = 24;
break;
795 else if ((primShape.ProfileCurve & 0x07) == (byte)
ProfileShape.HalfCircle)
799 case LevelOfDetail.High: sides = 24;
break;
800 case LevelOfDetail.Medium: sides = 12;
break;
801 case LevelOfDetail.Low: sides = 6;
break;
802 case LevelOfDetail.VeryLow: sides = 3;
break;
803 default: sides = 24;
break;
806 profileBegin = 0.5f * profileBegin + 0.5f;
807 profileEnd = 0.5f * profileEnd + 0.5f;
810 int hollowSides = sides;
815 case LevelOfDetail.High: hollowSides = 24;
break;
816 case LevelOfDetail.Medium: hollowSides = 12;
break;
817 case LevelOfDetail.Low: hollowSides = 6;
break;
818 case LevelOfDetail.VeryLow: hollowSides = 3;
break;
819 default: hollowSides = 24;
break;
822 else if (primShape.HollowShape ==
HollowShape.Square)
824 else if (primShape.HollowShape ==
HollowShape.Triangle)
827 primMesh =
new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
831 m_log.Error(
"[ERROR] " + primMesh.errorMessage);
833 primMesh.topShearX = pathShearX;
834 primMesh.topShearY = pathShearY;
835 primMesh.pathCutBegin = pathBegin;
836 primMesh.pathCutEnd = pathEnd;
838 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte)
Extrusion.Flexible)
840 primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10;
841 primMesh.twistEnd = primShape.PathTwist * 18 / 10;
842 primMesh.taperX = pathScaleX;
843 primMesh.taperY = pathScaleY;
845 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
847 ReportPrimError(
"*** CORRUPT PRIM!! ***", primName, primMesh);
848 if (profileBegin < 0.0f) profileBegin = 0.0f;
849 if (profileEnd > 1.0f) profileEnd = 1.0f;
852 m_log.Debug(
"****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
856 primMesh.ExtrudeLinear();
860 ReportPrimError(
"Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
866 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f;
867 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f;
868 primMesh.radius = 0.01f * primShape.PathRadiusOffset;
869 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions;
870 primMesh.skew = 0.01f * primShape.PathSkew;
871 primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10;
872 primMesh.twistEnd = primShape.PathTwist * 36 / 10;
873 primMesh.taperX = primShape.PathTaperX * 0.01f;
874 primMesh.taperY = primShape.PathTaperY * 0.01f;
876 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
878 ReportPrimError(
"*** CORRUPT PRIM!! ***", primName, primMesh);
879 if (profileBegin < 0.0f) profileBegin = 0.0f;
880 if (profileEnd > 1.0f) profileEnd = 1.0f;
883 m_log.Debug(
"****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString());
887 primMesh.ExtrudeCircular();
891 ReportPrimError(
"Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
896 primMesh.DumpRaw(baseDir, primName,
"primMesh");
898 primMesh.Scale(size.X, size.Y, size.Z);
900 coords = primMesh.coords;
901 faces = primMesh.faces;
913 if (mBoundingHull == null)
916 List<Vector3> verts =
new List<Vector3>();
917 foreach (var vert
in mBoundingHull)
918 verts.Add(vert * size);
930 if (mConvexHulls == null)
933 List<List<Vector3>> hulls =
new List<List<Vector3>>();
934 foreach (var hull
in mConvexHulls)
936 List<Vector3> verts =
new List<Vector3>();
937 foreach (var vert
in hull)
938 verts.Add(vert * size);
947 return CreateMesh(primName, primShape, size, lod,
false,
true);
952 return CreateMesh(primName, primShape, size, lod,
false);
957 return CreateMesh(primName, primShape, size, lod, isPhysical,
true);
962 return CreateMesh(primName, primShape, size, lod, isPhysical,
true);
968 m_log.DebugFormat(
"[MESH]: Creating mesh for {0}", primName);
978 key = primShape.GetMeshKey(size, lod);
979 lock (m_uniqueMeshes)
981 if (m_uniqueMeshes.TryGetValue(key, out mesh))
986 if (size.X < 0.01f) size.X = 0.01f;
987 if (size.Y < 0.01f) size.Y = 0.01f;
988 if (size.Z < 0.01f) size.Z = 0.01f;
990 mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);
994 if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh)
997 m_log.Debug(
"Meshmerizer: prim " + primName +
" has a size of " + size.ToString() +
" which is below threshold of " +
998 minSizeForComplexMesh.ToString() +
" - creating simple bounding box");
1000 mesh = CreateBoundingBoxMesh(mesh);
1001 mesh.DumpRaw(baseDir, primName,
"Z extruded");
1009 lock (m_uniqueMeshes)
1011 m_uniqueMeshes.Add(
key, mesh);
List< List< Vector3 > > GetConvexHulls(Vector3 size)
temporary prototype code - please do not use until the interface has been finalized! ...
OpenMetaverse.StructuredData.OSDArray OSDArray
OpenSim.Server.Handlers.Simulation.Utils Utils
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
OpenMetaverse.StructuredData.OSDMap OSDMap
void ReleaseMesh(IMesh imesh)
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString key
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
List< Vector3 > GetBoundingHull(Vector3 size)
temporary prototype code - please do not use until the interface has been finalized! ...
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType SculptType
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
OpenMetaverse.StructuredData.OSD OSD
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
Ionic.Zlib.CompressionMode CompressionMode
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
void ExpireReleaseMeshs()
IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)