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;
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();

View File

@ -174,7 +174,7 @@ public sealed class BSCharacter : BSPhysObject
BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius);
}
UpdatePhysicalMassProperties(RawMass);
UpdatePhysicalMassProperties(RawMass, false);
// Make so capsule does not fall over
BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero);
@ -224,7 +224,7 @@ public sealed class BSCharacter : BSPhysObject
if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
{
BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
UpdatePhysicalMassProperties(RawMass);
UpdatePhysicalMassProperties(RawMass, true);
// Make sure this change appears as a property update event
BulletSimAPI.PushUpdate2(PhysBody.ptr);
}
@ -260,7 +260,6 @@ public sealed class BSCharacter : BSPhysObject
public override void ZeroMotion(bool inTaintTime)
{
_velocity = OMV.Vector3.Zero;
_velocityMotor.Zero();
_acceleration = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero;
@ -390,7 +389,7 @@ public sealed class BSCharacter : BSPhysObject
public override float RawMass {
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);
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.
if (_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);

View File

@ -36,7 +36,7 @@ public abstract class BSConstraint : IDisposable
{
private static string LogHeader = "[BULLETSIM CONSTRAINT]";
protected BulletSim m_world;
protected BulletWorld m_world;
protected BulletBody m_body1;
protected BulletBody m_body2;
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; } }
// Create a btGeneric6DofConstraint
public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2,
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
@ -58,7 +58,7 @@ public sealed class BSConstraint6Dof : BSConstraint
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,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
{

View File

@ -41,9 +41,9 @@ public sealed class BSConstraintCollection : IDisposable
delegate bool ConstraintAction(BSConstraint constrain);
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_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 BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2,
public BSConstraintHinge(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 pivotInA, Vector3 pivotInB,
Vector3 axisInA, Vector3 axisInB,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)

View File

@ -573,6 +573,9 @@ namespace OpenSim.Region.Physics.BulletSNPlugin
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
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}",
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
protected float m_mass;
public float LinksetMass
{
get
{
return m_mass;
}
}
public float LinksetMass { get; protected set; }
public virtual bool LinksetIsColliding { get { return false; } }
@ -128,7 +121,7 @@ public abstract class BSLinkset
PhysicsScene = scene;
LinksetRoot = parent;
m_children = new HashSet<BSPhysObject>();
m_mass = parent.RawMass;
LinksetMass = parent.RawMass;
Rebuilding = false;
}
@ -143,7 +136,7 @@ public abstract class BSLinkset
// Don't add the root to its own linkset
if (!IsRoot(child))
AddChildToLinkset(child);
m_mass = ComputeLinksetMass();
LinksetMass = ComputeLinksetMass();
}
return this;
}
@ -162,7 +155,7 @@ public abstract class BSLinkset
return this;
}
RemoveChildFromLinkset(child);
m_mass = ComputeLinksetMass();
LinksetMass = ComputeLinksetMass();
}
// 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
// its internal properties.
// 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.
// 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.
public override void Refresh(BSPhysObject requestor)
{
base.Refresh(requestor);
// Something changed so do the rebuilding thing
// ScheduleRebuild();
}
@ -96,13 +98,13 @@ public sealed class BSLinksetCompound : BSLinkset
// Schedule a refresh to happen after all the other taint processing.
private void ScheduleRebuild(BSPhysObject requestor)
{
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,rebuilding={1}",
DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1}",
requestor.LocalID, Rebuilding);
// When rebuilding, it is possible to set properties that would normally require a rebuild.
// If already rebuilding, don't request another rebuild.
if (!Rebuilding)
{
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", LinksetRoot.LocalID, delegate()
PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
{
if (HasAnyChildren)
RecomputeLinksetCompound();
@ -123,7 +125,6 @@ public sealed class BSLinksetCompound : BSLinkset
if (IsRoot(child))
{
// The root is going dynamic. Make sure mass is properly set.
m_mass = ComputeLinksetMass();
ScheduleRebuild(LinksetRoot);
}
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.
float linksetMass = LinksetMass;
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
LinksetMass = LinksetMass;
LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
}
finally
{

View File

@ -46,6 +46,8 @@ public sealed class BSLinksetConstraints : BSLinkset
// refresh will happen once after all the other taints are applied.
public override void Refresh(BSPhysObject requestor)
{
base.Refresh(requestor);
// Queue to happen after all the other taint processing
PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
{
@ -279,7 +281,7 @@ public sealed class BSLinksetConstraints : BSLinkset
private void RecomputeLinksetConstraints()
{
float linksetMass = LinksetMass;
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
LinksetRoot.UpdatePhysicalMassProperties(linksetMass, true);
// DEBUG: see of inter-linkset collisions are causing problems
// 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.
// 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.)
child.UpdatePhysicalMassProperties(linksetMass);
child.UpdatePhysicalMassProperties(linksetMass, true);
BSConstraint 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] =
new MaterialAttributes("light",dDensity, dFriction, dRestitution);
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] =
new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
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] =
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] =
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] =
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] =
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] =
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] =
new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
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

