diff options
author | Robert Adams | 2012-11-02 09:53:41 -0700 |
---|---|---|
committer | Robert Adams | 2012-11-03 21:15:30 -0700 |
commit | b0eccd5044b1a20b995a62d6fb76fdd73b712f9a (patch) | |
tree | 877464740b99169d2e8f38bc8c75a33b37e9d475 | |
parent | BulletSim: Add RawPosition and RawOrientation to BSPhysObject and rename Mass... (diff) | |
download | opensim-SC-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.zip opensim-SC-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.tar.gz opensim-SC-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.tar.bz2 opensim-SC-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.tar.xz |
BulletSim: debugging of compound shape implementation of linksets.
Add compound shape creation and freeing in shape manager.
Add optional taint-time execution method and update code to use it.
Add API2 linkage for more compound shape methods (get num, get/remove by index, ...)
Modify perferred shape return so linkset children can have differet shapes than root.
Add Position and Orientation calls to linksets so children can be moved around by
the linkset by its own calculation. Allows for very general linkset implementations.
10 files changed, 274 insertions, 132 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 9e1206a..2a5397e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -200,7 +200,9 @@ public sealed class BSCharacter : BSPhysObject | |||
200 | } | 200 | } |
201 | // I want the physics engine to make an avatar capsule | 201 | // I want the physics engine to make an avatar capsule |
202 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape | 202 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape |
203 | { get { return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } } | 203 | { |
204 | get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } | ||
205 | } | ||
204 | 206 | ||
205 | public override bool Grabbed { | 207 | public override bool Grabbed { |
206 | set { _grabbed = value; } | 208 | set { _grabbed = value; } |
@@ -238,6 +240,7 @@ public sealed class BSCharacter : BSPhysObject | |||
238 | } | 240 | } |
239 | public override OMV.Vector3 Position { | 241 | public override OMV.Vector3 Position { |
240 | get { | 242 | get { |
243 | // Don't refetch the position because this function is called a zillion times | ||
241 | // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); | 244 | // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); |
242 | return _position; | 245 | return _position; |
243 | } | 246 | } |
@@ -304,15 +307,11 @@ public sealed class BSCharacter : BSPhysObject | |||
304 | { | 307 | { |
305 | // The new position value must be pushed into the physics engine but we can't | 308 | // The new position value must be pushed into the physics engine but we can't |
306 | // just assign to "Position" because of potential call loops. | 309 | // just assign to "Position" because of potential call loops. |
307 | BSScene.TaintCallback sanityOperation = delegate() | 310 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() |
308 | { | 311 | { |
309 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 312 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
310 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 313 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); |
311 | }; | 314 | }); |
312 | if (inTaintTime) | ||
313 | sanityOperation(); | ||
314 | else | ||
315 | PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); | ||
316 | ret = true; | 315 | ret = true; |
317 | } | 316 | } |
318 | return ret; | 317 | return ret; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 9e0f499..8f973f4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -48,7 +48,8 @@ public abstract class BSLinkset | |||
48 | */ | 48 | */ |
49 | 49 | ||
50 | // at the moment, there is only one | 50 | // at the moment, there is only one |
51 | ret = new BSLinksetConstraints(physScene, parent); | 51 | // ret = new BSLinksetConstraints(physScene, parent); |
52 | ret = new BSLinksetCompound(physScene, parent); | ||
52 | 53 | ||
53 | return ret; | 54 | return ret; |
54 | } | 55 | } |
@@ -69,10 +70,19 @@ public abstract class BSLinkset | |||
69 | protected object m_linksetActivityLock = new Object(); | 70 | protected object m_linksetActivityLock = new Object(); |
70 | 71 | ||
71 | // Some linksets have a preferred physical shape. | 72 | // Some linksets have a preferred physical shape. |
72 | // Returns SHAPE_UNKNOWN if there is no preference. | 73 | // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. |
73 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape | 74 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) |
74 | { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } | 75 | { |
76 | return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; | ||
77 | } | ||
75 | 78 | ||
79 | // Linksets move around the children so the linkset might need to compute the child position | ||
80 | public virtual OMV.Vector3 Position(BSPhysObject member) | ||
81 | { return member.RawPosition; } | ||
82 | public virtual OMV.Quaternion Orientation(BSPhysObject member) | ||
83 | { return member.RawOrientation; } | ||
84 | // TODO: does this need to be done for Velocity and RotationalVelocityy? | ||
85 | |||
76 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims | 86 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims |
77 | protected float m_mass; | 87 | protected float m_mass; |
78 | public float LinksetMass | 88 | public float LinksetMass |
@@ -177,7 +187,6 @@ public abstract class BSLinkset | |||
177 | } | 187 | } |
178 | 188 | ||
179 | // Perform an action on each member of the linkset including root prim. | 189 | // Perform an action on each member of the linkset including root prim. |
180 | // The action is performed only on the objects that are physically in the linkset. | ||
181 | // Depends on the action on whether this should be done at taint time. | 190 | // Depends on the action on whether this should be done at taint time. |
182 | public delegate bool ForEachMemberAction(BSPhysObject obj); | 191 | public delegate bool ForEachMemberAction(BSPhysObject obj); |
183 | public virtual bool ForEachMember(ForEachMemberAction action) | 192 | public virtual bool ForEachMember(ForEachMemberAction action) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 638fae1..8b97ebb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | |||
@@ -41,18 +41,31 @@ public sealed class BSLinksetCompound : BSLinkset | |||
41 | base.Initialize(scene, parent); | 41 | base.Initialize(scene, parent); |
42 | } | 42 | } |
43 | 43 | ||
44 | // For compound implimented linksets, if there are children, use compound shape for the root. | ||
45 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) | ||
46 | { | ||
47 | ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; | ||
48 | if (IsRoot(requestor) && HasAnyChildren) | ||
49 | { | ||
50 | ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; | ||
51 | } | ||
52 | // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
44 | // When physical properties are changed the linkset needs to recalculate | 56 | // When physical properties are changed the linkset needs to recalculate |
45 | // its internal properties. | 57 | // its internal properties. |
46 | // This is queued in the 'post taint' queue so the | 58 | // This is queued in the 'post taint' queue so the |
47 | // refresh will happen once after all the other taints are applied. | 59 | // refresh will happen once after all the other taints are applied. |
48 | public override void Refresh(BSPhysObject requestor) | 60 | public override void Refresh(BSPhysObject requestor) |
49 | { | 61 | { |
62 | DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); | ||
50 | // Queue to happen after all the other taint processing | 63 | // Queue to happen after all the other taint processing |
51 | PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() | 64 | PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() |
52 | { | 65 | { |
53 | if (HasAnyChildren && IsRoot(requestor)) | 66 | if (IsRoot(requestor) && HasAnyChildren) |
54 | RecomputeLinksetCompound(); | 67 | RecomputeLinksetCompound(); |
55 | }); | 68 | }); |
56 | } | 69 | } |
57 | 70 | ||
58 | // The object is going dynamic (physical). Do any setup necessary | 71 | // The object is going dynamic (physical). Do any setup necessary |
@@ -63,8 +76,17 @@ public sealed class BSLinksetCompound : BSLinkset | |||
63 | // Called at taint-time! | 76 | // Called at taint-time! |
64 | public override bool MakeDynamic(BSPhysObject child) | 77 | public override bool MakeDynamic(BSPhysObject child) |
65 | { | 78 | { |
66 | // What is done for each object in BSPrim is what we want. | 79 | bool ret = false; |
67 | return false; | 80 | DetailLog("{0},BSLinksetCompound.MakeDynamic,call,isChild={1}", child.LocalID, HasChild(child)); |
81 | if (HasChild(child)) | ||
82 | { | ||
83 | // Physical children are removed from the world as the shape ofthe root compound | ||
84 | // shape takes over. | ||
85 | BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
86 | BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); | ||
87 | ret = true; | ||
88 | } | ||
89 | return ret; | ||
68 | } | 90 | } |
69 | 91 | ||
70 | // The object is going static (non-physical). Do any setup necessary for a static linkset. | 92 | // The object is going static (non-physical). Do any setup necessary for a static linkset. |
@@ -74,8 +96,17 @@ public sealed class BSLinksetCompound : BSLinkset | |||
74 | // Called at taint-time! | 96 | // Called at taint-time! |
75 | public override bool MakeStatic(BSPhysObject child) | 97 | public override bool MakeStatic(BSPhysObject child) |
76 | { | 98 | { |
77 | // What is done for each object in BSPrim is what we want. | 99 | bool ret = false; |
78 | return false; | 100 | DetailLog("{0},BSLinksetCompound.MakeStatic,call,hasChild={1}", child.LocalID, HasChild(child)); |
101 | if (HasChild(child)) | ||
102 | { | ||
103 | // The non-physical children can come back to life. | ||
104 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
105 | // Don't force activation so setting of DISABLE_SIMULATION can stay. | ||
106 | BulletSimAPI.Activate2(child.PhysBody.ptr, false); | ||
107 | ret = true; | ||
108 | } | ||
109 | return ret; | ||
79 | } | 110 | } |
80 | 111 | ||
81 | // Called at taint-time!! | 112 | // Called at taint-time!! |
@@ -84,20 +115,35 @@ public sealed class BSLinksetCompound : BSLinkset | |||
84 | // Nothing to do for constraints on property updates | 115 | // Nothing to do for constraints on property updates |
85 | } | 116 | } |
86 | 117 | ||
118 | // The children move around in relationship to the root. | ||
119 | // Just grab the current values of wherever it is right now. | ||
120 | public override OMV.Vector3 Position(BSPhysObject member) | ||
121 | { | ||
122 | return BulletSimAPI.GetPosition2(member.PhysBody.ptr); | ||
123 | } | ||
124 | |||
125 | public override OMV.Quaternion Orientation(BSPhysObject member) | ||
126 | { | ||
127 | return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); | ||
128 | } | ||
129 | |||
87 | // Routine called when rebuilding the body of some member of the linkset. | 130 | // Routine called when rebuilding the body of some member of the linkset. |
88 | // Destroy all the constraints have have been made to root and set | 131 | // Since we don't keep in-physical world relationships, do nothing unless it's a child changing. |
89 | // up to rebuild the constraints before the next simulation step. | ||
90 | // Returns 'true' of something was actually removed and would need restoring | 132 | // Returns 'true' of something was actually removed and would need restoring |
91 | // Called at taint-time!! | 133 | // Called at taint-time!! |
92 | public override bool RemoveBodyDependencies(BSPrim child) | 134 | public override bool RemoveBodyDependencies(BSPrim child) |
93 | { | 135 | { |
94 | bool ret = false; | 136 | bool ret = false; |
95 | 137 | ||
96 | DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", | 138 | DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2},isRoot={3}", |
97 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); | 139 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); |
98 | 140 | ||
99 | // Cause the current shape to be freed and the new one to be built. | 141 | if (!IsRoot(child)) |
100 | Refresh(LinksetRoot); | 142 | { |
143 | // Cause the current shape to be freed and the new one to be built. | ||
144 | Refresh(LinksetRoot); | ||
145 | ret = true; | ||
146 | } | ||
101 | 147 | ||
102 | return ret; | 148 | return ret; |
103 | } | 149 | } |
@@ -139,13 +185,19 @@ public sealed class BSLinksetCompound : BSLinkset | |||
139 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), | 185 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), |
140 | child.LocalID, child.PhysBody.ptr.ToString("X")); | 186 | child.LocalID, child.PhysBody.ptr.ToString("X")); |
141 | 187 | ||
142 | // See that the linkset parameters are recomputed at the end of the taint time. | 188 | // Cause the child's body to be rebuilt and thus restored to normal operation |
143 | Refresh(LinksetRoot); | 189 | child.ForceBodyShapeRebuild(false); |
144 | } | 190 | |
145 | else | 191 | if (!HasAnyChildren) |
146 | { | 192 | { |
147 | // Non-fatal occurance. | 193 | // The linkset is now empty. The root needs rebuilding. |
148 | // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); | 194 | LinksetRoot.ForceBodyShapeRebuild(false); |
195 | } | ||
196 | else | ||
197 | { | ||
198 | // Schedule a rebuild of the linkset before the next simulation tick. | ||
199 | Refresh(LinksetRoot); | ||
200 | } | ||
149 | } | 201 | } |
150 | return; | 202 | return; |
151 | } | 203 | } |
@@ -158,16 +210,18 @@ public sealed class BSLinksetCompound : BSLinkset | |||
158 | // Called at taint time!! | 210 | // Called at taint time!! |
159 | private void RecomputeLinksetCompound() | 211 | private void RecomputeLinksetCompound() |
160 | { | 212 | { |
161 | // Release the existing shape | 213 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},numChildren={2}", |
162 | PhysicsScene.Shapes.DereferenceShape(LinksetRoot.PhysShape, true, null); | 214 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), NumberOfChildren); |
163 | 215 | ||
216 | LinksetRoot.ForceBodyShapeRebuild(true); | ||
217 | |||
164 | float linksetMass = LinksetMass; | 218 | float linksetMass = LinksetMass; |
165 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); | 219 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); |
166 | 220 | ||
167 | // DEBUG: see of inter-linkset collisions are causing problems | 221 | // DEBUG: see of inter-linkset collisions are causing problems |
168 | // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, | 222 | // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, |
169 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); | 223 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); |
170 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", | 224 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,end,rBody={1},linksetMass={2}", |
171 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); | 225 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); |
172 | 226 | ||
173 | 227 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 65aed77..67a59ef 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs | |||
@@ -84,6 +84,18 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
84 | // Nothing to do for constraints on property updates | 84 | // Nothing to do for constraints on property updates |
85 | } | 85 | } |
86 | 86 | ||
87 | // The children of the linkset are moved around by the constraints. | ||
88 | // Just grab the current values of wherever it is right now. | ||
89 | public override OMV.Vector3 Position(BSPhysObject member) | ||
90 | { | ||
91 | return BulletSimAPI.GetPosition2(member.PhysBody.ptr); | ||
92 | } | ||
93 | |||
94 | public override OMV.Quaternion Orientation(BSPhysObject member) | ||
95 | { | ||
96 | return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); | ||
97 | } | ||
98 | |||
87 | // Routine called when rebuilding the body of some member of the linkset. | 99 | // Routine called when rebuilding the body of some member of the linkset. |
88 | // Destroy all the constraints have have been made to root and set | 100 | // Destroy all the constraints have have been made to root and set |
89 | // up to rebuild the constraints before the next simulation step. | 101 | // up to rebuild the constraints before the next simulation step. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 65d7f34..7127aaf 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -81,7 +81,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
81 | // Some types of objects have preferred physical representations. | 81 | // Some types of objects have preferred physical representations. |
82 | // Returns SHAPE_UNKNOWN if there is no preference. | 82 | // Returns SHAPE_UNKNOWN if there is no preference. |
83 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape | 83 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape |
84 | { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } | 84 | { |
85 | get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } | ||
86 | } | ||
85 | 87 | ||
86 | // When the physical properties are updated, an EntityProperty holds the update values. | 88 | // When the physical properties are updated, an EntityProperty holds the update values. |
87 | // Keep the current and last EntityProperties to enable computation of differences | 89 | // Keep the current and last EntityProperties to enable computation of differences |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 1754be6..af403aa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -173,20 +173,16 @@ public sealed class BSPrim : BSPhysObject | |||
173 | } | 173 | } |
174 | // Whatever the linkset wants is what I want. | 174 | // Whatever the linkset wants is what I want. |
175 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape | 175 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape |
176 | { get { return Linkset.PreferredPhysicalShape; } } | 176 | { get { return Linkset.PreferredPhysicalShape(this); } } |
177 | 177 | ||
178 | public override bool ForceBodyShapeRebuild(bool inTaintTime) | 178 | public override bool ForceBodyShapeRebuild(bool inTaintTime) |
179 | { | 179 | { |
180 | LastAssetBuildFailed = false; | 180 | LastAssetBuildFailed = false; |
181 | BSScene.TaintCallback rebuildOperation = delegate() | 181 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() |
182 | { | 182 | { |
183 | _mass = CalculateMass(); // changing the shape changes the mass | 183 | _mass = CalculateMass(); // changing the shape changes the mass |
184 | CreateGeomAndObject(true); | 184 | CreateGeomAndObject(true); |
185 | }; | 185 | }); |
186 | if (inTaintTime) | ||
187 | rebuildOperation(); | ||
188 | else | ||
189 | PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation); | ||
190 | return true; | 186 | return true; |
191 | } | 187 | } |
192 | public override bool Grabbed { | 188 | public override bool Grabbed { |
@@ -263,9 +259,9 @@ public sealed class BSPrim : BSPhysObject | |||
263 | } | 259 | } |
264 | public override OMV.Vector3 Position { | 260 | public override OMV.Vector3 Position { |
265 | get { | 261 | get { |
262 | // child prims move around based on their parent. Need to get the latest location | ||
266 | if (!Linkset.IsRoot(this)) | 263 | if (!Linkset.IsRoot(this)) |
267 | // child prims move around based on their parent. Need to get the latest location | 264 | _position = Linkset.Position(this); |
268 | _position = BulletSimAPI.GetPosition2(PhysBody.ptr); | ||
269 | 265 | ||
270 | // don't do the GetObjectPosition for root elements because this function is called a zillion times | 266 | // don't do the GetObjectPosition for root elements because this function is called a zillion times |
271 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); | 267 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); |
@@ -344,16 +340,11 @@ public sealed class BSPrim : BSPhysObject | |||
344 | { | 340 | { |
345 | // The new position value must be pushed into the physics engine but we can't | 341 | // The new position value must be pushed into the physics engine but we can't |
346 | // just assign to "Position" because of potential call loops. | 342 | // just assign to "Position" because of potential call loops. |
347 | BSScene.TaintCallback sanityOperation = delegate() | 343 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() |
348 | { | 344 | { |
349 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 345 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
350 | ForcePosition = _position; | 346 | ForcePosition = _position; |
351 | }; | 347 | }); |
352 | if (inTaintTime) | ||
353 | sanityOperation(); | ||
354 | else | ||
355 | PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); | ||
356 | |||
357 | ret = true; | 348 | ret = true; |
358 | } | 349 | } |
359 | return ret; | 350 | return ret; |
@@ -542,10 +533,10 @@ public sealed class BSPrim : BSPhysObject | |||
542 | } | 533 | } |
543 | public override OMV.Quaternion Orientation { | 534 | public override OMV.Quaternion Orientation { |
544 | get { | 535 | get { |
536 | // Children move around because tied to parent. Get a fresh value. | ||
545 | if (!Linkset.IsRoot(this)) | 537 | if (!Linkset.IsRoot(this)) |
546 | { | 538 | { |
547 | // Children move around because tied to parent. Get a fresh value. | 539 | _orientation = Linkset.Orientation(this); |
548 | _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); | ||
549 | } | 540 | } |
550 | return _orientation; | 541 | return _orientation; |
551 | } | 542 | } |
@@ -946,7 +937,7 @@ public sealed class BSPrim : BSPhysObject | |||
946 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); | 937 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); |
947 | return; | 938 | return; |
948 | } | 939 | } |
949 | BSScene.TaintCallback addForceOperation = delegate() | 940 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() |
950 | { | 941 | { |
951 | OMV.Vector3 fSum = OMV.Vector3.Zero; | 942 | OMV.Vector3 fSum = OMV.Vector3.Zero; |
952 | lock (m_accumulatedForces) | 943 | lock (m_accumulatedForces) |
@@ -961,11 +952,7 @@ public sealed class BSPrim : BSPhysObject | |||
961 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); | 952 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); |
962 | if (fSum != OMV.Vector3.Zero) | 953 | if (fSum != OMV.Vector3.Zero) |
963 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); | 954 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); |
964 | }; | 955 | }); |
965 | if (inTaintTime) | ||
966 | addForceOperation(); | ||
967 | else | ||
968 | PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); | ||
969 | } | 956 | } |
970 | 957 | ||
971 | private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>(); | 958 | private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>(); |
@@ -985,7 +972,7 @@ public sealed class BSPrim : BSPhysObject | |||
985 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); | 972 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); |
986 | return; | 973 | return; |
987 | } | 974 | } |
988 | BSScene.TaintCallback addAngularForceOperation = delegate() | 975 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() |
989 | { | 976 | { |
990 | OMV.Vector3 fSum = OMV.Vector3.Zero; | 977 | OMV.Vector3 fSum = OMV.Vector3.Zero; |
991 | lock (m_accumulatedAngularForces) | 978 | lock (m_accumulatedAngularForces) |
@@ -1003,26 +990,19 @@ public sealed class BSPrim : BSPhysObject | |||
1003 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); | 990 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); |
1004 | _torque = fSum; | 991 | _torque = fSum; |
1005 | } | 992 | } |
1006 | }; | 993 | }); |
1007 | if (inTaintTime) | ||
1008 | addAngularForceOperation(); | ||
1009 | else | ||
1010 | PhysicsScene.TaintedObject("BSPrim.AddAngularForce", addAngularForceOperation); | ||
1011 | } | 994 | } |
1012 | // A torque impulse. | 995 | // A torque impulse. |
1013 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) | 996 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) |
1014 | { | 997 | { |
1015 | OMV.Vector3 applyImpulse = impulse; | 998 | OMV.Vector3 applyImpulse = impulse; |
1016 | BSScene.TaintCallback applyTorqueImpulseOperation = delegate() | 999 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() |
1017 | { | 1000 | { |
1018 | DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); | 1001 | DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); |
1019 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); | 1002 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); |
1020 | }; | 1003 | }); |
1021 | if (inTaintTime) | ||
1022 | applyTorqueImpulseOperation(); | ||
1023 | else | ||
1024 | PhysicsScene.TaintedObject("BSPrim.ApplyTorqueImpulse", applyTorqueImpulseOperation); | ||
1025 | } | 1004 | } |
1005 | |||
1026 | public override void SetMomentum(OMV.Vector3 momentum) { | 1006 | public override void SetMomentum(OMV.Vector3 momentum) { |
1027 | // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); | 1007 | // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); |
1028 | } | 1008 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index cc5dbb2..dcfcb83 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -692,6 +692,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
692 | return; | 692 | return; |
693 | } | 693 | } |
694 | 694 | ||
695 | // Sometimes a potentially tainted operation can be used in and out of taint time. | ||
696 | // This routine executes the command immediately if in taint-time otherwise it is queued. | ||
697 | public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) | ||
698 | { | ||
699 | if (inTaintTime) | ||
700 | callback(); | ||
701 | else | ||
702 | TaintedObject(ident, callback); | ||
703 | } | ||
704 | |||
695 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues | 705 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues |
696 | // a callback into itself to do the actual property change. That callback is called | 706 | // a callback into itself to do the actual property change. That callback is called |
697 | // here just before the physics engine is called to step the simulation. | 707 | // here just before the physics engine is called to step the simulation. |
@@ -1438,7 +1448,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1438 | { | 1448 | { |
1439 | PhysicsLogging.Write(msg, args); | 1449 | PhysicsLogging.Write(msg, args); |
1440 | // Add the Flush() if debugging crashes to get all the messages written out. | 1450 | // Add the Flush() if debugging crashes to get all the messages written out. |
1441 | // PhysicsLogging.Flush(); | 1451 | PhysicsLogging.Flush(); |
1442 | } | 1452 | } |
1443 | // Used to fill in the LocalID when there isn't one. It's the correct number of characters. | 1453 | // Used to fill in the LocalID when there isn't one. It's the correct number of characters. |
1444 | public const string DetailLogZero = "0000000000"; | 1454 | public const string DetailLogZero = "0000000000"; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index e131919..107befe 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |||
@@ -122,18 +122,14 @@ public sealed class BSShapeCollection : IDisposable | |||
122 | lock (m_collectionActivityLock) | 122 | lock (m_collectionActivityLock) |
123 | { | 123 | { |
124 | DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); | 124 | DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); |
125 | BSScene.TaintCallback createOperation = delegate() | 125 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() |
126 | { | 126 | { |
127 | if (!BulletSimAPI.IsInWorld2(body.ptr)) | 127 | if (!BulletSimAPI.IsInWorld2(body.ptr)) |
128 | { | 128 | { |
129 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); | 129 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); |
130 | DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); | 130 | DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); |
131 | } | 131 | } |
132 | }; | 132 | }); |
133 | if (inTaintTime) | ||
134 | createOperation(); | ||
135 | else | ||
136 | PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); | ||
137 | } | 133 | } |
138 | } | 134 | } |
139 | 135 | ||
@@ -146,7 +142,7 @@ public sealed class BSShapeCollection : IDisposable | |||
146 | 142 | ||
147 | lock (m_collectionActivityLock) | 143 | lock (m_collectionActivityLock) |
148 | { | 144 | { |
149 | BSScene.TaintCallback removeOperation = delegate() | 145 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() |
150 | { | 146 | { |
151 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", | 147 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", |
152 | body.ID, body.ptr.ToString("X"), inTaintTime); | 148 | body.ID, body.ptr.ToString("X"), inTaintTime); |
@@ -159,12 +155,7 @@ public sealed class BSShapeCollection : IDisposable | |||
159 | // Zero any reference to the shape so it is not freed when the body is deleted. | 155 | // Zero any reference to the shape so it is not freed when the body is deleted. |
160 | BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); | 156 | BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); |
161 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); | 157 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); |
162 | }; | 158 | }); |
163 | // If already in taint-time, do the operations now. Otherwise queue for later. | ||
164 | if (inTaintTime) | ||
165 | removeOperation(); | ||
166 | else | ||
167 | PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); | ||
168 | } | 159 | } |
169 | } | 160 | } |
170 | 161 | ||
@@ -238,7 +229,7 @@ public sealed class BSShapeCollection : IDisposable | |||
238 | if (shape.ptr == IntPtr.Zero) | 229 | if (shape.ptr == IntPtr.Zero) |
239 | return; | 230 | return; |
240 | 231 | ||
241 | BSScene.TaintCallback dereferenceOperation = delegate() | 232 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() |
242 | { | 233 | { |
243 | if (shape.ptr != IntPtr.Zero) | 234 | if (shape.ptr != IntPtr.Zero) |
244 | { | 235 | { |
@@ -270,18 +261,7 @@ public sealed class BSShapeCollection : IDisposable | |||
270 | } | 261 | } |
271 | } | 262 | } |
272 | } | 263 | } |
273 | }; | 264 | }); |
274 | if (inTaintTime) | ||
275 | { | ||
276 | lock (m_collectionActivityLock) | ||
277 | { | ||
278 | dereferenceOperation(); | ||
279 | } | ||
280 | } | ||
281 | else | ||
282 | { | ||
283 | PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation); | ||
284 | } | ||
285 | } | 265 | } |
286 | 266 | ||
287 | // Count down the reference count for a mesh shape | 267 | // Count down the reference count for a mesh shape |
@@ -311,7 +291,10 @@ public sealed class BSShapeCollection : IDisposable | |||
311 | { | 291 | { |
312 | hullDesc.referenceCount--; | 292 | hullDesc.referenceCount--; |
313 | // TODO: release the Bullet storage (aging old entries?) | 293 | // TODO: release the Bullet storage (aging old entries?) |
294 | |||
295 | // Tell upper layers that, if they have dependencies on this shape, this link is going away | ||
314 | if (shapeCallback != null) shapeCallback(shape); | 296 | if (shapeCallback != null) shapeCallback(shape); |
297 | |||
315 | hullDesc.lastReferenced = System.DateTime.Now; | 298 | hullDesc.lastReferenced = System.DateTime.Now; |
316 | Hulls[shape.shapeKey] = hullDesc; | 299 | Hulls[shape.shapeKey] = hullDesc; |
317 | DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", | 300 | DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", |
@@ -320,10 +303,48 @@ public sealed class BSShapeCollection : IDisposable | |||
320 | } | 303 | } |
321 | 304 | ||
322 | // Remove a reference to a compound shape. | 305 | // Remove a reference to a compound shape. |
306 | // Taking a compound shape apart is a little tricky because if you just delete the | ||
307 | // physical object, it will free all the underlying children. We can't do that because | ||
308 | // they could be shared. So, this removes each of the children from the compound and | ||
309 | // dereferences them separately before destroying the compound collision object itself. | ||
323 | // Called at taint-time. | 310 | // Called at taint-time. |
324 | private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) | 311 | private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) |
325 | { | 312 | { |
326 | // Compound shape is made of a bunch of meshes and natives. | 313 | if (!BulletSimAPI.IsCompound2(shape.ptr)) |
314 | { | ||
315 | // Failed the sanity check!! | ||
316 | PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", | ||
317 | LogHeader, shape.type, shape.ptr.ToString("X")); | ||
318 | DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", | ||
319 | BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); | ||
320 | return; | ||
321 | } | ||
322 | int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); | ||
323 | for (int ii = 0; ii < numChildren; ii++) | ||
324 | { | ||
325 | IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); | ||
326 | DereferenceAnonCollisionShape(childShape); | ||
327 | } | ||
328 | BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); | ||
329 | } | ||
330 | |||
331 | // Sometimes we have a pointer to a collision shape but don't know what type it is. | ||
332 | // Figure out type and call the correct dereference routine. | ||
333 | // This is coming from a compound shape that we created so we know it is either native or mesh. | ||
334 | // Called at taint-time. | ||
335 | private void DereferenceAnonCollisionShape(IntPtr cShape) | ||
336 | { | ||
337 | BulletShape shapeInfo = new BulletShape(cShape, ShapeData.PhysicsShapeType.SHAPE_MESH); | ||
338 | if (BulletSimAPI.IsCompound2(cShape)) | ||
339 | shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; | ||
340 | |||
341 | if (BulletSimAPI.IsNativeShape2(cShape)) | ||
342 | { | ||
343 | shapeInfo.isNativeShape = true; | ||
344 | shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) | ||
345 | } | ||
346 | |||
347 | DereferenceShape(shapeInfo, true, null); | ||
327 | } | 348 | } |
328 | 349 | ||
329 | // Create the geometry information in Bullet for later use. | 350 | // Create the geometry information in Bullet for later use. |
@@ -338,10 +359,8 @@ public sealed class BSShapeCollection : IDisposable | |||
338 | { | 359 | { |
339 | bool ret = false; | 360 | bool ret = false; |
340 | bool haveShape = false; | 361 | bool haveShape = false; |
341 | bool nativeShapePossible = true; | ||
342 | PrimitiveBaseShape pbs = prim.BaseShape; | ||
343 | 362 | ||
344 | if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) | 363 | if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) |
345 | { | 364 | { |
346 | // an avatar capsule is close to a native shape (it is not shared) | 365 | // an avatar capsule is close to a native shape (it is not shared) |
347 | ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, | 366 | ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, |
@@ -350,6 +369,31 @@ public sealed class BSShapeCollection : IDisposable | |||
350 | ret = true; | 369 | ret = true; |
351 | haveShape = true; | 370 | haveShape = true; |
352 | } | 371 | } |
372 | |||
373 | // Compound shapes are handled special as they are rebuilt from scratch. | ||
374 | // This isn't too great a hardship since most of the child shapes will already been created. | ||
375 | if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) | ||
376 | { | ||
377 | ret = GetReferenceToCompoundShape(prim, shapeCallback); | ||
378 | DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); | ||
379 | haveShape = true; | ||
380 | } | ||
381 | |||
382 | if (!haveShape) | ||
383 | { | ||
384 | ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); | ||
385 | } | ||
386 | |||
387 | return ret; | ||
388 | } | ||
389 | |||
390 | private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
391 | { | ||
392 | bool ret = false; | ||
393 | bool haveShape = false; | ||
394 | bool nativeShapePossible = true; | ||
395 | PrimitiveBaseShape pbs = prim.BaseShape; | ||
396 | |||
353 | // If the prim attributes are simple, this could be a simple Bullet native shape | 397 | // If the prim attributes are simple, this could be a simple Bullet native shape |
354 | if (!haveShape | 398 | if (!haveShape |
355 | && pbs != null | 399 | && pbs != null |
@@ -363,6 +407,7 @@ public sealed class BSShapeCollection : IDisposable | |||
363 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | 407 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 |
364 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) | 408 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) |
365 | { | 409 | { |
410 | // It doesn't look like Bullet scales spheres so make sure the scales are all equal | ||
366 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) | 411 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) |
367 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) | 412 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) |
368 | { | 413 | { |
@@ -378,7 +423,7 @@ public sealed class BSShapeCollection : IDisposable | |||
378 | prim.LocalID, forceRebuild, prim.PhysShape); | 423 | prim.LocalID, forceRebuild, prim.PhysShape); |
379 | } | 424 | } |
380 | } | 425 | } |
381 | if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | 426 | if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) |
382 | { | 427 | { |
383 | haveShape = true; | 428 | haveShape = true; |
384 | if (forceRebuild | 429 | if (forceRebuild |
@@ -393,9 +438,10 @@ public sealed class BSShapeCollection : IDisposable | |||
393 | } | 438 | } |
394 | } | 439 | } |
395 | } | 440 | } |
441 | |||
396 | // If a simple shape is not happening, create a mesh and possibly a hull. | 442 | // If a simple shape is not happening, create a mesh and possibly a hull. |
397 | // Note that if it's a native shape, the check for physical/non-physical is not | 443 | // Note that if it's a native shape, the check for physical/non-physical is not |
398 | // made. Native shapes are best used in either case. | 444 | // made. Native shapes work in either case. |
399 | if (!haveShape && pbs != null) | 445 | if (!haveShape && pbs != null) |
400 | { | 446 | { |
401 | if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) | 447 | if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) |
@@ -487,7 +533,7 @@ public sealed class BSShapeCollection : IDisposable | |||
487 | if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) | 533 | if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) |
488 | return false; | 534 | return false; |
489 | 535 | ||
490 | DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", | 536 | DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", |
491 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); | 537 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); |
492 | 538 | ||
493 | // Since we're recreating new, get rid of the reference to the previous shape | 539 | // Since we're recreating new, get rid of the reference to the previous shape |
@@ -535,7 +581,7 @@ public sealed class BSShapeCollection : IDisposable | |||
535 | verticesAsFloats[vi++] = vv.Z; | 581 | verticesAsFloats[vi++] = vv.Z; |
536 | } | 582 | } |
537 | 583 | ||
538 | // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", | 584 | // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", |
539 | // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); | 585 | // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); |
540 | 586 | ||
541 | meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, | 587 | meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, |
@@ -561,7 +607,7 @@ public sealed class BSShapeCollection : IDisposable | |||
561 | if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) | 607 | if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) |
562 | return false; | 608 | return false; |
563 | 609 | ||
564 | DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", | 610 | DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", |
565 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); | 611 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); |
566 | 612 | ||
567 | // Remove usage of the previous shape. | 613 | // Remove usage of the previous shape. |
@@ -693,6 +739,42 @@ public sealed class BSShapeCollection : IDisposable | |||
693 | return; | 739 | return; |
694 | } | 740 | } |
695 | 741 | ||
742 | // Compound shapes are always built from scratch. | ||
743 | // This shouldn't be to bad since most of the parts will be meshes that had been built previously. | ||
744 | private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
745 | { | ||
746 | BulletShape cShape = new BulletShape( | ||
747 | BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); | ||
748 | |||
749 | // The prim's linkset is the source of the children. | ||
750 | // TODO: there is too much knowledge here about the internals of linksets and too much | ||
751 | // dependency on the relationship of compound shapes and linksets (what if we want to use | ||
752 | // compound shapes for something else?). Think through this and clean up so the | ||
753 | // appropriate knowledge is used at the correct software levels. | ||
754 | |||
755 | // Recreate the geometry of the root prim (might have been a linkset root in the past) | ||
756 | CreateGeomNonSpecial(true, prim, null); | ||
757 | |||
758 | BSPhysObject rootPrim = prim.Linkset.LinksetRoot; | ||
759 | |||
760 | prim.Linkset.ForEachMember(delegate(BSPhysObject cPrim) | ||
761 | { | ||
762 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(rootPrim.RawOrientation); | ||
763 | OMV.Vector3 displacementPos = (cPrim.RawPosition - rootPrim.RawPosition) * invRootOrientation; | ||
764 | OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; | ||
765 | |||
766 | DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", | ||
767 | prim.LocalID, cPrim.LocalID, cPrim.PhysShape.ptr.ToString("X"), displacementPos, displacementRot); | ||
768 | |||
769 | BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); | ||
770 | return false; | ||
771 | }); | ||
772 | |||
773 | prim.PhysShape = cShape; | ||
774 | |||
775 | return true; | ||
776 | } | ||
777 | |||
696 | // Create a hash of all the shape parameters to be used as a key | 778 | // Create a hash of all the shape parameters to be used as a key |
697 | // for this particular shape. | 779 | // for this particular shape. |
698 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | 780 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 11298fe..7c34af2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | |||
@@ -238,7 +238,7 @@ public sealed class BSTerrainManager | |||
238 | DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", | 238 | DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", |
239 | BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); | 239 | BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); |
240 | 240 | ||
241 | BSScene.TaintCallback rebuildOperation = delegate() | 241 | PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() |
242 | { | 242 | { |
243 | if (MegaRegionParentPhysicsScene != null) | 243 | if (MegaRegionParentPhysicsScene != null) |
244 | { | 244 | { |
@@ -337,14 +337,7 @@ public sealed class BSTerrainManager | |||
337 | BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); | 337 | BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); |
338 | 338 | ||
339 | m_terrainModified = true; | 339 | m_terrainModified = true; |
340 | }; | 340 | }); |
341 | |||
342 | // There is the option to do the changes now (we're already in 'taint time'), or | ||
343 | // to do the Bullet operations later. | ||
344 | if (inTaintTime) | ||
345 | rebuildOperation(); | ||
346 | else | ||
347 | PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); | ||
348 | } | 341 | } |
349 | else | 342 | else |
350 | { | 343 | { |
@@ -364,7 +357,7 @@ public sealed class BSTerrainManager | |||
364 | BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); | 357 | BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); |
365 | 358 | ||
366 | // Code that must happen at taint-time | 359 | // Code that must happen at taint-time |
367 | BSScene.TaintCallback createOperation = delegate() | 360 | PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() |
368 | { | 361 | { |
369 | DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); | 362 | DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); |
370 | // Create a new mapInfo that will be filled with the new info | 363 | // Create a new mapInfo that will be filled with the new info |
@@ -377,13 +370,7 @@ public sealed class BSTerrainManager | |||
377 | UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); | 370 | UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); |
378 | 371 | ||
379 | m_terrainModified = true; | 372 | m_terrainModified = true; |
380 | }; | 373 | }); |
381 | |||
382 | // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. | ||
383 | if (inTaintTime) | ||
384 | createOperation(); | ||
385 | else | ||
386 | PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); | ||
387 | } | 374 | } |
388 | } | 375 | } |
389 | 376 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 3b6355c..143b8be 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -399,8 +399,6 @@ public enum CollisionFilterGroups : uint | |||
399 | 399 | ||
400 | }; | 400 | }; |
401 | 401 | ||
402 | |||
403 | |||
404 | // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 | 402 | // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 |
405 | // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. | 403 | // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. |
406 | public enum ConstraintParams : int | 404 | public enum ConstraintParams : int |
@@ -618,10 +616,19 @@ public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float | |||
618 | public static extern IntPtr CreateCompoundShape2(IntPtr sim); | 616 | public static extern IntPtr CreateCompoundShape2(IntPtr sim); |
619 | 617 | ||
620 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 618 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
621 | public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); | 619 | public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); |
620 | |||
621 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
622 | public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); | ||
623 | |||
624 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
625 | public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); | ||
626 | |||
627 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
628 | public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); | ||
622 | 629 | ||
623 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 630 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
624 | public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape); | 631 | public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); |
625 | 632 | ||
626 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 633 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
627 | public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); | 634 | public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); |