Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
avinationmerge
Melanie 2012-12-28 08:32:34 +00:00
commit 3ab1bd0403
31 changed files with 350 additions and 211 deletions

View File

@ -2447,10 +2447,15 @@ namespace OpenSim.Region.Framework.Scenes
m_lastSize = Appearance.AvatarSize; m_lastSize = Appearance.AvatarSize;
SendAvatarDataToAllAgents(); SendAvatarDataToAllAgents();
} }
// Throw away duplicate or insignificant updates
else if (
// If the velocity has become zero, send it no matter what.
(Velocity != m_lastVelocity && Velocity == Vector3.Zero)
// otherwise, if things have changed reasonably, send the update
|| (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
|| !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE)
|| !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)))
else if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
!Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
{ {
SendTerseUpdateToAllClients(); SendTerseUpdateToAllClients();

View File

@ -174,7 +174,7 @@ public sealed class BSCharacter : BSPhysObject
BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius); BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius);
} }
UpdatePhysicalMassProperties(RawMass); UpdatePhysicalMassProperties(RawMass, false);
// Make so capsule does not fall over // Make so capsule does not fall over
BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero);
@ -224,7 +224,7 @@ public sealed class BSCharacter : BSPhysObject
if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
{ {
BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
UpdatePhysicalMassProperties(RawMass); UpdatePhysicalMassProperties(RawMass, true);
// Make sure this change appears as a property update event // Make sure this change appears as a property update event
BulletSimAPI.PushUpdate2(PhysBody.ptr); BulletSimAPI.PushUpdate2(PhysBody.ptr);
} }
@ -260,7 +260,6 @@ public sealed class BSCharacter : BSPhysObject
public override void ZeroMotion(bool inTaintTime) public override void ZeroMotion(bool inTaintTime)
{ {
_velocity = OMV.Vector3.Zero; _velocity = OMV.Vector3.Zero;
_velocityMotor.Zero();
_acceleration = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero;
@ -390,7 +389,7 @@ public sealed class BSCharacter : BSPhysObject
public override float RawMass { public override float RawMass {
get {return _mass; } get {return _mass; }
} }
public override void UpdatePhysicalMassProperties(float physMass) public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
{ {
OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia);
@ -787,6 +786,7 @@ public sealed class BSCharacter : BSPhysObject
// the motor can be turned off. Set the velocity to zero so the zero motion is sent to the viewer. // the motor can be turned off. Set the velocity to zero so the zero motion is sent to the viewer.
if (_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero) if (_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero)
{ {
ZeroMotion(true);
stepVelocity = OMV.Vector3.Zero; stepVelocity = OMV.Vector3.Zero;
_velocityMotor.Enabled = false; _velocityMotor.Enabled = false;
DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor); DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor);

View File

@ -36,7 +36,7 @@ public abstract class BSConstraint : IDisposable
{ {
private static string LogHeader = "[BULLETSIM CONSTRAINT]"; private static string LogHeader = "[BULLETSIM CONSTRAINT]";
protected BulletSim m_world; protected BulletWorld m_world;
protected BulletBody m_body1; protected BulletBody m_body1;
protected BulletBody m_body2; protected BulletBody m_body2;
protected BulletConstraint m_constraint; protected BulletConstraint m_constraint;

View File

@ -39,7 +39,7 @@ public sealed class BSConstraint6Dof : BSConstraint
public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
// Create a btGeneric6DofConstraint // Create a btGeneric6DofConstraint
public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot, Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot, Vector3 frame2, Quaternion frame2rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
@ -58,7 +58,7 @@ public sealed class BSConstraint6Dof : BSConstraint
obj1.ID, obj1.ptr.ToString(), obj2.ID, obj2.ptr.ToString()); obj1.ID, obj1.ptr.ToString(), obj2.ID, obj2.ptr.ToString());
} }
public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 joinPoint, Vector3 joinPoint,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
{ {

View File

@ -41,9 +41,9 @@ public sealed class BSConstraintCollection : IDisposable
delegate bool ConstraintAction(BSConstraint constrain); delegate bool ConstraintAction(BSConstraint constrain);
private List<BSConstraint> m_constraints; private List<BSConstraint> m_constraints;
private BulletSim m_world; private BulletWorld m_world;
public BSConstraintCollection(BulletSim world) public BSConstraintCollection(BulletWorld world)
{ {
m_world = world; m_world = world;
m_constraints = new List<BSConstraint>(); m_constraints = new List<BSConstraint>();

View File

@ -36,7 +36,7 @@ public sealed class BSConstraintHinge : BSConstraint
{ {
public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } }
public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2, public BSConstraintHinge(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 pivotInA, Vector3 pivotInB, Vector3 pivotInA, Vector3 pivotInB,
Vector3 axisInA, Vector3 axisInB, Vector3 axisInA, Vector3 axisInB,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)

View File

@ -573,6 +573,9 @@ namespace OpenSim.Region.Physics.BulletSNPlugin
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy);
BulletSimAPI.SetGravity2(Prim.PhysBody.ptr, grav);
VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}",
Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
} }

View File

@ -97,14 +97,7 @@ public abstract class BSLinkset
} }
// We keep the prim's mass in the linkset structure since it could be dependent on other prims // We keep the prim's mass in the linkset structure since it could be dependent on other prims
protected float m_mass; public float LinksetMass { get; protected set; }
public float LinksetMass
{
get
{
return m_mass;
}
}
public virtual bool LinksetIsColliding { get { return false; } } public virtual bool LinksetIsColliding { get { return false; } }
@ -128,7 +121,7 @@ public abstract class BSLinkset
PhysicsScene = scene; PhysicsScene = scene;
LinksetRoot = parent; LinksetRoot = parent;
m_children = new HashSet<BSPhysObject>(); m_children = new HashSet<BSPhysObject>();
m_mass = parent.RawMass; LinksetMass = parent.RawMass;
Rebuilding = false; Rebuilding = false;
} }
@ -143,7 +136,7 @@ public abstract class BSLinkset
// Don't add the root to its own linkset // Don't add the root to its own linkset
if (!IsRoot(child)) if (!IsRoot(child))
AddChildToLinkset(child); AddChildToLinkset(child);
m_mass = ComputeLinksetMass(); LinksetMass = ComputeLinksetMass();
} }
return this; return this;
} }
@ -162,7 +155,7 @@ public abstract class BSLinkset
return this; return this;
} }
RemoveChildFromLinkset(child); RemoveChildFromLinkset(child);
m_mass = ComputeLinksetMass(); LinksetMass = ComputeLinksetMass();
} }
// The child is down to a linkset of just itself // The child is down to a linkset of just itself
@ -230,7 +223,10 @@ public abstract class BSLinkset
// When physical properties are changed the linkset needs to recalculate // When physical properties are changed the linkset needs to recalculate
// its internal properties. // its internal properties.
// May be called at runtime or taint-time. // May be called at runtime or taint-time.
public abstract void Refresh(BSPhysObject requestor); public virtual void Refresh(BSPhysObject requestor)
{
LinksetMass = ComputeLinksetMass();
}
// Flag denoting the linkset is in the process of being rebuilt. // Flag denoting the linkset is in the process of being rebuilt.
// Used to know not the schedule a rebuild in the middle of a rebuild. // Used to know not the schedule a rebuild in the middle of a rebuild.

