BulletSim: fix crash caused when linksets were rebuilt. A problem added

when individual child pos/rot changes were implementated a week or so ago.
Remove some passing of inTaintTime flag when it was never false.
user_profiles
Robert Adams 2013-01-31 15:52:50 -08:00
parent ed71c939fc
commit 75a05c16c5
5 changed files with 106 additions and 80 deletions

View File

@ -126,9 +126,9 @@ public sealed class BSCharacter : BSPhysObject
DetailLog("{0},BSCharacter.Destroy", LocalID); DetailLog("{0},BSCharacter.Destroy", LocalID);
PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
{ {
PhysicsScene.Shapes.DereferenceBody(PhysBody, true /* inTaintTime */, null /* bodyCallback */); PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
PhysBody.Clear(); PhysBody.Clear();
PhysicsScene.Shapes.DereferenceShape(PhysShape, true /* inTaintTime */, null /* bodyCallback */); PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */);
PhysShape.Clear(); PhysShape.Clear();
}); });
} }

View File

@ -219,28 +219,45 @@ 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;
// The linksetInfo will need to be rebuilt either here or when the linkset is rebuilt
if (LinksetRoot.PhysShape.HasPhysicalShape && lsi != null) if (LinksetRoot.PhysShape.HasPhysicalShape && lsi != null)
{ {
if (PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) if (PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
{ {
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index); int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
if (linksetChildShape.HasPhysicalShape) if (lsi.Index < numLinksetChildren)
{ {
// Compute the offset from the center-of-gravity // It is possible that the linkset is still under construction and the child is not yet
BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement); // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index, // build the whole thing with the new position or rotation.
newLsi.OffsetFromCenterOfMass, // This must be checked for because Bullet references the child array but does no validity
newLsi.OffsetRot, // checking of the child index passed.
true /* shouldRecalculateLocalAabb */); BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index);
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}", if (linksetChildShape.HasPhysicalShape)
updated.LocalID, whichUpdated, newLsi); {
updated.LinksetInfo = newLsi; // Compute the offset from the center-of-gravity
updatedChild = true; BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement);
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index,
newLsi.OffsetFromCenterOfMass,
newLsi.OffsetRot,
true /* shouldRecalculateLocalAabb */);
updated.LinksetInfo = newLsi;
updatedChild = true;
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
updated.LocalID, whichUpdated, newLsi);
}
else // DEBUG DEBUG
{ // DEBUG DEBUG
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
updated.LocalID, linksetChildShape);
} // DEBUG DEBUG
} }
else // DEBUG DEBUG else // DEBUG DEBUG
{ // DEBUG DEBUG { // DEBUG DEBUG
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}", // the child is not yet in the compound shape. This is non-fatal.
updated.LocalID, linksetChildShape); DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
updated.LocalID, numLinksetChildren, lsi.Index);
} // DEBUG DEBUG } // DEBUG DEBUG
} }
else // DEBUG DEBUG else // DEBUG DEBUG
@ -256,6 +273,9 @@ public sealed class BSLinksetCompound : BSLinkset
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
// occur if the linkset is being rebuilt. In this case, scheduling a rebuild is a NOOP since
// 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);
updated.LinksetInfo = null; // setting to 'null' causes relative position to be recomputed. updated.LinksetInfo = null; // setting to 'null' causes relative position to be recomputed.

View File