View File

@ -351,7 +351,7 @@ public static class BSParam
(s) => { return AvatarStandingFriction; },
(s,p,l,v) => { AvatarStandingFriction = v; } ),
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
60f,
3.5f,
(s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
(s) => { return AvatarDensity; },
(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
public abstract float RawMass { get; }
// 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
public OMV.Vector3 Inertia { get; set; }

View File

@ -115,6 +115,8 @@ public sealed class BSPrim : BSPhysObject
PhysBody = new BulletBody(LocalID);
PhysShape = new BulletShape();
Linkset.Refresh(this);
DetailLog("{0},BSPrim.constructor,call", LocalID);
// do the actual object creation at taint time
PhysicsScene.TaintedObject("BSPrim.create", delegate()
@ -384,13 +386,13 @@ public sealed class BSPrim : BSPhysObject
}
// 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
{
get
{
return Linkset.LinksetMass;
// return _mass;
return _mass;
}
}
@ -400,22 +402,45 @@ public sealed class BSPrim : BSPhysObject
}
// Set the physical mass to the passed mass.
// Note that this does not change _mass!
public override void UpdatePhysicalMassProperties(float physMass)
public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
{
if (IsStatic)
if (PhysBody.HasPhysicalBody)
{
Inertia = OMV.Vector3.Zero;
BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
}
else
{
Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
// center of mass is at the zero of the object
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia);
if (IsStatic)
{
Inertia = OMV.Vector3.Zero;
BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
}
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);
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
// center of mass is at the zero of the object
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
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);
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.
@ -737,7 +762,7 @@ public sealed class BSPrim : BSPhysObject
BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution);
// Mass is zero which disables a bunch of physics stuff in Bullet
UpdatePhysicalMassProperties(0f);
UpdatePhysicalMassProperties(0f, false);
// Set collision detection parameters
if (BSParam.CcdMotionThreshold > 0f)
{
@ -777,7 +802,7 @@ public sealed class BSPrim : BSPhysObject
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
// A dynamic object has mass
UpdatePhysicalMassProperties(RawMass);
UpdatePhysicalMassProperties(RawMass, false);
// Set collision detection parameters
if (BSParam.CcdMotionThreshold > 0f)
@ -950,13 +975,9 @@ public sealed class BSPrim : BSPhysObject
set {
_buoyancy = value;
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
// Buoyancy is faked by changing the gravity applied to the object
if (PhysBody.HasPhysicalBody)
{
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
ActivateIfPhysical(false);
}
// Force the recalculation of the various inertia,etc variables in the object
UpdatePhysicalMassProperties(_mass, true);
ActivateIfPhysical(false);
}
}
@ -993,7 +1014,9 @@ public sealed class BSPrim : BSPhysObject
public override float APIDDamping { set { return; } }
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.
// 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
if (force.IsFinite())
{
float magnitude = force.Length();
if (magnitude > 20000f)
{
// Force has a limit
force = force / magnitude * 20000f;
}
OMV.Vector3 addForce = force;
DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
{
// 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 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.
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);
World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, UnmanagedParams,
World = new BulletWorld(0, this, BulletSimAPI.Initialize2(worldExtent, UnmanagedParams,
m_maxCollisionsPerFrame, ref m_collisionArray,
m_maxUpdatesPerFrame,ref m_updateArray,
m_DebugLogCallbackHandle));
@ -497,13 +497,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
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
m_simulationStep++;
int numSubSteps = 0;
try
{
//if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
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);
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;
}

View File

