diff options
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 222 |
1 files changed, 123 insertions, 99 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 8a9260c..f97449c 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -301,131 +301,155 @@ namespace OpenSim.Region.Physics.Meshing | |||
301 | } | 301 | } |
302 | } | 302 | } |
303 | 303 | ||
304 | private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) | 304 | /// <summary> |
305 | /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim. | ||
306 | /// </summary> | ||
307 | /// <param name="primName"></param> | ||
308 | /// <param name="primShape"></param> | ||
309 | /// <param name="size"></param> | ||
310 | /// <param name="coords">Coords are added to this list by the method.</param> | ||
311 | /// <param name="faces">Faces are added to this list by the method.</param> | ||
312 | /// <returns>true if coords and faces were successfully generated, false if not</returns> | ||
313 | private bool GenerateCoordsAndFacesFromPrimMeshData(string primName, PrimitiveBaseShape primShape, Vector3 size, List<Coord> coords, List<Face> faces) | ||
305 | { | 314 | { |
306 | // m_log.DebugFormat( | 315 | m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); |
307 | // "[MESH]: Creating physics proxy for {0}, shape {1}", | ||
308 | // primName, (OpenMetaverse.SculptType)primShape.SculptType); | ||
309 | 316 | ||
310 | PrimMesh primMesh; | 317 | OSD meshOsd = null; |
311 | PrimMesher.SculptMesh sculptMesh; | ||
312 | |||
313 | List<Coord> coords = new List<Coord>(); | ||
314 | List<Face> faces = new List<Face>(); | ||
315 | 318 | ||
316 | Image idata = null; | 319 | if (primShape.SculptData.Length <= 0) |
317 | string decodedSculptFileName = ""; | 320 | { |
321 | m_log.Error("[MESH]: asset data is zero length"); | ||
322 | return false; | ||
323 | } | ||
318 | 324 | ||
319 | if (primShape.SculptEntry) | 325 | long start = 0; |
326 | using (MemoryStream data = new MemoryStream(primShape.SculptData)) | ||
320 | { | 327 | { |
321 | if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) | 328 | try |
322 | { | 329 | { |
323 | if (!useMeshiesPhysicsMesh) | 330 | OSD osd = OSDParser.DeserializeLLSDBinary(data); |
324 | return null; | 331 | if (osd is OSDMap) |
325 | 332 | meshOsd = (OSDMap)osd; | |
326 | m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); | 333 | else |
327 | |||
328 | OSD meshOsd = null; | ||
329 | |||
330 | if (primShape.SculptData.Length <= 0) | ||
331 | { | 334 | { |
332 | m_log.Error("[MESH]: asset data is zero length"); | 335 | m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap"); |
333 | return null; | 336 | return false; |
334 | } | 337 | } |
338 | } | ||
339 | catch (Exception e) | ||
340 | { | ||
341 | m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString()); | ||
342 | } | ||
335 | 343 | ||
336 | long start = 0; | 344 | start = data.Position; |
337 | using (MemoryStream data = new MemoryStream(primShape.SculptData)) | 345 | } |
338 | { | ||
339 | try | ||
340 | { | ||
341 | OSD osd = OSDParser.DeserializeLLSDBinary(data); | ||
342 | if (osd is OSDMap) | ||
343 | meshOsd = (OSDMap)osd; | ||
344 | else | ||
345 | { | ||
346 | m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap"); | ||
347 | return null; | ||
348 | } | ||
349 | } | ||
350 | catch (Exception e) | ||
351 | { | ||
352 | m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString()); | ||
353 | } | ||
354 | |||
355 | start = data.Position; | ||
356 | } | ||
357 | 346 | ||
358 | if (meshOsd is OSDMap) | 347 | if (meshOsd is OSDMap) |
359 | { | 348 | { |
360 | OSDMap physicsParms = null; | 349 | OSDMap physicsParms = null; |
361 | OSDMap map = (OSDMap)meshOsd; | 350 | OSDMap map = (OSDMap)meshOsd; |
362 | if (map.ContainsKey("physics_shape")) | 351 | if (map.ContainsKey("physics_shape")) |
363 | physicsParms = (OSDMap)map["physics_shape"]; // old asset format | 352 | physicsParms = (OSDMap)map["physics_shape"]; // old asset format |
364 | else if (map.ContainsKey("physics_mesh")) | 353 | else if (map.ContainsKey("physics_mesh")) |
365 | physicsParms = (OSDMap)map["physics_mesh"]; // new asset format | 354 | physicsParms = (OSDMap)map["physics_mesh"]; // new asset format |
366 | 355 | ||
367 | if (physicsParms == null) | 356 | if (physicsParms == null) |
368 | { | 357 | { |
369 | m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset"); | 358 | m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset"); |
370 | return null; | 359 | return false; |
371 | } | 360 | } |
372 | 361 | ||
373 | int physOffset = physicsParms["offset"].AsInteger() + (int)start; | 362 | int physOffset = physicsParms["offset"].AsInteger() + (int)start; |
374 | int physSize = physicsParms["size"].AsInteger(); | 363 | int physSize = physicsParms["size"].AsInteger(); |
375 | 364 | ||
376 | if (physOffset < 0 || physSize == 0) | 365 | if (physOffset < 0 || physSize == 0) |
377 | return null; // no mesh data in asset | 366 | return false; // no mesh data in asset |
378 | 367 | ||
379 | OSD decodedMeshOsd = new OSD(); | 368 | OSD decodedMeshOsd = new OSD(); |
380 | byte[] meshBytes = new byte[physSize]; | 369 | byte[] meshBytes = new byte[physSize]; |
381 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); | 370 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); |
382 | // byte[] decompressed = new byte[physSize * 5]; | 371 | // byte[] decompressed = new byte[physSize * 5]; |
383 | try | 372 | try |
373 | { | ||
374 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | ||
375 | { | ||
376 | using (MemoryStream outMs = new MemoryStream()) | ||
384 | { | 377 | { |
385 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | 378 | using (ZOutputStream zOut = new ZOutputStream(outMs)) |
386 | { | 379 | { |
387 | using (MemoryStream outMs = new MemoryStream()) | 380 | byte[] readBuffer = new byte[2048]; |
381 | int readLen = 0; | ||
382 | while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) | ||
388 | { | 383 | { |
389 | using (ZOutputStream zOut = new ZOutputStream(outMs)) | 384 | zOut.Write(readBuffer, 0, readLen); |
390 | { | ||
391 | byte[] readBuffer = new byte[2048]; | ||
392 | int readLen = 0; | ||
393 | while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) | ||
394 | { | ||
395 | zOut.Write(readBuffer, 0, readLen); | ||
396 | } | ||
397 | zOut.Flush(); | ||
398 | outMs.Seek(0, SeekOrigin.Begin); | ||
399 | |||
400 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
401 | |||
402 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
403 | } | ||
404 | } | 385 | } |
386 | zOut.Flush(); | ||
387 | outMs.Seek(0, SeekOrigin.Begin); | ||
388 | |||
389 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
390 | |||
391 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
405 | } | 392 | } |
406 | } | 393 | } |
407 | catch (Exception e) | 394 | } |
408 | { | 395 | } |
409 | m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); | 396 | catch (Exception e) |
410 | return null; | 397 | { |
411 | } | 398 | m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); |
399 | return false; | ||
400 | } | ||
412 | 401 | ||
413 | OSDArray decodedMeshOsdArray = null; | 402 | OSDArray decodedMeshOsdArray = null; |
414 | 403 | ||
415 | // physics_shape is an array of OSDMaps, one for each submesh | 404 | // physics_shape is an array of OSDMaps, one for each submesh |
416 | if (decodedMeshOsd is OSDArray) | 405 | if (decodedMeshOsd is OSDArray) |
417 | { | 406 | { |
418 | // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); | 407 | // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); |
419 | 408 | ||
420 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; | 409 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; |
421 | foreach (OSD subMeshOsd in decodedMeshOsdArray) | 410 | foreach (OSD subMeshOsd in decodedMeshOsdArray) |
422 | { | 411 | { |
423 | if (subMeshOsd is OSDMap) | 412 | if (subMeshOsd is OSDMap) |
424 | AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); | 413 | AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); |
425 | } | ||
426 | } | ||
427 | } | 414 | } |
428 | } | 415 | } |
416 | } | ||
417 | |||
418 | return true; | ||
419 | } | ||
420 | |||
421 | /// <summary> | ||
422 | /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type. | ||
423 | /// </summary> | ||
424 | /// <param name="primName"></param> | ||
425 | /// <param name="primShape"></param> | ||
426 | /// <param name="size"></param> | ||
427 | /// <param name="lod"></param> | ||
428 | /// <returns></returns> | ||
429 | private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) | ||
430 | { | ||
431 | // m_log.DebugFormat( | ||
432 | // "[MESH]: Creating physics proxy for {0}, shape {1}", | ||
433 | // primName, (OpenMetaverse.SculptType)primShape.SculptType); | ||
434 | |||
435 | PrimMesh primMesh; | ||
436 | PrimMesher.SculptMesh sculptMesh; | ||
437 | |||
438 | List<Coord> coords = new List<Coord>(); | ||
439 | List<Face> faces = new List<Face>(); | ||
440 | |||
441 | Image idata = null; | ||
442 | string decodedSculptFileName = ""; | ||
443 | |||
444 | if (primShape.SculptEntry) | ||
445 | { | ||
446 | if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) | ||
447 | { | ||
448 | if (!useMeshiesPhysicsMesh) | ||
449 | return null; | ||
450 | |||
451 | GeneratePointsAndFacesFromPrimMeshData(primName, primShape, size, coords, faces); | ||
452 | } | ||
429 | else | 453 | else |
430 | { | 454 | { |
431 | if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero) | 455 | if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero) |