BulletSim: Fix crash when linking large physical linksets.
Properly remove and restore linkage constraints when upgrading a prim's mesh to a hull. Lots more debug logging. Definitions and use of Bullet structure dumping. Centralize detail logging so a Flush() can be added for debugging.connector_plugin
parent
311a03befa
commit
87825b0abe
|
@ -49,11 +49,18 @@ public abstract class BSConstraint : IDisposable
|
||||||
if (m_enabled)
|
if (m_enabled)
|
||||||
{
|
{
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
|
if (m_constraint.ptr != IntPtr.Zero)
|
||||||
|
{
|
||||||
bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
|
bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
|
||||||
m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
|
m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
|
||||||
|
BSScene.DetailLogZero,
|
||||||
|
m_body1.ID, m_body1.ptr.ToString("X"),
|
||||||
|
m_body2.ID, m_body2.ptr.ToString("X"),
|
||||||
|
success);
|
||||||
m_constraint.ptr = System.IntPtr.Zero;
|
m_constraint.ptr = System.IntPtr.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public BulletBody Body1 { get { return m_body1; } }
|
public BulletBody Body1 { get { return m_body1; } }
|
||||||
public BulletBody Body2 { get { return m_body2; } }
|
public BulletBody Body2 { get { return m_body2; } }
|
||||||
|
|
|
@ -862,7 +862,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
private void VDetailLog(string msg, params Object[] args)
|
private void VDetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
if (Prim.PhysicsScene.VehicleLoggingEnabled)
|
if (Prim.PhysicsScene.VehicleLoggingEnabled)
|
||||||
Prim.PhysicsScene.PhysicsLogging.Write(msg, args);
|
Prim.PhysicsScene.DetailLog(msg, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,8 @@ public class BSLinkset
|
||||||
// the physical 'taint' children separately.
|
// the physical 'taint' children separately.
|
||||||
// After taint processing and before the simulation step, these
|
// After taint processing and before the simulation step, these
|
||||||
// two lists must be the same.
|
// two lists must be the same.
|
||||||
private List<BSPhysObject> m_children;
|
private HashSet<BSPhysObject> m_children;
|
||||||
private List<BSPhysObject> m_taintChildren;
|
private HashSet<BSPhysObject> m_taintChildren;
|
||||||
|
|
||||||
// We lock the diddling of linkset classes to prevent any badness.
|
// We lock the diddling of linkset classes to prevent any badness.
|
||||||
// This locks the modification of the instances of this class. Changes
|
// This locks the modification of the instances of this class. Changes
|
||||||
|
@ -90,8 +90,8 @@ public class BSLinkset
|
||||||
m_nextLinksetID = 1;
|
m_nextLinksetID = 1;
|
||||||
PhysicsScene = scene;
|
PhysicsScene = scene;
|
||||||
LinksetRoot = parent;
|
LinksetRoot = parent;
|
||||||
m_children = new List<BSPhysObject>();
|
m_children = new HashSet<BSPhysObject>();
|
||||||
m_taintChildren = new List<BSPhysObject>();
|
m_taintChildren = new HashSet<BSPhysObject>();
|
||||||
m_mass = parent.MassRaw;
|
m_mass = parent.MassRaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +197,8 @@ public class BSLinkset
|
||||||
PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate()
|
PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate()
|
||||||
{
|
{
|
||||||
RecomputeLinksetConstraintVariables();
|
RecomputeLinksetConstraintVariables();
|
||||||
|
DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}",
|
||||||
|
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,13 +217,10 @@ public class BSLinkset
|
||||||
if (IsRoot(child))
|
if (IsRoot(child))
|
||||||
{
|
{
|
||||||
// If the one with the dependency is root, must undo all children
|
// If the one with the dependency is root, must undo all children
|
||||||
DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}",
|
DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
|
||||||
child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
|
child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
|
||||||
foreach (BSPhysObject bpo in m_taintChildren)
|
|
||||||
{
|
ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
|
||||||
PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -229,12 +228,9 @@ public class BSLinkset
|
||||||
child.LocalID,
|
child.LocalID,
|
||||||
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
|
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
|
||||||
child.LocalID, child.BSBody.ptr.ToString("X"));
|
child.LocalID, child.BSBody.ptr.ToString("X"));
|
||||||
// Remove the dependency on the body of this one
|
// ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child);
|
||||||
if (m_taintChildren.Contains(child))
|
// Despite the function name, this removes any link to the specified object.
|
||||||
{
|
ret = PhysicallyUnlinkAllChildrenFromRoot(child);
|
||||||
PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -254,7 +250,7 @@ public class BSLinkset
|
||||||
child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
|
child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
|
||||||
foreach (BSPhysObject bpo in m_taintChildren)
|
foreach (BSPhysObject bpo in m_taintChildren)
|
||||||
{
|
{
|
||||||
PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
|
PhysicallyLinkAChildToRoot(LinksetRoot, bpo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -263,7 +259,7 @@ public class BSLinkset
|
||||||
LinksetRoot.LocalID,
|
LinksetRoot.LocalID,
|
||||||
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
|
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
|
||||||
child.LocalID, child.BSBody.ptr.ToString("X"));
|
child.LocalID, child.BSBody.ptr.ToString("X"));
|
||||||
PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
|
PhysicallyLinkAChildToRoot(LinksetRoot, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,22 +326,22 @@ public class BSLinkset
|
||||||
{
|
{
|
||||||
m_children.Add(child);
|
m_children.Add(child);
|
||||||
|
|
||||||
BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
|
BSPhysObject rootx = LinksetRoot; // capture the root as of now
|
||||||
BSPhysObject childx = child;
|
BSPhysObject childx = child;
|
||||||
|
|
||||||
DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
|
DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
|
||||||
rootx.LocalID,
|
|
||||||
rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
|
|
||||||
childx.LocalID, childx.BSBody.ptr.ToString("X"));
|
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
|
PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID);
|
DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}",
|
||||||
// build the physical binding between me and the child
|
rootx.LocalID,
|
||||||
m_taintChildren.Add(childx);
|
rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
|
||||||
|
childx.LocalID, childx.BSBody.ptr.ToString("X"));
|
||||||
// Since this is taint-time, the body and shape could have changed for the child
|
// Since this is taint-time, the body and shape could have changed for the child
|
||||||
PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody);
|
rootx.ForcePosition = rootx.Position; // DEBUG
|
||||||
|
childx.ForcePosition = childx.Position; // DEBUG
|
||||||
|
PhysicallyLinkAChildToRoot(rootx, childx);
|
||||||
|
m_taintChildren.Add(child);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -378,10 +374,8 @@ public class BSLinkset
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
|
PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
|
||||||
{
|
{
|
||||||
if (m_taintChildren.Contains(childx))
|
m_taintChildren.Remove(child);
|
||||||
m_taintChildren.Remove(childx);
|
PhysicallyUnlinkAChildFromRoot(rootx, childx);
|
||||||
|
|
||||||
PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody);
|
|
||||||
RecomputeLinksetConstraintVariables();
|
RecomputeLinksetConstraintVariables();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -396,8 +390,7 @@ public class BSLinkset
|
||||||
|
|
||||||
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody,
|
private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||||
BSPhysObject childPrim, BulletBody childBody)
|
|
||||||
{
|
{
|
||||||
// Zero motion for children so they don't interpolate
|
// Zero motion for children so they don't interpolate
|
||||||
childPrim.ZeroMotion();
|
childPrim.ZeroMotion();
|
||||||
|
@ -409,33 +402,17 @@ public class BSLinkset
|
||||||
// real world coordinate of midpoint between the two objects
|
// real world coordinate of midpoint between the two objects
|
||||||
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
|
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
|
||||||
|
|
||||||
DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
|
DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
|
||||||
rootPrim.LocalID,
|
rootPrim.LocalID,
|
||||||
rootPrim.LocalID, rootBody.ptr.ToString("X"),
|
rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
|
||||||
childPrim.LocalID, childBody.ptr.ToString("X"),
|
childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"),
|
||||||
rootPrim.Position, childPrim.Position, midPoint);
|
rootPrim.Position, childPrim.Position, midPoint);
|
||||||
|
|
||||||
// create a constraint that allows no freedom of movement between the two objects
|
// create a constraint that allows no freedom of movement between the two objects
|
||||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||||
|
|
||||||
// There is great subtlty in these paramters. Notice the check for a ptr of zero.
|
|
||||||
// We pass the BulletBody structure into the taint in order to capture the pointer
|
|
||||||
// of the body at the time of constraint creation. This doesn't work for the very first
|
|
||||||
// construction because there is no body yet. The body
|
|
||||||
// is constructed later at taint time. Thus we use the body address at time of the
|
|
||||||
// taint creation but, if it is zero, use what's in the prim at the moment.
|
|
||||||
// There is a possible race condition since shape can change without a taint call
|
|
||||||
// (like changing to a mesh that is already constructed). The fix for that would be
|
|
||||||
// to only change BSShape at taint time thus syncronizing these operations at
|
|
||||||
// the cost of efficiency and lag.
|
|
||||||
BS6DofConstraint constrain = new BS6DofConstraint(
|
BS6DofConstraint constrain = new BS6DofConstraint(
|
||||||
PhysicsScene.World,
|
PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true );
|
||||||
rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody,
|
|
||||||
childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody,
|
|
||||||
midPoint,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
|
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
|
||||||
* Using the midpoint is easier since it lets the Bullet code manipulate the transforms
|
* Using the midpoint is easier since it lets the Bullet code manipulate the transforms
|
||||||
|
@ -452,7 +429,7 @@ public class BSLinkset
|
||||||
|
|
||||||
// create a constraint that allows no freedom of movement between the two objects
|
// create a constraint that allows no freedom of movement between the two objects
|
||||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||||
DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
||||||
BS6DofConstraint constrain = new BS6DofConstraint(
|
BS6DofConstraint constrain = new BS6DofConstraint(
|
||||||
PhysicsScene.World, rootPrim.Body, childPrim.Body,
|
PhysicsScene.World, rootPrim.Body, childPrim.Body,
|
||||||
OMV.Vector3.Zero,
|
OMV.Vector3.Zero,
|
||||||
|
@ -486,39 +463,44 @@ public class BSLinkset
|
||||||
{
|
{
|
||||||
constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
|
constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecomputeLinksetConstraintVariables();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove linkage between myself and a particular child
|
// Remove linkage between myself and a particular child
|
||||||
// The root and child bodies are passed in because we need to remove the constraint between
|
// The root and child bodies are passed in because we need to remove the constraint between
|
||||||
// the bodies that were at unlink time.
|
// the bodies that were at unlink time.
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody,
|
private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||||
BSPhysObject childPrim, BulletBody childBody)
|
|
||||||
{
|
{
|
||||||
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
|
bool ret = false;
|
||||||
|
DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
|
||||||
rootPrim.LocalID,
|
rootPrim.LocalID,
|
||||||
rootPrim.LocalID, rootBody.ptr.ToString("X"),
|
rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
|
||||||
childPrim.LocalID, childBody.ptr.ToString("X"));
|
childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"));
|
||||||
|
|
||||||
// Find the constraint for this link and get rid of it from the overall collection and from my list
|
// Find the constraint for this link and get rid of it from the overall collection and from my list
|
||||||
PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody);
|
if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody))
|
||||||
|
{
|
||||||
// Make the child refresh its location
|
// Make the child refresh its location
|
||||||
BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
|
BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Remove linkage between myself and any possible children I might have.
|
// Remove linkage between myself and any possible children I might have.
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
|
private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
|
||||||
{
|
{
|
||||||
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody);
|
if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody))
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// Call each of the constraints that make up this linkset and recompute the
|
// Call each of the constraints that make up this linkset and recompute the
|
||||||
// various transforms and variables. Used when objects are added or removed
|
// various transforms and variables. Used when objects are added or removed
|
||||||
|
@ -550,11 +532,17 @@ public class BSLinkset
|
||||||
{
|
{
|
||||||
// If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
|
// If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
|
||||||
OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
|
OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
|
||||||
BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
|
BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr,
|
||||||
|
centerOfMass, OMV.Quaternion.Identity);
|
||||||
|
DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}",
|
||||||
|
LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"));
|
||||||
foreach (BSPhysObject child in m_taintChildren)
|
foreach (BSPhysObject child in m_taintChildren)
|
||||||
{
|
{
|
||||||
BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
|
BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr,
|
||||||
|
centerOfMass, OMV.Quaternion.Identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -563,7 +551,8 @@ public class BSLinkset
|
||||||
// Invoke the detailed logger and output something if it's enabled.
|
// Invoke the detailed logger and output something if it's enabled.
|
||||||
private void DetailLog(string msg, params Object[] args)
|
private void DetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
PhysicsScene.PhysicsLogging.Write(msg, args);
|
if (PhysicsScene.PhysicsLogging.Enabled)
|
||||||
|
PhysicsScene.DetailLog(msg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,8 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// High performance detailed logging routine used by the physical objects.
|
// High performance detailed logging routine used by the physical objects.
|
||||||
protected void DetailLog(string msg, params Object[] args)
|
protected void DetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
PhysicsScene.PhysicsLogging.Write(msg, args);
|
if (PhysicsScene.PhysicsLogging.Enabled)
|
||||||
|
PhysicsScene.DetailLog(msg, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_isSelected = value;
|
_isSelected = value;
|
||||||
PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
|
||||||
{
|
{
|
||||||
// DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
|
DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
|
||||||
SetObjectDynamic(false);
|
SetObjectDynamic(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -620,8 +620,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
|
BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
|
||||||
// There can be special things needed for implementing linksets
|
// There can be special things needed for implementing linksets
|
||||||
Linkset.MakeStatic(this);
|
Linkset.MakeStatic(this);
|
||||||
// The activation state is 'disabled' so Bullet will not try to act on it
|
// The activation state is 'disabled' so Bullet will not try to act on it.
|
||||||
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION);
|
// BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
|
// Start it out sleeping and physical actions could wake it up.
|
||||||
|
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
|
||||||
|
|
||||||
BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
|
BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
|
||||||
BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
||||||
|
@ -1204,6 +1206,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
{
|
{
|
||||||
// Called if the current prim body is about to be destroyed.
|
// Called if the current prim body is about to be destroyed.
|
||||||
// Remove all the physical dependencies on the old body.
|
// Remove all the physical dependencies on the old body.
|
||||||
|
// (Maybe someday make the changing of BSShape an event handled by BSLinkset.)
|
||||||
needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
|
needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
// The bounding box for the simulated world. The origin is 0,0,0 unless we're
|
// The bounding box for the simulated world. The origin is 0,0,0 unless we're
|
||||||
// a child in a mega-region.
|
// a child in a mega-region.
|
||||||
// Turns out that Bullet really doesn't care about the extents of the simulated
|
// Bullet actually doesn't care about the extents of the simulated
|
||||||
// area. It tracks active objects no matter where they are.
|
// area. It tracks active objects no matter where they are.
|
||||||
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
|
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// Called directly from unmanaged code so don't do much
|
// Called directly from unmanaged code so don't do much
|
||||||
private void BulletLoggerPhysLog(string msg)
|
private void BulletLoggerPhysLog(string msg)
|
||||||
{
|
{
|
||||||
PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
|
DetailLog("[BULLETS UNMANAGED]:" + msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
|
@ -494,8 +494,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
m_simulationStep++;
|
m_simulationStep++;
|
||||||
int numSubSteps = 0;
|
int numSubSteps = 0;
|
||||||
|
|
||||||
// Sometimes needed for debugging to find out what happened before the step
|
// DEBUG
|
||||||
// PhysicsLogging.Flush();
|
DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -715,6 +715,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
|
||||||
tcbe.callback();
|
tcbe.callback();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -1270,6 +1271,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
public void DetailLog(string msg, params Object[] args)
|
public void DetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
PhysicsLogging.Write(msg, args);
|
PhysicsLogging.Write(msg, args);
|
||||||
|
// Add the Flush() if debugging crashes to get all the messages written out.
|
||||||
|
PhysicsLogging.Flush(); // DEBUG DEBUG DEBUG
|
||||||
}
|
}
|
||||||
// used to fill in the LocalID when there isn't one
|
// used to fill in the LocalID when there isn't one
|
||||||
public const string DetailLogZero = "0000000000";
|
public const string DetailLogZero = "0000000000";
|
||||||
|
|
|
@ -136,7 +136,21 @@ public class BSShapeCollection : IDisposable
|
||||||
// New entry
|
// New entry
|
||||||
bodyDesc.ptr = body.ptr;
|
bodyDesc.ptr = body.ptr;
|
||||||
bodyDesc.referenceCount = 1;
|
bodyDesc.referenceCount = 1;
|
||||||
DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", body.ID, body, bodyDesc.referenceCount);
|
DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}",
|
||||||
|
body.ID, body, bodyDesc.referenceCount);
|
||||||
|
BSScene.TaintCallback createOperation = delegate()
|
||||||
|
{
|
||||||
|
if (!BulletSimAPI.IsInWorld2(body.ptr))
|
||||||
|
{
|
||||||
|
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
|
||||||
|
DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}",
|
||||||
|
body.ID, body);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (atTaintTime)
|
||||||
|
createOperation();
|
||||||
|
else
|
||||||
|
PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation);
|
||||||
}
|
}
|
||||||
bodyDesc.lastReferenced = System.DateTime.Now;
|
bodyDesc.lastReferenced = System.DateTime.Now;
|
||||||
Bodies[body.ID] = bodyDesc;
|
Bodies[body.ID] = bodyDesc;
|
||||||
|
@ -160,21 +174,22 @@ public class BSShapeCollection : IDisposable
|
||||||
Bodies[body.ID] = bodyDesc;
|
Bodies[body.ID] = bodyDesc;
|
||||||
DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount);
|
DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount);
|
||||||
|
|
||||||
// If body is no longer being used, free it -- bodies are never shared.
|
// If body is no longer being used, free it -- bodies can never be shared.
|
||||||
if (bodyDesc.referenceCount == 0)
|
if (bodyDesc.referenceCount == 0)
|
||||||
{
|
{
|
||||||
Bodies.Remove(body.ID);
|
Bodies.Remove(body.ID);
|
||||||
BSScene.TaintCallback removeOperation = delegate()
|
BSScene.TaintCallback removeOperation = delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}",
|
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}",
|
||||||
body.ID, body.ptr.ToString("X"));
|
body.ID, body.ptr.ToString("X"), inTaintTime);
|
||||||
// If the caller needs to know the old body is going away, pass the event up.
|
// If the caller needs to know the old body is going away, pass the event up.
|
||||||
if (bodyCallback != null) bodyCallback(body);
|
if (bodyCallback != null) bodyCallback(body);
|
||||||
|
|
||||||
// Zero any reference to the shape so it is not freed when the body is deleted.
|
|
||||||
BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
|
|
||||||
// It may have already been removed from the world in which case the next is a NOOP.
|
// It may have already been removed from the world in which case the next is a NOOP.
|
||||||
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
|
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
|
||||||
|
|
||||||
|
// Zero any reference to the shape so it is not freed when the body is deleted.
|
||||||
|
BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
|
||||||
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
|
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
|
||||||
};
|
};
|
||||||
// If already in taint-time, do the operations now. Otherwise queue for later.
|
// If already in taint-time, do the operations now. Otherwise queue for later.
|
||||||
|
@ -208,7 +223,7 @@ public class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
// There is an existing instance of this mesh.
|
// There is an existing instance of this mesh.
|
||||||
meshDesc.referenceCount++;
|
meshDesc.referenceCount++;
|
||||||
DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}",
|
DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
|
||||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -217,7 +232,7 @@ public class BSShapeCollection : IDisposable
|
||||||
meshDesc.ptr = shape.ptr;
|
meshDesc.ptr = shape.ptr;
|
||||||
// We keep a reference to the underlying IMesh data so a hull can be built
|
// We keep a reference to the underlying IMesh data so a hull can be built
|
||||||
meshDesc.referenceCount = 1;
|
meshDesc.referenceCount = 1;
|
||||||
DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}",
|
DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
|
||||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +245,7 @@ public class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
// There is an existing instance of this hull.
|
// There is an existing instance of this hull.
|
||||||
hullDesc.referenceCount++;
|
hullDesc.referenceCount++;
|
||||||
DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}",
|
DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
|
||||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -238,7 +253,7 @@ public class BSShapeCollection : IDisposable
|
||||||
// This is a new reference to a hull
|
// This is a new reference to a hull
|
||||||
hullDesc.ptr = shape.ptr;
|
hullDesc.ptr = shape.ptr;
|
||||||
hullDesc.referenceCount = 1;
|
hullDesc.referenceCount = 1;
|
||||||
DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}",
|
DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
|
||||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
|
@ -525,7 +540,7 @@ public class BSShapeCollection : IDisposable
|
||||||
DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
|
DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
|
||||||
prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
|
prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
|
||||||
|
|
||||||
// Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull.
|
// Remove usage of the previous shape.
|
||||||
DereferenceShape(prim.BSShape, true, shapeCallback);
|
DereferenceShape(prim.BSShape, true, shapeCallback);
|
||||||
|
|
||||||
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
|
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
|
||||||
|
@ -659,6 +674,7 @@ public class BSShapeCollection : IDisposable
|
||||||
if (pbs.SculptEntry)
|
if (pbs.SculptEntry)
|
||||||
lod = PhysicsScene.SculptLOD;
|
lod = PhysicsScene.SculptLOD;
|
||||||
|
|
||||||
|
// Mega prims usually get more detail because one can interact with shape approximations at this size.
|
||||||
float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
|
float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
|
||||||
if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
|
if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
|
||||||
lod = PhysicsScene.MeshMegaPrimLOD;
|
lod = PhysicsScene.MeshMegaPrimLOD;
|
||||||
|
@ -709,13 +725,13 @@ public class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
|
bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
|
||||||
shapeData.ID, shapeData.Position, shapeData.Rotation);
|
shapeData.ID, shapeData.Position, shapeData.Rotation);
|
||||||
// DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
|
bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
|
||||||
shapeData.ID, shapeData.Position, shapeData.Rotation);
|
shapeData.ID, shapeData.Position, shapeData.Rotation);
|
||||||
// DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
||||||
}
|
}
|
||||||
aBody = new BulletBody(shapeData.ID, bodyPtr);
|
aBody = new BulletBody(shapeData.ID, bodyPtr);
|
||||||
|
|
||||||
|
@ -731,7 +747,8 @@ public class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
private void DetailLog(string msg, params Object[] args)
|
private void DetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
PhysicsScene.PhysicsLogging.Write(msg, args);
|
if (PhysicsScene.PhysicsLogging.Enabled)
|
||||||
|
PhysicsScene.DetailLog(msg, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,8 +192,9 @@ public struct ShapeData
|
||||||
SHAPE_SPHERE = 5,
|
SHAPE_SPHERE = 5,
|
||||||
SHAPE_MESH = 6,
|
SHAPE_MESH = 6,
|
||||||
SHAPE_HULL = 7,
|
SHAPE_HULL = 7,
|
||||||
SHAPE_GROUNDPLANE = 8,
|
// following defined by BulletSim
|
||||||
SHAPE_TERRAIN = 9,
|
SHAPE_GROUNDPLANE = 20,
|
||||||
|
SHAPE_TERRAIN = 21,
|
||||||
};
|
};
|
||||||
public uint ID;
|
public uint ID;
|
||||||
public PhysicsShapeType Type;
|
public PhysicsShapeType Type;
|
||||||
|
@ -1107,6 +1108,15 @@ public static extern float GetMargin2(IntPtr shape);
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
|
public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void DumpAllInfo2(IntPtr sim);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue