diff options
author | Robert Adams | 2013-04-28 14:44:21 -0700 |
---|---|---|
committer | Robert Adams | 2013-04-29 07:38:40 -0700 |
commit | e5582939fd8d78b61c6f1eeda6de45d94f4b4926 (patch) | |
tree | 1f990ab6f73f4e787566031af35c7c59c89968aa /OpenSim/Region/Physics/BulletSPlugin | |
parent | BulletSim: complete BSShape classes. (diff) | |
download | opensim-SC_OLD-e5582939fd8d78b61c6f1eeda6de45d94f4b4926.zip opensim-SC_OLD-e5582939fd8d78b61c6f1eeda6de45d94f4b4926.tar.gz opensim-SC_OLD-e5582939fd8d78b61c6f1eeda6de45d94f4b4926.tar.bz2 opensim-SC_OLD-e5582939fd8d78b61c6f1eeda6de45d94f4b4926.tar.xz |
BulletSim: massive refactor of shape classes. Removed shape specific code from BSShapeCollection. Using BSShape* classes to hold references to shape. Simplified shape dependency callbacks. Remove 'PreferredShape' methods and have each class specify shape type. Disable compound shape linkset for a later commit that will simplify linkset implementation.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
20 files changed, 290 insertions, 1050 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs index fdf2cb9..8a22bc7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs | |||
@@ -79,7 +79,7 @@ private sealed class BulletShapeUnman : BulletShape | |||
79 | : base() | 79 | : base() |
80 | { | 80 | { |
81 | ptr = xx; | 81 | ptr = xx; |
82 | type = typ; | 82 | shapeType = typ; |
83 | } | 83 | } |
84 | public override bool HasPhysicalShape | 84 | public override bool HasPhysicalShape |
85 | { | 85 | { |
@@ -91,7 +91,7 @@ private sealed class BulletShapeUnman : BulletShape | |||
91 | } | 91 | } |
92 | public override BulletShape Clone() | 92 | public override BulletShape Clone() |
93 | { | 93 | { |
94 | return new BulletShapeUnman(ptr, type); | 94 | return new BulletShapeUnman(ptr, shapeType); |
95 | } | 95 | } |
96 | public override bool ReferenceSame(BulletShape other) | 96 | public override bool ReferenceSame(BulletShape other) |
97 | { | 97 | { |
@@ -375,7 +375,7 @@ public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletSha | |||
375 | { | 375 | { |
376 | BulletWorldUnman worldu = world as BulletWorldUnman; | 376 | BulletWorldUnman worldu = world as BulletWorldUnman; |
377 | BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman; | 377 | BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman; |
378 | return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type); | 378 | return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.shapeType); |
379 | } | 379 | } |
380 | 380 | ||
381 | public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) | 381 | public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs index b37265a..1ef8b17 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs | |||
@@ -85,7 +85,7 @@ private sealed class BulletShapeXNA : BulletShape | |||
85 | : base() | 85 | : base() |
86 | { | 86 | { |
87 | shape = xx; | 87 | shape = xx; |
88 | type = typ; | 88 | shapeType = typ; |
89 | } | 89 | } |
90 | public override bool HasPhysicalShape | 90 | public override bool HasPhysicalShape |
91 | { | 91 | { |
@@ -97,7 +97,7 @@ private sealed class BulletShapeXNA : BulletShape | |||
97 | } | 97 | } |
98 | public override BulletShape Clone() | 98 | public override BulletShape Clone() |
99 | { | 99 | { |
100 | return new BulletShapeXNA(shape, type); | 100 | return new BulletShapeXNA(shape, shapeType); |
101 | } | 101 | } |
102 | public override bool ReferenceSame(BulletShape other) | 102 | public override bool ReferenceSame(BulletShape other) |
103 | { | 103 | { |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index bd5ee0b1..ac05979 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | |||
@@ -87,8 +87,8 @@ public class BSActorAvatarMove : BSActor | |||
87 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | 87 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). |
88 | // Register a prestep action to restore physical requirements before the next simulation step. | 88 | // Register a prestep action to restore physical requirements before the next simulation step. |
89 | // Called at taint-time. | 89 | // Called at taint-time. |
90 | // BSActor.RemoveBodyDependencies() | 90 | // BSActor.RemoveDependencies() |
91 | public override void RemoveBodyDependencies() | 91 | public override void RemoveDependencies() |
92 | { | 92 | { |
93 | // Nothing to do for the hoverer since it is all software at pre-step action time. | 93 | // Nothing to do for the hoverer since it is all software at pre-step action time. |
94 | } | 94 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs index 92ace66..3630ca8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs | |||
@@ -87,8 +87,8 @@ public class BSActorHover : BSActor | |||
87 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | 87 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). |
88 | // Register a prestep action to restore physical requirements before the next simulation step. | 88 | // Register a prestep action to restore physical requirements before the next simulation step. |
89 | // Called at taint-time. | 89 | // Called at taint-time. |
90 | // BSActor.RemoveBodyDependencies() | 90 | // BSActor.RemoveDependencies() |
91 | public override void RemoveBodyDependencies() | 91 | public override void RemoveDependencies() |
92 | { | 92 | { |
93 | // Nothing to do for the hoverer since it is all software at pre-step action time. | 93 | // Nothing to do for the hoverer since it is all software at pre-step action time. |
94 | } | 94 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs index 09ee32b..6059af5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs | |||
@@ -85,8 +85,8 @@ public class BSActorLockAxis : BSActor | |||
85 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | 85 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). |
86 | // Register a prestep action to restore physical requirements before the next simulation step. | 86 | // Register a prestep action to restore physical requirements before the next simulation step. |
87 | // Called at taint-time. | 87 | // Called at taint-time. |
88 | // BSActor.RemoveBodyDependencies() | 88 | // BSActor.RemoveDependencies() |
89 | public override void RemoveBodyDependencies() | 89 | public override void RemoveDependencies() |
90 | { | 90 | { |
91 | if (LockAxisConstraint != null) | 91 | if (LockAxisConstraint != null) |
92 | { | 92 | { |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs index 56aacc5..1b598fd 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs | |||
@@ -88,8 +88,8 @@ public class BSActorMoveToTarget : BSActor | |||
88 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | 88 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). |
89 | // Register a prestep action to restore physical requirements before the next simulation step. | 89 | // Register a prestep action to restore physical requirements before the next simulation step. |
90 | // Called at taint-time. | 90 | // Called at taint-time. |
91 | // BSActor.RemoveBodyDependencies() | 91 | // BSActor.RemoveDependencies() |
92 | public override void RemoveBodyDependencies() | 92 | public override void RemoveDependencies() |
93 | { | 93 | { |
94 | // Nothing to do for the moveToTarget since it is all software at pre-step action time. | 94 | // Nothing to do for the moveToTarget since it is all software at pre-step action time. |
95 | } | 95 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs index 3ad138d..c0f40fd 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs | |||
@@ -89,8 +89,8 @@ public class BSActorSetForce : BSActor | |||
89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | 89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). |
90 | // Register a prestep action to restore physical requirements before the next simulation step. | 90 | // Register a prestep action to restore physical requirements before the next simulation step. |
91 | // Called at taint-time. | 91 | // Called at taint-time. |
92 | // BSActor.RemoveBodyDependencies() | 92 | // BSActor.RemoveDependencies() |
93 | public override void RemoveBodyDependencies() | 93 | public override void RemoveDependencies() |
94 | { | 94 | { |
95 | // Nothing to do for the hoverer since it is all software at pre-step action time. | 95 | // Nothing to do for the hoverer since it is all software at pre-step action time. |
96 | } | 96 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs index 7a791ec..b3806e1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs | |||
@@ -89,8 +89,8 @@ public class BSActorSetTorque : BSActor | |||
89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | 89 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). |
90 | // Register a prestep action to restore physical requirements before the next simulation step. | 90 | // Register a prestep action to restore physical requirements before the next simulation step. |
91 | // Called at taint-time. | 91 | // Called at taint-time. |
92 | // BSActor.RemoveBodyDependencies() | 92 | // BSActor.RemoveDependencies() |
93 | public override void RemoveBodyDependencies() | 93 | public override void RemoveDependencies() |
94 | { | 94 | { |
95 | // Nothing to do for the hoverer since it is all software at pre-step action time. | 95 | // Nothing to do for the hoverer since it is all software at pre-step action time. |
96 | } | 96 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs index 12a8817..5e3f1c4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs | |||
@@ -106,9 +106,9 @@ public class BSActorCollection | |||
106 | { | 106 | { |
107 | ForEachActor(a => a.Refresh()); | 107 | ForEachActor(a => a.Refresh()); |
108 | } | 108 | } |
109 | public void RemoveBodyDependencies() | 109 | public void RemoveDependencies() |
110 | { | 110 | { |
111 | ForEachActor(a => a.RemoveBodyDependencies()); | 111 | ForEachActor(a => a.RemoveDependencies()); |
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
@@ -154,7 +154,7 @@ public abstract class BSActor | |||
154 | public abstract void Refresh(); | 154 | public abstract void Refresh(); |
155 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). | 155 | // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). |
156 | // Register a prestep action to restore physical requirements before the next simulation step. | 156 | // Register a prestep action to restore physical requirements before the next simulation step. |
157 | public abstract void RemoveBodyDependencies(); | 157 | public abstract void RemoveDependencies(); |
158 | 158 | ||
159 | } | 159 | } |
160 | } | 160 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index a0d58d3..da23a262 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -123,8 +123,8 @@ public sealed class BSCharacter : BSPhysObject | |||
123 | { | 123 | { |
124 | PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); | 124 | PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); |
125 | PhysBody.Clear(); | 125 | PhysBody.Clear(); |
126 | PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */); | 126 | PhysShape.Dereference(PhysicsScene); |
127 | PhysShape.Clear(); | 127 | PhysShape = new BSShapeNull(); |
128 | }); | 128 | }); |
129 | } | 129 | } |
130 | 130 | ||
@@ -146,8 +146,8 @@ public sealed class BSCharacter : BSPhysObject | |||
146 | Flying = _flying; | 146 | Flying = _flying; |
147 | 147 | ||
148 | PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); | 148 | PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); |
149 | PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin); | 149 | PhysicsScene.PE.SetMargin(PhysShape.physShapeInfo, PhysicsScene.Params.collisionMargin); |
150 | PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); | 150 | PhysicsScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale); |
151 | PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); | 151 | PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); |
152 | if (BSParam.CcdMotionThreshold > 0f) | 152 | if (BSParam.CcdMotionThreshold > 0f) |
153 | { | 153 | { |
@@ -205,9 +205,9 @@ public sealed class BSCharacter : BSPhysObject | |||
205 | 205 | ||
206 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() | 206 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() |
207 | { | 207 | { |
208 | if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) | 208 | if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape) |
209 | { | 209 | { |
210 | PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); | 210 | PhysicsScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale); |
211 | UpdatePhysicalMassProperties(RawMass, true); | 211 | UpdatePhysicalMassProperties(RawMass, true); |
212 | // Make sure this change appears as a property update event | 212 | // Make sure this change appears as a property update event |
213 | PhysicsScene.PE.PushUpdate(PhysBody); | 213 | PhysicsScene.PE.PushUpdate(PhysBody); |
@@ -221,11 +221,6 @@ public sealed class BSCharacter : BSPhysObject | |||
221 | { | 221 | { |
222 | set { BaseShape = value; } | 222 | set { BaseShape = value; } |
223 | } | 223 | } |
224 | // I want the physics engine to make an avatar capsule | ||
225 | public override BSPhysicsShapeType PreferredPhysicalShape | ||
226 | { | ||
227 | get {return BSPhysicsShapeType.SHAPE_CAPSULE; } | ||
228 | } | ||
229 | 224 | ||
230 | public override bool Grabbed { | 225 | public override bool Grabbed { |
231 | set { _grabbed = value; } | 226 | set { _grabbed = value; } |
@@ -381,7 +376,7 @@ public sealed class BSCharacter : BSPhysObject | |||
381 | } | 376 | } |
382 | public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) | 377 | public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) |
383 | { | 378 | { |
384 | OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); | 379 | OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass); |
385 | PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia); | 380 | PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia); |
386 | } | 381 | } |
387 | 382 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 612c68b..e2e807e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -625,7 +625,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
625 | // Vehicles report collision events so we know when it's on the ground | 625 | // Vehicles report collision events so we know when it's on the ground |
626 | m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | 626 | m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); |
627 | 627 | ||
628 | ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape, m_vehicleMass); | 628 | ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass); |
629 | m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); | 629 | m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); |
630 | m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); | 630 | m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); |
631 | 631 | ||
@@ -649,7 +649,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
649 | } | 649 | } |
650 | 650 | ||
651 | // BSActor.RemoveBodyDependencies | 651 | // BSActor.RemoveBodyDependencies |
652 | public override void RemoveBodyDependencies() | 652 | public override void RemoveDependencies() |
653 | { | 653 | { |
654 | Refresh(); | 654 | Refresh(); |
655 | } | 655 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 4ece1eb..df1dd34 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -93,13 +93,6 @@ public abstract class BSLinkset | |||
93 | // to the physical representation is done via the tainting mechenism. | 93 | // to the physical representation is done via the tainting mechenism. |
94 | protected object m_linksetActivityLock = new Object(); | 94 | protected object m_linksetActivityLock = new Object(); |
95 | 95 | ||
96 | // Some linksets have a preferred physical shape. | ||
97 | // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. | ||
98 | public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor) | ||
99 | { | ||
100 | return BSPhysicsShapeType.SHAPE_UNKNOWN; | ||
101 | } | ||
102 | |||
103 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims | 96 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims |
104 | public float LinksetMass { get; protected set; } | 97 | public float LinksetMass { get; protected set; } |
105 | 98 | ||
@@ -263,7 +256,7 @@ public abstract class BSLinkset | |||
263 | // This is called when the root body is changing. | 256 | // This is called when the root body is changing. |
264 | // Returns 'true' of something was actually removed and would need restoring | 257 | // Returns 'true' of something was actually removed and would need restoring |
265 | // Called at taint-time!! | 258 | // Called at taint-time!! |
266 | public abstract bool RemoveBodyDependencies(BSPrimLinkable child); | 259 | public abstract bool RemoveDependencies(BSPrimLinkable child); |
267 | 260 | ||
268 | // ================================================================ | 261 | // ================================================================ |
269 | protected virtual float ComputeLinksetMass() | 262 | protected virtual float ComputeLinksetMass() |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index e05562a..a20bbc3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | |||
@@ -98,19 +98,6 @@ public sealed class BSLinksetCompound : BSLinkset | |||
98 | { | 98 | { |
99 | } | 99 | } |
100 | 100 | ||
101 | // For compound implimented linksets, if there are children, use compound shape for the root. | ||
102 | public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor) | ||
103 | { | ||
104 | // Returning 'unknown' means we don't have a preference. | ||
105 | BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; | ||
106 | if (IsRoot(requestor) && HasAnyChildren) | ||
107 | { | ||
108 | ret = BSPhysicsShapeType.SHAPE_COMPOUND; | ||
109 | } | ||
110 | // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | // When physical properties are changed the linkset needs to recalculate | 101 | // When physical properties are changed the linkset needs to recalculate |
115 | // its internal properties. | 102 | // its internal properties. |
116 | public override void Refresh(BSPrimLinkable requestor) | 103 | public override void Refresh(BSPrimLinkable requestor) |
@@ -218,22 +205,22 @@ public sealed class BSLinksetCompound : BSLinkset | |||
218 | // and that is caused by us updating the object. | 205 | // and that is caused by us updating the object. |
219 | if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) | 206 | if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) |
220 | { | 207 | { |
221 | // Find the physical instance of the child | 208 | // Find the physical instance of the child |
222 | if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) | 209 | if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo)) |
223 | { | 210 | { |
224 | // It is possible that the linkset is still under construction and the child is not yet | 211 | // It is possible that the linkset is still under construction and the child is not yet |
225 | // inserted into the compound shape. A rebuild of the linkset in a pre-step action will | 212 | // inserted into the compound shape. A rebuild of the linkset in a pre-step action will |
226 | // build the whole thing with the new position or rotation. | 213 | // build the whole thing with the new position or rotation. |
227 | // The index must be checked because Bullet references the child array but does no validity | 214 | // The index must be checked because Bullet references the child array but does no validity |
228 | // checking of the child index passed. | 215 | // checking of the child index passed. |
229 | int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); | 216 | int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo); |
230 | if (updated.LinksetChildIndex < numLinksetChildren) | 217 | if (updated.LinksetChildIndex < numLinksetChildren) |
231 | { | 218 | { |
232 | BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex); | 219 | BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex); |
233 | if (linksetChildShape.HasPhysicalShape) | 220 | if (linksetChildShape.HasPhysicalShape) |
234 | { | 221 | { |
235 | // Found the child shape within the compound shape | 222 | // Found the child shape within the compound shape |
236 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex, | 223 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex, |
237 | updated.RawPosition - LinksetRoot.RawPosition, | 224 | updated.RawPosition - LinksetRoot.RawPosition, |
238 | updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), | 225 | updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), |
239 | true /* shouldRecalculateLocalAabb */); | 226 | true /* shouldRecalculateLocalAabb */); |
@@ -278,7 +265,7 @@ public sealed class BSLinksetCompound : BSLinkset | |||
278 | // Since we don't keep in world relationships, do nothing unless it's a child changing. | 265 | // Since we don't keep in world relationships, do nothing unless it's a child changing. |
279 | // Returns 'true' of something was actually removed and would need restoring | 266 | // Returns 'true' of something was actually removed and would need restoring |
280 | // Called at taint-time!! | 267 | // Called at taint-time!! |
281 | public override bool RemoveBodyDependencies(BSPrimLinkable child) | 268 | public override bool RemoveDependencies(BSPrimLinkable child) |
282 | { | 269 | { |
283 | bool ret = false; | 270 | bool ret = false; |
284 | 271 | ||
@@ -404,11 +391,12 @@ public sealed class BSLinksetCompound : BSLinkset | |||
404 | { | 391 | { |
405 | try | 392 | try |
406 | { | 393 | { |
394 | /* | ||
407 | // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.) | 395 | // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.) |
408 | Rebuilding = true; | 396 | Rebuilding = true; |
409 | 397 | ||
410 | // Cause the root shape to be rebuilt as a compound object with just the root in it | 398 | // Cause the root shape to be rebuilt as a compound object with just the root in it |
411 | LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */); | 399 | LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime ); |
412 | 400 | ||
413 | // The center of mass for the linkset is the geometric center of the group. | 401 | // The center of mass for the linkset is the geometric center of the group. |
414 | // Compute a displacement for each component so it is relative to the center-of-mass. | 402 | // Compute a displacement for each component so it is relative to the center-of-mass. |
@@ -430,10 +418,10 @@ public sealed class BSLinksetCompound : BSLinkset | |||
430 | LinksetRoot.ForcePosition = LinksetRoot.RawPosition; | 418 | LinksetRoot.ForcePosition = LinksetRoot.RawPosition; |
431 | 419 | ||
432 | // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM | 420 | // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM |
433 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */, | 421 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, 0 /* childIndex , |
434 | -centerDisplacement, | 422 | -centerDisplacement, |
435 | OMV.Quaternion.Identity, // LinksetRoot.RawOrientation, | 423 | OMV.Quaternion.Identity, // LinksetRoot.RawOrientation, |
436 | false /* shouldRecalculateLocalAabb (is done later after linkset built) */); | 424 | false /* shouldRecalculateLocalAabb (is done later after linkset built) ); |
437 | 425 | ||
438 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", | 426 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", |
439 | LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement); | 427 | LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement); |
@@ -501,6 +489,7 @@ public sealed class BSLinksetCompound : BSLinkset | |||
501 | 489 | ||
502 | // Enable the physical position updator to return the position and rotation of the root shape | 490 | // Enable the physical position updator to return the position and rotation of the root shape |
503 | PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); | 491 | PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); |
492 | */ | ||
504 | } | 493 | } |
505 | finally | 494 | finally |
506 | { | 495 | { |
@@ -508,7 +497,7 @@ public sealed class BSLinksetCompound : BSLinkset | |||
508 | } | 497 | } |
509 | 498 | ||
510 | // See that the Aabb surrounds the new shape | 499 | // See that the Aabb surrounds the new shape |
511 | PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); | 500 | PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo); |
512 | } | 501 | } |
513 | } | 502 | } |
514 | } \ No newline at end of file | 503 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 6d252ca..1811772 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs | |||
@@ -93,11 +93,11 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
93 | // up to rebuild the constraints before the next simulation step. | 93 | // up to rebuild the constraints before the next simulation step. |
94 | // Returns 'true' of something was actually removed and would need restoring | 94 | // Returns 'true' of something was actually removed and would need restoring |
95 | // Called at taint-time!! | 95 | // Called at taint-time!! |
96 | public override bool RemoveBodyDependencies(BSPrimLinkable child) | 96 | public override bool RemoveDependencies(BSPrimLinkable child) |
97 | { | 97 | { |
98 | bool ret = false; | 98 | bool ret = false; |
99 | 99 | ||
100 | DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", | 100 | DetailLog("{0},BSLinksetConstraint.RemoveDependencies,removeChildrenForRoot,rID={1},rBody={2}", |
101 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString); | 101 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString); |
102 | 102 | ||
103 | lock (m_linksetActivityLock) | 103 | lock (m_linksetActivityLock) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 309d004..b6eb619 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -88,7 +88,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
88 | 88 | ||
89 | // We don't have any physical representation yet. | 89 | // We don't have any physical representation yet. |
90 | PhysBody = new BulletBody(localID); | 90 | PhysBody = new BulletBody(localID); |
91 | PhysShape = new BulletShape(); | 91 | PhysShape = new BSShapeNull(); |
92 | 92 | ||
93 | PrimAssetState = PrimAssetCondition.Unknown; | 93 | PrimAssetState = PrimAssetCondition.Unknown; |
94 | 94 | ||
@@ -138,7 +138,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
138 | // Reference to the physical body (btCollisionObject) of this object | 138 | // Reference to the physical body (btCollisionObject) of this object |
139 | public BulletBody PhysBody; | 139 | public BulletBody PhysBody; |
140 | // Reference to the physical shape (btCollisionShape) of this object | 140 | // Reference to the physical shape (btCollisionShape) of this object |
141 | public BulletShape PhysShape; | 141 | public BSShape PhysShape; |
142 | 142 | ||
143 | // The physical representation of the prim might require an asset fetch. | 143 | // The physical representation of the prim might require an asset fetch. |
144 | // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'. | 144 | // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'. |
@@ -151,13 +151,6 @@ public abstract class BSPhysObject : PhysicsActor | |||
151 | // The objects base shape information. Null if not a prim type shape. | 151 | // The objects base shape information. Null if not a prim type shape. |
152 | public PrimitiveBaseShape BaseShape { get; protected set; } | 152 | public PrimitiveBaseShape BaseShape { get; protected set; } |
153 | 153 | ||
154 | // Some types of objects have preferred physical representations. | ||
155 | // Returns SHAPE_UNKNOWN if there is no preference. | ||
156 | public virtual BSPhysicsShapeType PreferredPhysicalShape | ||
157 | { | ||
158 | get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } | ||
159 | } | ||
160 | |||
161 | // When the physical properties are updated, an EntityProperty holds the update values. | 154 | // When the physical properties are updated, an EntityProperty holds the update values. |
162 | // Keep the current and last EntityProperties to enable computation of differences | 155 | // Keep the current and last EntityProperties to enable computation of differences |
163 | // between the current update and the previous values. | 156 | // between the current update and the previous values. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 4bc266b..5d12338 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -134,8 +134,8 @@ public class BSPrim : BSPhysObject | |||
134 | // If there are physical body and shape, release my use of same. | 134 | // If there are physical body and shape, release my use of same. |
135 | PhysicsScene.Shapes.DereferenceBody(PhysBody, null); | 135 | PhysicsScene.Shapes.DereferenceBody(PhysBody, null); |
136 | PhysBody.Clear(); | 136 | PhysBody.Clear(); |
137 | PhysicsScene.Shapes.DereferenceShape(PhysShape, null); | 137 | PhysShape.Dereference(PhysicsScene); |
138 | PhysShape.Clear(); | 138 | PhysShape = new BSShapeNull(); |
139 | }); | 139 | }); |
140 | } | 140 | } |
141 | 141 | ||
@@ -161,25 +161,13 @@ public class BSPrim : BSPhysObject | |||
161 | ForceBodyShapeRebuild(false); | 161 | ForceBodyShapeRebuild(false); |
162 | } | 162 | } |
163 | } | 163 | } |
164 | // 'unknown' says to choose the best type | ||
165 | public override BSPhysicsShapeType PreferredPhysicalShape | ||
166 | { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } } | ||
167 | |||
168 | public override bool ForceBodyShapeRebuild(bool inTaintTime) | 164 | public override bool ForceBodyShapeRebuild(bool inTaintTime) |
169 | { | 165 | { |
170 | if (inTaintTime) | 166 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() |
171 | { | 167 | { |
172 | _mass = CalculateMass(); // changing the shape changes the mass | 168 | _mass = CalculateMass(); // changing the shape changes the mass |
173 | CreateGeomAndObject(true); | 169 | CreateGeomAndObject(true); |
174 | } | 170 | }); |
175 | else | ||
176 | { | ||
177 | PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate() | ||
178 | { | ||
179 | _mass = CalculateMass(); // changing the shape changes the mass | ||
180 | CreateGeomAndObject(true); | ||
181 | }); | ||
182 | } | ||
183 | return true; | 171 | return true; |
184 | } | 172 | } |
185 | public override bool Grabbed { | 173 | public override bool Grabbed { |
@@ -462,7 +450,7 @@ public class BSPrim : BSPhysObject | |||
462 | Gravity = ComputeGravity(Buoyancy); | 450 | Gravity = ComputeGravity(Buoyancy); |
463 | PhysicsScene.PE.SetGravity(PhysBody, Gravity); | 451 | PhysicsScene.PE.SetGravity(PhysBody, Gravity); |
464 | 452 | ||
465 | Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); | 453 | Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass); |
466 | PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); | 454 | PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); |
467 | PhysicsScene.PE.UpdateInertiaTensor(PhysBody); | 455 | PhysicsScene.PE.UpdateInertiaTensor(PhysBody); |
468 | 456 | ||
@@ -805,7 +793,8 @@ public class BSPrim : BSPhysObject | |||
805 | PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); | 793 | PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); |
806 | 794 | ||
807 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", | 795 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", |
808 | LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); | 796 | LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), |
797 | CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); | ||
809 | } | 798 | } |
810 | 799 | ||
811 | // "Making dynamic" means changing to and from static. | 800 | // "Making dynamic" means changing to and from static. |
@@ -1463,12 +1452,13 @@ public class BSPrim : BSPhysObject | |||
1463 | // Create the correct physical representation for this type of object. | 1452 | // Create the correct physical representation for this type of object. |
1464 | // Updates base.PhysBody and base.PhysShape with the new information. | 1453 | // Updates base.PhysBody and base.PhysShape with the new information. |
1465 | // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary. | 1454 | // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary. |
1466 | PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) | 1455 | PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, delegate(BulletBody pBody, BulletShape pShape) |
1467 | { | 1456 | { |
1468 | // Called if the current prim body is about to be destroyed. | 1457 | // Called if the current prim body is about to be destroyed. |
1469 | // Remove all the physical dependencies on the old body. | 1458 | // Remove all the physical dependencies on the old body. |
1470 | // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) | 1459 | // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) |
1471 | RemoveBodyDependencies(); | 1460 | // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints. |
1461 | RemoveDependencies(); | ||
1472 | }); | 1462 | }); |
1473 | 1463 | ||
1474 | // Make sure the properties are set on the new object | 1464 | // Make sure the properties are set on the new object |
@@ -1477,9 +1467,9 @@ public class BSPrim : BSPhysObject | |||
1477 | } | 1467 | } |
1478 | 1468 | ||
1479 | // Called at taint-time | 1469 | // Called at taint-time |
1480 | protected virtual void RemoveBodyDependencies() | 1470 | protected virtual void RemoveDependencies() |
1481 | { | 1471 | { |
1482 | PhysicalActors.RemoveBodyDependencies(); | 1472 | PhysicalActors.RemoveDependencies(); |
1483 | } | 1473 | } |
1484 | 1474 | ||
1485 | // The physics engine says that properties have updated. Update same and inform | 1475 | // The physics engine says that properties have updated. Update same and inform |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs index 28242d4..81104ec 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs | |||
@@ -61,9 +61,6 @@ public class BSPrimLinkable : BSPrimDisplaced | |||
61 | base.Destroy(); | 61 | base.Destroy(); |
62 | } | 62 | } |
63 | 63 | ||
64 | public override BSPhysicsShapeType PreferredPhysicalShape | ||
65 | { get { return Linkset.PreferredPhysicalShape(this); } } | ||
66 | |||
67 | public override void link(Manager.PhysicsActor obj) | 64 | public override void link(Manager.PhysicsActor obj) |
68 | { | 65 | { |
69 | BSPrimLinkable parent = obj as BSPrimLinkable; | 66 | BSPrimLinkable parent = obj as BSPrimLinkable; |
@@ -149,10 +146,10 @@ public class BSPrimLinkable : BSPrimDisplaced | |||
149 | } | 146 | } |
150 | 147 | ||
151 | // Body is being taken apart. Remove physical dependencies and schedule a rebuild. | 148 | // Body is being taken apart. Remove physical dependencies and schedule a rebuild. |
152 | protected override void RemoveBodyDependencies() | 149 | protected override void RemoveDependencies() |
153 | { | 150 | { |
154 | Linkset.RemoveBodyDependencies(this); | 151 | Linkset.RemoveDependencies(this); |
155 | base.RemoveBodyDependencies(); | 152 | base.RemoveDependencies(); |
156 | } | 153 | } |
157 | 154 | ||
158 | public override void UpdateProperties(EntityProperties entprop) | 155 | public override void UpdateProperties(EntityProperties entprop) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 0f9b3c3..3c23509 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |||
@@ -38,38 +38,15 @@ public sealed class BSShapeCollection : IDisposable | |||
38 | { | 38 | { |
39 | private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; | 39 | private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; |
40 | 40 | ||
41 | private BSScene PhysicsScene { get; set; } | 41 | private BSScene m_physicsScene { get; set; } |
42 | 42 | ||
43 | private Object m_collectionActivityLock = new Object(); | 43 | private Object m_collectionActivityLock = new Object(); |
44 | 44 | ||
45 | // Description of a Mesh | ||
46 | private struct MeshDesc | ||
47 | { | ||
48 | public BulletShape shape; | ||
49 | public int referenceCount; | ||
50 | public DateTime lastReferenced; | ||
51 | public UInt64 shapeKey; | ||
52 | } | ||
53 | |||
54 | // Description of a hull. | ||
55 | // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. | ||
56 | private struct HullDesc | ||
57 | { | ||
58 | public BulletShape shape; | ||
59 | public int referenceCount; | ||
60 | public DateTime lastReferenced; | ||
61 | public UInt64 shapeKey; | ||
62 | } | ||
63 | |||
64 | // The sharable set of meshes and hulls. Indexed by their shape hash. | ||
65 | private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>(); | ||
66 | private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>(); | ||
67 | |||
68 | private bool DDetail = false; | 45 | private bool DDetail = false; |
69 | 46 | ||
70 | public BSShapeCollection(BSScene physScene) | 47 | public BSShapeCollection(BSScene physScene) |
71 | { | 48 | { |
72 | PhysicsScene = physScene; | 49 | m_physicsScene = physScene; |
73 | // Set the next to 'true' for very detailed shape update detailed logging (detailed details?) | 50 | // Set the next to 'true' for very detailed shape update detailed logging (detailed details?) |
74 | // While detailed debugging is still active, this is better than commenting out all the | 51 | // While detailed debugging is still active, this is better than commenting out all the |
75 | // DetailLog statements. When debugging slows down, this and the protected logging | 52 | // DetailLog statements. When debugging slows down, this and the protected logging |
@@ -86,22 +63,18 @@ public sealed class BSShapeCollection : IDisposable | |||
86 | // Mostly used for changing bodies out from under Linksets. | 63 | // Mostly used for changing bodies out from under Linksets. |
87 | // Useful for other cases where parameters need saving. | 64 | // Useful for other cases where parameters need saving. |
88 | // Passing 'null' says no callback. | 65 | // Passing 'null' says no callback. |
89 | public delegate void ShapeDestructionCallback(BulletShape shape); | 66 | public delegate void PhysicalDestructionCallback(BulletBody pBody, BulletShape pShape); |
90 | public delegate void BodyDestructionCallback(BulletBody body); | ||
91 | 67 | ||
92 | // Called to update/change the body and shape for an object. | 68 | // Called to update/change the body and shape for an object. |
93 | // First checks the shape and updates that if necessary then makes | 69 | // The object has some shape and body on it. Here we decide if that is the correct shape |
94 | // sure the body is of the right type. | 70 | // for the current state of the object (static/dynamic/...). |
71 | // If bodyCallback is not null, it is called if either the body or the shape are changed | ||
72 | // so dependencies (like constraints) can be removed before the physical object is dereferenced. | ||
95 | // Return 'true' if either the body or the shape changed. | 73 | // Return 'true' if either the body or the shape changed. |
96 | // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before | 74 | // Called at taint-time. |
97 | // the current shape or body is destroyed. This allows the caller to remove any | 75 | public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback) |
98 | // higher level dependencies on the shape or body. Mostly used for LinkSets to | ||
99 | // remove the physical constraints before the body is destroyed. | ||
100 | // Called at taint-time!! | ||
101 | public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, | ||
102 | ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) | ||
103 | { | 76 | { |
104 | PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); | 77 | m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); |
105 | 78 | ||
106 | bool ret = false; | 79 | bool ret = false; |
107 | 80 | ||
@@ -111,12 +84,12 @@ public sealed class BSShapeCollection : IDisposable | |||
111 | // Do we have the correct geometry for this type of object? | 84 | // Do we have the correct geometry for this type of object? |
112 | // Updates prim.BSShape with information/pointers to shape. | 85 | // Updates prim.BSShape with information/pointers to shape. |
113 | // Returns 'true' of BSShape is changed to a new shape. | 86 | // Returns 'true' of BSShape is changed to a new shape. |
114 | bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); | 87 | bool newGeom = CreateGeom(forceRebuild, prim, bodyCallback); |
115 | // If we had to select a new shape geometry for the object, | 88 | // If we had to select a new shape geometry for the object, |
116 | // rebuild the body around it. | 89 | // rebuild the body around it. |
117 | // Updates prim.BSBody with information/pointers to requested body | 90 | // Updates prim.BSBody with information/pointers to requested body |
118 | // Returns 'true' if BSBody was changed. | 91 | // Returns 'true' if BSBody was changed. |
119 | bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback); | 92 | bool newBody = CreateBody((newGeom || forceRebuild), prim, m_physicsScene.World, bodyCallback); |
120 | ret = newGeom || newBody; | 93 | ret = newGeom || newBody; |
121 | } | 94 | } |
122 | DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", | 95 | DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", |
@@ -127,271 +100,20 @@ public sealed class BSShapeCollection : IDisposable | |||
127 | 100 | ||
128 | public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) | 101 | public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) |
129 | { | 102 | { |
130 | return GetBodyAndShape(forceRebuild, sim, prim, null, null); | 103 | return GetBodyAndShape(forceRebuild, sim, prim, null); |
131 | } | ||
132 | |||
133 | // Track another user of a body. | ||
134 | // We presume the caller has allocated the body. | ||
135 | // Bodies only have one user so the body is just put into the world if not already there. | ||
136 | private void ReferenceBody(BulletBody body) | ||
137 | { | ||
138 | lock (m_collectionActivityLock) | ||
139 | { | ||
140 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); | ||
141 | if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) | ||
142 | { | ||
143 | PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body); | ||
144 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | |||
149 | // Release the usage of a body. | ||
150 | // Called when releasing use of a BSBody. BSShape is handled separately. | ||
151 | // Called in taint time. | ||
152 | public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback ) | ||
153 | { | ||
154 | if (!body.HasPhysicalBody) | ||
155 | return; | ||
156 | |||
157 | PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody"); | ||
158 | |||
159 | lock (m_collectionActivityLock) | ||
160 | { | ||
161 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body); | ||
162 | // If the caller needs to know the old body is going away, pass the event up. | ||
163 | if (bodyCallback != null) bodyCallback(body); | ||
164 | |||
165 | // Removing an object not in the world is a NOOP | ||
166 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); | ||
167 | |||
168 | // Zero any reference to the shape so it is not freed when the body is deleted. | ||
169 | PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); | ||
170 | PhysicsScene.PE.DestroyObject(PhysicsScene.World, body); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | // Track the datastructures and use count for a shape. | ||
175 | // When creating a hull, this is called first to reference the mesh | ||
176 | // and then again to reference the hull. | ||
177 | // Meshes and hulls for the same shape have the same hash key. | ||
178 | // NOTE that native shapes are not added to the mesh list or removed. | ||
179 | // Returns 'true' if this is the initial reference to the shape. Otherwise reused. | ||
180 | public bool ReferenceShape(BulletShape shape) | ||
181 | { | ||
182 | bool ret = false; | ||
183 | switch (shape.type) | ||
184 | { | ||
185 | case BSPhysicsShapeType.SHAPE_MESH: | ||
186 | MeshDesc meshDesc; | ||
187 | if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) | ||
188 | { | ||
189 | // There is an existing instance of this mesh. | ||
190 | meshDesc.referenceCount++; | ||
191 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", | ||
192 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | // This is a new reference to a mesh | ||
197 | meshDesc.shape = shape.Clone(); | ||
198 | meshDesc.shapeKey = shape.shapeKey; | ||
199 | // We keep a reference to the underlying IMesh data so a hull can be built | ||
200 | meshDesc.referenceCount = 1; | ||
201 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", | ||
202 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); | ||
203 | ret = true; | ||
204 | } | ||
205 | meshDesc.lastReferenced = System.DateTime.Now; | ||
206 | Meshes[shape.shapeKey] = meshDesc; | ||
207 | break; | ||
208 | case BSPhysicsShapeType.SHAPE_HULL: | ||
209 | HullDesc hullDesc; | ||
210 | if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) | ||
211 | { | ||
212 | // There is an existing instance of this hull. | ||
213 | hullDesc.referenceCount++; | ||
214 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", | ||
215 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); | ||
216 | } | ||
217 | else | ||
218 | { | ||
219 | // This is a new reference to a hull | ||
220 | hullDesc.shape = shape.Clone(); | ||
221 | hullDesc.shapeKey = shape.shapeKey; | ||
222 | hullDesc.referenceCount = 1; | ||
223 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", | ||
224 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); | ||
225 | ret = true; | ||
226 | |||
227 | } | ||
228 | hullDesc.lastReferenced = System.DateTime.Now; | ||
229 | Hulls[shape.shapeKey] = hullDesc; | ||
230 | break; | ||
231 | case BSPhysicsShapeType.SHAPE_UNKNOWN: | ||
232 | break; | ||
233 | default: | ||
234 | // Native shapes are not tracked and they don't go into any list | ||
235 | break; | ||
236 | } | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | // Release the usage of a shape. | ||
241 | public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback) | ||
242 | { | ||
243 | if (!shape.HasPhysicalShape) | ||
244 | return; | ||
245 | |||
246 | PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape"); | ||
247 | |||
248 | if (shape.HasPhysicalShape) | ||
249 | { | ||
250 | if (shape.isNativeShape) | ||
251 | { | ||
252 | // Native shapes are not tracked and are released immediately | ||
253 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}", | ||
254 | BSScene.DetailLogZero, shape.AddrString); | ||
255 | if (shapeCallback != null) shapeCallback(shape); | ||
256 | PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); | ||
257 | } | ||
258 | else | ||
259 | { | ||
260 | switch (shape.type) | ||
261 | { | ||
262 | case BSPhysicsShapeType.SHAPE_HULL: | ||
263 | DereferenceHull(shape, shapeCallback); | ||
264 | break; | ||
265 | case BSPhysicsShapeType.SHAPE_MESH: | ||
266 | DereferenceMesh(shape, shapeCallback); | ||
267 | break; | ||
268 | case BSPhysicsShapeType.SHAPE_COMPOUND: | ||
269 | DereferenceCompound(shape, shapeCallback); | ||
270 | break; | ||
271 | case BSPhysicsShapeType.SHAPE_UNKNOWN: | ||
272 | break; | ||
273 | default: | ||
274 | break; | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | // Count down the reference count for a mesh shape | ||
281 | // Called at taint-time. | ||
282 | private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback) | ||
283 | { | ||
284 | MeshDesc meshDesc; | ||
285 | if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) | ||
286 | { | ||
287 | meshDesc.referenceCount--; | ||
288 | // TODO: release the Bullet storage | ||
289 | if (shapeCallback != null) shapeCallback(shape); | ||
290 | meshDesc.lastReferenced = System.DateTime.Now; | ||
291 | Meshes[shape.shapeKey] = meshDesc; | ||
292 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", | ||
293 | BSScene.DetailLogZero, shape, meshDesc.referenceCount); | ||
294 | |||
295 | } | ||
296 | } | 104 | } |
297 | 105 | ||
298 | // Count down the reference count for a hull shape | 106 | // If the existing prim's shape is to be replaced, remove the tie to the existing shape |
299 | // Called at taint-time. | 107 | // before replacing it. |
300 | private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback) | 108 | private void DereferenceExistingShape(BSPhysObject prim, PhysicalDestructionCallback shapeCallback) |
301 | { | 109 | { |
302 | HullDesc hullDesc; | 110 | if (prim.PhysShape.HasPhysicalShape) |
303 | if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) | ||
304 | { | 111 | { |
305 | hullDesc.referenceCount--; | 112 | if (shapeCallback != null) |
306 | // TODO: release the Bullet storage (aging old entries?) | 113 | shapeCallback(prim.PhysBody, prim.PhysShape.physShapeInfo); |
307 | 114 | prim.PhysShape.Dereference(m_physicsScene); | |
308 | // Tell upper layers that, if they have dependencies on this shape, this link is going away | ||
309 | if (shapeCallback != null) shapeCallback(shape); | ||
310 | |||
311 | hullDesc.lastReferenced = System.DateTime.Now; | ||
312 | Hulls[shape.shapeKey] = hullDesc; | ||
313 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", | ||
314 | BSScene.DetailLogZero, shape, hullDesc.referenceCount); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | // Remove a reference to a compound shape. | ||
319 | // Taking a compound shape apart is a little tricky because if you just delete the | ||
320 | // physical shape, it will free all the underlying children. We can't do that because | ||
321 | // they could be shared. So, this removes each of the children from the compound and | ||
322 | // dereferences them separately before destroying the compound collision object itself. | ||
323 | // Called at taint-time. | ||
324 | private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) | ||
325 | { | ||
326 | if (!PhysicsScene.PE.IsCompound(shape)) | ||
327 | { | ||
328 | // Failed the sanity check!! | ||
329 | PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", | ||
330 | LogHeader, shape.type, shape.AddrString); | ||
331 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", | ||
332 | BSScene.DetailLogZero, shape.type, shape.AddrString); | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape); | ||
337 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); | ||
338 | |||
339 | for (int ii = numChildren - 1; ii >= 0; ii--) | ||
340 | { | ||
341 | BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii); | ||
342 | DereferenceAnonCollisionShape(childShape); | ||
343 | } | ||
344 | PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); | ||
345 | } | ||
346 | |||
347 | // Sometimes we have a pointer to a collision shape but don't know what type it is. | ||
348 | // Figure out type and call the correct dereference routine. | ||
349 | // Called at taint-time. | ||
350 | private void DereferenceAnonCollisionShape(BulletShape shapeInfo) | ||
351 | { | ||
352 | MeshDesc meshDesc; | ||
353 | HullDesc hullDesc; | ||
354 | |||
355 | if (TryGetMeshByPtr(shapeInfo, out meshDesc)) | ||
356 | { | ||
357 | shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH; | ||
358 | shapeInfo.shapeKey = meshDesc.shapeKey; | ||
359 | } | ||
360 | else | ||
361 | { | ||
362 | if (TryGetHullByPtr(shapeInfo, out hullDesc)) | ||
363 | { | ||
364 | shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL; | ||
365 | shapeInfo.shapeKey = hullDesc.shapeKey; | ||
366 | } | ||
367 | else | ||
368 | { | ||
369 | if (PhysicsScene.PE.IsCompound(shapeInfo)) | ||
370 | { | ||
371 | shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND; | ||
372 | } | ||
373 | else | ||
374 | { | ||
375 | if (PhysicsScene.PE.IsNativeShape(shapeInfo)) | ||
376 | { | ||
377 | shapeInfo.isNativeShape = true; | ||
378 | shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | |||
384 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); | ||
385 | |||
386 | if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) | ||
387 | { | ||
388 | DereferenceShape(shapeInfo, null); | ||
389 | } | ||
390 | else | ||
391 | { | ||
392 | PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", | ||
393 | LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString); | ||
394 | } | 115 | } |
116 | prim.PhysShape = new BSShapeNull(); | ||
395 | } | 117 | } |
396 | 118 | ||
397 | // Create the geometry information in Bullet for later use. | 119 | // Create the geometry information in Bullet for later use. |
@@ -402,40 +124,7 @@ public sealed class BSShapeCollection : IDisposable | |||
402 | // Info in prim.BSShape is updated to the new shape. | 124 | // Info in prim.BSShape is updated to the new shape. |
403 | // Returns 'true' if the geometry was rebuilt. | 125 | // Returns 'true' if the geometry was rebuilt. |
404 | // Called at taint-time! | 126 | // Called at taint-time! |
405 | private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | 127 | private bool CreateGeom(bool forceRebuild, BSPhysObject prim, PhysicalDestructionCallback shapeCallback) |
406 | { | ||
407 | bool ret = false; | ||
408 | bool haveShape = false; | ||
409 | |||
410 | if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) | ||
411 | { | ||
412 | // an avatar capsule is close to a native shape (it is not shared) | ||
413 | GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); | ||
414 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); | ||
415 | ret = true; | ||
416 | haveShape = true; | ||
417 | } | ||
418 | |||
419 | // Compound shapes are handled special as they are rebuilt from scratch. | ||
420 | // This isn't too great a hardship since most of the child shapes will have already been created. | ||
421 | if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) | ||
422 | { | ||
423 | ret = GetReferenceToCompoundShape(prim, shapeCallback); | ||
424 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); | ||
425 | haveShape = true; | ||
426 | } | ||
427 | |||
428 | if (!haveShape) | ||
429 | { | ||
430 | ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); | ||
431 | } | ||
432 | |||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | // Create a mesh, hull or native shape. | ||
437 | // Return 'true' if the prim's shape was changed. | ||
438 | public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
439 | { | 128 | { |
440 | bool ret = false; | 129 | bool ret = false; |
441 | bool haveShape = false; | 130 | bool haveShape = false; |
@@ -443,19 +132,21 @@ public sealed class BSShapeCollection : IDisposable | |||
443 | PrimitiveBaseShape pbs = prim.BaseShape; | 132 | PrimitiveBaseShape pbs = prim.BaseShape; |
444 | 133 | ||
445 | // If the prim attributes are simple, this could be a simple Bullet native shape | 134 | // If the prim attributes are simple, this could be a simple Bullet native shape |
135 | // Native shapes work whether to object is static or physical. | ||
446 | if (!haveShape | 136 | if (!haveShape |
447 | && nativeShapePossible | 137 | && nativeShapePossible |
448 | && pbs != null | 138 | && pbs != null |
449 | && !pbs.SculptEntry | 139 | && PrimHasNoCuts(pbs) |
450 | && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) ) | 140 | && ( !pbs.SculptEntry || (pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) ) |
141 | ) | ||
451 | { | 142 | { |
452 | // Get the scale of any existing shape so we can see if the new shape is same native type and same size. | 143 | // Get the scale of any existing shape so we can see if the new shape is same native type and same size. |
453 | OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; | 144 | OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; |
454 | if (prim.PhysShape.HasPhysicalShape) | 145 | if (prim.PhysShape.HasPhysicalShape) |
455 | scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape); | 146 | scaleOfExistingShape = m_physicsScene.PE.GetLocalScaling(prim.PhysShape.physShapeInfo); |
456 | 147 | ||
457 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", | 148 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", |
458 | prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); | 149 | prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.physShapeInfo.shapeType); |
459 | 150 | ||
460 | // It doesn't look like Bullet scales native spheres so make sure the scales are all equal | 151 | // It doesn't look like Bullet scales native spheres so make sure the scales are all equal |
461 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) | 152 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) |
@@ -463,26 +154,28 @@ public sealed class BSShapeCollection : IDisposable | |||
463 | { | 154 | { |
464 | haveShape = true; | 155 | haveShape = true; |
465 | if (forceRebuild | 156 | if (forceRebuild |
466 | || prim.Scale != scaleOfExistingShape | 157 | || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_SPHERE |
467 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE | 158 | ) |
468 | ) | ||
469 | { | 159 | { |
470 | ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, | 160 | DereferenceExistingShape(prim, shapeCallback); |
471 | FixedShapeKey.KEY_SPHERE, shapeCallback); | 161 | prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim, |
162 | BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE); | ||
472 | } | 163 | } |
473 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}", | 164 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}", |
474 | prim.LocalID, forceRebuild, ret, prim.PhysShape); | 165 | prim.LocalID, forceRebuild, ret, prim.PhysShape); |
475 | } | 166 | } |
167 | // If we didn't make a sphere, maybe a box will work. | ||
476 | if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | 168 | if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) |
477 | { | 169 | { |
478 | haveShape = true; | 170 | haveShape = true; |
479 | if (forceRebuild | 171 | if (forceRebuild |
480 | || prim.Scale != scaleOfExistingShape | 172 | || prim.Scale != scaleOfExistingShape |
481 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX | 173 | || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_BOX |
482 | ) | 174 | ) |
483 | { | 175 | { |
484 | ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, | 176 | DereferenceExistingShape(prim, shapeCallback); |
485 | FixedShapeKey.KEY_BOX, shapeCallback); | 177 | prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim, |
178 | BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); | ||
486 | } | 179 | } |
487 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}", | 180 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}", |
488 | prim.LocalID, forceRebuild, ret, prim.PhysShape); | 181 | prim.LocalID, forceRebuild, ret, prim.PhysShape); |
@@ -511,7 +204,7 @@ public sealed class BSShapeCollection : IDisposable | |||
511 | } | 204 | } |
512 | 205 | ||
513 | // return 'true' if the prim's shape was changed. | 206 | // return 'true' if the prim's shape was changed. |
514 | public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | 207 | private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback shapeCallback) |
515 | { | 208 | { |
516 | 209 | ||
517 | bool ret = false; | 210 | bool ret = false; |
@@ -520,537 +213,70 @@ public sealed class BSShapeCollection : IDisposable | |||
520 | if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) | 213 | if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) |
521 | { | 214 | { |
522 | // Update prim.BSShape to reference a hull of this shape. | 215 | // Update prim.BSShape to reference a hull of this shape. |
523 | ret = GetReferenceToHull(prim, shapeCallback); | 216 | DereferenceExistingShape(prim, shapeCallback); |
217 | prim.PhysShape = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim); | ||
524 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", | 218 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", |
525 | prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); | 219 | prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X")); |
526 | } | 220 | } |
527 | else | 221 | else |
528 | { | 222 | { |
529 | ret = GetReferenceToMesh(prim, shapeCallback); | 223 | // Update prim.BSShape to reference a mesh of this shape. |
224 | DereferenceExistingShape(prim, shapeCallback); | ||
225 | prim.PhysShape = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim); | ||
530 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", | 226 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", |
531 | prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); | 227 | prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X")); |
532 | } | 228 | } |
533 | return ret; | 229 | return ret; |
534 | } | 230 | } |
535 | 231 | ||
536 | // Creates a native shape and assignes it to prim.BSShape. | 232 | // Track another user of a body. |
537 | // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). | 233 | // We presume the caller has allocated the body. |
538 | private bool GetReferenceToNativeShape(BSPhysObject prim, | 234 | // Bodies only have one user so the body is just put into the world if not already there. |
539 | BSPhysicsShapeType shapeType, FixedShapeKey shapeKey, | 235 | private void ReferenceBody(BulletBody body) |
540 | ShapeDestructionCallback shapeCallback) | ||
541 | { | ||
542 | // release any previous shape | ||
543 | DereferenceShape(prim.PhysShape, shapeCallback); | ||
544 | |||
545 | BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); | ||
546 | |||
547 | // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. | ||
548 | if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", | ||
549 | prim.LocalID, newShape, prim.Scale); | ||
550 | |||
551 | // native shapes are scaled by Bullet | ||
552 | prim.PhysShape = newShape; | ||
553 | return true; | ||
554 | } | ||
555 | |||
556 | private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType, | ||
557 | FixedShapeKey shapeKey) | ||
558 | { | ||
559 | BulletShape newShape; | ||
560 | // Need to make sure the passed shape information is for the native type. | ||
561 | ShapeData nativeShapeData = new ShapeData(); | ||
562 | nativeShapeData.Type = shapeType; | ||
563 | nativeShapeData.ID = prim.LocalID; | ||
564 | nativeShapeData.Scale = prim.Scale; | ||
565 | nativeShapeData.Size = prim.Scale; // unneeded, I think. | ||
566 | nativeShapeData.MeshKey = (ulong)shapeKey; | ||
567 | nativeShapeData.HullKey = (ulong)shapeKey; | ||
568 | |||
569 | if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) | ||
570 | { | ||
571 | |||
572 | newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); | ||
573 | if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); | ||
574 | } | ||
575 | else | ||
576 | { | ||
577 | // Native shapes are scaled in Bullet so set the scaling to the size | ||
578 | newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData); | ||
579 | |||
580 | } | ||
581 | if (!newShape.HasPhysicalShape) | ||
582 | { | ||
583 | PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", | ||
584 | LogHeader, prim.LocalID, shapeType); | ||
585 | } | ||
586 | newShape.shapeKey = (System.UInt64)shapeKey; | ||
587 | newShape.isNativeShape = true; | ||
588 | |||
589 | return newShape; | ||
590 | } | ||
591 | |||
592 | // Builds a mesh shape in the physical world and updates prim.BSShape. | ||
593 | // Dereferences previous shape in BSShape and adds a reference for this new shape. | ||
594 | // Returns 'true' of a mesh was actually built. Otherwise . | ||
595 | // Called at taint-time! | ||
596 | private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
597 | { | ||
598 | BulletShape newShape = new BulletShape(); | ||
599 | |||
600 | float lod; | ||
601 | System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | ||
602 | |||
603 | // if this new shape is the same as last time, don't recreate the mesh | ||
604 | if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) | ||
605 | return false; | ||
606 | |||
607 | if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2},size={3},lod={4}", | ||
608 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod); | ||
609 | |||
610 | // Since we're recreating new, get rid of the reference to the previous shape | ||
611 | DereferenceShape(prim.PhysShape, shapeCallback); | ||
612 | |||
613 | newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod); | ||
614 | // Take evasive action if the mesh was not constructed. | ||
615 | newShape = VerifyMeshCreated(PhysicsScene, newShape, prim); | ||
616 | |||
617 | ReferenceShape(newShape); | ||
618 | |||
619 | prim.PhysShape = newShape; | ||
620 | |||
621 | return true; // 'true' means a new shape has been added to this prim | ||
622 | } | ||
623 | |||
624 | private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) | ||
625 | { | 236 | { |
626 | BulletShape newShape = new BulletShape(); | 237 | lock (m_collectionActivityLock) |
627 | |||
628 | MeshDesc meshDesc; | ||
629 | if (Meshes.TryGetValue(newMeshKey, out meshDesc)) | ||
630 | { | ||
631 | // If the mesh has already been built just use it. | ||
632 | newShape = meshDesc.shape.Clone(); | ||
633 | } | ||
634 | else | ||
635 | { | 238 | { |
636 | IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, | 239 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); |
637 | false, // say it is not physical so a bounding box is not built | 240 | if (!m_physicsScene.PE.IsInWorld(m_physicsScene.World, body)) |
638 | false // do not cache the mesh and do not use previously built versions | ||
639 | ); | ||
640 | |||
641 | if (meshData != null) | ||
642 | { | 241 | { |
643 | 242 | m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, body); | |
644 | int[] indices = meshData.getIndexListAsInt(); | 243 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); |
645 | int realIndicesIndex = indices.Length; | ||
646 | float[] verticesAsFloats = meshData.getVertexListAsFloat(); | ||
647 | |||
648 | if (BSParam.ShouldRemoveZeroWidthTriangles) | ||
649 | { | ||
650 | // Remove degenerate triangles. These are triangles with two of the vertices | ||
651 | // are the same. This is complicated by the problem that vertices are not | ||
652 | // made unique in sculpties so we have to compare the values in the vertex. | ||
653 | realIndicesIndex = 0; | ||
654 | for (int tri = 0; tri < indices.Length; tri += 3) | ||
655 | { | ||
656 | // Compute displacements into vertex array for each vertex of the triangle | ||
657 | int v1 = indices[tri + 0] * 3; | ||
658 | int v2 = indices[tri + 1] * 3; | ||
659 | int v3 = indices[tri + 2] * 3; | ||
660 | // Check to see if any two of the vertices are the same | ||
661 | if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0] | ||
662 | && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1] | ||
663 | && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2]) | ||
664 | || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0] | ||
665 | && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1] | ||
666 | && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2]) | ||
667 | || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0] | ||
668 | && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1] | ||
669 | && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) ) | ||
670 | ) | ||
671 | { | ||
672 | // None of the vertices of the triangles are the same. This is a good triangle; | ||
673 | indices[realIndicesIndex + 0] = indices[tri + 0]; | ||
674 | indices[realIndicesIndex + 1] = indices[tri + 1]; | ||
675 | indices[realIndicesIndex + 2] = indices[tri + 2]; | ||
676 | realIndicesIndex += 3; | ||
677 | } | ||
678 | } | ||
679 | } | ||
680 | DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}", | ||
681 | BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3); | ||
682 | |||
683 | if (realIndicesIndex != 0) | ||
684 | { | ||
685 | newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, | ||
686 | realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats); | ||
687 | } | ||
688 | else | ||
689 | { | ||
690 | PhysicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}", | ||
691 | LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name); | ||
692 | } | ||
693 | } | 244 | } |
694 | } | 245 | } |
695 | newShape.shapeKey = newMeshKey; | ||
696 | |||
697 | return newShape; | ||
698 | } | ||
699 | |||
700 | // See that hull shape exists in the physical world and update prim.BSShape. | ||
701 | // We could be creating the hull because scale changed or whatever. | ||
702 | // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance. | ||
703 | private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
704 | { | ||
705 | BulletShape newShape; | ||
706 | |||
707 | float lod; | ||
708 | System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | ||
709 | |||
710 | // if the hull hasn't changed, don't rebuild it | ||
711 | if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) | ||
712 | return false; | ||
713 | |||
714 | if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", | ||
715 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); | ||
716 | |||
717 | // Remove usage of the previous shape. | ||
718 | DereferenceShape(prim.PhysShape, shapeCallback); | ||
719 | |||
720 | newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod); | ||
721 | // It might not have been created if we're waiting for an asset. | ||
722 | newShape = VerifyMeshCreated(PhysicsScene, newShape, prim); | ||
723 | |||
724 | ReferenceShape(newShape); | ||
725 | |||
726 | prim.PhysShape = newShape; | ||
727 | return true; // 'true' means a new shape has been added to this prim | ||
728 | } | 246 | } |
729 | 247 | ||
730 | List<ConvexResult> m_hulls; | 248 | // Release the usage of a body. |
731 | private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) | 249 | // Called when releasing use of a BSBody. BSShape is handled separately. |
250 | // Called in taint time. | ||
251 | public void DereferenceBody(BulletBody body, PhysicalDestructionCallback bodyCallback ) | ||
732 | { | 252 | { |
253 | if (!body.HasPhysicalBody) | ||
254 | return; | ||
733 | 255 | ||
734 | BulletShape newShape = new BulletShape(); | 256 | m_physicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody"); |
735 | IntPtr hullPtr = IntPtr.Zero; | ||
736 | 257 | ||
737 | HullDesc hullDesc; | 258 | lock (m_collectionActivityLock) |
738 | if (Hulls.TryGetValue(newHullKey, out hullDesc)) | ||
739 | { | ||
740 | // If the hull shape already has been created, just use the one shared instance. | ||
741 | newShape = hullDesc.shape.Clone(); | ||
742 | } | ||
743 | else | ||
744 | { | 259 | { |
745 | if (BSParam.ShouldUseBulletHACD) | 260 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body); |
746 | { | 261 | // If the caller needs to know the old body is going away, pass the event up. |
747 | DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID); | 262 | if (bodyCallback != null) |
748 | MeshDesc meshDesc; | 263 | bodyCallback(body, null); |
749 | if (!Meshes.TryGetValue(newHullKey, out meshDesc)) | ||
750 | { | ||
751 | // That's odd because the mesh should have been created before the hull | ||
752 | // but, since it doesn't exist, create it. | ||
753 | newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod); | ||
754 | DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); | ||
755 | |||
756 | if (newShape.HasPhysicalShape) | ||
757 | { | ||
758 | ReferenceShape(newShape); | ||
759 | Meshes.TryGetValue(newHullKey, out meshDesc); | ||
760 | } | ||
761 | } | ||
762 | if (meshDesc.shape.HasPhysicalShape) | ||
763 | { | ||
764 | HACDParams parms; | ||
765 | parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull; | ||
766 | parms.minClusters = BSParam.BHullMinClusters; | ||
767 | parms.compacityWeight = BSParam.BHullCompacityWeight; | ||
768 | parms.volumeWeight = BSParam.BHullVolumeWeight; | ||
769 | parms.concavity = BSParam.BHullConcavity; | ||
770 | parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints); | ||
771 | parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints); | ||
772 | parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints); | ||
773 | parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin); | ||
774 | |||
775 | DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape); | ||
776 | newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms); | ||
777 | DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); | ||
778 | } | ||
779 | DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); | ||
780 | } | ||
781 | if (!newShape.HasPhysicalShape) | ||
782 | { | ||
783 | // Build a new hull in the physical world. | ||
784 | // Pass true for physicalness as this prevents the creation of bounding box which is not needed | ||
785 | IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */); | ||
786 | if (meshData != null) | ||
787 | { | ||
788 | int[] indices = meshData.getIndexListAsInt(); | ||
789 | List<OMV.Vector3> vertices = meshData.getVertexList(); | ||
790 | |||
791 | //format conversion from IMesh format to DecompDesc format | ||
792 | List<int> convIndices = new List<int>(); | ||
793 | List<float3> convVertices = new List<float3>(); | ||
794 | for (int ii = 0; ii < indices.GetLength(0); ii++) | ||
795 | { | ||
796 | convIndices.Add(indices[ii]); | ||
797 | } | ||
798 | foreach (OMV.Vector3 vv in vertices) | ||
799 | { | ||
800 | convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); | ||
801 | } | ||
802 | |||
803 | uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit; | ||
804 | if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes) | ||
805 | { | ||
806 | // Simple primitive shapes we know are convex so they are better implemented with | ||
807 | // fewer hulls. | ||
808 | // Check for simple shape (prim without cuts) and reduce split parameter if so. | ||
809 | if (PrimHasNoCuts(pbs)) | ||
810 | { | ||
811 | maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes; | ||
812 | } | ||
813 | } | ||
814 | |||
815 | // setup and do convex hull conversion | ||
816 | m_hulls = new List<ConvexResult>(); | ||
817 | DecompDesc dcomp = new DecompDesc(); | ||
818 | dcomp.mIndices = convIndices; | ||
819 | dcomp.mVertices = convVertices; | ||
820 | dcomp.mDepth = maxDepthSplit; | ||
821 | dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent; | ||
822 | dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent; | ||
823 | dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices; | ||
824 | dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth; | ||
825 | ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); | ||
826 | // create the hull into the _hulls variable | ||
827 | convexBuilder.process(dcomp); | ||
828 | |||
829 | DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}", | ||
830 | BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count); | ||
831 | |||
832 | // Convert the vertices and indices for passing to unmanaged. | ||
833 | // The hull information is passed as a large floating point array. | ||
834 | // The format is: | ||
835 | // convHulls[0] = number of hulls | ||
836 | // convHulls[1] = number of vertices in first hull | ||
837 | // convHulls[2] = hull centroid X coordinate | ||
838 | // convHulls[3] = hull centroid Y coordinate | ||
839 | // convHulls[4] = hull centroid Z coordinate | ||
840 | // convHulls[5] = first hull vertex X | ||
841 | // convHulls[6] = first hull vertex Y | ||
842 | // convHulls[7] = first hull vertex Z | ||
843 | // convHulls[8] = second hull vertex X | ||
844 | // ... | ||
845 | // convHulls[n] = number of vertices in second hull | ||
846 | // convHulls[n+1] = second hull centroid X coordinate | ||
847 | // ... | ||
848 | // | ||
849 | // TODO: is is very inefficient. Someday change the convex hull generator to return | ||
850 | // data structures that do not need to be converted in order to pass to Bullet. | ||
851 | // And maybe put the values directly into pinned memory rather than marshaling. | ||
852 | int hullCount = m_hulls.Count; | ||
853 | int totalVertices = 1; // include one for the count of the hulls | ||
854 | foreach (ConvexResult cr in m_hulls) | ||
855 | { | ||
856 | totalVertices += 4; // add four for the vertex count and centroid | ||
857 | totalVertices += cr.HullIndices.Count * 3; // we pass just triangles | ||
858 | } | ||
859 | float[] convHulls = new float[totalVertices]; | ||
860 | |||
861 | convHulls[0] = (float)hullCount; | ||
862 | int jj = 1; | ||
863 | foreach (ConvexResult cr in m_hulls) | ||
864 | { | ||
865 | // copy vertices for index access | ||
866 | float3[] verts = new float3[cr.HullVertices.Count]; | ||
867 | int kk = 0; | ||
868 | foreach (float3 ff in cr.HullVertices) | ||
869 | { | ||
870 | verts[kk++] = ff; | ||
871 | } | ||
872 | |||
873 | // add to the array one hull's worth of data | ||
874 | convHulls[jj++] = cr.HullIndices.Count; | ||
875 | convHulls[jj++] = 0f; // centroid x,y,z | ||
876 | convHulls[jj++] = 0f; | ||
877 | convHulls[jj++] = 0f; | ||
878 | foreach (int ind in cr.HullIndices) | ||
879 | { | ||
880 | convHulls[jj++] = verts[ind].x; | ||
881 | convHulls[jj++] = verts[ind].y; | ||
882 | convHulls[jj++] = verts[ind].z; | ||
883 | } | ||
884 | } | ||
885 | // create the hull data structure in Bullet | ||
886 | newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls); | ||
887 | } | ||
888 | } | ||
889 | newShape.shapeKey = newHullKey; | ||
890 | } | ||
891 | |||
892 | return newShape; | ||
893 | } | ||
894 | |||
895 | // Callback from convex hull creater with a newly created hull. | ||
896 | // Just add it to our collection of hulls for this shape. | ||
897 | private void HullReturn(ConvexResult result) | ||
898 | { | ||
899 | m_hulls.Add(result); | ||
900 | return; | ||
901 | } | ||
902 | |||
903 | // Compound shapes are always built from scratch. | ||
904 | // This shouldn't be to bad since most of the parts will be meshes that had been built previously. | ||
905 | private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
906 | { | ||
907 | // Remove reference to the old shape | ||
908 | // Don't need to do this as the shape is freed when the new root shape is created below. | ||
909 | // DereferenceShape(prim.PhysShape, true, shapeCallback); | ||
910 | |||
911 | BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false); | ||
912 | |||
913 | // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. | ||
914 | CreateGeomMeshOrHull(prim, shapeCallback); | ||
915 | PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity); | ||
916 | if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", | ||
917 | prim.LocalID, cShape, prim.PhysShape); | ||
918 | |||
919 | prim.PhysShape = cShape; | ||
920 | |||
921 | return true; | ||
922 | } | ||
923 | |||
924 | // Create a hash of all the shape parameters to be used as a key | ||
925 | // for this particular shape. | ||
926 | public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | ||
927 | { | ||
928 | // level of detail based on size and type of the object | ||
929 | float lod = BSParam.MeshLOD; | ||
930 | |||
931 | // prims with curvy internal cuts need higher lod | ||
932 | if (pbs.HollowShape == HollowShape.Circle) | ||
933 | lod = BSParam.MeshCircularLOD; | ||
934 | |||
935 | if (pbs.SculptEntry) | ||
936 | lod = BSParam.SculptLOD; | ||
937 | |||
938 | // Mega prims usually get more detail because one can interact with shape approximations at this size. | ||
939 | float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); | ||
940 | if (maxAxis > BSParam.MeshMegaPrimThreshold) | ||
941 | lod = BSParam.MeshMegaPrimLOD; | ||
942 | |||
943 | retLod = lod; | ||
944 | return pbs.GetMeshKey(size, lod); | ||
945 | } | ||
946 | // For those who don't want the LOD | ||
947 | public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) | ||
948 | { | ||
949 | float lod; | ||
950 | return ComputeShapeKey(size, pbs, out lod); | ||
951 | } | ||
952 | |||
953 | // The creation of a mesh or hull can fail if an underlying asset is not available. | ||
954 | // There are two cases: 1) the asset is not in the cache and it needs to be fetched; | ||
955 | // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). | ||
956 | // The first case causes the asset to be fetched. The second case requires | ||
957 | // us to not loop forever. | ||
958 | // Called after creating a physical mesh or hull. If the physical shape was created, | ||
959 | // just return. | ||
960 | public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim) | ||
961 | { | ||
962 | // If the shape was successfully created, nothing more to do | ||
963 | if (newShape.HasPhysicalShape) | ||
964 | return newShape; | ||
965 | 264 | ||
966 | // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been | 265 | // Removing an object not in the world is a NOOP |
967 | // fetched but we end up here again, the meshing of the asset must have failed. | 266 | m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, body); |
968 | // Prevent trying to keep fetching the mesh by declaring failure. | ||
969 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) | ||
970 | { | ||
971 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
972 | physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}", | ||
973 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | ||
974 | } | ||
975 | else | ||
976 | { | ||
977 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset | ||
978 | if (prim.BaseShape.SculptEntry | ||
979 | && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed | ||
980 | && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting | ||
981 | && prim.BaseShape.SculptTexture != OMV.UUID.Zero | ||
982 | ) | ||
983 | { | ||
984 | physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); | ||
985 | // Multiple requestors will know we're waiting for this asset | ||
986 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; | ||
987 | 267 | ||
988 | BSPhysObject xprim = prim; | 268 | // Zero any reference to the shape so it is not freed when the body is deleted. |
989 | Util.FireAndForget(delegate | 269 | m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, body, null); |
990 | { | ||
991 | RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod; | ||
992 | if (assetProvider != null) | ||
993 | { | ||
994 | BSPhysObject yprim = xprim; // probably not necessary, but, just in case. | ||
995 | assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) | ||
996 | { | ||
997 | bool assetFound = false; | ||
998 | string mismatchIDs = String.Empty; // DEBUG DEBUG | ||
999 | if (asset != null && yprim.BaseShape.SculptEntry) | ||
1000 | { | ||
1001 | if (yprim.BaseShape.SculptTexture.ToString() == asset.ID) | ||
1002 | { | ||
1003 | yprim.BaseShape.SculptData = asset.Data; | ||
1004 | // This will cause the prim to see that the filler shape is not the right | ||
1005 | // one and try again to build the object. | ||
1006 | // No race condition with the normal shape setting since the rebuild is at taint time. | ||
1007 | yprim.ForceBodyShapeRebuild(false /* inTaintTime */); | ||
1008 | assetFound = true; | ||
1009 | } | ||
1010 | else | ||
1011 | { | ||
1012 | mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; | ||
1013 | } | ||
1014 | } | ||
1015 | if (assetFound) | ||
1016 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; | ||
1017 | else | ||
1018 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
1019 | physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", | ||
1020 | yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); | ||
1021 | 270 | ||
1022 | }); | 271 | m_physicsScene.PE.DestroyObject(m_physicsScene.World, body); |
1023 | } | ||
1024 | else | ||
1025 | { | ||
1026 | xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
1027 | physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", | ||
1028 | LogHeader, physicsScene.Name); | ||
1029 | } | ||
1030 | }); | ||
1031 | } | ||
1032 | else | ||
1033 | { | ||
1034 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) | ||
1035 | { | ||
1036 | physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}", | ||
1037 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | ||
1038 | } | ||
1039 | } | ||
1040 | } | 272 | } |
1041 | |||
1042 | // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. | ||
1043 | BulletShape fillinShape = physicsScene.Shapes.BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); | ||
1044 | physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID); | ||
1045 | |||
1046 | return fillinShape; | ||
1047 | } | 273 | } |
1048 | 274 | ||
1049 | // Create a body object in Bullet. | 275 | // Create a body object in Bullet. |
1050 | // Updates prim.BSBody with the information about the new body if one is created. | 276 | // Updates prim.BSBody with the information about the new body if one is created. |
1051 | // Returns 'true' if an object was actually created. | 277 | // Returns 'true' if an object was actually created. |
1052 | // Called at taint-time. | 278 | // Called at taint-time. |
1053 | private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback) | 279 | private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, PhysicalDestructionCallback bodyCallback) |
1054 | { | 280 | { |
1055 | bool ret = false; | 281 | bool ret = false; |
1056 | 282 | ||
@@ -1061,7 +287,7 @@ public sealed class BSShapeCollection : IDisposable | |||
1061 | // If not a solid object, body is a GhostObject. Otherwise a RigidBody. | 287 | // If not a solid object, body is a GhostObject. Otherwise a RigidBody. |
1062 | if (!mustRebuild) | 288 | if (!mustRebuild) |
1063 | { | 289 | { |
1064 | CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody); | 290 | CollisionObjectTypes bodyType = (CollisionObjectTypes)m_physicsScene.PE.GetBodyType(prim.PhysBody); |
1065 | if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY | 291 | if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY |
1066 | || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) | 292 | || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) |
1067 | { | 293 | { |
@@ -1079,12 +305,12 @@ public sealed class BSShapeCollection : IDisposable | |||
1079 | BulletBody aBody; | 305 | BulletBody aBody; |
1080 | if (prim.IsSolid) | 306 | if (prim.IsSolid) |
1081 | { | 307 | { |
1082 | aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); | 308 | aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation); |
1083 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); | 309 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); |
1084 | } | 310 | } |
1085 | else | 311 | else |
1086 | { | 312 | { |
1087 | aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); | 313 | aBody = m_physicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation); |
1088 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); | 314 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); |
1089 | } | 315 | } |
1090 | 316 | ||
@@ -1098,46 +324,10 @@ public sealed class BSShapeCollection : IDisposable | |||
1098 | return ret; | 324 | return ret; |
1099 | } | 325 | } |
1100 | 326 | ||
1101 | private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc) | ||
1102 | { | ||
1103 | bool ret = false; | ||
1104 | MeshDesc foundDesc = new MeshDesc(); | ||
1105 | foreach (MeshDesc md in Meshes.Values) | ||
1106 | { | ||
1107 | if (md.shape.ReferenceSame(shape)) | ||
1108 | { | ||
1109 | foundDesc = md; | ||
1110 | ret = true; | ||
1111 | break; | ||
1112 | } | ||
1113 | |||
1114 | } | ||
1115 | outDesc = foundDesc; | ||
1116 | return ret; | ||
1117 | } | ||
1118 | |||
1119 | private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc) | ||
1120 | { | ||
1121 | bool ret = false; | ||
1122 | HullDesc foundDesc = new HullDesc(); | ||
1123 | foreach (HullDesc hd in Hulls.Values) | ||
1124 | { | ||
1125 | if (hd.shape.ReferenceSame(shape)) | ||
1126 | { | ||
1127 | foundDesc = hd; | ||
1128 | ret = true; | ||
1129 | break; | ||
1130 | } | ||
1131 | |||
1132 | } | ||
1133 | outDesc = foundDesc; | ||
1134 | return ret; | ||
1135 | } | ||
1136 | |||
1137 | private void DetailLog(string msg, params Object[] args) | 327 | private void DetailLog(string msg, params Object[] args) |
1138 | { | 328 | { |
1139 | if (PhysicsScene.PhysicsLogging.Enabled) | 329 | if (m_physicsScene.PhysicsLogging.Enabled) |
1140 | PhysicsScene.DetailLog(msg, args); | 330 | m_physicsScene.DetailLog(msg, args); |
1141 | } | 331 | } |
1142 | } | 332 | } |
1143 | } | 333 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index e427dbc..a7b3f02 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | |||
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
39 | { | 39 | { |
40 | public abstract class BSShape | 40 | public abstract class BSShape |
41 | { | 41 | { |
42 | private static string LogHeader = "[BULLETSIM SHAPE]"; | ||
43 | |||
42 | public int referenceCount { get; set; } | 44 | public int referenceCount { get; set; } |
43 | public DateTime lastReferenced { get; set; } | 45 | public DateTime lastReferenced { get; set; } |
44 | public BulletShape physShapeInfo { get; set; } | 46 | public BulletShape physShapeInfo { get; set; } |
@@ -56,49 +58,6 @@ public abstract class BSShape | |||
56 | physShapeInfo = pShape; | 58 | physShapeInfo = pShape; |
57 | } | 59 | } |
58 | 60 | ||
59 | // Get a reference to a physical shape. Create if it doesn't exist | ||
60 | public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) | ||
61 | { | ||
62 | BSShape ret = null; | ||
63 | |||
64 | if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) | ||
65 | { | ||
66 | // an avatar capsule is close to a native shape (it is not shared) | ||
67 | ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE, | ||
68 | FixedShapeKey.KEY_CAPSULE); | ||
69 | physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); | ||
70 | } | ||
71 | |||
72 | // Compound shapes are handled special as they are rebuilt from scratch. | ||
73 | // This isn't too great a hardship since most of the child shapes will have already been created. | ||
74 | if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) | ||
75 | { | ||
76 | // Getting a reference to a compound shape gets you the compound shape with the root prim shape added | ||
77 | ret = BSShapeCompound.GetReference(physicsScene, prim); | ||
78 | physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); | ||
79 | } | ||
80 | |||
81 | // Avatars have their own unique shape | ||
82 | if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR) | ||
83 | { | ||
84 | // Getting a reference to a compound shape gets you the compound shape with the root prim shape added | ||
85 | ret = BSShapeAvatar.GetReference(prim); | ||
86 | physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret); | ||
87 | } | ||
88 | |||
89 | if (ret == null) | ||
90 | ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); | ||
91 | |||
92 | return ret; | ||
93 | } | ||
94 | private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) | ||
95 | { | ||
96 | // TODO: work needed here!! | ||
97 | BSShapeMesh.GetReference(physicsScene, forceRebuild, prim); | ||
98 | BSShapeHull.GetReference(physicsScene, forceRebuild, prim); | ||
99 | return null; | ||
100 | } | ||
101 | |||
102 | // Called when this shape is being used again. | 61 | // Called when this shape is being used again. |
103 | public virtual void IncrementReference() | 62 | public virtual void IncrementReference() |
104 | { | 63 | { |
@@ -116,6 +75,27 @@ public abstract class BSShape | |||
116 | // Release the use of a physical shape. | 75 | // Release the use of a physical shape. |
117 | public abstract void Dereference(BSScene physicsScene); | 76 | public abstract void Dereference(BSScene physicsScene); |
118 | 77 | ||
78 | // Return 'true' if there is an allocated physics physical shape under this class instance. | ||
79 | public virtual bool HasPhysicalShape | ||
80 | { | ||
81 | get | ||
82 | { | ||
83 | if (physShapeInfo != null) | ||
84 | return physShapeInfo.HasPhysicalShape; | ||
85 | return false; | ||
86 | } | ||
87 | } | ||
88 | public virtual BSPhysicsShapeType ShapeType | ||
89 | { | ||
90 | get | ||
91 | { | ||
92 | BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; | ||
93 | if (physShapeInfo != null && physShapeInfo.HasPhysicalShape) | ||
94 | ret = physShapeInfo.shapeType; | ||
95 | return ret; | ||
96 | } | ||
97 | } | ||
98 | |||
119 | // Returns a string for debugging that uniquily identifies the memory used by this instance | 99 | // Returns a string for debugging that uniquily identifies the memory used by this instance |
120 | public virtual string AddrString | 100 | public virtual string AddrString |
121 | { | 101 | { |
@@ -132,6 +112,119 @@ public abstract class BSShape | |||
132 | buff.Append(">"); | 112 | buff.Append(">"); |
133 | return buff.ToString(); | 113 | return buff.ToString(); |
134 | } | 114 | } |
115 | |||
116 | // Create a hash of all the shape parameters to be used as a key for this particular shape. | ||
117 | public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | ||
118 | { | ||
119 | // level of detail based on size and type of the object | ||
120 | float lod = BSParam.MeshLOD; | ||
121 | if (pbs.SculptEntry) | ||
122 | lod = BSParam.SculptLOD; | ||
123 | |||
124 | // Mega prims usually get more detail because one can interact with shape approximations at this size. | ||
125 | float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); | ||
126 | if (maxAxis > BSParam.MeshMegaPrimThreshold) | ||
127 | lod = BSParam.MeshMegaPrimLOD; | ||
128 | |||
129 | retLod = lod; | ||
130 | return pbs.GetMeshKey(size, lod); | ||
131 | } | ||
132 | |||
133 | // The creation of a mesh or hull can fail if an underlying asset is not available. | ||
134 | // There are two cases: 1) the asset is not in the cache and it needs to be fetched; | ||
135 | // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). | ||
136 | // The first case causes the asset to be fetched. The second case requires | ||
137 | // us to not loop forever. | ||
138 | // Called after creating a physical mesh or hull. If the physical shape was created, | ||
139 | // just return. | ||
140 | public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim) | ||
141 | { | ||
142 | // If the shape was successfully created, nothing more to do | ||
143 | if (newShape.HasPhysicalShape) | ||
144 | return newShape; | ||
145 | |||
146 | // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been | ||
147 | // fetched but we end up here again, the meshing of the asset must have failed. | ||
148 | // Prevent trying to keep fetching the mesh by declaring failure. | ||
149 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) | ||
150 | { | ||
151 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
152 | physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}", | ||
153 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset | ||
158 | if (prim.BaseShape.SculptEntry | ||
159 | && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed | ||
160 | && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting | ||
161 | && prim.BaseShape.SculptTexture != OMV.UUID.Zero | ||
162 | ) | ||
163 | { | ||
164 | physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); | ||
165 | // Multiple requestors will know we're waiting for this asset | ||
166 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; | ||
167 | |||
168 | BSPhysObject xprim = prim; | ||
169 | Util.FireAndForget(delegate | ||
170 | { | ||
171 | RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod; | ||
172 | if (assetProvider != null) | ||
173 | { | ||
174 | BSPhysObject yprim = xprim; // probably not necessary, but, just in case. | ||
175 | assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) | ||
176 | { | ||
177 | bool assetFound = false; | ||
178 | string mismatchIDs = String.Empty; // DEBUG DEBUG | ||
179 | if (asset != null && yprim.BaseShape.SculptEntry) | ||
180 | { | ||
181 | if (yprim.BaseShape.SculptTexture.ToString() == asset.ID) | ||
182 | { | ||
183 | yprim.BaseShape.SculptData = asset.Data; | ||
184 | // This will cause the prim to see that the filler shape is not the right | ||
185 | // one and try again to build the object. | ||
186 | // No race condition with the normal shape setting since the rebuild is at taint time. | ||
187 | yprim.ForceBodyShapeRebuild(false /* inTaintTime */); | ||
188 | assetFound = true; | ||
189 | } | ||
190 | else | ||
191 | { | ||
192 | mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; | ||
193 | } | ||
194 | } | ||
195 | if (assetFound) | ||
196 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; | ||
197 | else | ||
198 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
199 | physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", | ||
200 | yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); | ||
201 | }); | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
206 | physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", | ||
207 | LogHeader, physicsScene.Name); | ||
208 | } | ||
209 | }); | ||
210 | } | ||
211 | else | ||
212 | { | ||
213 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) | ||
214 | { | ||
215 | physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}", | ||
216 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | |||
221 | // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. | ||
222 | BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); | ||
223 | physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID); | ||
224 | |||
225 | return fillShape.physShapeInfo; | ||
226 | } | ||
227 | |||
135 | } | 228 | } |
136 | 229 | ||
137 | // ============================================================================================================ | 230 | // ============================================================================================================ |
@@ -199,7 +292,7 @@ public class BSShapeNative : BSShape | |||
199 | physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", | 292 | physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", |
200 | LogHeader, prim.LocalID, shapeType); | 293 | LogHeader, prim.LocalID, shapeType); |
201 | } | 294 | } |
202 | newShape.type = shapeType; | 295 | newShape.shapeType = shapeType; |
203 | newShape.isNativeShape = true; | 296 | newShape.isNativeShape = true; |
204 | newShape.shapeKey = (UInt64)shapeKey; | 297 | newShape.shapeKey = (UInt64)shapeKey; |
205 | return newShape; | 298 | return newShape; |
@@ -219,10 +312,11 @@ public class BSShapeMesh : BSShape | |||
219 | public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) | 312 | public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) |
220 | { | 313 | { |
221 | float lod; | 314 | float lod; |
222 | System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | 315 | System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); |
223 | 316 | ||
224 | physicsScene.DetailLog("{0},BSShapeMesh,getReference,oldKey={1},newKey={2},size={3},lod={4}", | 317 | physicsScene.DetailLog("{0},BSShapeMesh,getReference,oldKey={1},newKey={2},size={3},lod={4}", |
225 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod); | 318 | prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), |
319 | newMeshKey.ToString("X"), prim.Size, lod); | ||
226 | 320 | ||
227 | BSShapeMesh retMesh = new BSShapeMesh(new BulletShape()); | 321 | BSShapeMesh retMesh = new BSShapeMesh(new BulletShape()); |
228 | lock (Meshes) | 322 | lock (Meshes) |
@@ -238,8 +332,8 @@ public class BSShapeMesh : BSShape | |||
238 | BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); | 332 | BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); |
239 | 333 | ||
240 | // Check to see if mesh was created (might require an asset). | 334 | // Check to see if mesh was created (might require an asset). |
241 | newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim); | 335 | newShape = VerifyMeshCreated(physicsScene, newShape, prim); |
242 | if (newShape.type == BSPhysicsShapeType.SHAPE_MESH) | 336 | if (newShape.shapeType == BSPhysicsShapeType.SHAPE_MESH) |
243 | { | 337 | { |
244 | // If a mesh was what was created, remember the built shape for later sharing. | 338 | // If a mesh was what was created, remember the built shape for later sharing. |
245 | Meshes.Add(newMeshKey, retMesh); | 339 | Meshes.Add(newMeshKey, retMesh); |
@@ -360,10 +454,10 @@ public class BSShapeHull : BSShape | |||
360 | public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) | 454 | public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) |
361 | { | 455 | { |
362 | float lod; | 456 | float lod; |
363 | System.UInt64 newHullKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | 457 | System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); |
364 | 458 | ||
365 | physicsScene.DetailLog("{0},BSShapeHull,getReference,oldKey={1},newKey={2},size={3},lod={4}", | 459 | physicsScene.DetailLog("{0},BSShapeHull,getReference,oldKey={1},newKey={2},size={3},lod={4}", |
366 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod); | 460 | prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod); |
367 | 461 | ||
368 | BSShapeHull retHull = new BSShapeHull(new BulletShape()); | 462 | BSShapeHull retHull = new BSShapeHull(new BulletShape()); |
369 | lock (Hulls) | 463 | lock (Hulls) |
@@ -379,8 +473,8 @@ public class BSShapeHull : BSShape | |||
379 | BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod); | 473 | BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod); |
380 | 474 | ||
381 | // Check to see if mesh was created (might require an asset). | 475 | // Check to see if mesh was created (might require an asset). |
382 | newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim); | 476 | newShape = VerifyMeshCreated(physicsScene, newShape, prim); |
383 | if (newShape.type == BSPhysicsShapeType.SHAPE_MESH) | 477 | if (newShape.shapeType == BSPhysicsShapeType.SHAPE_MESH) |
384 | { | 478 | { |
385 | // If a mesh was what was created, remember the built shape for later sharing. | 479 | // If a mesh was what was created, remember the built shape for later sharing. |
386 | Hulls.Add(newHullKey, retHull); | 480 | Hulls.Add(newHullKey, retHull); |
@@ -569,7 +663,6 @@ public class BSShapeHull : BSShape | |||
569 | } | 663 | } |
570 | } | 664 | } |
571 | 665 | ||
572 | |||
573 | // ============================================================================================================ | 666 | // ============================================================================================================ |
574 | public class BSShapeCompound : BSShape | 667 | public class BSShapeCompound : BSShape |
575 | { | 668 | { |
@@ -589,9 +682,9 @@ public class BSShapeCompound : BSShape | |||
589 | { | 682 | { |
590 | // Failed the sanity check!! | 683 | // Failed the sanity check!! |
591 | physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", | 684 | physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", |
592 | LogHeader, physShapeInfo.type, physShapeInfo.AddrString); | 685 | LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString); |
593 | physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", | 686 | physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", |
594 | BSScene.DetailLogZero, physShapeInfo.type, physShapeInfo.AddrString); | 687 | BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString); |
595 | return; | 688 | return; |
596 | } | 689 | } |
597 | 690 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs index 8012d91..906e4f9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs | |||
@@ -104,11 +104,11 @@ public class BulletShape | |||
104 | { | 104 | { |
105 | public BulletShape() | 105 | public BulletShape() |
106 | { | 106 | { |
107 | type = BSPhysicsShapeType.SHAPE_UNKNOWN; | 107 | shapeType = BSPhysicsShapeType.SHAPE_UNKNOWN; |
108 | shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; | 108 | shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; |
109 | isNativeShape = false; | 109 | isNativeShape = false; |
110 | } | 110 | } |
111 | public BSPhysicsShapeType type; | 111 | public BSPhysicsShapeType shapeType; |
112 | public System.UInt64 shapeKey; | 112 | public System.UInt64 shapeKey; |
113 | public bool isNativeShape; | 113 | public bool isNativeShape; |
114 | 114 | ||
@@ -133,7 +133,7 @@ public class BulletShape | |||
133 | buff.Append("<p="); | 133 | buff.Append("<p="); |
134 | buff.Append(AddrString); | 134 | buff.Append(AddrString); |
135 | buff.Append(",s="); | 135 | buff.Append(",s="); |
136 | buff.Append(type.ToString()); | 136 | buff.Append(shapeType.ToString()); |
137 | buff.Append(",k="); | 137 | buff.Append(",k="); |
138 | buff.Append(shapeKey.ToString("X")); | 138 | buff.Append(shapeKey.ToString("X")); |
139 | buff.Append(",n="); | 139 | buff.Append(",n="); |