Merge branch 'master' of ssh://opensimulator.org/var/git/opensim

connector_plugin
Justin Clark-Casey (justincc) 2012-10-11 23:56:03 +01:00
commit f5f5f2e3fb
15 changed files with 348 additions and 203 deletions

View File

@ -263,7 +263,7 @@ public class BSCharacter : BSPhysObject
// A version of the sanity check that also makes sure a new position value is // A version of the sanity check that also makes sure a new position value is
// pushed back to the physics engine. This routine would be used by anyone // pushed back to the physics engine. This routine would be used by anyone
// who is not already pushing the value. // who is not already pushing the value.
private bool PositionSanityCheck2(bool atTaintTime) private bool PositionSanityCheck2(bool inTaintTime)
{ {
bool ret = false; bool ret = false;
if (PositionSanityCheck()) if (PositionSanityCheck())
@ -275,7 +275,7 @@ public class BSCharacter : BSPhysObject
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
}; };
if (atTaintTime) if (inTaintTime)
sanityOperation(); sanityOperation();
else else
PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation);
@ -332,6 +332,13 @@ public class BSCharacter : BSPhysObject
}); });
} }
} }
public override OMV.Vector3 ForceVelocity {
get { return _velocity; }
set {
_velocity = value;
BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity);
}
}
public override OMV.Vector3 Torque { public override OMV.Vector3 Torque {
get { return _torque; } get { return _torque; }
set { _torque = value; set { _torque = value;
@ -432,6 +439,10 @@ public class BSCharacter : BSPhysObject
get { return _rotationalVelocity; } get { return _rotationalVelocity; }
set { _rotationalVelocity = value; } set { _rotationalVelocity = value; }
} }
public override OMV.Vector3 ForceRotationalVelocity {
get { return _rotationalVelocity; }
set { _rotationalVelocity = value; }
}
public override bool Kinematic { public override bool Kinematic {
get { return _kinematic; } get { return _kinematic; }
set { _kinematic = value; } set { _kinematic = value; }

View File

@ -49,9 +49,16 @@ public abstract class BSConstraint : IDisposable
if (m_enabled) if (m_enabled)
{ {
m_enabled = false; m_enabled = false;
bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); if (m_constraint.ptr != IntPtr.Zero)
m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); {
m_constraint.ptr = System.IntPtr.Zero; bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
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;
}
} }
} }

View File

