BulletSim: fix problem with continuious rebuilding of physical linksets. This caused movement problems and large prim vehicles to take up a LOT of simulation time.
parent
60950bfab5
commit
31d3952477
|
@ -124,7 +124,7 @@ public abstract class BSLinkset
|
||||||
get { return ComputeLinksetGeometricCenter(); }
|
get { return ComputeLinksetGeometricCenter(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Initialize(BSScene scene, BSPhysObject parent)
|
protected BSLinkset(BSScene scene, BSPhysObject parent)
|
||||||
{
|
{
|
||||||
// A simple linkset of one (no children)
|
// A simple linkset of one (no children)
|
||||||
LinksetID = m_nextLinksetID++;
|
LinksetID = m_nextLinksetID++;
|
||||||
|
@ -135,6 +135,7 @@ public abstract class BSLinkset
|
||||||
LinksetRoot = parent;
|
LinksetRoot = parent;
|
||||||
m_children = new HashSet<BSPhysObject>();
|
m_children = new HashSet<BSPhysObject>();
|
||||||
m_mass = parent.RawMass;
|
m_mass = parent.RawMass;
|
||||||
|
Rebuilding = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link to a linkset where the child knows the parent.
|
// Link to a linkset where the child knows the parent.
|
||||||
|
@ -237,6 +238,10 @@ public abstract class BSLinkset
|
||||||
// May be called at runtime or taint-time.
|
// May be called at runtime or taint-time.
|
||||||
public abstract void Refresh(BSPhysObject requestor);
|
public abstract void Refresh(BSPhysObject requestor);
|
||||||
|
|
||||||
|
// Flag denoting the linkset is in the process of being rebuilt.
|
||||||
|
// Used to know not the schedule a rebuild in the middle of a rebuild.
|
||||||
|
protected bool Rebuilding { get; set; }
|
||||||
|
|
||||||
// The object is going dynamic (physical). Do any setup necessary
|
// The object is going dynamic (physical). Do any setup necessary
|
||||||
// for a dynamic linkset.
|
// for a dynamic linkset.
|
||||||
// Only the state of the passed object can be modified. The rest of the linkset
|
// Only the state of the passed object can be modified. The rest of the linkset
|
||||||
|
|
|
@ -61,9 +61,8 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
{
|
{
|
||||||
private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
|
private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
|
||||||
|
|
||||||
public BSLinksetCompound(BSScene scene, BSPhysObject parent)
|
public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent)
|
||||||
{
|
{
|
||||||
base.Initialize(scene, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For compound implimented linksets, if there are children, use compound shape for the root.
|
// For compound implimented linksets, if there are children, use compound shape for the root.
|
||||||
|
@ -81,8 +80,6 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
|
|
||||||
// When physical properties are changed the linkset needs to recalculate
|
// When physical properties are changed the linkset needs to recalculate
|
||||||
// its internal properties.
|
// its internal properties.
|
||||||
// This is queued in the 'post taint' queue so the
|
|
||||||
// refresh will happen once after all the other taints are applied.
|
|
||||||
public override void Refresh(BSPhysObject requestor)
|
public override void Refresh(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
// External request for Refresh (from BSPrim) doesn't need to do anything
|
// External request for Refresh (from BSPrim) doesn't need to do anything
|
||||||
|
@ -92,12 +89,18 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// Schedule a refresh to happen after all the other taint processing.
|
// Schedule a refresh to happen after all the other taint processing.
|
||||||
private void InternalRefresh(BSPhysObject requestor)
|
private void InternalRefresh(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
|
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1},rebuilding={2}",
|
||||||
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
|
LinksetRoot.LocalID, requestor.LocalID, Rebuilding);
|
||||||
|
// When rebuilding, it is possible to set properties that would normally require a rebuild.
|
||||||
|
// If already rebuilding, don't request another rebuild.
|
||||||
|
if (!Rebuilding)
|
||||||
{
|
{
|
||||||
if (IsRoot(requestor) && HasAnyChildren)
|
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
|
||||||
RecomputeLinksetCompound();
|
{
|
||||||
});
|
if (IsRoot(requestor) && HasAnyChildren)
|
||||||
|
RecomputeLinksetCompound();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The object is going dynamic (physical). Do any setup necessary
|
// The object is going dynamic (physical). Do any setup necessary
|
||||||
|
@ -115,11 +118,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// The root is going dynamic. Make sure mass is properly set.
|
// The root is going dynamic. Make sure mass is properly set.
|
||||||
m_mass = ComputeLinksetMass();
|
m_mass = ComputeLinksetMass();
|
||||||
if (HasAnyChildren)
|
if (HasAnyChildren)
|
||||||
{
|
|
||||||
// Schedule a rebuilding as this will construct the complete compound shape
|
|
||||||
// and set all the properties correctly.
|
|
||||||
InternalRefresh(LinksetRoot);
|
InternalRefresh(LinksetRoot);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -149,16 +148,13 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
if (IsRoot(child))
|
if (IsRoot(child))
|
||||||
{
|
{
|
||||||
if (HasAnyChildren)
|
if (HasAnyChildren)
|
||||||
{
|
|
||||||
// Schedule a rebuilding as this will construct the complete compound shape
|
|
||||||
// and set all the properties correctly.
|
|
||||||
InternalRefresh(LinksetRoot);
|
InternalRefresh(LinksetRoot);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The non-physical children can come back to life.
|
// The non-physical children can come back to life.
|
||||||
BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||||
|
|
||||||
child.PhysBody.collisionType = CollisionType.LinksetChild;
|
child.PhysBody.collisionType = CollisionType.LinksetChild;
|
||||||
|
|
||||||
// Don't force activation so setting of DISABLE_SIMULATION can stay if used.
|
// Don't force activation so setting of DISABLE_SIMULATION can stay if used.
|
||||||
|
@ -307,74 +303,83 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// Called at taint time!!
|
// Called at taint time!!
|
||||||
private void RecomputeLinksetCompound()
|
private void RecomputeLinksetCompound()
|
||||||
{
|
{
|
||||||
// Cause the root shape to be rebuilt as a compound object with just the root in it
|
try
|
||||||
LinksetRoot.ForceBodyShapeRebuild(true);
|
|
||||||
|
|
||||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
|
|
||||||
LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
|
|
||||||
|
|
||||||
// Add a shape for each of the other children in the linkset
|
|
||||||
ForEachMember(delegate(BSPhysObject cPrim)
|
|
||||||
{
|
{
|
||||||
if (!IsRoot(cPrim))
|
// Suppress rebuilding while rebuilding
|
||||||
|
Rebuilding = true;
|
||||||
|
|
||||||
|
// Cause the root shape to be rebuilt as a compound object with just the root in it
|
||||||
|
LinksetRoot.ForceBodyShapeRebuild(true);
|
||||||
|
|
||||||
|
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
|
||||||
|
LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
|
||||||
|
|
||||||
|
// Add a shape for each of the other children in the linkset
|
||||||
|
ForEachMember(delegate(BSPhysObject cPrim)
|
||||||
{
|
{
|
||||||
// Compute the displacement of the child from the root of the linkset.
|
if (!IsRoot(cPrim))
|
||||||
// This info is saved in the child prim so the relationship does not
|
|
||||||
// change over time and the new child position can be computed
|
|
||||||
// when the linkset is being disassembled (the linkset may have moved).
|
|
||||||
BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
|
|
||||||
if (lci == null)
|
|
||||||
{
|
{
|
||||||
// Each child position and rotation is given relative to the root.
|
// Compute the displacement of the child from the root of the linkset.
|
||||||
OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
|
// This info is saved in the child prim so the relationship does not
|
||||||
OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
|
// change over time and the new child position can be computed
|
||||||
OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
|
// when the linkset is being disassembled (the linkset may have moved).
|
||||||
|
BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
|
||||||
// Save relative position for recomputing child's world position after moving linkset.
|
if (lci == null)
|
||||||
lci = new BSLinksetCompoundInfo(displacementPos, displacementRot);
|
|
||||||
cPrim.LinksetInfo = lci;
|
|
||||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
|
|
||||||
}
|
|
||||||
|
|
||||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
|
|
||||||
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
|
|
||||||
|
|
||||||
if (cPrim.PhysShape.isNativeShape)
|
|
||||||
{
|
|
||||||
// A native shape is turning into a hull collision shape because native
|
|
||||||
// shapes are not shared so we have to hullify it so it will be tracked
|
|
||||||
// and freed at the correct time. This also solves the scaling problem
|
|
||||||
// (native shapes scaled but hull/meshes are assumed to not be).
|
|
||||||
// TODO: decide of the native shape can just be used in the compound shape.
|
|
||||||
// Use call to CreateGeomNonSpecial().
|
|
||||||
BulletShape saveShape = cPrim.PhysShape;
|
|
||||||
cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
|
|
||||||
// PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
|
|
||||||
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
|
|
||||||
BulletShape newShape = cPrim.PhysShape;
|
|
||||||
cPrim.PhysShape = saveShape;
|
|
||||||
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos , lci.OffsetRot);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// For the shared shapes (meshes and hulls), just use the shape in the child.
|
|
||||||
// The reference count added here will be decremented when the compound shape
|
|
||||||
// is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
|
|
||||||
if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
|
|
||||||
{
|
{
|
||||||
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
|
// Each child position and rotation is given relative to the root.
|
||||||
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
|
OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
|
||||||
|
OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
|
||||||
|
OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
|
||||||
|
|
||||||
|
// Save relative position for recomputing child's world position after moving linkset.
|
||||||
|
lci = new BSLinksetCompoundInfo(displacementPos, displacementRot);
|
||||||
|
cPrim.LinksetInfo = lci;
|
||||||
|
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
|
||||||
|
}
|
||||||
|
|
||||||
|
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
|
||||||
|
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
|
||||||
|
|
||||||
|
if (cPrim.PhysShape.isNativeShape)
|
||||||
|
{
|
||||||
|
// A native shape is turning into a hull collision shape because native
|
||||||
|
// shapes are not shared so we have to hullify it so it will be tracked
|
||||||
|
// and freed at the correct time. This also solves the scaling problem
|
||||||
|
// (native shapes scaled but hull/meshes are assumed to not be).
|
||||||
|
// TODO: decide of the native shape can just be used in the compound shape.
|
||||||
|
// Use call to CreateGeomNonSpecial().
|
||||||
|
BulletShape saveShape = cPrim.PhysShape;
|
||||||
|
cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
|
||||||
|
// PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
|
||||||
|
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
|
||||||
|
BulletShape newShape = cPrim.PhysShape;
|
||||||
|
cPrim.PhysShape = saveShape;
|
||||||
|
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos, lci.OffsetRot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For the shared shapes (meshes and hulls), just use the shape in the child.
|
||||||
|
// The reference count added here will be decremented when the compound shape
|
||||||
|
// is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
|
||||||
|
if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
|
||||||
|
{
|
||||||
|
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
|
||||||
|
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
|
||||||
|
}
|
||||||
|
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos, lci.OffsetRot);
|
||||||
}
|
}
|
||||||
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos , lci.OffsetRot);
|
|
||||||
}
|
}
|
||||||
}
|
return false; // 'false' says to move onto the next child in the list
|
||||||
|
});
|
||||||
|
|
||||||
return false; // 'false' says to move onto the next child in the list
|
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
||||||
});
|
float linksetMass = LinksetMass;
|
||||||
|
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
|
||||||
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
}
|
||||||
float linksetMass = LinksetMass;
|
finally
|
||||||
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
|
{
|
||||||
|
Rebuilding = false;
|
||||||
|
}
|
||||||
|
|
||||||
BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr);
|
BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr);
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,8 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
{
|
{
|
||||||
// private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
|
// private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
|
||||||
|
|
||||||
public BSLinksetConstraints(BSScene scene, BSPhysObject parent)
|
public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent)
|
||||||
{
|
{
|
||||||
base.Initialize(scene, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When physical properties are changed the linkset needs to recalculate
|
// When physical properties are changed the linkset needs to recalculate
|
||||||
|
|
Loading…
Reference in New Issue