aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs185
1 files changed, 95 insertions, 90 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 3e82642..43b1262 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
@@ -160,6 +160,28 @@ public class BSLinkset
160 return ret; 160 return ret;
161 } 161 }
162 162
163 // When physical properties are changed the linkset needs to recalculate
164 // its internal properties.
165 // May be called at runtime or taint-time (just pass the appropriate flag).
166 public void Refresh(BSPhysObject requestor, bool inTaintTime)
167 {
168 // If there are no children, not physical or not root, I am not the one that recomputes the constraints
169 // (For the moment, static linksets do create constraints so remove the test for physical.)
170 if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor))
171 return;
172
173 BSScene.TaintCallback refreshOperation = delegate()
174 {
175 RecomputeLinksetConstraintVariables();
176 DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}",
177 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
178 };
179 if (inTaintTime)
180 refreshOperation();
181 else
182 PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation);
183 }
184
163 // The object is going dynamic (physical). Do any setup necessary 185 // The object is going dynamic (physical). Do any setup necessary
164 // for a dynamic linkset. 186 // for a dynamic linkset.
165 // Only the state of the passed object can be modified. The rest of the linkset 187 // Only the state of the passed object can be modified. The rest of the linkset
@@ -182,22 +204,19 @@ public class BSLinkset
182 return false; 204 return false;
183 } 205 }
184 206
185 // When physical properties are changed the linkset needs to recalculate 207 // If the software is handling the movement of all the objects in a linkset
186 // its internal properties. 208 // (like if one doesn't use constraints for static linksets), this is called
187 // Called at runtime. 209 // when an update for the root of the linkset is received.
188 public void Refresh(BSPhysObject requestor) 210 // Called at taint-time!!
211 public void UpdateProperties(BSPhysObject physObject)
189 { 212 {
190 // If there are no children, there can't be any constraints to recompute 213 // The root local properties have been updated. Apply to the children if appropriate.
191 if (!HasAnyChildren) 214 if (IsRoot(physObject) && HasAnyChildren)
192 return;
193
194 // Only the root does the recomputation
195 if (IsRoot(requestor))
196 { 215 {
197 PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() 216 if (!physObject.IsPhysical)
198 { 217 {
199 RecomputeLinksetConstraintVariables(); 218 // TODO: implement software linkset update for static object linksets
200 }); 219 }
201 } 220 }
202 } 221 }
203 222
@@ -215,13 +234,10 @@ public class BSLinkset
215 if (IsRoot(child)) 234 if (IsRoot(child))
216 { 235 {
217 // If the one with the dependency is root, must undo all children 236 // If the one with the dependency is root, must undo all children
218 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", 237 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
219 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); 238 child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
220 foreach (BSPhysObject bpo in m_taintChildren) 239
221 { 240 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
222 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
223 ret = true;
224 }
225 } 241 }
226 else 242 else
227 { 243 {
@@ -229,20 +245,16 @@ public class BSLinkset
229 child.LocalID, 245 child.LocalID,
230 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), 246 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
231 child.LocalID, child.BSBody.ptr.ToString("X")); 247 child.LocalID, child.BSBody.ptr.ToString("X"));
232 // Remove the dependency on the body of this one 248 // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child);
233 if (m_taintChildren.Contains(child)) 249 // Despite the function name, this removes any link to the specified object.
234 { 250 ret = PhysicallyUnlinkAllChildrenFromRoot(child);
235 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
236 ret = true;
237 }
238 } 251 }
239 } 252 }
240 return ret; 253 return ret;
241 } 254 }
242 255
243 // Routine used when rebuilding the body of the root of the linkset 256 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
244 // This is called after RemoveAllLinksToRoot() to restore all the constraints. 257 // this routine will restore the removed constraints.
245 // This is called when the root body has been changed.
246 // Called at taint-time!! 258 // Called at taint-time!!
247 public void RestoreBodyDependencies(BSPrim child) 259 public void RestoreBodyDependencies(BSPrim child)
248 { 260 {
@@ -254,7 +266,7 @@ public class BSLinkset
254 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); 266 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
255 foreach (BSPhysObject bpo in m_taintChildren) 267 foreach (BSPhysObject bpo in m_taintChildren)
256 { 268 {
257 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); 269 PhysicallyLinkAChildToRoot(LinksetRoot, bpo);
258 } 270 }
259 } 271 }
260 else 272 else
@@ -263,7 +275,7 @@ public class BSLinkset
263 LinksetRoot.LocalID, 275 LinksetRoot.LocalID,
264 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), 276 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
265 child.LocalID, child.BSBody.ptr.ToString("X")); 277 child.LocalID, child.BSBody.ptr.ToString("X"));
266 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); 278 PhysicallyLinkAChildToRoot(LinksetRoot, child);
267 } 279 }
268 } 280 }
269 } 281 }
@@ -330,22 +342,22 @@ public class BSLinkset
330 { 342 {
331 m_children.Add(child); 343 m_children.Add(child);
332 344
333 BSPhysObject rootx = LinksetRoot; // capture the root and body as of now 345 BSPhysObject rootx = LinksetRoot; // capture the root as of now
334 BSPhysObject childx = child; 346 BSPhysObject childx = child;
335 347
336 DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", 348 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 349
341 PhysicsScene.TaintedObject("AddChildToLinkset", delegate() 350 PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
342 { 351 {
343 DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); 352 DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}",
344 // build the physical binding between me and the child 353 rootx.LocalID,
345 m_taintChildren.Add(childx); 354 rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
346 355 childx.LocalID, childx.BSBody.ptr.ToString("X"));
347 // Since this is taint-time, the body and shape could have changed for the child 356 // Since this is taint-time, the body and shape could have changed for the child
348 PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody); 357 rootx.ForcePosition = rootx.Position; // DEBUG
358 childx.ForcePosition = childx.Position; // DEBUG
359 PhysicallyLinkAChildToRoot(rootx, childx);
360 m_taintChildren.Add(child);
349 }); 361 });
350 } 362 }
351 return; 363 return;
@@ -378,10 +390,8 @@ public class BSLinkset
378 390
379 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 391 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
380 { 392 {
381 if (m_taintChildren.Contains(childx)) 393 m_taintChildren.Remove(child);
382 m_taintChildren.Remove(childx); 394 PhysicallyUnlinkAChildFromRoot(rootx, childx);
383
384 PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody);
385 RecomputeLinksetConstraintVariables(); 395 RecomputeLinksetConstraintVariables();
386 }); 396 });
387 397
@@ -396,8 +406,7 @@ public class BSLinkset
396 406
397 // Create a constraint between me (root of linkset) and the passed prim (the child). 407 // Create a constraint between me (root of linkset) and the passed prim (the child).
398 // Called at taint time! 408 // Called at taint time!
399 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody, 409 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
400 BSPhysObject childPrim, BulletBody childBody)
401 { 410 {
402 // Zero motion for children so they don't interpolate 411 // Zero motion for children so they don't interpolate
403 childPrim.ZeroMotion(); 412 childPrim.ZeroMotion();
@@ -409,33 +418,17 @@ public class BSLinkset
409 // real world coordinate of midpoint between the two objects 418 // real world coordinate of midpoint between the two objects
410 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); 419 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
411 420
412 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", 421 DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
413 rootPrim.LocalID, 422 rootPrim.LocalID,
414 rootPrim.LocalID, rootBody.ptr.ToString("X"), 423 rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
415 childPrim.LocalID, childBody.ptr.ToString("X"), 424 childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"),
416 rootPrim.Position, childPrim.Position, midPoint); 425 rootPrim.Position, childPrim.Position, midPoint);
417 426
418 // create a constraint that allows no freedom of movement between the two objects 427 // create a constraint that allows no freedom of movement between the two objects
419 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 428 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
420 429
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( 430 BS6DofConstraint constrain = new BS6DofConstraint(
432 PhysicsScene.World, 431 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 432
440 /* NOTE: below is an attempt to build constraint with full frame computation, etc. 433 /* 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 434 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
@@ -452,7 +445,7 @@ public class BSLinkset
452 445
453 // create a constraint that allows no freedom of movement between the two objects 446 // create a constraint that allows no freedom of movement between the two objects
454 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 447 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
455 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 448 DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
456 BS6DofConstraint constrain = new BS6DofConstraint( 449 BS6DofConstraint constrain = new BS6DofConstraint(
457 PhysicsScene.World, rootPrim.Body, childPrim.Body, 450 PhysicsScene.World, rootPrim.Body, childPrim.Body,
458 OMV.Vector3.Zero, 451 OMV.Vector3.Zero,
@@ -486,39 +479,44 @@ public class BSLinkset
486 { 479 {
487 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); 480 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
488 } 481 }
489
490 RecomputeLinksetConstraintVariables();
491 } 482 }
492 483
493 // Remove linkage between myself and a particular child 484 // 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 485 // The root and child bodies are passed in because we need to remove the constraint between
495 // the bodies that were at unlink time. 486 // the bodies that were at unlink time.
496 // Called at taint time! 487 // Called at taint time!
497 private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, 488 private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
498 BSPhysObject childPrim, BulletBody childBody)
499 { 489 {
500 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", 490 bool ret = false;
491 DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
501 rootPrim.LocalID, 492 rootPrim.LocalID,
502 rootPrim.LocalID, rootBody.ptr.ToString("X"), 493 rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
503 childPrim.LocalID, childBody.ptr.ToString("X")); 494 childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"));
504 495
505 // Find the constraint for this link and get rid of it from the overall collection and from my list 496 // 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); 497 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody))
498 {
499 // Make the child refresh its location
500 BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
501 ret = true;
502 }
507 503
508 // Make the child refresh its location 504 return ret;
509 BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
510 } 505 }
511 506
512 /*
513 // Remove linkage between myself and any possible children I might have. 507 // Remove linkage between myself and any possible children I might have.
514 // Called at taint time! 508 // Called at taint time!
515 private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) 509 private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
516 { 510 {
517 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 511 DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
512 bool ret = false;
518 513
519 PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); 514 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody))
515 {
516 ret = true;
517 }
518 return ret;
520 } 519 }
521 */
522 520
523 // Call each of the constraints that make up this linkset and recompute the 521 // 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 522 // various transforms and variables. Used when objects are added or removed
@@ -550,11 +548,17 @@ public class BSLinkset
550 { 548 {
551 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass 549 // 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(); 550 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
553 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); 551 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr,
552 centerOfMass, OMV.Quaternion.Identity);
553 DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}",
554 LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"));
554 foreach (BSPhysObject child in m_taintChildren) 555 foreach (BSPhysObject child in m_taintChildren)
555 { 556 {
556 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); 557 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr,
558 centerOfMass, OMV.Quaternion.Identity);
557 } 559 }
560
561 // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG
558 } 562 }
559 return; 563 return;
560 } 564 }
@@ -563,7 +567,8 @@ public class BSLinkset
563 // Invoke the detailed logger and output something if it's enabled. 567 // Invoke the detailed logger and output something if it's enabled.
564 private void DetailLog(string msg, params Object[] args) 568 private void DetailLog(string msg, params Object[] args)
565 { 569 {
566 PhysicsScene.PhysicsLogging.Write(msg, args); 570 if (PhysicsScene.PhysicsLogging.Enabled)
571 PhysicsScene.DetailLog(msg, args);
567 } 572 }
568 573
569} 574}