diff options
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Meshmerizer.cs')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 131 |
1 files changed, 87 insertions, 44 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 3e3a0f0..72dce6d 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,113 @@ 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; |
288 | using (MemoryStream data = new MemoryStream(primShape.SculptData)) | ||
297 | { | 289 | { |
298 | meshOsd = OSDParser.DeserializeLLSDBinary(primShape.SculptData, true); | 290 | meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data, true); |
299 | } | 291 | start = data.Position; |
300 | catch (Exception e) | ||
301 | { | ||
302 | m_log.Error("[MESH]: exception decoding mesh asset: " + e.ToString()); | ||
303 | return null; | ||
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 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | |
325 | //int bytesRead = gzStream.Read(readBuffer, 0, maxSize); | 311 | { |
326 | 312 | using (MemoryStream outMs = new MemoryStream()) | |
327 | //OSD physMeshOsd = OSDParser.DeserializeLLSDBinary(readBuffer); | 313 | { |
328 | 314 | using (ZOutputStream zOut = new ZOutputStream(outMs)) | |
329 | 315 | { | |
330 | 316 | byte[] readBuffer = new byte[2048]; | |
317 | int readLen = 0; | ||
318 | while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) | ||
319 | { | ||
320 | zOut.Write(readBuffer, 0, readLen); | ||
321 | } | ||
322 | zOut.Flush(); | ||
323 | outMs.Seek(0, SeekOrigin.Begin); | ||
324 | |||
325 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
326 | |||
327 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf, true); | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | catch (Exception e) | ||
333 | { | ||
334 | m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); | ||
335 | return null; | ||
336 | } | ||
331 | 337 | ||
338 | OSDArray decodedMeshOsdArray = null; | ||
332 | 339 | ||
340 | // physics_shape is an array of OSDMaps, one for each submesh | ||
341 | if (decodedMeshOsd is OSDArray) | ||
342 | { | ||
343 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; | ||
344 | foreach (OSD subMeshOsd in decodedMeshOsdArray) | ||
345 | { | ||
346 | if (subMeshOsd is OSDMap) | ||
347 | { | ||
348 | OSDMap subMeshMap = (OSDMap)subMeshOsd; | ||
349 | |||
350 | OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"].AsVector3(); | ||
351 | OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"].AsVector3(); | ||
352 | |||
353 | byte[] posBytes = subMeshMap["Position"].AsBinary(); | ||
354 | for (int i = 0; i < posBytes.Length; i += 6) | ||
355 | { | ||
356 | ushort uX = Utils.BytesToUInt16(posBytes, i); | ||
357 | ushort uY = Utils.BytesToUInt16(posBytes, i + 2); | ||
358 | ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); | ||
359 | |||
360 | Coord c = new Coord( | ||
361 | Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X, | ||
362 | Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y, | ||
363 | Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z); | ||
364 | |||
365 | coords.Add(c); | ||
366 | } | ||
367 | |||
368 | byte[] triangleBytes = subMeshMap["TriangleList"].AsBinary(); | ||
369 | for (int i = 0; i < triangleBytes.Length; i += 6) | ||
370 | { | ||
371 | ushort v1 = Utils.BytesToUInt16(triangleBytes, i); | ||
372 | ushort v2 = Utils.BytesToUInt16(triangleBytes, i + 2); | ||
373 | ushort v3 = Utils.BytesToUInt16(triangleBytes, i + 4); | ||
374 | Face f = new Face(v1, v2, v3); | ||
375 | faces.Add(f); | ||
376 | } | ||
377 | } | ||
378 | } | ||
379 | } | ||
333 | } | 380 | } |
334 | |||
335 | //just bail out for now until mesh code is finished | ||
336 | return null; | ||
337 | |||
338 | } | 381 | } |
339 | else | 382 | else |
340 | { | 383 | { |