View File

@ -89,6 +89,8 @@ public sealed class BSLinksetCompound : BSLinkset
// its internal properties. // its internal properties.
public override void Refresh(BSPhysObject requestor) public override void Refresh(BSPhysObject requestor)
{ {
base.Refresh(requestor);
// Something changed so do the rebuilding thing // Something changed so do the rebuilding thing
// ScheduleRebuild(); // ScheduleRebuild();
} }
@ -96,13 +98,13 @@ public sealed class BSLinksetCompound : BSLinkset
// Schedule a refresh to happen after all the other taint processing. // Schedule a refresh to happen after all the other taint processing.
private void ScheduleRebuild(BSPhysObject requestor) private void ScheduleRebuild(BSPhysObject requestor)
{ {
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,rebuilding={1}", DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1}",
requestor.LocalID, Rebuilding); requestor.LocalID, Rebuilding);
// When rebuilding, it is possible to set properties that would normally require a rebuild. // When rebuilding, it is possible to set properties that would normally require a rebuild.
// If already rebuilding, don't request another rebuild. // If already rebuilding, don't request another rebuild.
if (!Rebuilding) if (!Rebuilding)
{ {
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", LinksetRoot.LocalID, delegate() PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
{ {
if (HasAnyChildren) if (HasAnyChildren)
RecomputeLinksetCompound(); RecomputeLinksetCompound();
@ -123,7 +125,6 @@ public sealed class BSLinksetCompound : BSLinkset
if (IsRoot(child)) if (IsRoot(child))
{ {
// The root is going dynamic. Make sure mass is properly set. // The root is going dynamic. Make sure mass is properly set.
m_mass = ComputeLinksetMass();
ScheduleRebuild(LinksetRoot); ScheduleRebuild(LinksetRoot);
} }
else else
@ -377,8 +378,8 @@ public sealed class BSLinksetCompound : BSLinkset
}); });
// With all of the linkset packed into the root prim, it has the mass of everyone. // With all of the linkset packed into the root prim, it has the mass of everyone.
float linksetMass = LinksetMass; LinksetMass = LinksetMass;
LinksetRoot.UpdatePhysicalMassProperties(linksetMass); LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
} }
finally finally
{ {

View File

@ -46,6 +46,8 @@ public sealed class BSLinksetConstraints : BSLinkset
// refresh will happen once after all the other taints are applied. // refresh will happen once after all the other taints are applied.
public override void Refresh(BSPhysObject requestor) public override void Refresh(BSPhysObject requestor)
{ {
base.Refresh(requestor);
// Queue to happen after all the other taint processing // Queue to happen after all the other taint processing
PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
{ {
@ -279,7 +281,7 @@ public sealed class BSLinksetConstraints : BSLinkset
private void RecomputeLinksetConstraints() private void RecomputeLinksetConstraints()
{ {
float linksetMass = LinksetMass; float linksetMass = LinksetMass;
LinksetRoot.UpdatePhysicalMassProperties(linksetMass); LinksetRoot.UpdatePhysicalMassProperties(linksetMass, true);
// DEBUG: see of inter-linkset collisions are causing problems // DEBUG: see of inter-linkset collisions are causing problems
// BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
@ -292,7 +294,7 @@ public sealed class BSLinksetConstraints : BSLinkset
// A child in the linkset physically shows the mass of the whole linkset. // A child in the linkset physically shows the mass of the whole linkset.
// This allows Bullet to apply enough force on the child to move the whole linkset. // This allows Bullet to apply enough force on the child to move the whole linkset.
// (Also do the mass stuff before recomputing the constraint so mass is not zero.) // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
child.UpdatePhysicalMassProperties(linksetMass); child.UpdatePhysicalMassProperties(linksetMass, true);
BSConstraint constrain; BSConstraint constrain;
if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))

View File

@ -119,26 +119,26 @@ public static class BSMaterials
Attributes[(int)MaterialAttributes.Material.Light] = Attributes[(int)MaterialAttributes.Material.Light] =
new MaterialAttributes("light",dDensity, dFriction, dRestitution); new MaterialAttributes("light",dDensity, dFriction, dRestitution);
Attributes[(int)MaterialAttributes.Material.Avatar] = Attributes[(int)MaterialAttributes.Material.Avatar] =
new MaterialAttributes("avatar",60f, 0.2f, 0f); new MaterialAttributes("avatar",3.5f, 0.2f, 0f);
Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f); new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f); new MaterialAttributes("metalPhysical",dDensity, 0.3f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f); new MaterialAttributes("glassPhysical",dDensity, 0.2f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f); new MaterialAttributes("woodPhysical",dDensity, 0.6f, 0.5f);
Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f); new MaterialAttributes("fleshPhysical",dDensity, 0.9f, 0.3f);
Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f); new MaterialAttributes("plasticPhysical",dDensity, 0.4f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f); new MaterialAttributes("rubberPhysical",dDensity, 0.9f, 0.9f);
Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution); new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f); new MaterialAttributes("avatarPhysical",3.5f, 0.2f, 0f);
} }
// Under the [BulletSim] section, one can change the individual material // Under the [BulletSim] section, one can change the individual material

View File

@ -351,7 +351,7 @@ public static class BSParam
(s) => { return AvatarStandingFriction; }, (s) => { return AvatarStandingFriction; },
(s,p,l,v) => { AvatarStandingFriction = v; } ), (s,p,l,v) => { AvatarStandingFriction = v; } ),
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
60f, 3.5f,
(s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); }, (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
(s) => { return AvatarDensity; }, (s) => { return AvatarDensity; },
(s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ), (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ),

View File

@ -96,7 +96,8 @@ public abstract class BSPhysObject : PhysicsActor
// Return the object mass without calculating it or having side effects // Return the object mass without calculating it or having side effects
public abstract float RawMass { get; } public abstract float RawMass { get; }
// Set the raw mass but also update physical mass properties (inertia, ...) // Set the raw mass but also update physical mass properties (inertia, ...)
public abstract void UpdatePhysicalMassProperties(float mass); // 'inWorld' true if the object has already been added to the dynamic world.
public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld);
// The last value calculated for the prim's inertia // The last value calculated for the prim's inertia
public OMV.Vector3 Inertia { get; set; } public OMV.Vector3 Inertia { get; set; }

