aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs155
1 files changed, 74 insertions, 81 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 36bae9b..4ce58c7 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -93,7 +93,8 @@ public sealed class BSLinksetCompound : BSLinkset
93{ 93{
94 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; 94 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
95 95
96 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) : base(scene, parent) 96 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
97 : base(scene, parent)
97 { 98 {
98 } 99 }
99 100
@@ -217,59 +218,45 @@ public sealed class BSLinksetCompound : BSLinkset
217 // and that is caused by us updating the object. 218 // and that is caused by us updating the object.
218 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) 219 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
219 { 220 {
220 // Gather the child info. It might not be there if the linkset is in transition.
221 BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo;
222 if (lsi != null)
223 {
224 // Since the child moved or rotationed, it needs a new relative position within the linkset
225 BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, OMV.Vector3.Zero);
226 updated.LinksetInfo = newLsi;
227
228 // Find the physical instance of the child 221 // Find the physical instance of the child
229 if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) 222 if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
223 {
224 // It is possible that the linkset is still under construction and the child is not yet
225 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
226 // build the whole thing with the new position or rotation.
227 // The index must be checked because Bullet references the child array but does no validity
228 // checking of the child index passed.
229 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
230 if (updated.LinksetChildIndex < numLinksetChildren)
230 { 231 {
231 // It is possible that the linkset is still under construction and the child is not yet 232 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex);
232 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will 233 if (linksetChildShape.HasPhysicalShape)
233 // build the whole thing with the new position or rotation.
234 // The index must be checked because Bullet references the child array but does no validity
235 // checking of the child index passed.
236 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
237 if (lsi.Index < numLinksetChildren)
238 { 234 {
239 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index); 235 // Found the child shape within the compound shape
240 if (linksetChildShape.HasPhysicalShape) 236 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex,
241 { 237 updated.RawPosition - LinksetRoot.RawPosition,
242 // Found the child shape within the compound shape 238 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
243 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index, 239 true /* shouldRecalculateLocalAabb */);
244 newLsi.OffsetFromCenterOfMass, 240 updatedChild = true;
245 newLsi.OffsetRot, 241 DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},pos={2},rot={3}",
246 true /* shouldRecalculateLocalAabb */); 242 updated.LocalID, whichUpdated, updated.RawPosition, updated.RawOrientation);
247 updatedChild = true;
248 DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
249 updated.LocalID, whichUpdated, newLsi);
250 }
251 else // DEBUG DEBUG
252 { // DEBUG DEBUG
253 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
254 updated.LocalID, linksetChildShape);
255 } // DEBUG DEBUG
256 } 243 }
257 else // DEBUG DEBUG 244 else // DEBUG DEBUG
258 { // DEBUG DEBUG 245 { // DEBUG DEBUG
259 // the child is not yet in the compound shape. This is non-fatal. 246 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
260 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}", 247 updated.LocalID, linksetChildShape);
261 updated.LocalID, numLinksetChildren, lsi.Index);
262 } // DEBUG DEBUG 248 } // DEBUG DEBUG
263 } 249 }
264 else // DEBUG DEBUG 250 else // DEBUG DEBUG
265 { // DEBUG DEBUG 251 { // DEBUG DEBUG
266 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID); 252 // the child is not yet in the compound shape. This is non-fatal.
253 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
254 updated.LocalID, numLinksetChildren, updated.LinksetChildIndex);
267 } // DEBUG DEBUG 255 } // DEBUG DEBUG
268 } 256 }
269 else // DEBUG DEBUG 257 else // DEBUG DEBUG
270 { // DEBUG DEBUG 258 { // DEBUG DEBUG
271 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}", 259 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
272 updated.LocalID, LinksetRoot.PhysShape);
273 } // DEBUG DEBUG 260 } // DEBUG DEBUG
274 261
275 if (!updatedChild) 262 if (!updatedChild)
@@ -379,6 +366,8 @@ public sealed class BSLinksetCompound : BSLinkset
379 // Safe to call even if the child is not really in the linkset. 366 // Safe to call even if the child is not really in the linkset.
380 protected override void RemoveChildFromLinkset(BSPrimLinkable child) 367 protected override void RemoveChildFromLinkset(BSPrimLinkable child)
381 { 368 {
369 child.ClearDisplacement();
370
382 if (m_children.Remove(child)) 371 if (m_children.Remove(child))
383 { 372 {
384 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", 373 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
@@ -424,30 +413,31 @@ public sealed class BSLinksetCompound : BSLinkset
424 // The center of mass for the linkset is the geometric center of the group. 413 // The center of mass for the linkset is the geometric center of the group.
425 // Compute a displacement for each component so it is relative to the center-of-mass. 414 // Compute a displacement for each component so it is relative to the center-of-mass.
426 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass 415 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
427 OMV.Vector3 centerOfMass; 416 OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition;
428 OMV.Vector3 centerDisplacement = OMV.Vector3.Zero; 417 if (!disableCOM) // DEBUG DEBUG
429 if (disableCOM) // DEBUG DEBUG
430 { // DEBUG DEBUG
431 centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG
432 // LinksetRoot.PositionDisplacement = OMV.Vector3.Zero;
433 } // DEBUG DEBUG
434 else
435 { 418 {
436 centerOfMass = ComputeLinksetCenterOfMass(); 419 // Compute a center-of-mass in world coordinates.
437 // 'centerDisplacement' is the value to *add* to all the shape offsets 420 centerOfMassW = ComputeLinksetCenterOfMass();
438 centerDisplacement = LinksetRoot.RawPosition - centerOfMass;
439
440 // Since we're displacing the center of the shape, we need to move the body in the world
441 // LinksetRoot.PositionDisplacement = centerDisplacement;
442
443 // This causes the root prim position to be set properly based on the new PositionDisplacement
444 LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
445 // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
446 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false);
447 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
448 LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement);
449 } 421 }
450 422
423 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
424
425 // 'centerDisplacement' is the value to subtract from children to give physical offset position
426 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
427 LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement);
428
429 // This causes the physical position of the root prim to be offset to accomodate for the displacements
430 LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
431
432 // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
433 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */,
434 -centerDisplacement,
435 OMV.Quaternion.Identity, // LinksetRoot.RawOrientation,
436 false /* shouldRecalculateLocalAabb (is done later after linkset built) */);
437
438 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
439 LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement);
440
451 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", 441 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
452 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); 442 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
453 443
@@ -455,38 +445,33 @@ public sealed class BSLinksetCompound : BSLinkset
455 int memberIndex = 1; 445 int memberIndex = 1;
456 ForEachMember(delegate(BSPrimLinkable cPrim) 446 ForEachMember(delegate(BSPrimLinkable cPrim)
457 { 447 {
458 if (!IsRoot(cPrim)) 448 if (IsRoot(cPrim))
459 { 449 {
460 // Compute the displacement of the child from the root of the linkset. 450 cPrim.LinksetChildIndex = 0;
461 // This info is saved in the child prim so the relationship does not 451 }
462 // change over time and the new child position can be computed 452 else
463 // when the linkset is being disassembled (the linkset may have moved). 453 {
464 BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; 454 cPrim.LinksetChildIndex = memberIndex;
465 if (lci == null)
466 {
467 lci = new BSLinksetCompoundInfo(memberIndex, LinksetRoot, cPrim, centerDisplacement);
468 cPrim.LinksetInfo = lci;
469 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
470 }
471
472 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
473 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
474 455
475 if (cPrim.PhysShape.isNativeShape) 456 if (cPrim.PhysShape.isNativeShape)
476 { 457 {
477 // A native shape is turned into a hull collision shape because native 458 // A native shape is turned into a hull collision shape because native
478 // shapes are not shared so we have to hullify it so it will be tracked 459 // shapes are not shared so we have to hullify it so it will be tracked
479 // and freed at the correct time. This also solves the scaling problem 460 // and freed at the correct time. This also solves the scaling problem
480 // (native shapes scaled but hull/meshes are assumed to not be). 461 // (native shapes scale but hull/meshes are assumed to not be).
481 // TODO: decide of the native shape can just be used in the compound shape. 462 // TODO: decide of the native shape can just be used in the compound shape.
482 // Use call to CreateGeomNonSpecial(). 463 // Use call to CreateGeomNonSpecial().
483 BulletShape saveShape = cPrim.PhysShape; 464 BulletShape saveShape = cPrim.PhysShape;
484 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape 465 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
485 // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
486 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); 466 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
487 BulletShape newShape = cPrim.PhysShape; 467 BulletShape newShape = cPrim.PhysShape;
488 cPrim.PhysShape = saveShape; 468 cPrim.PhysShape = saveShape;
489 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot); 469
470 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
471 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
472 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
473 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
474 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
490 } 475 }
491 else 476 else
492 { 477 {
@@ -498,9 +483,13 @@ public sealed class BSLinksetCompound : BSLinkset
498 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", 483 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
499 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); 484 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
500 } 485 }
501 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot); 486 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
487 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
488 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
489 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
490 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
491
502 } 492 }
503 lci.Index = memberIndex;
504 memberIndex++; 493 memberIndex++;
505 } 494 }
506 return false; // 'false' says to move onto the next child in the list 495 return false; // 'false' says to move onto the next child in the list
@@ -509,12 +498,16 @@ public sealed class BSLinksetCompound : BSLinkset
509 // With all of the linkset packed into the root prim, it has the mass of everyone. 498 // With all of the linkset packed into the root prim, it has the mass of everyone.
510 LinksetMass = ComputeLinksetMass(); 499 LinksetMass = ComputeLinksetMass();
511 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); 500 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
501
502 // Enable the physical position updator to return the position and rotation of the root shape
503 PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
512 } 504 }
513 finally 505 finally
514 { 506 {
515 Rebuilding = false; 507 Rebuilding = false;
516 } 508 }
517 509
510 // See that the Aabb surrounds the new shape
518 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); 511 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
519 } 512 }
520} 513}