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);
PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
{
PhysicsScene.Shapes.DereferenceBody(PhysBody, true /* inTaintTime */, null /* bodyCallback */);
PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
PhysBody.Clear();
PhysicsScene.Shapes.DereferenceShape(PhysShape, true /* inTaintTime */, null /* bodyCallback */);
PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */);
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.
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 (PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
{
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index);
if (linksetChildShape.HasPhysicalShape)
int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
if (lsi.Index < numLinksetChildren)
{
// Compute the offset from the center-of-gravity
BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement);
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index,
newLsi.OffsetFromCenterOfMass,
newLsi.OffsetRot,
true /* shouldRecalculateLocalAabb */);
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
updated.LocalID, whichUpdated, newLsi);
updated.LinksetInfo = newLsi;
updatedChild = true;
// 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);
if (linksetChildShape.HasPhysicalShape)
{
// Compute the offset from the center-of-gravity
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
{ // DEBUG DEBUG
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
updated.LocalID, linksetChildShape);
// the child is not yet in the compound shape. This is non-fatal.
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
updated.LocalID, numLinksetChildren, lsi.Index);
} // DEBUG DEBUG
}
else // DEBUG DEBUG
@ -256,6 +273,9 @@ public sealed class BSLinksetCompound : BSLinkset
if (!updatedChild)
{
// 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}",
updated.LocalID, whichUpdated);
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);
// 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();
PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
PhysicsScene.Shapes.DereferenceShape(PhysShape, null);
PhysShape.Clear();
});
}
@ -181,11 +181,19 @@ public sealed class BSPrim : BSPhysObject
public override bool ForceBodyShapeRebuild(bool inTaintTime)
{
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
if (inTaintTime)
{
_mass = CalculateMass(); // changing the shape changes the mass
CreateGeomAndObject(true);
});
}
else
{
PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
{
_mass = CalculateMass(); // changing the shape changes the mass
CreateGeomAndObject(true);
});
}
return true;
}
public override bool Grabbed {

View File

@ -133,48 +133,44 @@ public sealed class BSShapeCollection : IDisposable
// Track another user of a 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.
public void ReferenceBody(BulletBody body, bool inTaintTime)
private void ReferenceBody(BulletBody body)
{
lock (m_collectionActivityLock)
{
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.
// 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)
return;
PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
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}",
body.ID, body, inTaintTime);
// If the caller needs to know the old body is going away, pass the event up.
if (bodyCallback != null) bodyCallback(body);
PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
}
if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
{
PhysicsScene.PE.RemoveObjectFromWorld(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);
});
// 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.
public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback)
{
if (!shape.HasPhysicalShape)
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
if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
BSScene.DetailLogZero, shape.AddrString, inTaintTime);
if (shapeCallback != null) shapeCallback(shape);
PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
}
else
{
switch (shape.type)
{
case BSPhysicsShapeType.SHAPE_HULL:
DereferenceHull(shape, shapeCallback);
break;
case BSPhysicsShapeType.SHAPE_MESH:
DereferenceMesh(shape, shapeCallback);
break;
case BSPhysicsShapeType.SHAPE_COMPOUND:
DereferenceCompound(shape, shapeCallback);
break;
case BSPhysicsShapeType.SHAPE_UNKNOWN:
break;
default:
break;
}
case BSPhysicsShapeType.SHAPE_HULL:
DereferenceHull(shape, shapeCallback);
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
@ -393,7 +388,7 @@ public sealed class BSShapeCollection : IDisposable
if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
{
DereferenceShape(shapeInfo, true, null);
DereferenceShape(shapeInfo, null);
}
else
{
@ -543,7 +538,7 @@ public sealed class BSShapeCollection : IDisposable
ShapeDestructionCallback shapeCallback)
{
// release any previous shape
DereferenceShape(prim.PhysShape, true, shapeCallback);
DereferenceShape(prim.PhysShape, shapeCallback);
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"));
// 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);
// 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"));
// 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 = 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.
// DereferenceShape(prim.PhysShape, true, shapeCallback);
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.
@ -956,7 +950,7 @@ public sealed class BSShapeCollection : IDisposable
if (mustRebuild || forceRebuild)
{
// Free any old body
DereferenceBody(prim.PhysBody, true, bodyCallback);
DereferenceBody(prim.PhysBody, bodyCallback);
BulletBody aBody;
if (prim.IsSolid)
@ -970,7 +964,7 @@ public sealed class BSShapeCollection : IDisposable
if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
}
ReferenceBody(aBody, true);
ReferenceBody(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:
=================================================
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.
Compute CCD parameters based on body size
Can solver iterations be changed per body/shape? Can be for constraints but what