View File

@ -115,6 +115,8 @@ public sealed class BSPrim : BSPhysObject
PhysBody = new BulletBody(LocalID); PhysBody = new BulletBody(LocalID);
PhysShape = new BulletShape(); PhysShape = new BulletShape();
Linkset.Refresh(this);
DetailLog("{0},BSPrim.constructor,call", LocalID); DetailLog("{0},BSPrim.constructor,call", LocalID);
// do the actual object creation at taint time // do the actual object creation at taint time
PhysicsScene.TaintedObject("BSPrim.create", delegate() PhysicsScene.TaintedObject("BSPrim.create", delegate()
@ -384,13 +386,13 @@ public sealed class BSPrim : BSPhysObject
} }
// Return the effective mass of the object. // Return the effective mass of the object.
// If there are multiple items in the linkset, add them together for the root // The definition of this call is to return the mass of the prim.
// If the simulator cares about the mass of the linkset, it will sum it itself.
public override float Mass public override float Mass
{ {
get get
{ {
return Linkset.LinksetMass; return _mass;
// return _mass;
} }
} }
@ -400,7 +402,9 @@ public sealed class BSPrim : BSPhysObject
} }
// Set the physical mass to the passed mass. // Set the physical mass to the passed mass.
// Note that this does not change _mass! // Note that this does not change _mass!
public override void UpdatePhysicalMassProperties(float physMass) public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
{
if (PhysBody.HasPhysicalBody)
{ {
if (IsStatic) if (IsStatic)
{ {
@ -410,12 +414,33 @@ public sealed class BSPrim : BSPhysObject
} }
else else
{ {
if (inWorld)
{
// Changing interesting properties doesn't change proxy and collision cache
// information. The Bullet solution is to re-add the object to the world
// after parameters are changed.
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
}
Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia); BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
// center of mass is at the zero of the object // center of mass is at the zero of the object
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia); DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},inWorld={3}", LocalID, physMass, Inertia, inWorld);
if (inWorld)
{
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr,_position,_orientation);
}
// Must set gravity after it has been added to the world because, for unknown reasons,
// adding the object resets the object's gravity to world gravity
OMV.Vector3 grav = PhysicsScene.DefaultGravity * (1f - Buoyancy);
BulletSimAPI.SetGravity2(PhysBody.ptr, grav);
}
} }
} }
@ -714,7 +739,7 @@ public sealed class BSPrim : BSPhysObject
Linkset.Refresh(this); Linkset.Refresh(this);
DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape);
} }
// "Making dynamic" means changing to and from static. // "Making dynamic" means changing to and from static.
@ -737,7 +762,7 @@ public sealed class BSPrim : BSPhysObject
BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution); BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution);
// Mass is zero which disables a bunch of physics stuff in Bullet // Mass is zero which disables a bunch of physics stuff in Bullet
UpdatePhysicalMassProperties(0f); UpdatePhysicalMassProperties(0f, false);
// Set collision detection parameters // Set collision detection parameters
if (BSParam.CcdMotionThreshold > 0f) if (BSParam.CcdMotionThreshold > 0f)
{ {
@ -777,7 +802,7 @@ public sealed class BSPrim : BSPhysObject
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
// A dynamic object has mass // A dynamic object has mass
UpdatePhysicalMassProperties(RawMass); UpdatePhysicalMassProperties(RawMass, false);
// Set collision detection parameters // Set collision detection parameters
if (BSParam.CcdMotionThreshold > 0f) if (BSParam.CcdMotionThreshold > 0f)
@ -950,15 +975,11 @@ public sealed class BSPrim : BSPhysObject
set { set {
_buoyancy = value; _buoyancy = value;
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
// Buoyancy is faked by changing the gravity applied to the object // Force the recalculation of the various inertia,etc variables in the object
if (PhysBody.HasPhysicalBody) UpdatePhysicalMassProperties(_mass, true);
{
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
ActivateIfPhysical(false); ActivateIfPhysical(false);
} }
} }
}
// Used for MoveTo // Used for MoveTo
public override OMV.Vector3 PIDTarget { public override OMV.Vector3 PIDTarget {
@ -993,7 +1014,9 @@ public sealed class BSPrim : BSPhysObject
public override float APIDDamping { set { return; } } public override float APIDDamping { set { return; } }
public override void AddForce(OMV.Vector3 force, bool pushforce) { public override void AddForce(OMV.Vector3 force, bool pushforce) {
AddForce(force, pushforce, false); // Since this force is being applied in only one step, make this a force per second.
OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep;
AddForce(addForce, pushforce, false);
} }
// Applying a force just adds this to the total force on the object. // Applying a force just adds this to the total force on the object.
// This added force will only last the next simulation tick. // This added force will only last the next simulation tick.
@ -1001,8 +1024,16 @@ public sealed class BSPrim : BSPhysObject
// 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())
{ {
float magnitude = force.Length();
if (magnitude > 20000f)
{
// Force has a limit
force = force / magnitude * 20000f;
}
OMV.Vector3 addForce = force; OMV.Vector3 addForce = force;
DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
{ {
// Bullet adds this central force to the total force for this tick // Bullet adds this central force to the total force for this tick

View File

@ -74,7 +74,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
public IMesher mesher; public IMesher mesher;
public uint WorldID { get; private set; } public uint WorldID { get; private set; }
public BulletSim World { get; private set; } public BulletWorld World { get; private set; }
// All the constraints that have been allocated in this instance. // All the constraints that have been allocated in this instance.
public BSConstraintCollection Constraints { get; private set; } public BSConstraintCollection Constraints { get; private set; }
@ -244,7 +244,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, UnmanagedParams, World = new BulletWorld(0, this, BulletSimAPI.Initialize2(worldExtent, UnmanagedParams,
m_maxCollisionsPerFrame, ref m_collisionArray, m_maxCollisionsPerFrame, ref m_collisionArray,
m_maxUpdatesPerFrame,ref m_updateArray, m_maxUpdatesPerFrame,ref m_updateArray,
m_DebugLogCallbackHandle)); m_DebugLogCallbackHandle));
@ -497,13 +497,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
InTaintTime = false; // Only used for debugging so locking is not necessary. InTaintTime = false; // Only used for debugging so locking is not necessary.
// The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
// Only enable this in a limited test world with few objects.
// BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG
// step the physical world one interval // step the physical world one interval
m_simulationStep++; m_simulationStep++;
int numSubSteps = 0; int numSubSteps = 0;
try try
{ {
//if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
@ -833,7 +836,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{ {
DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
Util.PrintCallStack(); // Prints the stack into the DEBUG log file. Util.PrintCallStack(DetailLog);
} }
return InTaintTime; return InTaintTime;
} }

View File

@ -98,7 +98,7 @@ public sealed class BSShapeCollection : IDisposable
// higher level dependencies on the shape or body. Mostly used for LinkSets to // higher level dependencies on the shape or body. Mostly used for LinkSets to
// remove the physical constraints before the body is destroyed. // remove the physical constraints before the body is destroyed.
// Called at taint-time!! // Called at taint-time!!
public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
{ {
PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
@ -126,7 +126,7 @@ public sealed class BSShapeCollection : IDisposable
return ret; return ret;
} }
public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim) public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
{ {
return GetBodyAndShape(forceRebuild, sim, prim, null, null); return GetBodyAndShape(forceRebuild, sim, prim, null, null);
} }
@ -637,7 +637,7 @@ public sealed class BSShapeCollection : IDisposable
} }
else else
{ {
meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false); meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
if (meshData != null) if (meshData != null)
{ {
@ -709,7 +709,7 @@ public sealed class BSShapeCollection : IDisposable
{ {
// Build a new hull in the physical world // Build a new hull in the physical world
// Pass true for physicalness as this creates some sort of bounding box which we don't need // Pass true for physicalness as this creates some sort of bounding box which we don't need
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false); IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
if (meshData != null) if (meshData != null)
{ {
@ -918,7 +918,7 @@ public sealed class BSShapeCollection : IDisposable
// Updates prim.BSBody with the information about the new body if one is created. // Updates prim.BSBody with the information about the new body if one is created.
// Returns 'true' if an object was actually created. // Returns 'true' if an object was actually created.
// Called at taint-time. // Called at taint-time.
private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BulletShape shape,
BodyDestructionCallback bodyCallback) BodyDestructionCallback bodyCallback)
{ {
bool ret = false; bool ret = false;

View File

@ -103,7 +103,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
Vector3 centerPos; Vector3 centerPos;
centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f);
centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f + 0.5f); centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f - 0.5f);
m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID,
BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr,

View File

@ -140,7 +140,7 @@ public sealed class BSTerrainManager : IDisposable
m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
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, Vector3.Zero, Quaternion.Identity);
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr); BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr);
// Ground plane does not move // Ground plane does not move
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
@ -376,6 +376,7 @@ public sealed class BSTerrainManager : IDisposable
DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
BSScene.DetailLogZero, pos, terrainBaseXYZ); BSScene.DetailLogZero, pos, terrainBaseXYZ);
} }
lastHeight = ret; lastHeight = ret;
return ret; return ret;
} }

