diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d3ba273..b1833c5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |||
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
36 | { | 36 | { |
37 | public class BSShapeCollection : IDisposable | 37 | public class BSShapeCollection : IDisposable |
38 | { | 38 | { |
39 | // private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; | 39 | private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; |
40 | 40 | ||
41 | protected BSScene PhysicsScene { get; set; } | 41 | protected BSScene PhysicsScene { get; set; } |
42 | 42 | ||
@@ -89,7 +89,7 @@ public class BSShapeCollection : IDisposable | |||
89 | // higher level dependencies on the shape or body. Mostly used for LinkSets to | 89 | // higher level dependencies on the shape or body. Mostly used for LinkSets to |
90 | // remove the physical constraints before the body is destroyed. | 90 | // remove the physical constraints before the body is destroyed. |
91 | // Called at taint-time!! | 91 | // Called at taint-time!! |
92 | public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, | 92 | public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, |
93 | ShapeData shapeData, PrimitiveBaseShape pbs, | 93 | ShapeData shapeData, PrimitiveBaseShape pbs, |
94 | ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) | 94 | ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) |
95 | { | 95 | { |
@@ -105,7 +105,7 @@ public class BSShapeCollection : IDisposable | |||
105 | // If we had to select a new shape geometry for the object, | 105 | // If we had to select a new shape geometry for the object, |
106 | // rebuild the body around it. | 106 | // rebuild the body around it. |
107 | // Updates prim.BSBody with information/pointers to requested body | 107 | // Updates prim.BSBody with information/pointers to requested body |
108 | bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, | 108 | bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, |
109 | prim.BSShape, shapeData, bodyCallback); | 109 | prim.BSShape, shapeData, bodyCallback); |
110 | ret = newGeom || newBody; | 110 | ret = newGeom || newBody; |
111 | } | 111 | } |
@@ -325,7 +325,7 @@ public class BSShapeCollection : IDisposable | |||
325 | // Info in prim.BSShape is updated to the new shape. | 325 | // Info in prim.BSShape is updated to the new shape. |
326 | // Returns 'true' if the geometry was rebuilt. | 326 | // Returns 'true' if the geometry was rebuilt. |
327 | // Called at taint-time! | 327 | // Called at taint-time! |
328 | private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, | 328 | private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, |
329 | PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) | 329 | PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) |
330 | { | 330 | { |
331 | bool ret = false; | 331 | bool ret = false; |
@@ -335,7 +335,7 @@ public class BSShapeCollection : IDisposable | |||
335 | if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) | 335 | if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) |
336 | { | 336 | { |
337 | // an avatar capsule is close to a native shape (it is not shared) | 337 | // an avatar capsule is close to a native shape (it is not shared) |
338 | ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, | 338 | ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, |
339 | ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); | 339 | ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); |
340 | DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); | 340 | DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); |
341 | haveShape = true; | 341 | haveShape = true; |
@@ -362,7 +362,7 @@ public class BSShapeCollection : IDisposable | |||
362 | || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE | 362 | || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE |
363 | ) | 363 | ) |
364 | { | 364 | { |
365 | ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, | 365 | ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, |
366 | ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); | 366 | ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); |
367 | DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", | 367 | DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", |
368 | prim.LocalID, forceRebuild, prim.BSShape); | 368 | prim.LocalID, forceRebuild, prim.BSShape); |
@@ -376,7 +376,7 @@ public class BSShapeCollection : IDisposable | |||
376 | || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX | 376 | || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX |
377 | ) | 377 | ) |
378 | { | 378 | { |
379 | ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, | 379 | ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, |
380 | ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); | 380 | ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); |
381 | DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", | 381 | DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", |
382 | prim.LocalID, forceRebuild, prim.BSShape); | 382 | prim.LocalID, forceRebuild, prim.BSShape); |
@@ -423,27 +423,37 @@ public class BSShapeCollection : IDisposable | |||
423 | BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); | 423 | BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); |
424 | 424 | ||
425 | // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. | 425 | // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. |
426 | DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", | 426 | DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", |
427 | shapeData.ID, newShape, shapeData.Scale); | 427 | shapeData.ID, newShape, shapeData.Scale); |
428 | 428 | ||
429 | prim.BSShape = newShape; | 429 | prim.BSShape = newShape; |
430 | return true; | 430 | return true; |
431 | } | 431 | } |
432 | 432 | ||
433 | private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, | 433 | private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, |
434 | ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) | 434 | ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) |
435 | { | 435 | { |
436 | BulletShape newShape; | 436 | BulletShape newShape; |
437 | // Need to make sure the passed shape information is for the native type. | ||
438 | ShapeData nativeShapeData = shapeData; | ||
439 | nativeShapeData.Type = shapeType; | ||
440 | nativeShapeData.MeshKey = (ulong)shapeKey; | ||
441 | nativeShapeData.HullKey = (ulong)shapeKey; | ||
437 | 442 | ||
438 | if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) | 443 | if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) |
439 | { | 444 | { |
440 | newShape = new BulletShape( | 445 | newShape = new BulletShape( |
441 | BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), | 446 | BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, nativeShapeData.Scale), shapeType); |
442 | shapeType); | 447 | DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); |
443 | } | 448 | } |
444 | else | 449 | else |
445 | { | 450 | { |
446 | newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); | 451 | newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); |
452 | } | ||
453 | if (newShape.ptr == IntPtr.Zero) | ||
454 | { | ||
455 | PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", | ||
456 | LogHeader, nativeShapeData.ID, nativeShapeData.Type); | ||
447 | } | 457 | } |
448 | newShape.shapeKey = (System.UInt64)shapeKey; | 458 | newShape.shapeKey = (System.UInt64)shapeKey; |
449 | newShape.isNativeShape = true; | 459 | newShape.isNativeShape = true; |
@@ -698,19 +708,26 @@ public class BSShapeCollection : IDisposable | |||
698 | return ComputeShapeKey(shapeData, pbs, out lod); | 708 | return ComputeShapeKey(shapeData, pbs, out lod); |
699 | } | 709 | } |
700 | 710 | ||
711 | // The creation of a mesh or hull can fail if an underlying asset is not available. | ||
712 | // There are two cases: 1) the asset is not in the cache and it needs to be fetched; | ||
713 | // and 2) the asset cannot be converted (like decompressing JPEG2000s). | ||
714 | // The first case causes the asset to be fetched. The second case just requires | ||
715 | // us to not loop forever. | ||
716 | // Called after creating a physical mesh or hull. If the physical shape was created, | ||
717 | // just return. | ||
701 | private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) | 718 | private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) |
702 | { | 719 | { |
703 | // If the shape was successfully created, nothing more to do | 720 | // If the shape was successfully created, nothing more to do |
704 | if (newShape.ptr != IntPtr.Zero) | 721 | if (newShape.ptr != IntPtr.Zero) |
705 | return newShape; | 722 | return newShape; |
706 | 723 | ||
707 | // The most common reason for failure is that an underlying asset is not available | ||
708 | |||
709 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset | 724 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset |
710 | if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) | 725 | if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) |
711 | { | 726 | { |
712 | prim.LastAssetBuildFailed = true; | 727 | prim.LastAssetBuildFailed = true; |
713 | BSPhysObject xprim = prim; | 728 | BSPhysObject xprim = prim; |
729 | DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", | ||
730 | LogHeader, shapeData.ID.ToString("X"), prim.LastAssetBuildFailed); | ||
714 | Util.FireAndForget(delegate | 731 | Util.FireAndForget(delegate |
715 | { | 732 | { |
716 | RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; | 733 | RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; |
@@ -724,20 +741,28 @@ public class BSShapeCollection : IDisposable | |||
724 | if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) | 741 | if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) |
725 | return; | 742 | return; |
726 | 743 | ||
727 | yprim.BaseShape.SculptData = new byte[asset.Data.Length]; | 744 | yprim.BaseShape.SculptData = asset.Data; |
728 | asset.Data.CopyTo(yprim.BaseShape.SculptData, 0); | ||
729 | // This will cause the prim to see that the filler shape is not the right | 745 | // This will cause the prim to see that the filler shape is not the right |
730 | // one and try again to build the object. | 746 | // one and try again to build the object. |
747 | // No race condition with the native sphere setting since the rebuild is at taint time. | ||
731 | yprim.ForceBodyShapeRebuild(false); | 748 | yprim.ForceBodyShapeRebuild(false); |
732 | 749 | ||
733 | }); | 750 | }); |
734 | } | 751 | } |
735 | }); | 752 | }); |
736 | } | 753 | } |
754 | else | ||
755 | { | ||
756 | if (prim.LastAssetBuildFailed) | ||
757 | { | ||
758 | PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", | ||
759 | LogHeader, shapeData.ID, pbs.SculptTexture); | ||
760 | } | ||
761 | } | ||
737 | 762 | ||
738 | // While we figure out the real problem, stick a simple native shape on the object. | 763 | // While we figure out the real problem, stick a simple native shape on the object. |
739 | BulletShape fillinShape = | 764 | BulletShape fillinShape = |
740 | BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE); | 765 | BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_BOX, shapeData, ShapeData.FixedShapeKey.KEY_BOX); |
741 | 766 | ||
742 | return fillinShape; | 767 | return fillinShape; |
743 | } | 768 | } |
@@ -746,7 +771,7 @@ public class BSShapeCollection : IDisposable | |||
746 | // Updates prim.BSBody with the information about the new body if one is created. | 771 | // Updates prim.BSBody with the information about the new body if one is created. |
747 | // Returns 'true' if an object was actually created. | 772 | // Returns 'true' if an object was actually created. |
748 | // Called at taint-time. | 773 | // Called at taint-time. |
749 | private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, | 774 | private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, |
750 | ShapeData shapeData, BodyDestructionCallback bodyCallback) | 775 | ShapeData shapeData, BodyDestructionCallback bodyCallback) |
751 | { | 776 | { |
752 | bool ret = false; | 777 | bool ret = false; |