@ -146,9 +146,9 @@ public sealed class BSPrim : BSPhysObject
{ {
DetailLog("{0},BSPrim.Destroy,taint,", LocalID); DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
// If there are physical body and shape, release my use of same. // If there are physical body and shape, release my use of same.
PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); PhysicsScene.Shapes.DereferenceBody(PhysBody, null);
PhysBody.Clear(); PhysBody.Clear();
PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); PhysicsScene.Shapes.DereferenceShape(PhysShape, null);
PhysShape.Clear(); PhysShape.Clear();
}); });
} }
@ -181,11 +181,19 @@ public sealed class BSPrim : BSPhysObject
public override bool ForceBodyShapeRebuild(bool inTaintTime) public override bool ForceBodyShapeRebuild(bool inTaintTime)
{ {
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() if (inTaintTime)
{ {
_mass = CalculateMass(); // changing the shape changes the mass _mass = CalculateMass(); // changing the shape changes the mass
CreateGeomAndObject(true); CreateGeomAndObject(true);
}); }
else
{
PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
{
_mass = CalculateMass(); // changing the shape changes the mass
CreateGeomAndObject(true);
});
}
return true; return true;
} }
public override bool Grabbed { public override bool Grabbed {

View File

@ -133,48 +133,44 @@ public sealed class BSShapeCollection : IDisposable
// Track another user of a body. // Track another user of a body.
// We presume the caller has allocated the body. // We presume the caller has allocated the body.
// Bodies only have one user so the body is just put into the world if not already there. // Bodies only have one user so the body is just put into the world if not already there.
public void ReferenceBody(BulletBody body, bool inTaintTime) private void ReferenceBody(BulletBody body)
{ {
lock (m_collectionActivityLock) lock (m_collectionActivityLock)
{ {
if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
{ {
if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
{ if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body); }
if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
}
});
} }
} }
// Release the usage of a body. // Release the usage of a body.
// Called when releasing use of a BSBody. BSShape is handled separately. // Called when releasing use of a BSBody. BSShape is handled separately.
public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) // Called in taint time.
public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback )
{ {
if (!body.HasPhysicalBody) if (!body.HasPhysicalBody)
return; return;
PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
lock (m_collectionActivityLock) lock (m_collectionActivityLock)
{ {
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
// If the caller needs to know the old body is going away, pass the event up.
if (bodyCallback != null) bodyCallback(body);
if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
{ {
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
body.ID, body, inTaintTime); if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
// If the caller needs to know the old body is going away, pass the event up. }
if (bodyCallback != null) bodyCallback(body);
if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) // Zero any reference to the shape so it is not freed when the body is deleted.
{ PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
}
// Zero any reference to the shape so it is not freed when the body is deleted.
PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
});
} }
} }
@ -245,44 +241,43 @@ public sealed class BSShapeCollection : IDisposable
} }
// Release the usage of a shape. // Release the usage of a shape.
public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback)
{ {
if (!shape.HasPhysicalShape) if (!shape.HasPhysicalShape)
return; return;
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape");
if (shape.HasPhysicalShape)
{ {
if (shape.HasPhysicalShape) if (shape.isNativeShape)
{ {
if (shape.isNativeShape) // Native shapes are not tracked and are released immediately
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}",
BSScene.DetailLogZero, shape.AddrString);
if (shapeCallback != null) shapeCallback(shape);
PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
}
else
{
switch (shape.type)
{ {
// Native shapes are not tracked and are released immediately case BSPhysicsShapeType.SHAPE_HULL:
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", DereferenceHull(shape, shapeCallback);
BSScene.DetailLogZero, shape.AddrString, inTaintTime); break;
if (shapeCallback != null) shapeCallback(shape); case BSPhysicsShapeType.SHAPE_MESH:
PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); DereferenceMesh(shape, shapeCallback);
} break;
else case BSPhysicsShapeType.SHAPE_COMPOUND:
{ DereferenceCompound(shape, shapeCallback);
switch (shape.type) break;
{ case BSPhysicsShapeType.SHAPE_UNKNOWN:
case BSPhysicsShapeType.SHAPE_HULL: break;
DereferenceHull(shape, shapeCallback); default:
break; break;
case BSPhysicsShapeType.SHAPE_MESH:
DereferenceMesh(shape, shapeCallback);
break;
case BSPhysicsShapeType.SHAPE_COMPOUND:
DereferenceCompound(shape, shapeCallback);
break;
case BSPhysicsShapeType.SHAPE_UNKNOWN:
break;
default:
break;
}
} }
} }
}); }
} }
// Count down the reference count for a mesh shape // Count down the reference count for a mesh shape
@ -393,7 +388,7 @@ public sealed class BSShapeCollection : IDisposable
if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
{ {
DereferenceShape(shapeInfo, true, null); DereferenceShape(shapeInfo, null);
} }
else else
{ {
@ -543,7 +538,7 @@ public sealed class BSShapeCollection : IDisposable
ShapeDestructionCallback shapeCallback) ShapeDestructionCallback shapeCallback)
{ {
// release any previous shape // release any previous shape
DereferenceShape(prim.PhysShape, true, shapeCallback); DereferenceShape(prim.PhysShape, shapeCallback);
BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
@ -611,7 +606,7 @@ public sealed class BSShapeCollection : IDisposable
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
// Since we're recreating new, get rid of the reference to the previous shape // Since we're recreating new, get rid of the reference to the previous shape
DereferenceShape(prim.PhysShape, true, shapeCallback); DereferenceShape(prim.PhysShape, shapeCallback);
newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod);
// Take evasive action if the mesh was not constructed. // Take evasive action if the mesh was not constructed.
@ -682,7 +677,7 @@ public sealed class BSShapeCollection : IDisposable
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
// Remove usage of the previous shape. // Remove usage of the previous shape.
DereferenceShape(prim.PhysShape, true, shapeCallback); DereferenceShape(prim.PhysShape, shapeCallback);
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
newShape = VerifyMeshCreated(newShape, prim); newShape = VerifyMeshCreated(newShape, prim);
@ -817,7 +812,6 @@ public sealed class BSShapeCollection : IDisposable
// Don't need to do this as the shape is freed when the new root shape is created below. // Don't need to do this as the shape is freed when the new root shape is created below.
// DereferenceShape(prim.PhysShape, true, shapeCallback); // DereferenceShape(prim.PhysShape, true, shapeCallback);
BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false); BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false);
// Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
@ -956,7 +950,7 @@ public sealed class BSShapeCollection : IDisposable
if (mustRebuild || forceRebuild) if (mustRebuild || forceRebuild)
{ {
// Free any old body // Free any old body
DereferenceBody(prim.PhysBody, true, bodyCallback); DereferenceBody(prim.PhysBody, bodyCallback);
BulletBody aBody; BulletBody aBody;
if (prim.IsSolid) if (prim.IsSolid)
@ -970,7 +964,7 @@ public sealed class BSShapeCollection : IDisposable
if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
} }
ReferenceBody(aBody, true); ReferenceBody(aBody);
prim.PhysBody = aBody; prim.PhysBody = aBody;

View File

@ -65,6 +65,10 @@ Vehicle attributes are not restored when a vehicle is rezzed on region creation
GENERAL TODO LIST: GENERAL TODO LIST:
================================================= =================================================
Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't.
If arrow show at prim, collision reported about 1/3 of time. If collision reported,
both arrow and prim report it. The arrow bounces off the prim 9 out of 10 times.
Shooting 5m sphere "arrows" at 60m/s.
llMoveToTarget objects are not effected by gravity until target is removed. llMoveToTarget objects are not effected by gravity until target is removed.
Compute CCD parameters based on body size Compute CCD parameters based on body size
Can solver iterations be changed per body/shape? Can be for constraints but what Can solver iterations be changed per body/shape? Can be for constraints but what