View File

@ -58,7 +58,6 @@ public enum ConstraintType : int
MAX_CONSTRAINT_TYPE MAX_CONSTRAINT_TYPE
} }
// =============================================================================== // ===============================================================================
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct ConvexHull public struct ConvexHull

View File

@ -35,9 +35,9 @@ namespace OpenSim.Region.Physics.BulletSNPlugin
// These hold pointers to allocated objects in the unmanaged space. // These hold pointers to allocated objects in the unmanaged space.
// The physics engine controller class created at initialization // The physics engine controller class created at initialization
public struct BulletSim public struct BulletWorld
{ {
public BulletSim(uint worldId, BSScene bss, object xx) public BulletWorld(uint worldId, BSScene bss, object xx)
{ {
ptr = xx; ptr = xx;
worldID = worldId; worldID = worldId;

View File

@ -260,7 +260,6 @@ public sealed class BSCharacter : BSPhysObject
public override void ZeroMotion(bool inTaintTime) public override void ZeroMotion(bool inTaintTime)
{ {
_velocity = OMV.Vector3.Zero; _velocity = OMV.Vector3.Zero;
_velocityMotor.Zero();
_acceleration = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero;
@ -585,18 +584,6 @@ public sealed class BSCharacter : BSPhysObject
get { return _throttleUpdates; } get { return _throttleUpdates; }
set { _throttleUpdates = value; } set { _throttleUpdates = value; }
} }
public override bool IsColliding {
get { return (CollidingStep == PhysicsScene.SimulationStep); }
set { _isColliding = value; }
}
public override bool CollidingGround {
get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
set { CollidingGround = value; }
}
public override bool CollidingObj {
get { return _collidingObj; }
set { _collidingObj = value; }
}
public override bool FloatOnWater { public override bool FloatOnWater {
set { set {
_floatOnWater = value; _floatOnWater = value;
@ -684,22 +671,31 @@ public sealed class BSCharacter : BSPhysObject
public override void AddForce(OMV.Vector3 force, bool pushforce) { public override void AddForce(OMV.Vector3 force, bool pushforce) {
if (force.IsFinite()) if (force.IsFinite())
{ {
_force.X += force.X; float magnitude = force.Length();
_force.Y += force.Y; if (magnitude > BSParam.MaxAddForceMagnitude)
_force.Z += force.Z; {
// m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); // Force has a limit
force = force / magnitude * BSParam.MaxAddForceMagnitude;
}
OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep;
DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
{ {
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); // Bullet adds this central force to the total force for this tick
DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
if (PhysBody.HasPhysicalBody) if (PhysBody.HasPhysicalBody)
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); {
BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, addForce);
}
}); });
} }
else else
{ {
m_log.ErrorFormat("{0}: Got a NaN force applied to a Character", LogHeader); m_log.WarnFormat("{0}: Got a NaN force applied to a character. LocalID={1}", LogHeader, LocalID);
return;
} }
//m_lastUpdateSent = false;
} }
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
@ -761,21 +757,25 @@ public sealed class BSCharacter : BSPhysObject
OMV.Vector3 stepVelocity = _velocityMotor.Step(PhysicsScene.LastTimeStep); OMV.Vector3 stepVelocity = _velocityMotor.Step(PhysicsScene.LastTimeStep);
// Check for cases to turn off the motor.
if (
// If the walking motor is all done, turn it off
(_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero) )
{
ZeroMotion(true);
stepVelocity = OMV.Vector3.Zero;
_velocityMotor.Enabled = false;
DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor);
}
else
{
// If the motor is not being turned off...
// If falling, we keep the world's downward vector no matter what the other axis specify. // If falling, we keep the world's downward vector no matter what the other axis specify.
if (!Flying && !IsColliding) if (!Flying && !IsColliding)
{ {
stepVelocity.Z = entprop.Velocity.Z; stepVelocity.Z = entprop.Velocity.Z;
DetailLog("{0},BSCharacter.UpdateProperties,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); DetailLog("{0},BSCharacter.UpdateProperties,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
} }
// If the user has said stop and we've stopped applying velocity correction,
// the motor can be turned off. Set the velocity to zero so the zero motion is sent to the viewer.
if (_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero)
{
_velocityMotor.Enabled = false;
stepVelocity = OMV.Vector3.Zero;
ZeroMotion(true);
DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor);
} }
_velocity = stepVelocity; _velocity = stepVelocity;

View File

@ -573,6 +573,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy);
BulletSimAPI.SetGravity2(Prim.PhysBody.ptr, grav);
VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}",
Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
} }
@ -819,6 +822,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
if (!IsActive) return; if (!IsActive) return;
if (PhysicsScene.VehiclePhysicalLoggingEnabled)
BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, Prim.PhysBody.ptr);
ForgetKnownVehicleProperties(); ForgetKnownVehicleProperties();
MoveLinear(pTimestep); MoveLinear(pTimestep);
@ -833,6 +839,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// for the physics engine to note the changes so an UpdateProperties event will happen. // for the physics engine to note the changes so an UpdateProperties event will happen.
PushKnownChanged(); PushKnownChanged();
if (PhysicsScene.VehiclePhysicalLoggingEnabled)
BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, Prim.PhysBody.ptr);
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, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity); Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity);
} }

