Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
f5f5f2e3fb
|
@ -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; }
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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.
Loading…
Reference in New Issue