@ -462,7 +462,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
return; return;
// Set the prim's inertia to zero. The vehicle code handles that and this // Set the prim's inertia to zero. The vehicle code handles that and this
// removes the torque action introduced by Bullet. // removes the motion and torque actions introduced by Bullet.
Vector3 inertia = Vector3.Zero; Vector3 inertia = Vector3.Zero;
BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia);
BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr);
@ -481,7 +481,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_lastPositionVector = Prim.ForcePosition; m_lastPositionVector = Prim.ForcePosition;
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
}// end Step }// end Step
// Apply the effect of the linear motor. // Apply the effect of the linear motor.
@ -540,7 +540,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// add Gravity and Buoyancy // add Gravity and Buoyancy
// There is some gravity, make a gravity force vector that is applied after object velocity. // There is some gravity, make a gravity force vector that is applied after object velocity.
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Mass * (1f - m_VehicleBuoyancy)); Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy));
/* /*
* RA: Not sure why one would do this * RA: Not sure why one would do this
@ -678,10 +678,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_newVelocity.Z = 0; m_newVelocity.Z = 0;
// Apply velocity // Apply velocity
Prim.Velocity = m_newVelocity; Prim.ForceVelocity = m_newVelocity;
// apply gravity force // apply gravity force
// Why is this set here? The physics engine already does gravity. // Why is this set here? The physics engine already does gravity.
// m_prim.AddForce(grav, false); Prim.AddForce(grav, false, true);
// Apply friction // Apply friction
Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
@ -704,7 +704,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_lastAngularVelocity // what was last applied to body // m_lastAngularVelocity // what was last applied to body
// Get what the body is doing, this includes 'external' influences // Get what the body is doing, this includes 'external' influences
Vector3 angularVelocity = Prim.RotationalVelocity; Vector3 angularVelocity = Prim.ForceRotationalVelocity;
if (m_angularMotorApply > 0) if (m_angularMotorApply > 0)
{ {
@ -810,7 +810,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
// Apply to the body // Apply to the body
Prim.RotationalVelocity = m_lastAngularVelocity; Prim.ForceRotationalVelocity = m_lastAngularVelocity;
VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity);
} //end MoveAngular } //end MoveAngular
@ -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);
} }
} }
} }

View File

@ -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;
} }
@ -160,6 +160,28 @@ public class BSLinkset
return ret; return ret;
} }
// When physical properties are changed the linkset needs to recalculate
// its internal properties.
// May be called at runtime or taint-time (just pass the appropriate flag).
public void Refresh(BSPhysObject requestor, bool inTaintTime)
{
// If there are no children, not physical or not root, I am not the one that recomputes the constraints
// (For the moment, static linksets do create constraints so remove the test for physical.)
if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor))
return;
BSScene.TaintCallback refreshOperation = delegate()
{
RecomputeLinksetConstraintVariables();
DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}",
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
};
if (inTaintTime)
refreshOperation();
else
PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation);
}
// 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
@ -182,22 +204,19 @@ public class BSLinkset
return false; return false;
} }
// When physical properties are changed the linkset needs to recalculate // If the software is handling the movement of all the objects in a linkset
// its internal properties. // (like if one doesn't use constraints for static linksets), this is called
// Called at runtime. // when an update for the root of the linkset is received.
public void Refresh(BSPhysObject requestor) // Called at taint-time!!
public void UpdateProperties(BSPhysObject physObject)
{ {
// If there are no children, there can't be any constraints to recompute // The root local properties have been updated. Apply to the children if appropriate.
if (!HasAnyChildren) if (IsRoot(physObject) && HasAnyChildren)
return;
// Only the root does the recomputation
if (IsRoot(requestor))
{ {
PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() if (!physObject.IsPhysical)
{ {
RecomputeLinksetConstraintVariables(); // TODO: implement software linkset update for static object linksets
}); }
} }
} }
@ -215,13 +234,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,20 +245,16 @@ 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;
} }
// Routine used when rebuilding the body of the root of the linkset // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
// This is called after RemoveAllLinksToRoot() to restore all the constraints. // this routine will restore the removed constraints.
// This is called when the root body has been changed.
// Called at taint-time!! // Called at taint-time!!
public void RestoreBodyDependencies(BSPrim child) public void RestoreBodyDependencies(BSPrim child)
{ {
@ -254,7 +266,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 +275,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 +342,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 +390,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 +406,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 +418,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 +445,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 +479,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
BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
ret = true;
}
// Make the child refresh its location return ret;
BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
} }
/*
// 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 +548,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 +567,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);
} }
} }

View File

@ -85,6 +85,10 @@ public abstract class BSPhysObject : PhysicsActor
public abstract OMV.Quaternion ForceOrientation { get; set; } public abstract OMV.Quaternion ForceOrientation { get; set; }
public abstract OMV.Vector3 ForceVelocity { get; set; }
public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
#region Collisions #region Collisions
// Requested number of milliseconds between collision events. Zero means disabled. // Requested number of milliseconds between collision events. Zero means disabled.
@ -207,7 +211,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);
} }
} }
} }

View File

@ -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);
}); });
} }
@ -265,6 +265,11 @@ public sealed class BSPrim : BSPhysObject
return _position; return _position;
} }
set { set {
// If you must push the position into the physics engine, use ForcePosition.
if (_position == value)
{
return;
}
_position = value; _position = value;
// TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
PositionSanityCheck(); PositionSanityCheck();
@ -322,7 +327,7 @@ public sealed class BSPrim : BSPhysObject
// A version of the sanity check that also makes sure a new position value is // A version of the sanity check that also makes sure a new position value is
// pushed back to the physics engine. This routine would be used by anyone // pushed back to the physics engine. This routine would be used by anyone
// who is not already pushing the value. // who is not already pushing the value.
private bool PositionSanityCheck2(bool atTaintTime) private bool PositionSanityCheck2(bool inTaintTime)
{ {
bool ret = false; bool ret = false;
if (PositionSanityCheck()) if (PositionSanityCheck())
@ -334,7 +339,7 @@ public sealed class BSPrim : BSPhysObject
DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
}; };
if (atTaintTime) if (inTaintTime)
sanityOperation(); sanityOperation();
else else
PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation);
@ -453,7 +458,6 @@ public sealed class BSPrim : BSPhysObject
} }
return; return;
} }
public override OMV.Vector3 Velocity { public override OMV.Vector3 Velocity {
get { return _velocity; } get { return _velocity; }
set { set {
@ -465,6 +469,13 @@ public sealed class BSPrim : BSPhysObject
}); });
} }
} }
public override OMV.Vector3 ForceVelocity {
get { return _velocity; }
set {
_velocity = value;
BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
}
}
public override OMV.Vector3 Torque { public override OMV.Vector3 Torque {
get { return _torque; } get { return _torque; }
set { _torque = value; set { _torque = value;
@ -490,6 +501,8 @@ public sealed class BSPrim : BSPhysObject
return _orientation; return _orientation;
} }
set { set {
if (_orientation == value)
return;
_orientation = value; _orientation = value;
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
@ -570,7 +583,7 @@ public sealed class BSPrim : BSPhysObject
// Set up the object physicalness (does gravity and collisions move this object) // Set up the object physicalness (does gravity and collisions move this object)
MakeDynamic(IsStatic); MakeDynamic(IsStatic);
// Update vehicle specific parameters // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
_vehicle.Refresh(); _vehicle.Refresh();
// Arrange for collision events if the simulator wants them // Arrange for collision events if the simulator wants them
@ -593,7 +606,7 @@ public sealed class BSPrim : BSPhysObject
// Recompute any linkset parameters. // Recompute any linkset parameters.
// When going from non-physical to physical, this re-enables the constraints that // When going from non-physical to physical, this re-enables the constraints that
// had been automatically disabled when the mass was set to zero. // had been automatically disabled when the mass was set to zero.
Linkset.Refresh(this); Linkset.Refresh(this, true);
DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape);
@ -620,8 +633,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;
@ -638,6 +653,9 @@ public sealed class BSPrim : BSPhysObject
// per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
BulletSimAPI.ClearAllForces2(BSBody.ptr); BulletSimAPI.ClearAllForces2(BSBody.ptr);
// For good measure, make sure the transform is set through to the motion state
BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
// A dynamic object has mass // A dynamic object has mass
IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr);
OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
@ -655,8 +673,8 @@ public sealed class BSPrim : BSPhysObject
// Force activation of the object so Bullet will act on it. // Force activation of the object so Bullet will act on it.
// Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
BulletSimAPI.Activate2(BSBody.ptr, true); // BulletSimAPI.Activate2(BSBody.ptr, true);
BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
BSBody.collisionMask = CollisionFilterGroups.ObjectMask; BSBody.collisionMask = CollisionFilterGroups.ObjectMask;
@ -774,6 +792,15 @@ public sealed class BSPrim : BSPhysObject
}); });
} }
} }
public override OMV.Vector3 ForceRotationalVelocity {
get {
return _rotationalVelocity;
}
set {
_rotationalVelocity = value;
BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity);
}
}
public override bool Kinematic { public override bool Kinematic {
get { return _kinematic; } get { return _kinematic; }
set { _kinematic = value; set { _kinematic = value;
@ -828,6 +855,9 @@ public sealed class BSPrim : BSPhysObject
private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
public override void AddForce(OMV.Vector3 force, bool pushforce) { public override void AddForce(OMV.Vector3 force, bool pushforce) {
AddForce(force, pushforce, false);
}
public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
// for an object, doesn't matter if force is a pushforce or not // for an object, doesn't matter if force is a pushforce or not
if (force.IsFinite()) if (force.IsFinite())
{ {
@ -840,11 +870,12 @@ public sealed class BSPrim : BSPhysObject
m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
return; return;
} }
PhysicsScene.TaintedObject("BSPrim.AddForce", delegate() BSScene.TaintCallback addForceOperation = delegate()
{ {
OMV.Vector3 fSum = OMV.Vector3.Zero; OMV.Vector3 fSum = OMV.Vector3.Zero;
lock (m_accumulatedForces) lock (m_accumulatedForces)
{ {
// Sum the accumulated additional forces for one big force to apply once.
foreach (OMV.Vector3 v in m_accumulatedForces) foreach (OMV.Vector3 v in m_accumulatedForces)
{ {
fSum += v; fSum += v;
@ -854,7 +885,11 @@ public sealed class BSPrim : BSPhysObject
// DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
// For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum);
}); };
if (inTaintTime)
addForceOperation();
else
PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation);
} }
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
@ -1204,6 +1239,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);
}); });
@ -1294,6 +1330,8 @@ public sealed class BSPrim : BSPhysObject
PositionSanityCheck2(true); PositionSanityCheck2(true);
Linkset.UpdateProperties(this);
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
@ -1304,7 +1342,7 @@ public sealed class BSPrim : BSPhysObject
/* /*
else else
{ {
// For debugging, we can also report the movement of children // For debugging, report the movement of children
DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
entprop.Acceleration, entprop.RotationalVelocity); entprop.Acceleration, entprop.RotationalVelocity);

View File

@ -39,7 +39,6 @@ using log4net;
using OpenMetaverse; using OpenMetaverse;
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
// Move all logic out of the C++ code and into the C# code for easier future modifications.
// Test sculpties (verified that they don't work) // Test sculpties (verified that they don't work)
// Compute physics FPS reasonably // Compute physics FPS reasonably
// Based on material, set density and friction // Based on material, set density and friction
@ -90,10 +89,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// let my minuions use my logger // let my minuions use my logger
public ILog Logger { get { return m_log; } } public ILog Logger { get { return m_log; } }
// If non-zero, the number of simulation steps between calls to the physics
// engine to output detailed physics stats. Debug logging level must be on also.
private int m_detailedStatsStep = 0;
public IMesher mesher; public IMesher mesher;
// Level of Detail values kept as float because that's what the Meshmerizer wants // Level of Detail values kept as float because that's what the Meshmerizer wants
public float MeshLOD { get; private set; } public float MeshLOD { get; private set; }
@ -112,6 +107,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
private float m_fixedTimeStep; private float m_fixedTimeStep;
private long m_simulationStep = 0; private long m_simulationStep = 0;
public long SimulationStep { get { return m_simulationStep; } } public long SimulationStep { get { return m_simulationStep; } }
private int m_taintsToProcessPerStep;
// A value of the time now so all the collision and update routines do not have to get their own // A value of the time now so all the collision and update routines do not have to get their own
// Set to 'now' just before all the prims and actors are called for collisions and updates // Set to 'now' just before all the prims and actors are called for collisions and updates
@ -131,6 +127,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
public float PID_D { get; private set; } // derivative public float PID_D { get; private set; } // derivative
public float PID_P { get; private set; } // proportional public float PID_P { get; private set; } // proportional
@ -254,7 +251,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 +328,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 +491,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
{ {
@ -505,8 +502,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}", DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
} }
catch (Exception e) catch (Exception e)
{ {
@ -582,19 +579,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
} }
} }
// If enabled, call into the physics engine to dump statistics
if (m_detailedStatsStep > 0)
{
if ((m_simulationStep % m_detailedStatsStep) == 0)
{
BulletSimAPI.DumpBulletStatistics();
}
}
// The physics engine returns the number of milliseconds it simulated this call. // The physics engine returns the number of milliseconds it simulated this call.
// These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
// Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. // We multiply by 45 to give a recognizable running rate (45 or less).
return numSubSteps * m_fixedTimeStep * 1000; return numSubSteps * m_fixedTimeStep * 1000 * 45;
// return timeStep * 1000 * 45;
} }
// Something has collided // Something has collided
@ -617,7 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
BSPhysObject collidee = null; BSPhysObject collidee = null;
PhysObjects.TryGetValue(collidingWith, out collidee); PhysObjects.TryGetValue(collidingWith, out collidee);
DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
{ {
@ -703,6 +692,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
{ {
if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
{ {
// swizzle a new list into the list location so we can process what's there
int taintCount = m_taintsToProcessPerStep;
TaintCallbackEntry oneCallback = new TaintCallbackEntry();
while (_taintedObjects.Count > 0 && taintCount-- > 0)
{
bool gotOne = false;
lock (_taintLock)
{
if (_taintedObjects.Count > 0)
{
oneCallback = _taintedObjects[0];
_taintedObjects.RemoveAt(0);
gotOne = true;
}
}
if (gotOne)
{
try
{
DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
oneCallback.callback();
}
catch (Exception e)
{
m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
}
}
}
/*
// swizzle a new list into the list location so we can process what's there // swizzle a new list into the list location so we can process what's there
List<TaintCallbackEntry> oldList; List<TaintCallbackEntry> oldList;
lock (_taintLock) lock (_taintLock)
@ -715,6 +733,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)
@ -723,6 +742,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
} }
} }
oldList.Clear(); oldList.Clear();
*/
} }
} }
@ -834,6 +854,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
(s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
(s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
ConfigurationParameters.numericTrue,
(s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
(s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
(s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
8f, 8f,
@ -876,6 +901,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
(s) => { return (float)s.m_maxUpdatesPerFrame; }, (s) => { return (float)s.m_maxUpdatesPerFrame; },
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
100f,
(s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
(s) => { return (float)s.m_taintsToProcessPerStep; },
(s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
10000.01f, 10000.01f,
(s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
@ -1070,12 +1100,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
(s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
0.1f, 0.001f,
(s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].linkConstraintCFM; }, (s) => { return s.m_params[0].linkConstraintCFM; },
(s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
0.2f, 0.8f,
(s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].linkConstraintERP; }, (s) => { return s.m_params[0].linkConstraintERP; },
(s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
@ -1085,11 +1115,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s) => { return s.m_params[0].linkConstraintSolverIterations; }, (s) => { return s.m_params[0].linkConstraintSolverIterations; },
(s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
0f, 0f,
(s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
(s) => { return (float)s.m_detailedStatsStep; }, (s) => { return (float)s.m_params[0].physicsLoggingFrames; },
(s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ),
}; };
// Convert a boolean to our numeric true and false values // Convert a boolean to our numeric true and false values
@ -1270,6 +1300,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();
} }
// 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";

View File

@ -67,8 +67,8 @@ public class BSShapeCollection : IDisposable
public DateTime lastReferenced; public DateTime lastReferenced;
} }
private Dictionary<ulong, MeshDesc> Meshes = new Dictionary<ulong, MeshDesc>(); private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
private Dictionary<ulong, HullDesc> Hulls = new Dictionary<ulong, HullDesc>(); private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>(); private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>();
public BSShapeCollection(BSScene physScene) public BSShapeCollection(BSScene physScene)
@ -121,7 +121,7 @@ public 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 reference count is either 1 or 0. // Bodies only have one user so the reference count is either 1 or 0.
public void ReferenceBody(BulletBody body, bool atTaintTime) public void ReferenceBody(BulletBody body, bool inTaintTime)
{ {
lock (m_collectionActivityLock) lock (m_collectionActivityLock)
{ {
@ -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 (inTaintTime)
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;
@ -257,7 +272,7 @@ public class BSShapeCollection : IDisposable
// Release the usage of a shape. // Release the usage of a shape.
// The collisionObject is released since it is a copy of the real collision shape. // The collisionObject is released since it is a copy of the real collision shape.
public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
{ {
if (shape.ptr == IntPtr.Zero) if (shape.ptr == IntPtr.Zero)
return; return;
@ -279,14 +294,14 @@ public class BSShapeCollection : IDisposable
if (shape.ptr != IntPtr.Zero & shape.isNativeShape) if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
{ {
DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
if (shapeCallback != null) shapeCallback(shape); if (shapeCallback != null) shapeCallback(shape);
BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
} }
break; break;
} }
}; };
if (atTaintTime) if (inTaintTime)
{ {
lock (m_collectionActivityLock) lock (m_collectionActivityLock)
{ {
@ -392,7 +407,7 @@ public class BSShapeCollection : IDisposable
// made. Native shapes are best used in either case. // made. Native shapes are best used in either case.
if (!haveShape) if (!haveShape)
{ {
if (prim.IsPhysical) if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects)
{ {
// Update prim.BSShape to reference a hull of this shape. // Update prim.BSShape to reference a hull of this shape.
ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback);
@ -426,7 +441,7 @@ public class BSShapeCollection : IDisposable
// Native shapes are always built independently. // Native shapes are always built independently.
newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
newShape.shapeKey = (ulong)shapeKey; newShape.shapeKey = (System.UInt64)shapeKey;
newShape.isNativeShape = true; newShape.isNativeShape = true;
// Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked.
@ -446,7 +461,7 @@ public class BSShapeCollection : IDisposable
BulletShape newShape = new BulletShape(IntPtr.Zero); BulletShape newShape = new BulletShape(IntPtr.Zero);
float lod; float lod;
ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);
// if this new shape is the same as last time, don't recreate the mesh // if this new shape is the same as last time, don't recreate the mesh
if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
@ -469,7 +484,7 @@ public class BSShapeCollection : IDisposable
return true; // 'true' means a new shape has been added to this prim return true; // 'true' means a new shape has been added to this prim
} }
private BulletShape CreatePhysicalMesh(string objName, ulong newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{ {
IMesh meshData = null; IMesh meshData = null;
IntPtr meshPtr; IntPtr meshPtr;
@ -516,7 +531,7 @@ public class BSShapeCollection : IDisposable
BulletShape newShape; BulletShape newShape;
float lod; float lod;
ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod);
// if the hull hasn't changed, don't rebuild it // if the hull hasn't changed, don't rebuild it
if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
@ -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);
@ -539,7 +554,7 @@ public class BSShapeCollection : IDisposable
} }
List<ConvexResult> m_hulls; List<ConvexResult> m_hulls;
private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{ {
IntPtr hullPtr; IntPtr hullPtr;
@ -652,22 +667,23 @@ public class BSShapeCollection : IDisposable
// Create a hash of all the shape parameters to be used as a key // Create a hash of all the shape parameters to be used as a key
// for this particular shape. // for this particular shape.
private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod)
{ {
// level of detail based on size and type of the object // level of detail based on size and type of the object
float lod = PhysicsScene.MeshLOD; float lod = PhysicsScene.MeshLOD;
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;
retLod = lod; retLod = lod;
return (ulong)pbs.GetMeshKey(shapeData.Size, lod); return pbs.GetMeshKey(shapeData.Size, lod);
} }
// For those who don't want the LOD // For those who don't want the LOD
private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs)
{ {
float lod; float lod;
return ComputeShapeKey(shapeData, pbs, out lod); return ComputeShapeKey(shapeData, pbs, out lod);
@ -701,6 +717,7 @@ public class BSShapeCollection : IDisposable
if (mustRebuild || forceRebuild) if (mustRebuild || forceRebuild)
{ {
// Free any old body
DereferenceBody(prim.BSBody, true, bodyCallback); DereferenceBody(prim.BSBody, true, bodyCallback);
BulletBody aBody; BulletBody aBody;
@ -709,13 +726,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 +748,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);
} }
} }
} }

View File

@ -114,6 +114,8 @@ public class BSTerrainManager
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
Vector3.Zero, Quaternion.Identity)); Vector3.Zero, Quaternion.Identity));
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
// Ground plane does not move
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
// Everything collides with the ground plane. // Everything collides with the ground plane.
BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
(uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
@ -201,10 +203,10 @@ public class BSTerrainManager
// The 'doNow' boolean says whether to do all the unmanaged activities right now (like when // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
// calling this routine from initialization or taint-time routines) or whether to delay // calling this routine from initialization or taint-time routines) or whether to delay
// all the unmanaged activities to taint-time. // all the unmanaged activities to taint-time.
private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool atTaintTime) private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
{ {
DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},atTaintTime={3}", DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
BSScene.DetailLogZero, minCoords, maxCoords, atTaintTime); BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
float minZ = float.MaxValue; float minZ = float.MaxValue;
float maxZ = float.MinValue; float maxZ = float.MinValue;
@ -296,16 +298,16 @@ public class BSTerrainManager
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID,
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
// Create the terrain shape from the mapInfo
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
// The terrain object initial position is at the center of the object // The terrain object initial position is at the center of the object
Vector3 centerPos; Vector3 centerPos;
centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
centerPos.Z = minZ + ((maxZ - minZ) / 2f); centerPos.Z = minZ + ((maxZ - minZ) / 2f);
// Create the terrain shape from the mapInfo
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
mapInfo.terrainBody = new BulletBody(mapInfo.ID, mapInfo.terrainBody = new BulletBody(mapInfo.ID,
BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr,
id, centerPos, Quaternion.Identity)); id, centerPos, Quaternion.Identity));
@ -320,9 +322,6 @@ public class BSTerrainManager
BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, 0f, Vector3.Zero);
BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr);
// Return the new terrain to the world of physical objects // Return the new terrain to the world of physical objects
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
@ -342,7 +341,7 @@ public class BSTerrainManager
// There is the option to do the changes now (we're already in 'taint time'), or // There is the option to do the changes now (we're already in 'taint time'), or
// to do the Bullet operations later. // to do the Bullet operations later.
if (atTaintTime) if (inTaintTime)
rebuildOperation(); rebuildOperation();
else else
PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
@ -381,7 +380,7 @@ public class BSTerrainManager
}; };
// If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
if (atTaintTime) if (inTaintTime)
createOperation(); createOperation();
else else
PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);