View File

@ -5,7 +5,7 @@
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclat simer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD * * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
@ -98,11 +98,12 @@ public sealed class BSLinksetCompound : BSLinkset
// Schedule a refresh to happen after all the other taint processing. // Schedule a refresh to happen after all the other taint processing.
private void ScheduleRebuild(BSPhysObject requestor) private void ScheduleRebuild(BSPhysObject requestor)
{ {
DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1}", DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2}",
requestor.LocalID, Rebuilding); requestor.LocalID, Rebuilding, HasAnyChildren);
// When rebuilding, it is possible to set properties that would normally require a rebuild. // When rebuilding, it is possible to set properties that would normally require a rebuild.
// If already rebuilding, don't request another rebuild. // If already rebuilding, don't request another rebuild.
if (!Rebuilding) // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
if (!Rebuilding && HasAnyChildren)
{ {
PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate() PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
{ {
@ -112,8 +113,7 @@ public sealed class BSLinksetCompound : BSLinkset
} }
} }
// 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
// has not yet been fully constructed. // has not yet been fully constructed.
// Return 'true' if any properties updated on the passed object. // Return 'true' if any properties updated on the passed object.
@ -124,7 +124,7 @@ public sealed class BSLinksetCompound : BSLinkset
DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
if (IsRoot(child)) if (IsRoot(child))
{ {
// The root is going dynamic. Make sure mass is properly set. // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
ScheduleRebuild(LinksetRoot); ScheduleRebuild(LinksetRoot);
} }
else else
@ -378,7 +378,7 @@ public sealed class BSLinksetCompound : BSLinkset
}); });
// With all of the linkset packed into the root prim, it has the mass of everyone. // With all of the linkset packed into the root prim, it has the mass of everyone.
LinksetMass = LinksetMass; LinksetMass = ComputeLinksetMass();
LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
} }
finally finally

View File

@ -241,8 +241,8 @@ public class BSVMotor : BSMotor
public override string ToString() public override string ToString()
{ {
return String.Format("<{0},curr={1},targ={2},decayTS={3},frictTS={4}>", return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>",
UseName, CurrentValue, TargetValue, TargetValueDecayTimeScale, FrictionTimescale); UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale);
} }
} }

View File

