aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs145
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs3
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs25
3 files changed, 93 insertions, 80 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index dff71af..4f225ae 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -43,8 +43,17 @@ public class BSLinkset
43 static int m_nextLinksetID = 1; 43 static int m_nextLinksetID = 1;
44 public int LinksetID { get; private set; } 44 public int LinksetID { get; private set; }
45 45
46 // The children under the root in this linkset 46 // The children under the root in this linkset.
47 // There are two lists of children: the current children at runtime
48 // and the children at taint-time. For instance, if you delink a
49 // child from the linkset, the child is removed from m_children
50 // but the constraint won't be removed until taint time.
51 // Two lists lets this track the 'current' children and
52 // the physical 'taint' children separately.
53 // After taint processing and before the simulation step, these
54 // two lists must be the same.
47 private List<BSPhysObject> m_children; 55 private List<BSPhysObject> m_children;
56 private List<BSPhysObject> m_taintChildren;
48 57
49 // We lock the diddling of linkset classes to prevent any badness. 58 // We lock the diddling of linkset classes to prevent any badness.
50 // This locks the modification of the instances of this class. Changes 59 // This locks the modification of the instances of this class. Changes
@@ -82,6 +91,7 @@ public class BSLinkset
82 PhysicsScene = scene; 91 PhysicsScene = scene;
83 LinksetRoot = parent; 92 LinksetRoot = parent;
84 m_children = new List<BSPhysObject>(); 93 m_children = new List<BSPhysObject>();
94 m_taintChildren = new List<BSPhysObject>();
85 m_mass = parent.MassRaw; 95 m_mass = parent.MassRaw;
86 } 96 }
87 97
@@ -194,30 +204,40 @@ public class BSLinkset
194 // Routine used when rebuilding the body of the root of the linkset 204 // Routine used when rebuilding the body of the root of the linkset
195 // Destroy all the constraints have have been made to root. 205 // Destroy all the constraints have have been made to root.
196 // This is called when the root body is changing. 206 // This is called when the root body is changing.
207 // Returns 'true' of something eas actually removed and would need restoring
197 // Called at taint-time!! 208 // Called at taint-time!!
198 public void RemoveBodyDependencies(BSPrim child) 209 public bool RemoveBodyDependencies(BSPrim child)
199 { 210 {
211 bool ret = false;
212
200 lock (m_linksetActivityLock) 213 lock (m_linksetActivityLock)
201 { 214 {
202 if (IsRoot(child)) 215 if (IsRoot(child))
203 { 216 {
204 // If the one with the dependency is root, must undo all children 217 // If the one with the dependency is root, must undo all children
205 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", 218 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}",
206 LinksetRoot.LocalID, m_children.Count); 219 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
207 foreach (BSPhysObject bpo in m_children) 220 foreach (BSPhysObject bpo in m_taintChildren)
208 { 221 {
209 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); 222 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
223 ret = true;
210 } 224 }
211 } 225 }
212 else 226 else
213 { 227 {
214 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", 228 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}",
229 child.LocalID,
215 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), 230 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
216 child.LocalID, child.BSBody.ptr.ToString("X")); 231 child.LocalID, child.BSBody.ptr.ToString("X"));
217 // Remove the dependency on the body of this one 232 // Remove the dependency on the body of this one
218 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); 233 if (m_taintChildren.Contains(child))
234 {
235 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
236 ret = true;
237 }
219 } 238 }
220 } 239 }
240 return ret;
221 } 241 }
222 242
223 // Routine used when rebuilding the body of the root of the linkset 243 // Routine used when rebuilding the body of the root of the linkset
@@ -231,8 +251,8 @@ public class BSLinkset
231 if (IsRoot(child)) 251 if (IsRoot(child))
232 { 252 {
233 DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", 253 DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}",
234 LinksetRoot.LocalID, m_children.Count); 254 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
235 foreach (BSPhysObject bpo in m_children) 255 foreach (BSPhysObject bpo in m_taintChildren)
236 { 256 {
237 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); 257 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
238 } 258 }
@@ -240,6 +260,7 @@ public class BSLinkset
240 else 260 else
241 { 261 {
242 DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", 262 DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}",
263 LinksetRoot.LocalID,
243 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), 264 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
244 child.LocalID, child.BSBody.ptr.ToString("X")); 265 child.LocalID, child.BSBody.ptr.ToString("X"));
245 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); 266 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
@@ -256,7 +277,7 @@ public class BSLinkset
256 lock (m_linksetActivityLock) 277 lock (m_linksetActivityLock)
257 { 278 {
258 mass = LinksetRoot.MassRaw; 279 mass = LinksetRoot.MassRaw;
259 foreach (BSPhysObject bp in m_children) 280 foreach (BSPhysObject bp in m_taintChildren)
260 { 281 {
261 mass += bp.MassRaw; 282 mass += bp.MassRaw;
262 } 283 }
@@ -272,7 +293,7 @@ public class BSLinkset
272 com = LinksetRoot.Position * LinksetRoot.MassRaw; 293 com = LinksetRoot.Position * LinksetRoot.MassRaw;
273 float totalMass = LinksetRoot.MassRaw; 294 float totalMass = LinksetRoot.MassRaw;
274 295
275 foreach (BSPhysObject bp in m_children) 296 foreach (BSPhysObject bp in m_taintChildren)
276 { 297 {
277 com += bp.Position * bp.MassRaw; 298 com += bp.Position * bp.MassRaw;
278 totalMass += bp.MassRaw; 299 totalMass += bp.MassRaw;
@@ -291,70 +312,16 @@ public class BSLinkset
291 { 312 {
292 com = LinksetRoot.Position; 313 com = LinksetRoot.Position;
293 314
294 foreach (BSPhysObject bp in m_children) 315 foreach (BSPhysObject bp in m_taintChildren)
295 { 316 {
296 com += bp.Position * bp.MassRaw; 317 com += bp.Position * bp.MassRaw;
297 } 318 }
298 com /= (m_children.Count + 1); 319 com /= (m_taintChildren.Count + 1);
299 } 320 }
300 321
301 return com; 322 return com;
302 } 323 }
303 324
304 // Call each of the constraints that make up this linkset and recompute the
305 // various transforms and variables. Used when objects are added or removed
306 // from a linkset to make sure the constraints know about the new mass and
307 // geometry.
308 // Must only be called at taint time!!
309 private void RecomputeLinksetConstraintVariables()
310 {
311 float linksetMass = LinksetMass;
312 lock (m_linksetActivityLock)
313 {
314 bool somethingMissing = false;
315 foreach (BSPhysObject child in m_children)
316 {
317 BSConstraint constrain;
318 if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
319 {
320 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
321 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
322 constrain.RecomputeConstraintVariables(linksetMass);
323 }
324 else
325 {
326 // Non-fatal error that happens when children are being added to the linkset but
327 // their constraints have not been created yet.
328 // Caused by the fact that m_children is built at run time but building constraints
329 // happens at taint time.
330 somethingMissing = true;
331 break;
332 }
333 }
334
335 // If the whole linkset is not here, doesn't make sense to recompute linkset wide values
336 if (!somethingMissing)
337 {
338 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
339 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
340 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
341 foreach (BSPhysObject child in m_children)
342 {
343 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
344 }
345 /*
346 // The root prim takes on the weight of the whole linkset
347 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass);
348 BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia);
349 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
350 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
351 BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr);
352 */
353 }
354 }
355 return;
356 }
357
358 // I am the root of a linkset and a new child is being added 325 // I am the root of a linkset and a new child is being added
359 // Called while LinkActivity is locked. 326 // Called while LinkActivity is locked.
360 private void AddChildToLinkset(BSPhysObject child) 327 private void AddChildToLinkset(BSPhysObject child)
@@ -377,6 +344,7 @@ public class BSLinkset
377 { 344 {
378 DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); 345 DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID);
379 // build the physical binding between me and the child 346 // build the physical binding between me and the child
347 m_taintChildren.Add(childx);
380 PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx); 348 PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx);
381 }); 349 });
382 } 350 }
@@ -405,13 +373,16 @@ public class BSLinkset
405 BSPhysObject childx = child; 373 BSPhysObject childx = child;
406 BulletBody childBodyx = child.BSBody; 374 BulletBody childBodyx = child.BSBody;
407 375
408 DetailLog("{0},RemoveChildFromLinkset,call,child={1}", 376 DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
409 rootx.LocalID, 377 childx.LocalID,
410 rootx.LocalID, rootBodyx.ptr.ToString("X"), 378 rootx.LocalID, rootBodyx.ptr.ToString("X"),
411 childx.LocalID, childBodyx.ptr.ToString("X")); 379 childx.LocalID, childBodyx.ptr.ToString("X"));
412 380
413 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 381 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
414 { 382 {
383 if (m_taintChildren.Contains(childx))
384 m_taintChildren.Remove(childx);
385
415 PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); 386 PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx);
416 RecomputeLinksetConstraintVariables(); 387 RecomputeLinksetConstraintVariables();
417 }); 388 });
@@ -551,6 +522,46 @@ public class BSLinkset
551 } 522 }
552 */ 523 */
553 524
525 // Call each of the constraints that make up this linkset and recompute the
526 // various transforms and variables. Used when objects are added or removed
527 // from a linkset to make sure the constraints know about the new mass and
528 // geometry.
529 // Must only be called at taint time!!
530 private void RecomputeLinksetConstraintVariables()
531 {
532 float linksetMass = LinksetMass;
533 foreach (BSPhysObject child in m_taintChildren)
534 {
535 BSConstraint constrain;
536 if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
537 {
538 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
539 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
540 constrain.RecomputeConstraintVariables(linksetMass);
541 }
542 else
543 {
544 // Non-fatal error that happens when children are being added to the linkset but
545 // their constraints have not been created yet.
546 break;
547 }
548 }
549
550 // If the whole linkset is not here, doesn't make sense to recompute linkset wide values
551 if (m_children.Count == m_taintChildren.Count)
552 {
553 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
554 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
555 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
556 foreach (BSPhysObject child in m_taintChildren)
557 {
558 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
559 }
560 }
561 return;
562 }
563
564
554 // Invoke the detailed logger and output something if it's enabled. 565 // Invoke the detailed logger and output something if it's enabled.
555 private void DetailLog(string msg, params Object[] args) 566 private void DetailLog(string msg, params Object[] args)
556 { 567 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index c879143..87ffe3e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -1120,8 +1120,7 @@ public sealed class BSPrim : BSPhysObject
1120 { 1120 {
1121 // Called if the current prim body is about to be destroyed. 1121 // Called if the current prim body is about to be destroyed.
1122 // The problem is the constraints for Linksets which need to be updated for the new body. 1122 // The problem is the constraints for Linksets which need to be updated for the new body.
1123 Linkset.RemoveBodyDependencies(this); 1123 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
1124 needToRestoreLinkset = true;
1125 }); 1124 });
1126 1125
1127 if (needToRestoreLinkset) 1126 if (needToRestoreLinkset)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 2618971..648910a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -144,34 +144,37 @@ public class BSShapeCollection : IDisposable
144 144
145 // Release the usage of a body. 145 // Release the usage of a body.
146 // Called when releasing use of a BSBody. BSShape is handled separately. 146 // Called when releasing use of a BSBody. BSShape is handled separately.
147 public void DereferenceBody(BulletBody shape, bool inTaintTime, BodyDestructionCallback bodyCallback ) 147 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
148 { 148 {
149 if (shape.ptr == IntPtr.Zero) 149 if (body.ptr == IntPtr.Zero)
150 return; 150 return;
151 151
152 lock (m_collectionActivityLock) 152 lock (m_collectionActivityLock)
153 { 153 {
154 BodyDesc bodyDesc; 154 BodyDesc bodyDesc;
155 if (Bodies.TryGetValue(shape.ID, out bodyDesc)) 155 if (Bodies.TryGetValue(body.ID, out bodyDesc))
156 { 156 {
157 bodyDesc.referenceCount--; 157 bodyDesc.referenceCount--;
158 bodyDesc.lastReferenced = System.DateTime.Now; 158 bodyDesc.lastReferenced = System.DateTime.Now;
159 Bodies[shape.ID] = bodyDesc; 159 Bodies[body.ID] = bodyDesc;
160 DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", shape.ID, bodyDesc.referenceCount); 160 DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount);
161 161
162 // If body is no longer being used, free it -- bodies are never shared. 162 // If body is no longer being used, free it -- bodies are never shared.
163 if (bodyDesc.referenceCount == 0) 163 if (bodyDesc.referenceCount == 0)
164 { 164 {
165 Bodies.Remove(shape.ID); 165 Bodies.Remove(body.ID);
166 BSScene.TaintCallback removeOperation = delegate() 166 BSScene.TaintCallback removeOperation = delegate()
167 { 167 {
168 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", 168 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}",
169 shape.ID, shape.ptr.ToString("X")); 169 body.ID, body.ptr.ToString("X"));
170 // If the caller needs to know, pass the event up.
171 if (bodyCallback != null) bodyCallback(body);
172
170 // Zero any reference to the shape so it is not freed when the body is deleted. 173 // Zero any reference to the shape so it is not freed when the body is deleted.
171 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, shape.ptr, IntPtr.Zero); 174 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
172 // It may have already been removed from the world in which case the next is a NOOP. 175 // It may have already been removed from the world in which case the next is a NOOP.
173 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, shape.ptr); 176 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
174 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, shape.ptr); 177 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
175 }; 178 };
176 // If already in taint-time, do the operations now. Otherwise queue for later. 179 // If already in taint-time, do the operations now. Otherwise queue for later.
177 if (inTaintTime) 180 if (inTaintTime)
@@ -182,7 +185,7 @@ public class BSShapeCollection : IDisposable
182 } 185 }
183 else 186 else
184 { 187 {
185 DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", shape.ID, bodyDesc.referenceCount); 188 DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount);
186 } 189 }
187 } 190 }
188 } 191 }