diff options
author | dahlia | 2010-10-18 04:17:36 -0700 |
---|---|---|
committer | dahlia | 2010-10-18 04:17:36 -0700 |
commit | 7fa3335fd53f863b20190025c3cfc8e8e36f96ed (patch) | |
tree | 13751d65acea1fab7ef0b6bdb6824524cc19dc19 /OpenSim/Region | |
parent | Merge branch 'master' of ssh://diva@opensimulator.org/var/git/opensim (diff) | |
download | opensim-SC_OLD-7fa3335fd53f863b20190025c3cfc8e8e36f96ed.zip opensim-SC_OLD-7fa3335fd53f863b20190025c3cfc8e8e36f96ed.tar.gz opensim-SC_OLD-7fa3335fd53f863b20190025c3cfc8e8e36f96ed.tar.bz2 opensim-SC_OLD-7fa3335fd53f863b20190025c3cfc8e8e36f96ed.tar.xz |
initial support for meshies physics. Must set ini option UseMeshiesPhysicsMesh = true to enable. See file OpenSimDefaults.ini for example.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 137 |
1 files changed, 94 insertions, 43 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 3e3a0f0..89ee5af 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -40,6 +40,7 @@ using log4net; | |||
40 | using Nini.Config; | 40 | using Nini.Config; |
41 | using System.Reflection; | 41 | using System.Reflection; |
42 | using System.IO; | 42 | using System.IO; |
43 | using ComponentAce.Compression.Libs.zlib; | ||
43 | 44 | ||
44 | namespace OpenSim.Region.Physics.Meshing | 45 | namespace OpenSim.Region.Physics.Meshing |
45 | { | 46 | { |
@@ -74,6 +75,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
74 | 75 | ||
75 | private bool cacheSculptMaps = true; | 76 | private bool cacheSculptMaps = true; |
76 | private string decodedSculptMapPath = null; | 77 | private string decodedSculptMapPath = null; |
78 | private bool useMeshiesPhysicsMesh = false; | ||
77 | 79 | ||
78 | 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 |
79 | 81 | ||
@@ -85,6 +87,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
85 | 87 | ||
86 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); | 88 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); |
87 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | 89 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); |
90 | useMeshiesPhysicsMesh = start_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | ||
88 | 91 | ||
89 | try | 92 | try |
90 | { | 93 | { |
@@ -268,73 +271,121 @@ namespace OpenSim.Region.Physics.Meshing | |||
268 | { | 271 | { |
269 | if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) | 272 | if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) |
270 | { | 273 | { |
271 | // add code for mesh physics proxy generation here | 274 | if (!useMeshiesPhysicsMesh) |
272 | m_log.Debug("[MESH]: mesh proxy generation not implemented yet "); | 275 | return null; |
273 | |||
274 | OSD meshOsd; | ||
275 | 276 | ||
276 | if (primShape.SculptData.Length > 0) | 277 | m_log.Debug("[MESH]: experimental mesh proxy generation"); |
277 | { | ||
278 | |||
279 | |||
280 | m_log.Debug("[MESH]: asset data length: " + primShape.SculptData.Length.ToString()); | ||
281 | byte[] header = Util.StringToBytes256("<? LLSD/Binary ?>"); | ||
282 | 278 | ||
283 | ////dump to debugging file | 279 | OSD meshOsd; |
284 | //string filename = System.IO.Path.Combine(decodedSculptMapPath, "mesh_" + primShape.SculptTexture.ToString()); | ||
285 | //BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Create)); | ||
286 | //writer.Write(primShape.SculptData); | ||
287 | //writer.Close(); | ||
288 | 280 | ||
289 | } | 281 | if (primShape.SculptData.Length <= 0) |
290 | else | ||
291 | { | 282 | { |
292 | m_log.Error("[MESH]: asset data is zero length"); | 283 | m_log.Error("[MESH]: asset data is zero length"); |
293 | return null; | 284 | return null; |
294 | } | 285 | } |
295 | 286 | ||
296 | try | 287 | long start = 0; |
297 | { | 288 | using (MemoryStream data = new MemoryStream(primShape.SculptData)) |
298 | meshOsd = OSDParser.DeserializeLLSDBinary(primShape.SculptData, true); | ||
299 | } | ||
300 | catch (Exception e) | ||
301 | { | 289 | { |
302 | m_log.Error("[MESH]: exception decoding mesh asset: " + e.ToString()); | 290 | meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data, true); |
303 | return null; | 291 | start = data.Position; |
304 | } | 292 | } |
305 | 293 | ||
306 | if (meshOsd is OSDMap) | 294 | if (meshOsd is OSDMap) |
307 | { | 295 | { |
308 | OSDMap map = (OSDMap)meshOsd; | 296 | OSDMap map = (OSDMap)meshOsd; |
309 | //foreach (string name in map.Keys) | ||
310 | // m_log.Debug("[MESH]: key:" + name + " value:" + map[name].AsString()); | ||
311 | OSDMap physicsParms = (OSDMap)map["physics_shape"]; | 297 | OSDMap physicsParms = (OSDMap)map["physics_shape"]; |
312 | int physOffset = physicsParms["offset"].AsInteger(); | 298 | int physOffset = physicsParms["offset"].AsInteger() + (int)start; |
313 | int physSize = physicsParms["size"].AsInteger(); | 299 | int physSize = physicsParms["size"].AsInteger(); |
314 | 300 | ||
315 | if (physOffset < 0 || physSize == 0) | 301 | if (physOffset < 0 || physSize == 0) |
316 | return null; // no mesh data in asset | 302 | return null; // no mesh data in asset |
317 | 303 | ||
318 | m_log.Debug("[MESH]: physOffset:" + physOffset.ToString() + " physSize:" + physSize.ToString()); | 304 | OSD decodedMeshOsd = new OSD(); |
319 | //MemoryStream ms = new MemoryStream(primShape.SculptData, physOffset, physSize); | 305 | byte[] meshBytes = new byte[physSize]; |
320 | //GZipStream gzStream = new GZipStream(ms, CompressionMode.Decompress); | 306 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); |
321 | 307 | byte[] decompressed = new byte[physSize * 5]; | |
322 | //int maxSize = physSize * 5; // arbitrary guess | 308 | try |
323 | //byte[] readBuffer = new byte[maxSize]; | 309 | { |
324 | 310 | { | |
325 | //int bytesRead = gzStream.Read(readBuffer, 0, maxSize); | 311 | string filename = System.IO.Path.Combine(decodedSculptMapPath, "meshInput_" + primShape.SculptTexture.ToString()); |
326 | 312 | using (FileStream fs = new FileStream(filename, FileMode.Create)) | |
327 | //OSD physMeshOsd = OSDParser.DeserializeLLSDBinary(readBuffer); | 313 | { |
328 | 314 | fs.Write(meshBytes, 0, meshBytes.Length); | |
329 | 315 | } | |
316 | } | ||
330 | 317 | ||
318 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | ||
319 | { | ||
320 | using (MemoryStream outMs = new MemoryStream()) | ||
321 | { | ||
322 | using (ZOutputStream zOut = new ZOutputStream(outMs)) | ||
323 | { | ||
324 | byte[] readBuffer = new byte[2048]; | ||
325 | int readLen = 0; | ||
326 | while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) | ||
327 | { | ||
328 | zOut.Write(readBuffer, 0, readLen); | ||
329 | } | ||
330 | zOut.Flush(); | ||
331 | outMs.Seek(0, SeekOrigin.Begin); | ||
332 | |||
333 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
334 | |||
335 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf, true); | ||
336 | } | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | catch (Exception e) | ||
341 | { | ||
342 | m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); | ||
343 | return null; | ||
344 | } | ||
331 | 345 | ||
346 | OSDArray decodedMeshOsdArray = null; | ||
332 | 347 | ||
348 | // physics_shape is an array of OSDMaps, one for each submesh | ||
349 | if (decodedMeshOsd is OSDArray) | ||
350 | { | ||
351 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; | ||
352 | foreach (OSD subMeshOsd in decodedMeshOsdArray) | ||
353 | { | ||
354 | if (subMeshOsd is OSDMap) | ||
355 | { | ||
356 | OSDMap subMeshMap = (OSDMap)subMeshOsd; | ||
357 | |||
358 | OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"].AsVector3(); | ||
359 | OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"].AsVector3(); | ||
360 | |||
361 | byte[] posBytes = subMeshMap["Position"].AsBinary(); | ||
362 | for (int i = 0; i < posBytes.Length; i += 6) | ||
363 | { | ||
364 | ushort uX = Utils.BytesToUInt16(posBytes, i); | ||
365 | ushort uY = Utils.BytesToUInt16(posBytes, i + 2); | ||
366 | ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); | ||
367 | |||
368 | Coord c = new Coord( | ||
369 | Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X, | ||
370 | Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y, | ||
371 | Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z); | ||
372 | |||
373 | coords.Add(c); | ||
374 | } | ||
375 | |||
376 | byte[] triangleBytes = subMeshMap["TriangleList"].AsBinary(); | ||
377 | for (int i = 0; i < triangleBytes.Length; i += 6) | ||
378 | { | ||
379 | ushort v1 = Utils.BytesToUInt16(triangleBytes, i); | ||
380 | ushort v2 = Utils.BytesToUInt16(triangleBytes, i + 2); | ||
381 | ushort v3 = Utils.BytesToUInt16(triangleBytes, i + 4); | ||
382 | Face f = new Face(v1, v2, v3); | ||
383 | faces.Add(f); | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | } | ||
333 | } | 388 | } |
334 | |||
335 | //just bail out for now until mesh code is finished | ||
336 | return null; | ||
337 | |||
338 | } | 389 | } |
339 | else | 390 | else |
340 | { | 391 | { |