@ -89,6 +89,18 @@ public static class BSParam
public static float PID_D { get; private set; } // derivative public static float PID_D { get; private set; } // derivative
public static float PID_P { get; private set; } // proportional public static float PID_P { get; private set; } // proportional
// Various constants that come from that other virtual world that shall not be named
public const float MinGravityZ = -1f;
public const float MaxGravityZ = 28f;
public const float MinFriction = 0f;
public const float MaxFriction = 255f;
public const float MinDensity = 0f;
public const float MaxDensity = 22587f;
public const float MinRestitution = 0f;
public const float MaxRestitution = 1f;
public const float MaxAddForceMagnitude = 20000f;
// ===========================================================================
public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
public delegate float ParamGet(BSScene scene); public delegate float ParamGet(BSScene scene);
public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
@ -200,6 +212,11 @@ public static class BSParam
(s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
(s) => { return (float)s.m_fixedTimeStep; }, (s) => { return (float)s.m_fixedTimeStep; },
(s,p,l,v) => { s.m_fixedTimeStep = v; } ), (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
new ParameterDefn("NominalFrameRate", "The base frame rate we claim",
55f,
(s,cf,p,v) => { s.NominalFrameRate = cf.GetInt(p, (int)v); },
(s) => { return (float)s.NominalFrameRate; },
(s,p,l,v) => { s.NominalFrameRate = (int)v; } ),
new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
2048f, 2048f,
(s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },

View File

@ -182,9 +182,40 @@ public abstract class BSPhysObject : PhysicsActor
protected long CollidingStep { get; set; } protected long CollidingStep { get; set; }
// The simulation step that last had a collision with the ground // The simulation step that last had a collision with the ground
protected long CollidingGroundStep { get; set; } protected long CollidingGroundStep { get; set; }
// The simulation step that last collided with an object
protected long CollidingObjectStep { get; set; }
// The collision flags we think are set in Bullet // The collision flags we think are set in Bullet
protected CollisionFlags CurrentCollisionFlags { get; set; } protected CollisionFlags CurrentCollisionFlags { get; set; }
public override bool IsColliding {
get { return (CollidingStep == PhysicsScene.SimulationStep); }
set {
if (value)
CollidingStep = PhysicsScene.SimulationStep;
else
CollidingStep = 0;
}
}
public override bool CollidingGround {
get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
set
{
if (value)
CollidingGroundStep = PhysicsScene.SimulationStep;
else
CollidingGroundStep = 0;
}
}
public override bool CollidingObj {
get { return (CollidingObjectStep == PhysicsScene.SimulationStep); }
set {
if (value)
CollidingObjectStep = PhysicsScene.SimulationStep;
else
CollidingObjectStep = 0;
}
}
// The collisions that have been collected this tick // The collisions that have been collected this tick
protected CollisionEventUpdate CollisionCollection; protected CollisionEventUpdate CollisionCollection;
@ -196,12 +227,16 @@ public abstract class BSPhysObject : PhysicsActor
{ {
bool ret = false; bool ret = false;
// The following lines make IsColliding() and IsCollidingGround() work // The following lines make IsColliding(), CollidingGround() and CollidingObj work
CollidingStep = PhysicsScene.SimulationStep; CollidingStep = PhysicsScene.SimulationStep;
if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
{ {
CollidingGroundStep = PhysicsScene.SimulationStep; CollidingGroundStep = PhysicsScene.SimulationStep;
} }
else
{
CollidingObjectStep = PhysicsScene.SimulationStep;
}
// prims in the same linkset cannot collide with each other // prims in the same linkset cannot collide with each other
if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))

View File

@ -94,7 +94,7 @@ public sealed class BSPrim : BSPhysObject
_size = size; _size = size;
Scale = size; // prims are the size the user wants them to be (different for BSCharactes). Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
_orientation = rotation; _orientation = rotation;
_buoyancy = 1f; _buoyancy = 0f;
_velocity = OMV.Vector3.Zero; _velocity = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero;
BaseShape = pbs; BaseShape = pbs;
@ -408,12 +408,15 @@ public sealed class BSPrim : BSPhysObject
{ {
if (IsStatic) if (IsStatic)
{ {
BulletSimAPI.SetGravity2(PhysBody.ptr, PhysicsScene.DefaultGravity);
Inertia = OMV.Vector3.Zero; Inertia = OMV.Vector3.Zero;
BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia); BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
} }
else else
{ {
OMV.Vector3 grav = ComputeGravity();
if (inWorld) if (inWorld)
{ {
// Changing interesting properties doesn't change proxy and collision cache // Changing interesting properties doesn't change proxy and collision cache
@ -422,22 +425,39 @@ public sealed class BSPrim : BSPhysObject
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
} }
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); // The computation of mass props requires gravity to be set on the object.
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); BulletSimAPI.SetGravity2(PhysBody.ptr, grav);
Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia); BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
// center of mass is at the zero of the object // center of mass is at the zero of the object
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia); DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", LocalID, physMass, Inertia, grav, inWorld);
if (inWorld) if (inWorld)
{ {
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); AddObjectToPhysicalWorld();
}
// Must set gravity after it has been added to the world because, for unknown reasons,
// adding the object resets the object's gravity to world gravity
BulletSimAPI.SetGravity2(PhysBody.ptr, grav);
} }
} }
} }
// Return what gravity should be set to this very moment
private OMV.Vector3 ComputeGravity()
{
OMV.Vector3 ret = PhysicsScene.DefaultGravity;
if (!IsStatic)
ret *= (1f - Buoyancy);
return ret;
} }
// Is this used? // Is this used?
@ -665,7 +685,7 @@ public sealed class BSPrim : BSPhysObject
_isPhysical = value; _isPhysical = value;
PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
{ {
// DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
SetObjectDynamic(true); SetObjectDynamic(true);
// whether phys-to-static or static-to-phys, the object is not moving. // whether phys-to-static or static-to-phys, the object is not moving.
ZeroMotion(true); ZeroMotion(true);
@ -720,22 +740,19 @@ public sealed class BSPrim : BSPhysObject
// Make solid or not (do things bounce off or pass through this object). // Make solid or not (do things bounce off or pass through this object).
MakeSolid(IsSolid); MakeSolid(IsSolid);
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); AddObjectToPhysicalWorld();
// Rebuild its shape // Rebuild its shape
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
// Collision filter can be set only when the object is in the world
PhysBody.ApplyCollisionMask();
// 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.
// For compound based linksets, this enables and disables interactions of the children. // For compound based linksets, this enables and disables interactions of the children.
Linkset.Refresh(this); Linkset.Refresh(this);
DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
} }
// "Making dynamic" means changing to and from static. // "Making dynamic" means changing to and from static.
@ -876,6 +893,28 @@ public sealed class BSPrim : BSPhysObject
} }
} }
// Add me to the physical world.
// Object MUST NOT already be in the world.
// This routine exists because some assorted properties get mangled by adding to the world.
internal void AddObjectToPhysicalWorld()
{
if (PhysBody.HasPhysicalBody)
{
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
// TODO: Fix this. Total kludge because adding object to world resets its gravity to default.
// Replace this when the new AddObjectToWorld function is complete.
BulletSimAPI.SetGravity2(PhysBody.ptr, ComputeGravity());
// Collision filter can be set only when the object is in the world
if (!PhysBody.ApplyCollisionMask())
{
m_log.ErrorFormat("{0} Failed setting object collision mask: id={1}", LogHeader, LocalID);
DetailLog("{0},BSPrim.UpdatePhysicalParameters,failedSetMaskGroup,cType={1}", LocalID, PhysBody.collisionType);
}
}
}
// prims don't fly // prims don't fly
public override bool Flying { public override bool Flying {
get { return _flying; } get { return _flying; }
@ -891,18 +930,6 @@ public sealed class BSPrim : BSPhysObject
get { return _throttleUpdates; } get { return _throttleUpdates; }
set { _throttleUpdates = value; } set { _throttleUpdates = value; }
} }
public override bool IsColliding {
get { return (CollidingStep == PhysicsScene.SimulationStep); }
set { _isColliding = value; }
}
public override bool CollidingGround {
get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
set { _collidingGround = value; }
}
public override bool CollidingObj {
get { return _collidingObj; }
set { _collidingObj = value; }
}
public bool IsPhantom { public bool IsPhantom {
get { get {
// SceneObjectPart removes phantom objects from the physics scene // SceneObjectPart removes phantom objects from the physics scene
@ -972,6 +999,7 @@ public sealed class BSPrim : BSPhysObject
_buoyancy = value; _buoyancy = value;
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
// Force the recalculation of the various inertia,etc variables in the object // Force the recalculation of the various inertia,etc variables in the object
DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2}", LocalID, _buoyancy, _mass);
UpdatePhysicalMassProperties(_mass, true); UpdatePhysicalMassProperties(_mass, true);
ActivateIfPhysical(false); ActivateIfPhysical(false);
} }
@ -981,12 +1009,12 @@ public sealed class BSPrim : BSPhysObject
public override OMV.Vector3 PIDTarget { public override OMV.Vector3 PIDTarget {
set { _PIDTarget = value; } set { _PIDTarget = value; }
} }
public override bool PIDActive {
set { _usePID = value; }
}
public override float PIDTau { public override float PIDTau {
set { _PIDTau = value; } set { _PIDTau = value; }
} }
public override bool PIDActive {
set { _usePID = value; }
}
// Used for llSetHoverHeight and maybe vehicle height // Used for llSetHoverHeight and maybe vehicle height
// Hover Height will override MoveTo target's Z // Hover Height will override MoveTo target's Z
@ -1010,7 +1038,9 @@ public sealed class BSPrim : BSPhysObject
public override float APIDDamping { set { return; } } public override float APIDDamping { set { return; } }
public override void AddForce(OMV.Vector3 force, bool pushforce) { public override void AddForce(OMV.Vector3 force, bool pushforce) {
AddForce(force, pushforce, false); // Since this force is being applied in only one step, make this a force per second.
OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep;
AddForce(addForce, pushforce, false);
} }
// Applying a force just adds this to the total force on the object. // Applying a force just adds this to the total force on the object.
// This added force will only last the next simulation tick. // This added force will only last the next simulation tick.
@ -1018,8 +1048,16 @@ public sealed class BSPrim : BSPhysObject
// 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())
{ {
float magnitude = force.Length();
if (magnitude > BSParam.MaxAddForceMagnitude)
{
// Force has a limit
force = force / magnitude * BSParam.MaxAddForceMagnitude;
}
OMV.Vector3 addForce = force; OMV.Vector3 addForce = force;
DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
{ {
// Bullet adds this central force to the total force for this tick // Bullet adds this central force to the total force for this tick

View File

@ -38,15 +38,6 @@ using Nini.Config;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
// Based on material, set density and friction
// More efficient memory usage when passing hull information from BSPrim to BulletSim
// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
// Implement LockAngularMotion
// Add PID movement operations. What does ScenePresence.MoveToTarget do?
// Check terrain size. 128 or 127?
// Raycast
//
namespace OpenSim.Region.Physics.BulletSPlugin namespace OpenSim.Region.Physics.BulletSPlugin
{ {
public sealed class BSScene : PhysicsScene, IPhysicsParameters public sealed class BSScene : PhysicsScene, IPhysicsParameters
@ -83,6 +74,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
internal int m_maxSubSteps; internal int m_maxSubSteps;
internal float m_fixedTimeStep; internal float m_fixedTimeStep;
internal long m_simulationStep = 0; internal long m_simulationStep = 0;
internal float NominalFrameRate { get; set; }
public long SimulationStep { get { return m_simulationStep; } } public long SimulationStep { get { return m_simulationStep; } }
internal int m_taintsToProcessPerStep; internal int m_taintsToProcessPerStep;
internal float LastTimeStep { get; private set; } internal float LastTimeStep { get; private set; }
@ -171,6 +163,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
private string m_physicsLoggingPrefix; private string m_physicsLoggingPrefix;
private int m_physicsLoggingFileMinutes; private int m_physicsLoggingFileMinutes;
private bool m_physicsLoggingDoFlush; private bool m_physicsLoggingDoFlush;
private bool m_physicsPhysicalDumpEnabled;
// 'true' of the vehicle code is to log lots of details // 'true' of the vehicle code is to log lots of details
public bool VehicleLoggingEnabled { get; private set; } public bool VehicleLoggingEnabled { get; private set; }
public bool VehiclePhysicalLoggingEnabled { get; private set; } public bool VehiclePhysicalLoggingEnabled { get; private set; }
@ -276,11 +269,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
BSParam.SetParameterConfigurationValues(this, pConfig); BSParam.SetParameterConfigurationValues(this, pConfig);
// Very detailed logging for physics debugging // Very detailed logging for physics debugging
// TODO: the boolean values can be moved to the normal parameter processing.
m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false); m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
m_physicsPhysicalDumpEnabled = pConfig.GetBoolean("PhysicsPhysicalDumpEnabled", false);
// Very detailed logging for vehicle debugging // Very detailed logging for vehicle debugging
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false); VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false);
@ -495,6 +490,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
InTaintTime = false; // Only used for debugging so locking is not necessary. InTaintTime = false; // Only used for debugging so locking is not necessary.
// The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
// Only enable this in a limited test world with few objects.
if (m_physicsPhysicalDumpEnabled)
BulletSimAPI.DumpAllInfo2(World.ptr);
// step the physical world one interval // step the physical world one interval
m_simulationStep++; m_simulationStep++;
int numSubSteps = 0; int numSubSteps = 0;
@ -592,12 +592,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
// Only enable this in a limited test world with few objects. // Only enable this in a limited test world with few objects.
// BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG if (m_physicsPhysicalDumpEnabled)
BulletSimAPI.DumpAllInfo2(World.ptr);
// 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.
// Multiply by 55 to give a nominal frame rate of 55. // Multiply by 55 to give a nominal frame rate of 55.
return (float)numSubSteps * m_fixedTimeStep * 1000f * 55f; return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
} }
// Something has collided // Something has collided

View File

@ -250,20 +250,20 @@ public enum CollisionFilterGroups : uint
// filter/mask definition below. This way collision interactions // filter/mask definition below. This way collision interactions
// are more easily found and debugged. // are more easily found and debugged.
BNoneGroup = 0, BNoneGroup = 0,
BDefaultGroup = 1 << 0, BDefaultGroup = 1 << 0, // 0001
BStaticGroup = 1 << 1, BStaticGroup = 1 << 1, // 0002
BKinematicGroup = 1 << 2, BKinematicGroup = 1 << 2, // 0004
BDebrisGroup = 1 << 3, BDebrisGroup = 1 << 3, // 0008
BSensorTrigger = 1 << 4, BSensorTrigger = 1 << 4, // 0010
BCharacterGroup = 1 << 5, BCharacterGroup = 1 << 5, // 0020
BAllGroup = 0xFFFFFFFF, BAllGroup = 0x000FFFFF,
// Filter groups defined by BulletSim // Filter groups defined by BulletSim
BGroundPlaneGroup = 1 << 10, BGroundPlaneGroup = 1 << 10, // 0400
BTerrainGroup = 1 << 11, BTerrainGroup = 1 << 11, // 0800
BRaycastGroup = 1 << 12, BRaycastGroup = 1 << 12, // 1000
BSolidGroup = 1 << 13, BSolidGroup = 1 << 13, // 2000
// BLinksetGroup = xx // a linkset proper is either static or dynamic // BLinksetGroup = xx // a linkset proper is either static or dynamic
BLinksetChildGroup = 1 << 14, BLinksetChildGroup = 1 << 14, // 4000
}; };
// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0

