BulletSim: fix problem where editting a physical linkset caused the

child prim physical positions to get out of sync with the view.
More reliably compute the offset of children in a physical linkset.
user_profiles
Robert Adams 2013-02-01 11:52:27 -08:00
parent 75a05c16c5
commit 5bb85a14d4
2 changed files with 33 additions and 19 deletions

View File

@ -219,30 +219,31 @@ public sealed class BSLinksetCompound : BSLinkset
{ {
// Gather the child info. It might not be there if the linkset is in transition. // Gather the child info. It might not be there if the linkset is in transition.
BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo; BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo;
if (lsi != null)
// The linksetInfo will need to be rebuilt either here or when the linkset is rebuilt
if (LinksetRoot.PhysShape.HasPhysicalShape && lsi != null)
{ {
if (PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) // Since the child moved or rotationed, it needs a new relative position within the linkset
BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement);
updated.LinksetInfo = newLsi;
// Find the physical instance of the child
if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
{ {
// It is possible that the linkset is still under construction and the child is not yet
// inserted into the compound shape. A rebuild of the linkset in a pre-step action will
// build the whole thing with the new position or rotation.
// The index must be checked because Bullet references the child array but does no validity
// checking of the child index passed.
int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
if (lsi.Index < numLinksetChildren) if (lsi.Index < numLinksetChildren)
{ {
// It is possible that the linkset is still under construction and the child is not yet
// inserted into the compound shape. A rebuild of the linkset in a pre-step action will
// build the whole thing with the new position or rotation.
// This must be checked for because Bullet references the child array but does no validity
// checking of the child index passed.
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index); BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index);
if (linksetChildShape.HasPhysicalShape) if (linksetChildShape.HasPhysicalShape)
{ {
// Compute the offset from the center-of-gravity // Found the child shape within the compound shape
BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement);
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index, PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index,
newLsi.OffsetFromCenterOfMass, newLsi.OffsetFromCenterOfMass,
newLsi.OffsetRot, newLsi.OffsetRot,
true /* shouldRecalculateLocalAabb */); true /* shouldRecalculateLocalAabb */);
updated.LinksetInfo = newLsi;
updatedChild = true; updatedChild = true;
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}", DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
updated.LocalID, whichUpdated, newLsi); updated.LocalID, whichUpdated, newLsi);
@ -262,19 +263,20 @@ public sealed class BSLinksetCompound : BSLinkset
} }
else // DEBUG DEBUG else // DEBUG DEBUG
{ // DEBUG DEBUG { // DEBUG DEBUG
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,notCompound", updated.LocalID); DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
} // DEBUG DEBUG } // DEBUG DEBUG
} }
else // DEBUG DEBUG else // DEBUG DEBUG
{ // DEBUG DEBUG { // DEBUG DEBUG
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,rootPhysShape={1},lsi={2}", DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}",
updated.LocalID, LinksetRoot.PhysShape, lsi == null ? "NULL" : lsi.ToString()); updated.LocalID, LinksetRoot.PhysShape);
} // DEBUG DEBUG } // DEBUG DEBUG
if (!updatedChild) if (!updatedChild)
{ {
// If couldn't do the individual child, the linkset needs a rebuild to incorporate the new child info. // If couldn't do the individual child, the linkset needs a rebuild to incorporate the new child info.
// Note that there are several ways through this code that will not update the child that can // Note: there are several ways through this code that will not update the child if
// occur if the linkset is being rebuilt. In this case, scheduling a rebuild is a NOOP since // the linkset is being rebuilt. In this case, scheduling a rebuild is a NOOP since
// there will already be a rebuild scheduled. // there will already be a rebuild scheduled.
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}", DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
updated.LocalID, whichUpdated); updated.LocalID, whichUpdated);
@ -300,7 +302,8 @@ public sealed class BSLinksetCompound : BSLinkset
{ {
// Because it is a convenient time, recompute child world position and rotation based on // Because it is a convenient time, recompute child world position and rotation based on
// its position in the linkset. // its position in the linkset.
RecomputeChildWorldPosition(child, true); RecomputeChildWorldPosition(child, true /* inTaintTime */);
child.LinksetInfo = null;
} }
// Cannot schedule a refresh/rebuild here because this routine is called when // Cannot schedule a refresh/rebuild here because this routine is called when
@ -315,6 +318,14 @@ public sealed class BSLinksetCompound : BSLinkset
// prim. The child prim's location must be recomputed based on the location of the root shape. // prim. The child prim's location must be recomputed based on the location of the root shape.
private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime) private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime)
{ {
// For the moment (20130201), disable this computation (converting the child physical addr back to
// a region address) until we have a good handle on center-of-mass offsets and what the physics
// engine moving a child actually means.
// The simulator keeps track of where children should be as the linkset moves. Setting
// the pos/rot here does not effect that knowledge as there is no good way for the
// physics engine to send the simulator an update for a child.
/*
BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo; BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
if (lci != null) if (lci != null)
{ {
@ -343,6 +354,7 @@ public sealed class BSLinksetCompound : BSLinkset
// LogHeader, child.LocalID); // LogHeader, child.LocalID);
DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID); DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
} }
*/
} }
// ================================================================ // ================================================================
@ -376,6 +388,7 @@ public sealed class BSLinksetCompound : BSLinkset
// Cause the child's body to be rebuilt and thus restored to normal operation // Cause the child's body to be rebuilt and thus restored to normal operation
RecomputeChildWorldPosition(child, false); RecomputeChildWorldPosition(child, false);
child.LinksetInfo = null;
child.ForceBodyShapeRebuild(false); child.ForceBodyShapeRebuild(false);
if (!HasAnyChildren) if (!HasAnyChildren)
@ -397,7 +410,7 @@ public sealed class BSLinksetCompound : BSLinkset
// Constraint linksets are rebuilt every time. // Constraint linksets are rebuilt every time.
// Note that this works for rebuilding just the root after a linkset is taken apart. // Note that this works for rebuilding just the root after a linkset is taken apart.
// Called at taint time!! // Called at taint time!!
private bool disableCOM = true; // disable until we get this debugged private bool disableCOM = true; // DEBUG DEBUG: disable until we get this debugged
private void RecomputeLinksetCompound() private void RecomputeLinksetCompound()
{ {
try try

View File

@ -127,6 +127,7 @@ Physical and phantom will drop through the terrain
LINKSETS LINKSETS
====================================================== ======================================================
Child prims do not report collisions
Editing a child of a linkset causes the child to go phantom Editing a child of a linkset causes the child to go phantom
Move a child prim once when it is physical and can never move it again without it going phantom Move a child prim once when it is physical and can never move it again without it going phantom
Offset the center of the linkset to be the geometric center of all the prims Offset the center of the linkset to be the geometric center of all the prims