diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 137 |
1 files changed, 63 insertions, 74 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3e82642..20db4de 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -52,8 +52,8 @@ public class BSLinkset | |||
52 | // the physical 'taint' children separately. | 52 | // the physical 'taint' children separately. |
53 | // After taint processing and before the simulation step, these | 53 | // After taint processing and before the simulation step, these |
54 | // two lists must be the same. | 54 | // two lists must be the same. |
55 | private List<BSPhysObject> m_children; | 55 | private HashSet<BSPhysObject> m_children; |
56 | private List<BSPhysObject> m_taintChildren; | 56 | private HashSet<BSPhysObject> m_taintChildren; |
57 | 57 | ||
58 | // We lock the diddling of linkset classes to prevent any badness. | 58 | // We lock the diddling of linkset classes to prevent any badness. |
59 | // This locks the modification of the instances of this class. Changes | 59 | // This locks the modification of the instances of this class. Changes |
@@ -90,8 +90,8 @@ public class BSLinkset | |||
90 | m_nextLinksetID = 1; | 90 | m_nextLinksetID = 1; |
91 | PhysicsScene = scene; | 91 | PhysicsScene = scene; |
92 | LinksetRoot = parent; | 92 | LinksetRoot = parent; |
93 | m_children = new List<BSPhysObject>(); | 93 | m_children = new HashSet<BSPhysObject>(); |
94 | m_taintChildren = new List<BSPhysObject>(); | 94 | m_taintChildren = new HashSet<BSPhysObject>(); |
95 | m_mass = parent.MassRaw; | 95 | m_mass = parent.MassRaw; |
96 | } | 96 | } |
97 | 97 | ||
@@ -197,6 +197,8 @@ public class BSLinkset | |||
197 | PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() | 197 | PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() |
198 | { | 198 | { |
199 | RecomputeLinksetConstraintVariables(); | 199 | RecomputeLinksetConstraintVariables(); |
200 | DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", | ||
201 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); | ||
200 | }); | 202 | }); |
201 | } | 203 | } |
202 | } | 204 | } |
@@ -215,13 +217,10 @@ public class BSLinkset | |||
215 | if (IsRoot(child)) | 217 | if (IsRoot(child)) |
216 | { | 218 | { |
217 | // If the one with the dependency is root, must undo all children | 219 | // If the one with the dependency is root, must undo all children |
218 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", | 220 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", |
219 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); | 221 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); |
220 | foreach (BSPhysObject bpo in m_taintChildren) | 222 | |
221 | { | 223 | ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); |
222 | PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); | ||
223 | ret = true; | ||
224 | } | ||
225 | } | 224 | } |
226 | else | 225 | else |
227 | { | 226 | { |
@@ -229,12 +228,9 @@ public class BSLinkset | |||
229 | child.LocalID, | 228 | child.LocalID, |
230 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), | 229 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), |
231 | child.LocalID, child.BSBody.ptr.ToString("X")); | 230 | child.LocalID, child.BSBody.ptr.ToString("X")); |
232 | // Remove the dependency on the body of this one | 231 | // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); |
233 | if (m_taintChildren.Contains(child)) | 232 | // Despite the function name, this removes any link to the specified object. |
234 | { | 233 | ret = PhysicallyUnlinkAllChildrenFromRoot(child); |
235 | PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); | ||
236 | ret = true; | ||
237 | } | ||
238 | } | 234 | } |
239 | } | 235 | } |
240 | return ret; | 236 | return ret; |
@@ -254,7 +250,7 @@ public class BSLinkset | |||
254 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); | 250 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); |
255 | foreach (BSPhysObject bpo in m_taintChildren) | 251 | foreach (BSPhysObject bpo in m_taintChildren) |
256 | { | 252 | { |
257 | PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); | 253 | PhysicallyLinkAChildToRoot(LinksetRoot, bpo); |
258 | } | 254 | } |
259 | } | 255 | } |
260 | else | 256 | else |
@@ -263,7 +259,7 @@ public class BSLinkset | |||
263 | LinksetRoot.LocalID, | 259 | LinksetRoot.LocalID, |
264 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), | 260 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), |
265 | child.LocalID, child.BSBody.ptr.ToString("X")); | 261 | child.LocalID, child.BSBody.ptr.ToString("X")); |
266 | PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); | 262 | PhysicallyLinkAChildToRoot(LinksetRoot, child); |
267 | } | 263 | } |
268 | } | 264 | } |
269 | } | 265 | } |
@@ -330,22 +326,22 @@ public class BSLinkset | |||
330 | { | 326 | { |
331 | m_children.Add(child); | 327 | m_children.Add(child); |
332 | 328 | ||
333 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now | 329 | BSPhysObject rootx = LinksetRoot; // capture the root as of now |
334 | BSPhysObject childx = child; | 330 | BSPhysObject childx = child; |
335 | 331 | ||
336 | DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | 332 | DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); |
337 | rootx.LocalID, | ||
338 | rootx.LocalID, rootx.BSBody.ptr.ToString("X"), | ||
339 | childx.LocalID, childx.BSBody.ptr.ToString("X")); | ||
340 | 333 | ||
341 | PhysicsScene.TaintedObject("AddChildToLinkset", delegate() | 334 | PhysicsScene.TaintedObject("AddChildToLinkset", delegate() |
342 | { | 335 | { |
343 | DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); | 336 | DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", |
344 | // build the physical binding between me and the child | 337 | rootx.LocalID, |
345 | m_taintChildren.Add(childx); | 338 | rootx.LocalID, rootx.BSBody.ptr.ToString("X"), |
346 | 339 | childx.LocalID, childx.BSBody.ptr.ToString("X")); | |
347 | // Since this is taint-time, the body and shape could have changed for the child | 340 | // Since this is taint-time, the body and shape could have changed for the child |
348 | PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody); | 341 | rootx.ForcePosition = rootx.Position; // DEBUG |
342 | childx.ForcePosition = childx.Position; // DEBUG | ||
343 | PhysicallyLinkAChildToRoot(rootx, childx); | ||
344 | m_taintChildren.Add(child); | ||
349 | }); | 345 | }); |
350 | } | 346 | } |
351 | return; | 347 | return; |
@@ -378,10 +374,8 @@ public class BSLinkset | |||
378 | 374 | ||
379 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() | 375 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() |
380 | { | 376 | { |
381 | if (m_taintChildren.Contains(childx)) | 377 | m_taintChildren.Remove(child); |
382 | m_taintChildren.Remove(childx); | 378 | PhysicallyUnlinkAChildFromRoot(rootx, childx); |
383 | |||
384 | PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody); | ||
385 | RecomputeLinksetConstraintVariables(); | 379 | RecomputeLinksetConstraintVariables(); |
386 | }); | 380 | }); |
387 | 381 | ||
@@ -396,8 +390,7 @@ public class BSLinkset | |||
396 | 390 | ||
397 | // Create a constraint between me (root of linkset) and the passed prim (the child). | 391 | // Create a constraint between me (root of linkset) and the passed prim (the child). |
398 | // Called at taint time! | 392 | // Called at taint time! |
399 | private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody, | 393 | private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) |
400 | BSPhysObject childPrim, BulletBody childBody) | ||
401 | { | 394 | { |
402 | // Zero motion for children so they don't interpolate | 395 | // Zero motion for children so they don't interpolate |
403 | childPrim.ZeroMotion(); | 396 | childPrim.ZeroMotion(); |
@@ -409,33 +402,17 @@ public class BSLinkset | |||
409 | // real world coordinate of midpoint between the two objects | 402 | // real world coordinate of midpoint between the two objects |
410 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); | 403 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); |
411 | 404 | ||
412 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", | 405 | DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", |
413 | rootPrim.LocalID, | 406 | rootPrim.LocalID, |
414 | rootPrim.LocalID, rootBody.ptr.ToString("X"), | 407 | rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), |
415 | childPrim.LocalID, childBody.ptr.ToString("X"), | 408 | childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), |
416 | rootPrim.Position, childPrim.Position, midPoint); | 409 | rootPrim.Position, childPrim.Position, midPoint); |
417 | 410 | ||
418 | // create a constraint that allows no freedom of movement between the two objects | 411 | // create a constraint that allows no freedom of movement between the two objects |
419 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | 412 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 |
420 | 413 | ||
421 | // There is great subtlty in these paramters. Notice the check for a ptr of zero. | ||
422 | // We pass the BulletBody structure into the taint in order to capture the pointer | ||
423 | // of the body at the time of constraint creation. This doesn't work for the very first | ||
424 | // construction because there is no body yet. The body | ||
425 | // is constructed later at taint time. Thus we use the body address at time of the | ||
426 | // taint creation but, if it is zero, use what's in the prim at the moment. | ||
427 | // There is a possible race condition since shape can change without a taint call | ||
428 | // (like changing to a mesh that is already constructed). The fix for that would be | ||
429 | // to only change BSShape at taint time thus syncronizing these operations at | ||
430 | // the cost of efficiency and lag. | ||
431 | BS6DofConstraint constrain = new BS6DofConstraint( | 414 | BS6DofConstraint constrain = new BS6DofConstraint( |
432 | PhysicsScene.World, | 415 | PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); |
433 | rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody, | ||
434 | childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody, | ||
435 | midPoint, | ||
436 | true, | ||
437 | true | ||
438 | ); | ||
439 | 416 | ||
440 | /* NOTE: below is an attempt to build constraint with full frame computation, etc. | 417 | /* NOTE: below is an attempt to build constraint with full frame computation, etc. |
441 | * Using the midpoint is easier since it lets the Bullet code manipulate the transforms | 418 | * Using the midpoint is easier since it lets the Bullet code manipulate the transforms |
@@ -452,7 +429,7 @@ public class BSLinkset | |||
452 | 429 | ||
453 | // create a constraint that allows no freedom of movement between the two objects | 430 | // create a constraint that allows no freedom of movement between the two objects |
454 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | 431 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 |
455 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); | 432 | DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); |
456 | BS6DofConstraint constrain = new BS6DofConstraint( | 433 | BS6DofConstraint constrain = new BS6DofConstraint( |
457 | PhysicsScene.World, rootPrim.Body, childPrim.Body, | 434 | PhysicsScene.World, rootPrim.Body, childPrim.Body, |
458 | OMV.Vector3.Zero, | 435 | OMV.Vector3.Zero, |
@@ -486,39 +463,44 @@ public class BSLinkset | |||
486 | { | 463 | { |
487 | constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); | 464 | constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); |
488 | } | 465 | } |
489 | |||
490 | RecomputeLinksetConstraintVariables(); | ||
491 | } | 466 | } |
492 | 467 | ||
493 | // Remove linkage between myself and a particular child | 468 | // Remove linkage between myself and a particular child |
494 | // The root and child bodies are passed in because we need to remove the constraint between | 469 | // The root and child bodies are passed in because we need to remove the constraint between |
495 | // the bodies that were at unlink time. | 470 | // the bodies that were at unlink time. |
496 | // Called at taint time! | 471 | // Called at taint time! |
497 | private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, | 472 | private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) |
498 | BSPhysObject childPrim, BulletBody childBody) | ||
499 | { | 473 | { |
500 | DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", | 474 | bool ret = false; |
475 | DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", | ||
501 | rootPrim.LocalID, | 476 | rootPrim.LocalID, |
502 | rootPrim.LocalID, rootBody.ptr.ToString("X"), | 477 | rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), |
503 | childPrim.LocalID, childBody.ptr.ToString("X")); | 478 | childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); |
504 | 479 | ||
505 | // Find the constraint for this link and get rid of it from the overall collection and from my list | 480 | // Find the constraint for this link and get rid of it from the overall collection and from my list |
506 | PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody); | 481 | if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) |
482 | { | ||
483 | // Make the child refresh its location | ||
484 | BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); | ||
485 | ret = true; | ||
486 | } | ||
507 | 487 | ||
508 | // Make the child refresh its location | 488 | return ret; |
509 | BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); | ||
510 | } | 489 | } |
511 | 490 | ||
512 | /* | ||
513 | // Remove linkage between myself and any possible children I might have. | 491 | // Remove linkage between myself and any possible children I might have. |
514 | // Called at taint time! | 492 | // Called at taint time! |
515 | private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) | 493 | private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) |
516 | { | 494 | { |
517 | DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); | 495 | DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); |
496 | bool ret = false; | ||
518 | 497 | ||
519 | PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); | 498 | if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) |
499 | { | ||
500 | ret = true; | ||
501 | } | ||
502 | return ret; | ||
520 | } | 503 | } |
521 | */ | ||
522 | 504 | ||
523 | // Call each of the constraints that make up this linkset and recompute the | 505 | // Call each of the constraints that make up this linkset and recompute the |
524 | // various transforms and variables. Used when objects are added or removed | 506 | // various transforms and variables. Used when objects are added or removed |
@@ -550,11 +532,17 @@ public class BSLinkset | |||
550 | { | 532 | { |
551 | // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass | 533 | // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass |
552 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); | 534 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); |
553 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); | 535 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, |
536 | centerOfMass, OMV.Quaternion.Identity); | ||
537 | DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", | ||
538 | LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); | ||
554 | foreach (BSPhysObject child in m_taintChildren) | 539 | foreach (BSPhysObject child in m_taintChildren) |
555 | { | 540 | { |
556 | BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); | 541 | BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, |
542 | centerOfMass, OMV.Quaternion.Identity); | ||
557 | } | 543 | } |
544 | |||
545 | // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG | ||
558 | } | 546 | } |
559 | return; | 547 | return; |
560 | } | 548 | } |
@@ -563,7 +551,8 @@ public class BSLinkset | |||
563 | // Invoke the detailed logger and output something if it's enabled. | 551 | // Invoke the detailed logger and output something if it's enabled. |
564 | private void DetailLog(string msg, params Object[] args) | 552 | private void DetailLog(string msg, params Object[] args) |
565 | { | 553 | { |
566 | PhysicsScene.PhysicsLogging.Write(msg, args); | 554 | if (PhysicsScene.PhysicsLogging.Enabled) |
555 | PhysicsScene.DetailLog(msg, args); | ||
567 | } | 556 | } |
568 | 557 | ||
569 | } | 558 | } |