View File

@ -72,12 +72,12 @@ public struct BulletBody
public bool HasPhysicalBody { get { return ptr != IntPtr.Zero; } } public bool HasPhysicalBody { get { return ptr != IntPtr.Zero; } }
// Apply the specificed collision mask into the physical world // Apply the specificed collision mask into the physical world
public void ApplyCollisionMask() public bool ApplyCollisionMask()
{ {
// Should assert the body has been added to the physical world. // Should assert the body has been added to the physical world.
// (The collision masks are stored in the collision proxy cache which only exists for // (The collision masks are stored in the collision proxy cache which only exists for
// a collision body that is in the world.) // a collision body that is in the world.)
BulletSimAPI.SetCollisionGroupMask2(ptr, return BulletSimAPI.SetCollisionGroupMask2(ptr,
BulletSimData.CollisionTypeMasks[collisionType].group, BulletSimData.CollisionTypeMasks[collisionType].group,
BulletSimData.CollisionTypeMasks[collisionType].mask); BulletSimData.CollisionTypeMasks[collisionType].mask);
} }
@ -207,26 +207,6 @@ public struct CollisionTypeFilterGroup
public uint mask; public uint mask;
}; };
/* NOTE: old definitions kept for reference. Delete when things are working.
// The collsion filters and masked are defined in one place -- don't want them scattered
AvatarGroup = BCharacterGroup,
AvatarMask = BAllGroup,
ObjectGroup = BSolidGroup,
ObjectMask = BAllGroup,
StaticObjectGroup = BStaticGroup,
StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much
LinksetGroup = BLinksetGroup,
LinksetMask = BAllGroup,
LinksetChildGroup = BLinksetChildGroup,
LinksetChildMask = BNoneGroup, // Linkset children disappear from the world
VolumeDetectGroup = BSensorTrigger,
VolumeDetectMask = ~BSensorTrigger,
TerrainGroup = BTerrainGroup,
TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide
GroundPlaneGroup = BGroundPlaneGroup,
GroundPlaneMask = BAllGroup
*/
public static class BulletSimData public static class BulletSimData
{ {
@ -269,8 +249,9 @@ public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeM
}, },
{ CollisionType.LinksetChild, { CollisionType.LinksetChild,
new CollisionTypeFilterGroup(CollisionType.LinksetChild, new CollisionTypeFilterGroup(CollisionType.LinksetChild,
(uint)CollisionFilterGroups.BTerrainGroup, (uint)CollisionFilterGroups.BLinksetChildGroup,
(uint)(CollisionFilterGroups.BNoneGroup)) (uint)(CollisionFilterGroups.BNoneGroup))
// (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
}, },
}; };

