diff options
Merge branch 'master' of git://opensimulator.org/git/opensim
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | 155 |
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 | } |