View File

@ -101,9 +101,8 @@ public struct BulletShape
} }
public IntPtr ptr; public IntPtr ptr;
public ShapeData.PhysicsShapeType type; public ShapeData.PhysicsShapeType type;
public ulong shapeKey; public System.UInt64 shapeKey;
public bool isNativeShape; public bool isNativeShape;
// Hulls have an underlying mesh. A pointer to it is hidden here.
public override string ToString() public override string ToString()
{ {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
@ -192,8 +191,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;
@ -305,6 +305,8 @@ public struct ConfigurationParameters
public float linkConstraintCFM; public float linkConstraintCFM;
public float linkConstraintSolverIterations; public float linkConstraintSolverIterations;
public float physicsLoggingFrames;
public const float numericTrue = 1f; public const float numericTrue = 1f;
public const float numericFalse = 0f; public const float numericFalse = 0f;
} }
@ -1036,18 +1038,6 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int GetNumConstraintRefs2(IntPtr obj); public static extern int GetNumConstraintRefs2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 GetPushVelocity2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 GetTurnVelocity2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
@ -1107,6 +1097,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);

View File

@ -21,7 +21,38 @@
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>] ; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
; * ; *
[Startup] [Startup]
ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
[ServiceList]
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector"
VoiceConnector = "8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector"
GridServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridServiceConnector"
GridInfoServerInConnector = "8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector"
AuthenticationServiceConnector = "8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector"
OpenIdServerConnector = "8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector"
AvatarServiceConnector = "8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector"
LLLoginServiceInConnector = "8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector"
PresenceServiceConnector = "8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector"
UserAccountServiceConnector = "8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector"
GridUserServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector"
FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
;; Additions for Hypergrid
GatekeeperServiceInConnector = "8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector"
UserAgentServerConnector = "8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector"
HeloServiceInConnector = "8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector"
HGFriendsServerConnector = "8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector"
InstantMessageServerConnector = "8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector"
HGInventoryServiceConnector = "HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector"
HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector"
;; Additions for other add-on modules. For example:
;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
; * This is common for all services, it's the network setup for the entire ; * This is common for all services, it's the network setup for the entire
; * server instance, if none is specified above ; * server instance, if none is specified above

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.