From 7fa3335fd53f863b20190025c3cfc8e8e36f96ed Mon Sep 17 00:00:00 2001 From: dahlia Date: Mon, 18 Oct 2010 04:17:36 -0700 Subject: [PATCH] initial support for meshies physics. Must set ini option UseMeshiesPhysicsMesh = true to enable. See file OpenSimDefaults.ini for example. --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 129 ++++++++++++------ bin/OpenSimDefaults.ini | 6 + bin/zlib.net.dll | Bin 0 -> 65536 bytes prebuild.xml | 2 +- 4 files changed, 97 insertions(+), 40 deletions(-) create mode 100644 bin/zlib.net.dll diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 3e3a0f0589..89ee5afb47 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -40,6 +40,7 @@ using log4net; using Nini.Config; using System.Reflection; using System.IO; +using ComponentAce.Compression.Libs.zlib; namespace OpenSim.Region.Physics.Meshing { @@ -74,6 +75,7 @@ namespace OpenSim.Region.Physics.Meshing private bool cacheSculptMaps = true; private string decodedSculptMapPath = null; + private bool useMeshiesPhysicsMesh = false; private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh @@ -85,6 +87,7 @@ namespace OpenSim.Region.Physics.Meshing decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); + useMeshiesPhysicsMesh = start_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); try { @@ -268,73 +271,121 @@ namespace OpenSim.Region.Physics.Meshing { if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) { - // add code for mesh physics proxy generation here - m_log.Debug("[MESH]: mesh proxy generation not implemented yet "); + if (!useMeshiesPhysicsMesh) + return null; + + m_log.Debug("[MESH]: experimental mesh proxy generation"); OSD meshOsd; - if (primShape.SculptData.Length > 0) - { - - - m_log.Debug("[MESH]: asset data length: " + primShape.SculptData.Length.ToString()); - byte[] header = Util.StringToBytes256(""); - - ////dump to debugging file - //string filename = System.IO.Path.Combine(decodedSculptMapPath, "mesh_" + primShape.SculptTexture.ToString()); - //BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Create)); - //writer.Write(primShape.SculptData); - //writer.Close(); - - } - else + if (primShape.SculptData.Length <= 0) { m_log.Error("[MESH]: asset data is zero length"); return null; } - try + long start = 0; + using (MemoryStream data = new MemoryStream(primShape.SculptData)) { - meshOsd = OSDParser.DeserializeLLSDBinary(primShape.SculptData, true); - } - catch (Exception e) - { - m_log.Error("[MESH]: exception decoding mesh asset: " + e.ToString()); - return null; + meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data, true); + start = data.Position; } if (meshOsd is OSDMap) { OSDMap map = (OSDMap)meshOsd; - //foreach (string name in map.Keys) - // m_log.Debug("[MESH]: key:" + name + " value:" + map[name].AsString()); OSDMap physicsParms = (OSDMap)map["physics_shape"]; - int physOffset = physicsParms["offset"].AsInteger(); + int physOffset = physicsParms["offset"].AsInteger() + (int)start; int physSize = physicsParms["size"].AsInteger(); if (physOffset < 0 || physSize == 0) return null; // no mesh data in asset - m_log.Debug("[MESH]: physOffset:" + physOffset.ToString() + " physSize:" + physSize.ToString()); - //MemoryStream ms = new MemoryStream(primShape.SculptData, physOffset, physSize); - //GZipStream gzStream = new GZipStream(ms, CompressionMode.Decompress); - - //int maxSize = physSize * 5; // arbitrary guess - //byte[] readBuffer = new byte[maxSize]; + OSD decodedMeshOsd = new OSD(); + byte[] meshBytes = new byte[physSize]; + System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); + byte[] decompressed = new byte[physSize * 5]; + try + { + { + string filename = System.IO.Path.Combine(decodedSculptMapPath, "meshInput_" + primShape.SculptTexture.ToString()); + using (FileStream fs = new FileStream(filename, FileMode.Create)) + { + fs.Write(meshBytes, 0, meshBytes.Length); + } + } - //int bytesRead = gzStream.Read(readBuffer, 0, maxSize); + using (MemoryStream inMs = new MemoryStream(meshBytes)) + { + using (MemoryStream outMs = new MemoryStream()) + { + using (ZOutputStream zOut = new ZOutputStream(outMs)) + { + byte[] readBuffer = new byte[2048]; + int readLen = 0; + while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) + { + zOut.Write(readBuffer, 0, readLen); + } + zOut.Flush(); + outMs.Seek(0, SeekOrigin.Begin); - //OSD physMeshOsd = OSDParser.DeserializeLLSDBinary(readBuffer); + byte[] decompressedBuf = outMs.GetBuffer(); + decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf, true); + } + } + } + } + catch (Exception e) + { + m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); + return null; + } + OSDArray decodedMeshOsdArray = null; + // physics_shape is an array of OSDMaps, one for each submesh + if (decodedMeshOsd is OSDArray) + { + decodedMeshOsdArray = (OSDArray)decodedMeshOsd; + foreach (OSD subMeshOsd in decodedMeshOsdArray) + { + if (subMeshOsd is OSDMap) + { + OSDMap subMeshMap = (OSDMap)subMeshOsd; + OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"].AsVector3(); + OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"].AsVector3(); + byte[] posBytes = subMeshMap["Position"].AsBinary(); + for (int i = 0; i < posBytes.Length; i += 6) + { + ushort uX = Utils.BytesToUInt16(posBytes, i); + ushort uY = Utils.BytesToUInt16(posBytes, i + 2); + ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); + + Coord c = new Coord( + Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X, + Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y, + Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z); + + coords.Add(c); + } + + byte[] triangleBytes = subMeshMap["TriangleList"].AsBinary(); + for (int i = 0; i < triangleBytes.Length; i += 6) + { + ushort v1 = Utils.BytesToUInt16(triangleBytes, i); + ushort v2 = Utils.BytesToUInt16(triangleBytes, i + 2); + ushort v3 = Utils.BytesToUInt16(triangleBytes, i + 4); + Face f = new Face(v1, v2, v3); + faces.Add(f); + } + } + } + } } - - //just bail out for now until mesh code is finished - return null; - } else { diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 05358c4373..82267edcc9 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -147,6 +147,12 @@ ; to false if you have compatibility problems. ;CacheSculptMaps = true + ; if you use Meshmerizer and want collisions for meshies, setting this to true + ; will cause OpenSim to attempt to decode meshies assets, extract the physics + ; mesh, and use it for collisions. This is currently experimental code and enabling + ; it may cause unexpected physics problems. + ;UseMeshiesPhysicsMesh = false + ; Choose one of the physics engines below ; OpenDynamicsEngine is by some distance the most developed physics engine ; basicphysics effectively does not model physics at all, making all objects phantom diff --git a/bin/zlib.net.dll b/bin/zlib.net.dll new file mode 100644 index 0000000000000000000000000000000000000000..9d156547f336ff1e7b51e28a2369a344fec2831c GIT binary patch literal 65536 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../../../../bin/ - @@ -597,6 +596,7 @@ +