@ -98,7 +98,7 @@ public sealed class BSShapeCollection : IDisposable
// higher level dependencies on the shape or body. Mostly used for LinkSets to
// remove the physical constraints before the body is destroyed.
// 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)
{
PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
@ -126,7 +126,7 @@ public sealed class BSShapeCollection : IDisposable
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);
}
@ -637,7 +637,7 @@ public sealed class BSShapeCollection : IDisposable
}
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)
{
@ -709,7 +709,7 @@ public sealed class BSShapeCollection : IDisposable
{
// 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
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)
{
@ -918,7 +918,7 @@ public sealed class BSShapeCollection : IDisposable
// Updates prim.BSBody with the information about the new body if one is created.
// Returns 'true' if an object was actually created.
// 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)
{
bool ret = false;

View File

@ -103,7 +103,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
Vector3 centerPos;
centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 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,
BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr,

View File

@ -140,7 +140,7 @@ public sealed class BSTerrainManager : IDisposable
m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
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);
// Ground plane does not move
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}",
BSScene.DetailLogZero, pos, terrainBaseXYZ);
}
lastHeight = ret;
return ret;
}

View File

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

View File

@ -35,9 +35,9 @@ namespace OpenSim.Region.Physics.BulletSNPlugin
// These hold pointers to allocated objects in the unmanaged space.
// 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;
worldID = worldId;

View File

@ -260,7 +260,6 @@ public sealed class BSCharacter : BSPhysObject
public override void ZeroMotion(bool inTaintTime)
{
_velocity = OMV.Vector3.Zero;
_velocityMotor.Zero();
_acceleration = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero;
@ -585,18 +584,6 @@ public sealed class BSCharacter : BSPhysObject
get { return _throttleUpdates; }
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 {
set {
_floatOnWater = value;
@ -684,22 +671,31 @@ public sealed class BSCharacter : BSPhysObject
public override void AddForce(OMV.Vector3 force, bool pushforce) {
if (force.IsFinite())
{
_force.X += force.X;
_force.Y += force.Y;
_force.Z += force.Z;
// m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
float magnitude = force.Length();
if (magnitude > BSParam.MaxAddForceMagnitude)
{
// 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()
{
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)
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
{
BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, addForce);
}
});
}
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) {
@ -761,22 +757,26 @@ public sealed class BSCharacter : BSPhysObject
OMV.Vector3 stepVelocity = _velocityMotor.Step(PhysicsScene.LastTimeStep);
// If falling, we keep the world's downward vector no matter what the other axis specify.
if (!Flying && !IsColliding)
// 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) )
{
stepVelocity.Z = entprop.Velocity.Z;
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);
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 (!Flying && !IsColliding)
{
stepVelocity.Z = entprop.Velocity.Z;
DetailLog("{0},BSCharacter.UpdateProperties,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
}
}
_velocity = stepVelocity;
entprop.Velocity = _velocity;

View File

@ -573,6 +573,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
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}",
Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
}
@ -819,6 +822,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
if (!IsActive) return;
if (PhysicsScene.VehiclePhysicalLoggingEnabled)
BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, Prim.PhysBody.ptr);
ForgetKnownVehicleProperties();
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.
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}",
Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity);
}

View File

@ -5,7 +5,7 @@
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * 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
* notice, this list of conditions and the following disclaimer in the
* 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.
private void ScheduleRebuild(BSPhysObject requestor)
{
DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1}",
requestor.LocalID, Rebuilding);
DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2}",
requestor.LocalID, Rebuilding, HasAnyChildren);
// When rebuilding, it is possible to set properties that would normally require a rebuild.
// If already rebuilding, don't request another rebuild.
if (!Rebuilding)
// If 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()
{
@ -112,8 +113,7 @@ public sealed class BSLinksetCompound : BSLinkset
}
}
// The object is going dynamic (physical). Do any setup necessary
// for a dynamic linkset.
// The object is going dynamic (physical). Do any setup necessary for a dynamic linkset.
// Only the state of the passed object can be modified. The rest of the linkset
// has not yet been fully constructed.
// 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));
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);
}
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.
LinksetMass = LinksetMass;
LinksetMass = ComputeLinksetMass();
LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
}
finally

View File