View File

@ -1,22 +1,22 @@
CURRENT PRIORITIES CURRENT PRIORITIES
================================================= =================================================
Smooth avatar movement with motor (DONE) Redo BulletSimAPI to allow native C# implementation of Bullet option.
Should motor update be all at taint-time? (Yes, DONE) Avatar movement
Fix avatar slowly sliding when standing (zero motion when stopped) flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle
llApplyImpulse() walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
Compare mass/movement in OS and SL. Calibrate actions. avatar capsule rotation completed
llSetBuoyancy() llMoveToTarget
Boats float low in the water
Enable vehicle border crossings (at least as poorly as ODE) Enable vehicle border crossings (at least as poorly as ODE)
Terrain skirts Terrain skirts
Avatar created in previous region and not new region when crossing border Avatar created in previous region and not new region when crossing border
Vehicle recreated in new sim at small Z value (offset from root value?) (DONE) Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
Add material densities to the material types.
Vehicle movement on terrain smoothness Vehicle movement on terrain smoothness
Vehicle script tuning/debugging Vehicle script tuning/debugging
Avanti speed script Avanti speed script
Weapon shooter script Weapon shooter script
limitMotorUp calibration (more down?) limitMotorUp calibration (more down?)
Boats float low in the water
Add material densities to the material types.
CRASHES CRASHES
================================================= =================================================
@ -35,6 +35,8 @@ Border crossing with linked vehicle causes crash
Vehicles (Move smoothly) Vehicles (Move smoothly)
Add vehicle collisions so IsColliding is properly reported. Add vehicle collisions so IsColliding is properly reported.
Needed for banking, limitMotorUp, movementLimiting, ... Needed for banking, limitMotorUp, movementLimiting, ...
VehicleAddForce is not scaled by the simulation step but it is only
applied for one step. Should it be scaled?
Some vehicles should not be able to turn if no speed or off ground. Some vehicles should not be able to turn if no speed or off ground.
Cannot edit/move a vehicle being ridden: it jumps back to the origional position. Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
Neb car jiggling left and right Neb car jiggling left and right
@ -58,7 +60,6 @@ Incorporate inter-relationship of angular corrections. For instance, angularDefl
BULLETSIM TODO LIST: BULLETSIM TODO LIST:
================================================= =================================================
In SL, perfect spheres don't seem to have rolling friction. Add special case.
Avatar density is WAY off. Compare and calibrate with what's in SL. Avatar density is WAY off. Compare and calibrate with what's in SL.
Revisit CollisionMargin. Builders notice the 0.04 spacing between prims. Revisit CollisionMargin. Builders notice the 0.04 spacing between prims.
Duplicating a physical prim causes old prim to jump away Duplicating a physical prim causes old prim to jump away
@ -93,6 +94,9 @@ Should the different PID factors have non-equal contributions for different
Selecting and deselecting physical objects causes CPU processing time to jump Selecting and deselecting physical objects causes CPU processing time to jump
http://www.youtube.com/watch?v=Hjg57fWg8yI&hd=1 http://www.youtube.com/watch?v=Hjg57fWg8yI&hd=1
put thousand physical objects, select and deselect same. CPU time will be large. put thousand physical objects, select and deselect same. CPU time will be large.
Re-implement buoyancy as a separate force on the object rather than diddling gravity.
Register a pre-step event to add the force.
More efficient memory usage when passing hull information from BSPrim to BulletSim
LINKSETS LINKSETS
====================================================== ======================================================
@ -146,6 +150,8 @@ Is there are more efficient method of implementing pre and post step actions?
See http://www.codeproject.com/Articles/29922/Weak-Events-in-C See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
Physics Arena central pyramid: why is one side permiable? Physics Arena central pyramid: why is one side permiable?
In SL, perfect spheres don't seem to have rolling friction. Add special case.
Enforce physical parameter min/max: Enforce physical parameter min/max:
Gravity: [-1, 28] Gravity: [-1, 28]
Friction: [0, 255] Friction: [0, 255]
@ -188,6 +194,7 @@ Should taints check for existance or activeness of target?
actually gone when the taint happens. Crashes don't happen because the taint closure actually gone when the taint happens. Crashes don't happen because the taint closure
keeps the object from being freed, but that is just an accident. keeps the object from being freed, but that is just an accident.
Possibly have and 'active' flag that is checked by the taint processor? Possibly have and 'active' flag that is checked by the taint processor?
Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones)
THREADING THREADING
================================================= =================================================
@ -237,3 +244,12 @@ Should vehicle angular/linear movement friction happen after all the components
What is expected by some vehicles (turning up friction to moderate speed)) What is expected by some vehicles (turning up friction to moderate speed))
Tune terrain/object friction to be closer to SL. Tune terrain/object friction to be closer to SL.
(Resolution: added material type with friction and resolution) (Resolution: added material type with friction and resolution)
Smooth avatar movement with motor (DONE)
Should motor update be all at taint-time? (Yes, DONE)
Fix avatar slowly sliding when standing (zero motion when stopped) (DONE)
(Resolution: added BSVMotor for avatar starting and stopping)
llApplyImpulse()
Compare mass/movement in OS and SL. Calibrate actions. (DONE)
(Resolution: tested on SL and OS. AddForce scales the force for timestep)
llSetBuoyancy() (DONE)
(Resolution: Bullet resets object gravity when added to world. Moved set gravity)