@ -241,8 +241,8 @@ public class BSVMotor : BSMotor
public override string ToString()
{
return String.Format("<{0},curr={1},targ={2},decayTS={3},frictTS={4}>",
UseName, CurrentValue, TargetValue, TargetValueDecayTimeScale, FrictionTimescale);
return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>",
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_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 float ParamGet(BSScene scene);
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) => { return (float)s.m_fixedTimeStep; },
(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",
2048f,
(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; }
// The simulation step that last had a collision with the ground
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
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
protected CollisionEventUpdate CollisionCollection;
@ -196,12 +227,16 @@ public abstract class BSPhysObject : PhysicsActor
{
bool ret = false;
// The following lines make IsColliding() and IsCollidingGround() work
// The following lines make IsColliding(), CollidingGround() and CollidingObj work
CollidingStep = PhysicsScene.SimulationStep;
if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
{
CollidingGroundStep = PhysicsScene.SimulationStep;
}
else
{
CollidingObjectStep = PhysicsScene.SimulationStep;
}
// prims in the same linkset cannot collide with each other
if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))

View File

@ -94,7 +94,7 @@ public sealed class BSPrim : BSPhysObject
_size = size;
Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
_orientation = rotation;
_buoyancy = 1f;
_buoyancy = 0f;
_velocity = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero;
BaseShape = pbs;
@ -408,12 +408,15 @@ public sealed class BSPrim : BSPhysObject
{
if (IsStatic)
{
BulletSimAPI.SetGravity2(PhysBody.ptr, PhysicsScene.DefaultGravity);
Inertia = OMV.Vector3.Zero;
BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
}
else
{
OMV.Vector3 grav = ComputeGravity();
if (inWorld)
{
// Changing interesting properties doesn't change proxy and collision cache
@ -422,24 +425,41 @@ public sealed class BSPrim : BSPhysObject
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
}
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
// The computation of mass props requires gravity to be set on the object.
BulletSimAPI.SetGravity2(PhysBody.ptr, grav);
Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
// center of mass is at the zero of the object
// 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)
{
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?
public override OMV.Vector3 CenterOfMass
{
@ -665,7 +685,7 @@ public sealed class BSPrim : BSPhysObject
_isPhysical = value;
PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
{
// DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
SetObjectDynamic(true);
// whether phys-to-static or static-to-phys, the object is not moving.
ZeroMotion(true);
@ -720,22 +740,19 @@ public sealed class BSPrim : BSPhysObject
// Make solid or not (do things bounce off or pass through this object).
MakeSolid(IsSolid);
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
AddObjectToPhysicalWorld();
// Rebuild its shape
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.
// When going from non-physical to physical, this re-enables the constraints that
// had been automatically disabled when the mass was set to zero.
// For compound based linksets, this enables and disables interactions of the children.
Linkset.Refresh(this);
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);
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.collisionType, PhysBody, PhysShape);
}
// "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
public override bool Flying {
get { return _flying; }
@ -891,18 +930,6 @@ public sealed class BSPrim : BSPhysObject
get { return _throttleUpdates; }
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 {
get {
// SceneObjectPart removes phantom objects from the physics scene
@ -972,6 +999,7 @@ public sealed class BSPrim : BSPhysObject
_buoyancy = value;
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
// 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);
ActivateIfPhysical(false);
}
@ -981,12 +1009,12 @@ public sealed class BSPrim : BSPhysObject
public override OMV.Vector3 PIDTarget {
set { _PIDTarget = value; }
}
public override bool PIDActive {
set { _usePID = value; }
}
public override float PIDTau {
set { _PIDTau = value; }
}
public override bool PIDActive {
set { _usePID = value; }
}
// Used for llSetHoverHeight and maybe vehicle height
// 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 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.
// 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
if (force.IsFinite())
{
float magnitude = force.Length();
if (magnitude > BSParam.MaxAddForceMagnitude)
{
// Force has a limit
force = force / magnitude * BSParam.MaxAddForceMagnitude;
}
OMV.Vector3 addForce = force;
DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
{
// Bullet adds this central force to the total force for this tick

View File

@ -38,15 +38,6 @@ using Nini.Config;
using log4net;
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
{
public sealed class BSScene : PhysicsScene, IPhysicsParameters
@ -83,6 +74,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
internal int m_maxSubSteps;
internal float m_fixedTimeStep;
internal long m_simulationStep = 0;
internal float NominalFrameRate { get; set; }
public long SimulationStep { get { return m_simulationStep; } }
internal int m_taintsToProcessPerStep;
internal float LastTimeStep { get; private set; }
@ -171,6 +163,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
private string m_physicsLoggingPrefix;
private int m_physicsLoggingFileMinutes;
private bool m_physicsLoggingDoFlush;
private bool m_physicsPhysicalDumpEnabled;
// 'true' of the vehicle code is to log lots of details
public bool VehicleLoggingEnabled { get; private set; }
public bool VehiclePhysicalLoggingEnabled { get; private set; }
@ -276,11 +269,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
BSParam.SetParameterConfigurationValues(this, pConfig);
// 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_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
m_physicsPhysicalDumpEnabled = pConfig.GetBoolean("PhysicsPhysicalDumpEnabled", false);
// Very detailed logging for vehicle debugging
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", 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.
// 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
m_simulationStep++;
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.
// 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.
// 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.
return (float)numSubSteps * m_fixedTimeStep * 1000f * 55f;
return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
}
// Something has collided

View File

@ -250,20 +250,20 @@ public enum CollisionFilterGroups : uint
// filter/mask definition below. This way collision interactions
// are more easily found and debugged.
BNoneGroup = 0,
BDefaultGroup = 1 << 0,
BStaticGroup = 1 << 1,
BKinematicGroup = 1 << 2,
BDebrisGroup = 1 << 3,
BSensorTrigger = 1 << 4,
BCharacterGroup = 1 << 5,
BAllGroup = 0xFFFFFFFF,
BDefaultGroup = 1 << 0, // 0001
BStaticGroup = 1 << 1, // 0002
BKinematicGroup = 1 << 2, // 0004
BDebrisGroup = 1 << 3, // 0008
BSensorTrigger = 1 << 4, // 0010
BCharacterGroup = 1 << 5, // 0020
BAllGroup = 0x000FFFFF,
// Filter groups defined by BulletSim
BGroundPlaneGroup = 1 << 10,
BTerrainGroup = 1 << 11,
BRaycastGroup = 1 << 12,
BSolidGroup = 1 << 13,
BGroundPlaneGroup = 1 << 10, // 0400
BTerrainGroup = 1 << 11, // 0800
BRaycastGroup = 1 << 12, // 1000
BSolidGroup = 1 << 13, // 2000
// 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

View File

@ -72,12 +72,12 @@ public struct BulletBody
public bool HasPhysicalBody { get { return ptr != IntPtr.Zero; } }
// 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.
// (The collision masks are stored in the collision proxy cache which only exists for
// a collision body that is in the world.)
BulletSimAPI.SetCollisionGroupMask2(ptr,
return BulletSimAPI.SetCollisionGroupMask2(ptr,
BulletSimData.CollisionTypeMasks[collisionType].group,
BulletSimData.CollisionTypeMasks[collisionType].mask);
}
@ -207,26 +207,6 @@ public struct CollisionTypeFilterGroup
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
{
@ -269,8 +249,9 @@ public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeM
},
{ CollisionType.LinksetChild,
new CollisionTypeFilterGroup(CollisionType.LinksetChild,
(uint)CollisionFilterGroups.BTerrainGroup,
(uint)CollisionFilterGroups.BLinksetChildGroup,
(uint)(CollisionFilterGroups.BNoneGroup))
// (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
},
};

View File

@ -1,22 +1,22 @@
CURRENT PRIORITIES
=================================================
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)
llApplyImpulse()
Compare mass/movement in OS and SL. Calibrate actions.
llSetBuoyancy()
Boats float low in the water
Redo BulletSimAPI to allow native C# implementation of Bullet option.
Avatar movement
flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle
walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
avatar capsule rotation completed
llMoveToTarget
Enable vehicle border crossings (at least as poorly as ODE)
Terrain skirts
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)
Add material densities to the material types.
Vehicle movement on terrain smoothness
Vehicle script tuning/debugging
Avanti speed script
Weapon shooter script
limitMotorUp calibration (more down?)
Boats float low in the water
Add material densities to the material types.
CRASHES
=================================================
@ -35,6 +35,8 @@ Border crossing with linked vehicle causes crash
Vehicles (Move smoothly)
Add vehicle collisions so IsColliding is properly reported.
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.
Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
Neb car jiggling left and right
@ -58,7 +60,6 @@ Incorporate inter-relationship of angular corrections. For instance, angularDefl
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.
Revisit CollisionMargin. Builders notice the 0.04 spacing between prims.
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
http://www.youtube.com/watch?v=Hjg57fWg8yI&hd=1
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
======================================================
@ -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
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:
Gravity: [-1, 28]
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
keeps the object from being freed, but that is just an accident.
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
=================================================
@ -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))
Tune terrain/object friction to be closer to SL.
(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)