Merge commit '8bf0a9f85dda4b1831630b65620d5c6868196c11' into careminster

Conflicts:
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
avinationmerge
Melanie 2013-01-16 01:11:20 +00:00
commit fc5711fa7a
29 changed files with 512 additions and 232 deletions

View File

@ -4649,9 +4649,9 @@ namespace OpenSim.Region.Framework.Scenes
PhysicsShapeType, PhysicsShapeType,
m_localId); m_localId);
} }
catch (Exception ex) catch (Exception e)
{ {
m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message); m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
pa = null; pa = null;
} }
@ -5288,4 +5288,4 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
} }

View File

@ -49,7 +49,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
public PhysicsScene GetScene(string sceneIdentifier) public PhysicsScene GetScene(string sceneIdentifier)
{ {
return new BasicScene(sceneIdentifier); return new BasicScene(GetName(), sceneIdentifier);
} }
public string GetName() public string GetName()

View File

@ -49,8 +49,10 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
//protected internal string sceneIdentifier; //protected internal string sceneIdentifier;
public BasicScene(string _sceneIdentifier) public BasicScene(string engineType, string _sceneIdentifier)
{ {
EngineType = engineType;
Name = EngineType + "/" + _sceneIdentifier;
//sceneIdentifier = _sceneIdentifier; //sceneIdentifier = _sceneIdentifier;
} }

View File

@ -327,6 +327,12 @@ public override void RemoveChildShapeFromCompoundShape(BulletShape shape, Bullet
BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr); BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr);
} }
public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb)
{
BulletShapeUnman shapeu = pShape as BulletShapeUnman;
BSAPICPP.UpdateChildTransform2(shapeu.ptr, childIndex, pos, rot, shouldRecalculateLocalAabb);
}
public override void RecalculateCompoundShapeLocalAabb(BulletShape shape) public override void RecalculateCompoundShapeLocalAabb(BulletShape shape)
{ {
BulletShapeUnman shapeu = shape as BulletShapeUnman; BulletShapeUnman shapeu = shape as BulletShapeUnman;
@ -1356,6 +1362,9 @@ public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShap
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void UpdateChildTransform2(IntPtr pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape); public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);

View File

@ -1212,6 +1212,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; } public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; }
public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ } public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb) { /* TODO */ }
public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin) public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin)
{ {

View File

@ -342,6 +342,8 @@ public abstract BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape c
public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape); public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape);
public abstract void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape); public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape);
public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id); public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id);

View File

@ -328,6 +328,10 @@ public sealed class BSCharacter : BSPhysObject
public override bool Selected { public override bool Selected {
set { _selected = value; } set { _selected = value; }
} }
public override bool IsSelected
{
get { return _selected; }
}
public override void CrossingFailure() { return; } public override void CrossingFailure() { return; }
public override void link(PhysicsActor obj) { return; } public override void link(PhysicsActor obj) { return; }
public override void delink() { return; } public override void delink() { return; }

View File

@ -108,10 +108,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private float m_VhoverEfficiency = 0f; private float m_VhoverEfficiency = 0f;
private float m_VhoverTimescale = 0f; private float m_VhoverTimescale = 0f;
private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
// Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) private float m_VehicleBuoyancy = 0f;
// KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. private Vector3 m_VehicleGravity = Vector3.Zero; // Gravity computed when buoyancy set
// Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
//Attractor properties //Attractor properties
private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
@ -124,17 +123,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
static readonly float PIOverFour = ((float)Math.PI) / 4f; static readonly float PIOverFour = ((float)Math.PI) / 4f;
static readonly float PIOverTwo = ((float)Math.PI) / 2f; static readonly float PIOverTwo = ((float)Math.PI) / 2f;
// For debugging, flags to turn on and off individual corrections.
private bool enableAngularVerticalAttraction = true;
private bool enableAngularDeflection = true;
private bool enableAngularBanking = true;
public BSDynamics(BSScene myScene, BSPrim myPrim) public BSDynamics(BSScene myScene, BSPrim myPrim)
{ {
PhysicsScene = myScene; PhysicsScene = myScene;
Prim = myPrim; Prim = myPrim;
Type = Vehicle.TYPE_NONE; Type = Vehicle.TYPE_NONE;
SetupVehicleDebugging();
}
// Stopgap debugging enablement. Allows source level debugging but still checking
// in changes by making enablement of debugging flags from INI file.
public void SetupVehicleDebugging()
{
enableAngularVerticalAttraction = true;
enableAngularDeflection = true;
enableAngularBanking = true;
if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse)
{
enableAngularVerticalAttraction = false;
enableAngularDeflection = false;
enableAngularBanking = false;
}
} }
// Return 'true' if this vehicle is doing vehicle things // Return 'true' if this vehicle is doing vehicle things
public bool IsActive public bool IsActive
{ {
get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; } get { return (Type != Vehicle.TYPE_NONE && !Prim.IsStatic); }
} }
#region Vehicle parameter setting #region Vehicle parameter setting
@ -168,6 +188,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
break; break;
case Vehicle.BUOYANCY: case Vehicle.BUOYANCY:
m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy);
break; break;
case Vehicle.HOVER_EFFICIENCY: case Vehicle.HOVER_EFFICIENCY:
m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
@ -540,12 +561,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1f); 1f);
m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
/* Not implemented
m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
BSMotor.Infinite, BSMotor.InfiniteVector, BSMotor.Infinite, BSMotor.InfiniteVector,
m_verticalAttractionEfficiency); m_verticalAttractionEfficiency);
// Z goes away and we keep X and Y // Z goes away and we keep X and Y
m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
*/
} }
#endregion // Vehicle parameter setting #endregion // Vehicle parameter setting
@ -571,15 +594,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Vehicles report collision events so we know when it's on the ground // Vehicles report collision events so we know when it's on the ground
PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass); Prim.Inertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass);
PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, localInertia); PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, Prim.Inertia);
PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody); PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody);
Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy); // Set the gravity for the vehicle depending on the buoyancy
PhysicsScene.PE.SetGravity(Prim.PhysBody, grav); // TODO: what should be done if prim and vehicle buoyancy differ?
m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy);
// The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
PhysicsScene.PE.SetGravity(Prim.PhysBody, Vector3.Zero);
VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4},grav={5}",
Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); Prim.LocalID, m_vehicleMass, friction, Prim.Inertia, angularDamping, m_VehicleGravity);
} }
else else
{ {
@ -619,6 +645,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private Vector3 m_knownPosition; private Vector3 m_knownPosition;
private Vector3 m_knownVelocity; private Vector3 m_knownVelocity;
private Vector3 m_knownForce; private Vector3 m_knownForce;
private Vector3 m_knownForceImpulse;
private Quaternion m_knownOrientation; private Quaternion m_knownOrientation;
private Vector3 m_knownRotationalVelocity; private Vector3 m_knownRotationalVelocity;
private Vector3 m_knownRotationalForce; private Vector3 m_knownRotationalForce;
@ -627,12 +654,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private const int m_knownChangedPosition = 1 << 0; private const int m_knownChangedPosition = 1 << 0;
private const int m_knownChangedVelocity = 1 << 1; private const int m_knownChangedVelocity = 1 << 1;
private const int m_knownChangedForce = 1 << 2; private const int m_knownChangedForce = 1 << 2;
private const int m_knownChangedOrientation = 1 << 3; private const int m_knownChangedForceImpulse = 1 << 3;
private const int m_knownChangedRotationalVelocity = 1 << 4; private const int m_knownChangedOrientation = 1 << 4;
private const int m_knownChangedRotationalForce = 1 << 5; private const int m_knownChangedRotationalVelocity = 1 << 5;
private const int m_knownChangedTerrainHeight = 1 << 6; private const int m_knownChangedRotationalForce = 1 << 6;
private const int m_knownChangedWaterLevel = 1 << 7; private const int m_knownChangedTerrainHeight = 1 << 7;
private const int m_knownChangedForwardVelocity = 1 << 8; private const int m_knownChangedWaterLevel = 1 << 8;
private const int m_knownChangedForwardVelocity = 1 << 9;
private void ForgetKnownVehicleProperties() private void ForgetKnownVehicleProperties()
{ {
@ -653,21 +681,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if ((m_knownChanged & m_knownChangedVelocity) != 0) if ((m_knownChanged & m_knownChangedVelocity) != 0)
{ {
Prim.ForceVelocity = m_knownVelocity; Prim.ForceVelocity = m_knownVelocity;
PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, VehicleVelocity); // Fake out Bullet by making it think the velocity is the same as last time.
// Bullet does a bunch of smoothing for changing parameters.
// Since the vehicle is demanding this setting, we override Bullet's smoothing
// by telling Bullet the value was the same last time.
PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, m_knownVelocity);
} }
if ((m_knownChanged & m_knownChangedForce) != 0) if ((m_knownChanged & m_knownChangedForce) != 0)
Prim.AddForce((Vector3)m_knownForce, false, true); Prim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/);
if ((m_knownChanged & m_knownChangedForceImpulse) != 0)
Prim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/);
if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
{ {
Prim.ForceRotationalVelocity = m_knownRotationalVelocity; Prim.ForceRotationalVelocity = m_knownRotationalVelocity;
// Fake out Bullet by making it think the velocity is the same as last time.
PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity);
} }
if ((m_knownChanged & m_knownChangedRotationalForce) != 0) if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true); {
Prim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/);
}
// If we set one of the values (ie, the physics engine didn't do it) we must force // If we set one of the values (ie, the physics engine didn't do it) we must force
// an UpdateProperties event to send the changes up to the simulator. // an UpdateProperties event to send the changes up to the simulator.
@ -757,15 +793,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} }
} }
private void VehicleAddForce(Vector3 aForce) private void VehicleAddForce(Vector3 pForce)
{ {
if ((m_knownHas & m_knownChangedForce) == 0) if ((m_knownHas & m_knownChangedForce) == 0)
{ {
m_knownForce = Vector3.Zero; m_knownForce = Vector3.Zero;
m_knownHas |= m_knownChangedForce;
} }
m_knownForce += aForce; m_knownForce += pForce;
m_knownChanged |= m_knownChangedForce; m_knownChanged |= m_knownChangedForce;
m_knownHas |= m_knownChangedForce; }
private void VehicleAddForceImpulse(Vector3 pImpulse)
{
if ((m_knownHas & m_knownChangedForceImpulse) == 0)
{
m_knownForceImpulse = Vector3.Zero;
m_knownHas |= m_knownChangedForceImpulse;
}
m_knownForceImpulse += pImpulse;
m_knownChanged |= m_knownChangedForceImpulse;
} }
private Vector3 VehicleRotationalVelocity private Vector3 VehicleRotationalVelocity
@ -844,86 +891,92 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if (PhysicsScene.VehiclePhysicalLoggingEnabled) if (PhysicsScene.VehiclePhysicalLoggingEnabled)
PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
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, m_knownForce, VehicleVelocity, VehicleRotationalVelocity);
} }
// Apply the effect of the linear motor and other linear motions (like hover and float). // Apply the effect of the linear motor and other linear motions (like hover and float).
private void MoveLinear(float pTimestep) private void MoveLinear(float pTimestep)
{ {
Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep); ComputeLinearVelocity(pTimestep);
// The movement computed in the linear motor is relative to the vehicle ComputeLinearTerrainHeightCorrection(pTimestep);
// coordinates. Rotate the movement to world coordinates.
linearMotorContribution *= VehicleOrientation;
// All the contributions after this are world relative (mostly Z modifications)
// ================================================================== ComputeLinearHover(pTimestep);
// Buoyancy: force to overcome gravity.
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
// So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity.
Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy;
Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
Vector3 hoverContribution = ComputeLinearHover(pTimestep);
ComputeLinearBlockingEndPoint(pTimestep); ComputeLinearBlockingEndPoint(pTimestep);
Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep); ComputeLinearMotorUp(pTimestep);
// ================================================================== ApplyGravity(pTimestep);
Vector3 newVelocity = linearMotorContribution
+ terrainHeightContribution
+ hoverContribution
+ limitMotorUpContribution;
Vector3 newForce = buoyancyContribution;
// If not changing some axis, reduce out velocity // If not changing some axis, reduce out velocity
if ((m_flags & (VehicleFlag.NO_X)) != 0) if ((m_flags & (VehicleFlag.NO_X | VehicleFlag.NO_Y | VehicleFlag.NO_Z)) != 0)
newVelocity.X = 0; {
if ((m_flags & (VehicleFlag.NO_Y)) != 0) Vector3 vel = VehicleVelocity;
newVelocity.Y = 0; if ((m_flags & (VehicleFlag.NO_X)) != 0)
if ((m_flags & (VehicleFlag.NO_Z)) != 0) vel.X = 0;
newVelocity.Z = 0; if ((m_flags & (VehicleFlag.NO_Y)) != 0)
vel.Y = 0;
if ((m_flags & (VehicleFlag.NO_Z)) != 0)
vel.Z = 0;
VehicleVelocity = vel;
}
// ================================================================== // ==================================================================
// Clamp high or low velocities // Clamp high or low velocities
float newVelocityLengthSq = newVelocity.LengthSquared(); float newVelocityLengthSq = VehicleVelocity.LengthSquared();
if (newVelocityLengthSq > 1000f) if (newVelocityLengthSq > 1000f)
{ {
newVelocity /= newVelocity.Length(); VehicleVelocity /= VehicleVelocity.Length();
newVelocity *= 1000f; VehicleVelocity *= 1000f;
} }
else if (newVelocityLengthSq < 0.001f) else if (newVelocityLengthSq < 0.001f)
newVelocity = Vector3.Zero; VehicleVelocity = Vector3.Zero;
// ================================================================== VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", Prim.LocalID, Prim.IsColliding, VehicleVelocity );
// Stuff new linear velocity into the vehicle.
// Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us.
VehicleVelocity = newVelocity;
// Other linear forces are applied as forces.
Vector3 totalDownForce = newForce * m_vehicleMass;
if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
{
VehicleAddForce(totalDownForce);
}
VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}",
Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding);
VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}",
Prim.LocalID,
linearMotorContribution, terrainHeightContribution, hoverContribution,
limitMotorUpContribution, buoyancyContribution
);
} // end MoveLinear() } // end MoveLinear()
public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep) public void ComputeLinearVelocity(float pTimestep)
{
Vector3 linearMotorStep = m_linearMotor.Step(pTimestep);
// The movement computed in the linear motor is relative to the vehicle
// coordinates. Rotate the movement to world coordinates.
Vector3 linearMotorVelocity = linearMotorStep * VehicleOrientation;
// If we're a ground vehicle, don't loose any Z action (like gravity acceleration).
float mixFactor = 1f; // 1 means use all linear motor Z value, 0 means use all existing Z
if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
{
if (!Prim.IsColliding)
{
// If a ground vehicle and not on the ground, I want gravity effect
mixFactor = 0.2f;
}
}
else
{
// I'm not a ground vehicle but don't totally loose the effect of the environment
mixFactor = 0.8f;
}
linearMotorVelocity.Z = mixFactor * linearMotorVelocity.Z + (1f - mixFactor) * VehicleVelocity.Z;
// What we want to contribute to the vehicle's existing velocity
Vector3 linearMotorForce = linearMotorVelocity - VehicleVelocity;
// Act against the inertia of the vehicle
linearMotorForce *= m_vehicleMass;
VehicleAddForceImpulse(linearMotorForce * pTimestep);
VDetailLog("{0}, MoveLinear,velocity,vehVel={1},step={2},stepVel={3},mix={4},force={5}",
Prim.LocalID, VehicleVelocity, linearMotorStep, linearMotorVelocity, mixFactor, linearMotorForce);
}
public void ComputeLinearTerrainHeightCorrection(float pTimestep)
{ {
Vector3 ret = Vector3.Zero;
// If below the terrain, move us above the ground a little. // If below the terrain, move us above the ground a little.
// TODO: Consider taking the rotated size of the object or possibly casting a ray. // TODO: Consider taking the rotated size of the object or possibly casting a ray.
if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
@ -935,13 +988,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}",
Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
} }
return ret;
} }
public Vector3 ComputeLinearHover(float pTimestep) public void ComputeLinearHover(float pTimestep)
{ {
Vector3 ret = Vector3.Zero;
// m_VhoverEfficiency: 0=bouncy, 1=totally damped // m_VhoverEfficiency: 0=bouncy, 1=totally damped
// m_VhoverTimescale: time to achieve height // m_VhoverTimescale: time to achieve height
if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
@ -974,23 +1024,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
Vector3 pos = VehiclePosition; Vector3 pos = VehiclePosition;
pos.Z = m_VhoverTargetHeight; pos.Z = m_VhoverTargetHeight;
VehiclePosition = pos; VehiclePosition = pos;
VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", Prim.LocalID, pos);
} }
} }
else else
{ {
// Error is positive if below the target and negative if above. // Error is positive if below the target and negative if above.
float verticalError = m_VhoverTargetHeight - VehiclePosition.Z; float verticalError = m_VhoverTargetHeight - VehiclePosition.Z;
float verticalCorrectionVelocity = verticalError / m_VhoverTimescale; float verticalCorrectionVelocity = verticalError / m_VhoverTimescale * pTimestep;
// TODO: implement m_VhoverEfficiency correctly // TODO: implement m_VhoverEfficiency correctly
ret = new Vector3(0f, 0f, verticalCorrectionVelocity); VehicleAddForceImpulse(new Vector3(0f, 0f, verticalCorrectionVelocity));
VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corrVel={7}",
Prim.LocalID, VehiclePosition, m_VhoverEfficiency,
m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
verticalError, verticalCorrectionVelocity);
} }
VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},ret={6}",
Prim.LocalID, VehiclePosition, m_VhoverEfficiency, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, ret);
} }
return ret;
} }
public bool ComputeLinearBlockingEndPoint(float pTimestep) public bool ComputeLinearBlockingEndPoint(float pTimestep)
@ -1045,30 +1098,67 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// TODO: this code is wrong. Also, what should it do for boats (height from water)? // TODO: this code is wrong. Also, what should it do for boats (height from water)?
// This is just using the ground and a general collision check. Should really be using // This is just using the ground and a general collision check. Should really be using
// a downward raycast to find what is below. // a downward raycast to find what is below.
public Vector3 ComputeLinearMotorUp(float pTimestep) public void ComputeLinearMotorUp(float pTimestep)
{ {
Vector3 ret = Vector3.Zero; Vector3 ret = Vector3.Zero;
float distanceAboveGround = 0f;
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
{ {
// This code tries to decide if the object is not on the ground and then pushing down
/*
float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
distanceAboveGround = VehiclePosition.Z - targetHeight; distanceAboveGround = VehiclePosition.Z - targetHeight;
// Not colliding if the vehicle is off the ground // Not colliding if the vehicle is off the ground
if (!Prim.IsColliding) if (!Prim.IsColliding)
{ {
// downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
ret = new Vector3(0, 0, -distanceAboveGround); VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
} }
// TODO: this calculation is wrong. From the description at // TODO: this calculation is wrong. From the description at
// (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
// has a decay factor. This says this force should // has a decay factor. This says this force should
// be computed with a motor. // be computed with a motor.
// TODO: add interaction with banking. // TODO: add interaction with banking.
} VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret);
return ret; */
// Another approach is to measure if we're going up. If going up and not colliding,
// the vehicle is in the air. Fix that by pushing down.
if (!Prim.IsColliding && VehicleVelocity.Z > 0.1)
{
// Get rid of any of the velocity vector that is pushing us up.
VehicleVelocity += new Vector3(0, 0, -VehicleVelocity.Z);
// If we're pointed up into the air, we should nose down
Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
// The rotation around the Y axis is pitch up or down
if (pointingDirection.Y > 0.01f)
{
float angularCorrectionForce = -(float)Math.Asin(pointingDirection.Y);
Vector3 angularCorrectionVector = new Vector3(0f, angularCorrectionForce, 0f);
// Rotate into world coordinates and apply to vehicle
angularCorrectionVector *= VehicleOrientation;
VehicleAddAngularForce(angularCorrectionVector);
VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2},corrFrc={3},aCorr={4}",
Prim.LocalID, VehicleVelocity, pointingDirection, angularCorrectionForce, angularCorrectionVector);
}
else
{
VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2}",
Prim.LocalID, VehicleVelocity, pointingDirection);
}
}
}
}
private void ApplyGravity(float pTimeStep)
{
Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
VehicleAddForce(appliedGravity);
VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},appliedForce-{2}",
Prim.LocalID, m_VehicleGravity, appliedGravity);
} }
// ======================================================================= // =======================================================================
@ -1088,6 +1178,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// for preventing ground vehicles with large linear deflection, like bumper cars, // for preventing ground vehicles with large linear deflection, like bumper cars,
// from climbing their linear deflection into the sky. // from climbing their linear deflection into the sky.
// That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
// TODO: This is here because this is where ODE put it but documentation says it
// is a linear effect. Where should this check go?
if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
{ {
angularMotorContribution.X = 0f; angularMotorContribution.X = 0f;
@ -1179,7 +1271,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
Vector3 ret = Vector3.Zero; Vector3 ret = Vector3.Zero;
// If vertical attaction timescale is reasonable // If vertical attaction timescale is reasonable
if (m_verticalAttractionTimescale < m_verticalAttractionCutoff) if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
{ {
// Take a vector pointing up and convert it from world to vehicle relative coords. // Take a vector pointing up and convert it from world to vehicle relative coords.
Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
@ -1230,7 +1322,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// this creates an over-correction and then wabbling as the target is overshot. // this creates an over-correction and then wabbling as the target is overshot.
// TODO: rethink how the different correction computations inter-relate. // TODO: rethink how the different correction computations inter-relate.
if (m_angularDeflectionEfficiency != 0 && VehicleVelocity != Vector3.Zero) if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
{ {
// The direction the vehicle is moving // The direction the vehicle is moving
Vector3 movingDirection = VehicleVelocity; Vector3 movingDirection = VehicleVelocity;
@ -1303,7 +1395,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
Vector3 ret = Vector3.Zero; Vector3 ret = Vector3.Zero;
if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
{ {
// Rotate a UnitZ vector (pointing up) to how the vehicle is oriented. // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented.
// As the vehicle rolls to the right or left, the Y value will increase from // As the vehicle rolls to the right or left, the Y value will increase from

View File

@ -152,6 +152,7 @@ public abstract class BSLinkset
if (IsRoot(child)) if (IsRoot(child))
{ {
// Cannot remove the root from a linkset. // Cannot remove the root from a linkset.
child.PositionDisplacement = OMV.Vector3.Zero;
return this; return this;
} }
RemoveChildFromLinkset(child); RemoveChildFromLinkset(child);
@ -159,6 +160,7 @@ public abstract class BSLinkset
} }
// The child is down to a linkset of just itself // The child is down to a linkset of just itself
child.PositionDisplacement = OMV.Vector3.Zero;
return BSLinkset.Factory(PhysicsScene, child); return BSLinkset.Factory(PhysicsScene, child);
} }
@ -310,7 +312,7 @@ public abstract class BSLinkset
foreach (BSPhysObject bp in m_children) foreach (BSPhysObject bp in m_children)
{ {
com += bp.Position * bp.RawMass; com += bp.Position;
} }
com /= (m_children.Count + 1); com /= (m_children.Count + 1);
} }

View File

@ -40,23 +40,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// removed from the linkset. // removed from the linkset.
sealed class BSLinksetCompoundInfo : BSLinksetInfo sealed class BSLinksetCompoundInfo : BSLinksetInfo
{ {
public OMV.Vector3 OffsetPos; public int Index;
public OMV.Vector3 OffsetFromRoot;
public OMV.Vector3 OffsetFromCenterOfMass;
public OMV.Quaternion OffsetRot; public OMV.Quaternion OffsetRot;
public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r) public BSLinksetCompoundInfo(int indx, OMV.Vector3 p, OMV.Quaternion r)
{ {
OffsetPos = p; Index = indx;
OffsetFromRoot = p;
OffsetFromCenterOfMass = p;
OffsetRot = r; OffsetRot = r;
} }
public override void Clear() public override void Clear()
{ {
OffsetPos = OMV.Vector3.Zero; Index = 0;
OffsetFromRoot = OMV.Vector3.Zero;
OffsetFromCenterOfMass = OMV.Vector3.Zero;
OffsetRot = OMV.Quaternion.Identity; OffsetRot = OMV.Quaternion.Identity;
} }
public override string ToString() public override string ToString()
{ {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.Append("<p="); buff.Append("<i=");
buff.Append(OffsetPos.ToString()); buff.Append(Index.ToString());
buff.Append(",p=");
buff.Append(OffsetFromRoot.ToString());
buff.Append(",m=");
buff.Append(OffsetFromCenterOfMass.ToString());
buff.Append(",r="); buff.Append(",r=");
buff.Append(OffsetRot.ToString()); buff.Append(OffsetRot.ToString());
buff.Append(">"); buff.Append(">");
@ -170,6 +180,8 @@ public sealed class BSLinksetCompound : BSLinkset
return ret; return ret;
} }
// 'physicalUpdate' is true if these changes came directly from the physics engine. Don't need to rebuild then.
// Called at taint-time.
public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate) public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate)
{ {
// The user moving a child around requires the rebuilding of the linkset compound shape // The user moving a child around requires the rebuilding of the linkset compound shape
@ -182,6 +194,7 @@ public sealed class BSLinksetCompound : BSLinkset
&& !physicalUpdate && !physicalUpdate
&& PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
{ {
// TODO: replace this with are calculation of the child prim's orientation and pos.
updated.LinksetInfo = null; updated.LinksetInfo = null;
ScheduleRebuild(updated); ScheduleRebuild(updated);
} }
@ -230,7 +243,7 @@ public sealed class BSLinksetCompound : BSLinkset
if (inTaintTime) if (inTaintTime)
{ {
OMV.Vector3 oldPos = child.RawPosition; OMV.Vector3 oldPos = child.RawPosition;
child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos; child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot; child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}", DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
child.LocalID, oldPos, lci, child.RawPosition); child.LocalID, oldPos, lci, child.RawPosition);
@ -238,7 +251,7 @@ public sealed class BSLinksetCompound : BSLinkset
else else
{ {
// TaintedObject is not used here so the raw position is set now and not at taint-time. // TaintedObject is not used here so the raw position is set now and not at taint-time.
child.Position = LinksetRoot.RawPosition + lci.OffsetPos; child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot; child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
} }
} }
@ -306,6 +319,7 @@ public sealed class BSLinksetCompound : BSLinkset
// Constraint linksets are rebuilt every time. // Constraint linksets are rebuilt every time.
// Note that this works for rebuilding just the root after a linkset is taken apart. // Note that this works for rebuilding just the root after a linkset is taken apart.
// Called at taint time!! // Called at taint time!!
private bool disableCOM = true; // disable until we get this debugged
private void RecomputeLinksetCompound() private void RecomputeLinksetCompound()
{ {
try try
@ -316,10 +330,34 @@ public sealed class BSLinksetCompound : BSLinkset
// Cause the root shape to be rebuilt as a compound object with just the root in it // Cause the root shape to be rebuilt as a compound object with just the root in it
LinksetRoot.ForceBodyShapeRebuild(true); LinksetRoot.ForceBodyShapeRebuild(true);
// The center of mass for the linkset is the geometric center of the group.
// Compute a displacement for each component so it is relative to the center-of-mass.
// Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
OMV.Vector3 centerOfMass;
OMV.Vector3 centerDisplacement = OMV.Vector3.Zero;
if (disableCOM) // DEBUG DEBUG
{ // DEBUG DEBUG
centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG
LinksetRoot.PositionDisplacement = OMV.Vector3.Zero;
} // DEBUG DEBUG
else
{
centerOfMass = ComputeLinksetGeometricCenter();
centerDisplacement = centerOfMass - LinksetRoot.RawPosition;
// Since we're displacing the center of the shape, we need to move the body in the world
LinksetRoot.PositionDisplacement = centerDisplacement;
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false);
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement);
}
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
// Add a shape for each of the other children in the linkset // Add a shape for each of the other children in the linkset
int memberIndex = 1;
ForEachMember(delegate(BSPhysObject cPrim) ForEachMember(delegate(BSPhysObject cPrim)
{ {
if (!IsRoot(cPrim)) if (!IsRoot(cPrim))
@ -331,19 +369,21 @@ public sealed class BSLinksetCompound : BSLinkset
BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
if (lci == null) if (lci == null)
{ {
// Each child position and rotation is given relative to the root. // Each child position and rotation is given relative to the center-of-mass.
OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; OMV.Vector3 displacementFromRoot = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
OMV.Vector3 displacementFromCOM = displacementFromRoot - centerDisplacement;
OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
// Save relative position for recomputing child's world position after moving linkset. // Save relative position for recomputing child's world position after moving linkset.
lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); lci = new BSLinksetCompoundInfo(memberIndex, displacementFromCOM, displacementRot);
lci.OffsetFromRoot = displacementFromRoot;
cPrim.LinksetInfo = lci; cPrim.LinksetInfo = lci;
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
} }
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
if (cPrim.PhysShape.isNativeShape) if (cPrim.PhysShape.isNativeShape)
{ {
@ -359,7 +399,7 @@ public sealed class BSLinksetCompound : BSLinkset
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
BulletShape newShape = cPrim.PhysShape; BulletShape newShape = cPrim.PhysShape;
cPrim.PhysShape = saveShape; cPrim.PhysShape = saveShape;
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetPos, lci.OffsetRot); PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
} }
else else
{ {
@ -371,8 +411,10 @@ public sealed class BSLinksetCompound : BSLinkset
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
} }
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
} }
lci.Index = memberIndex;
memberIndex++;
} }
return false; // 'false' says to move onto the next child in the list return false; // 'false' says to move onto the next child in the list
}); });

View File

@ -80,6 +80,7 @@ public static class BSParam
public static float AvatarStepForceFactor { get; private set; } public static float AvatarStepForceFactor { get; private set; }
public static float VehicleAngularDamping { get; private set; } public static float VehicleAngularDamping { get; private set; }
public static float VehicleDebuggingEnabled { get; private set; }
public static float LinksetImplementation { get; private set; } public static float LinksetImplementation { get; private set; }
public static float LinkConstraintUseFrameOffset { get; private set; } public static float LinkConstraintUseFrameOffset { get; private set; }
@ -427,6 +428,11 @@ public static class BSParam
(s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); }, (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
(s) => { return VehicleAngularDamping; }, (s) => { return VehicleAngularDamping; },
(s,p,l,v) => { VehicleAngularDamping = v; } ), (s,p,l,v) => { VehicleAngularDamping = v; } ),
new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
ConfigurationParameters.numericFalse,
(s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
(s) => { return VehicleDebuggingEnabled; },
(s,p,l,v) => { VehicleDebuggingEnabled = v; } ),
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
0f, 0f,

View File

@ -73,6 +73,8 @@ public abstract class BSPhysObject : PhysicsActor
// A linkset of just me // A linkset of just me
Linkset = BSLinkset.Factory(PhysicsScene, this); Linkset = BSLinkset.Factory(PhysicsScene, this);
PositionDisplacement = OMV.Vector3.Zero;
LastAssetBuildFailed = false; LastAssetBuildFailed = false;
// Default material type // Default material type
@ -135,6 +137,7 @@ public abstract class BSPhysObject : PhysicsActor
public virtual OMV.Vector3 Scale { get; set; } public virtual OMV.Vector3 Scale { get; set; }
public abstract bool IsSolid { get; } public abstract bool IsSolid { get; }
public abstract bool IsStatic { get; } public abstract bool IsStatic { get; }
public abstract bool IsSelected { get; }
// Materialness // Materialness
public MaterialAttributes.Material Material { get; private set; } public MaterialAttributes.Material Material { get; private set; }
@ -156,6 +159,14 @@ public abstract class BSPhysObject : PhysicsActor
public abstract OMV.Vector3 RawPosition { get; set; } public abstract OMV.Vector3 RawPosition { get; set; }
public abstract OMV.Vector3 ForcePosition { get; set; } public abstract OMV.Vector3 ForcePosition { get; set; }
// Position is what the simulator thinks the positions of the prim is.
// Because Bullet needs the zero coordinate to be the center of mass of the linkset,
// sometimes it is necessary to displace the position the physics engine thinks
// the position is. PositionDisplacement must be added and removed from the
// position as the simulator position is stored and fetched from the physics
// engine.
public virtual OMV.Vector3 PositionDisplacement { get; set; }
public abstract OMV.Quaternion RawOrientation { get; set; } public abstract OMV.Quaternion RawOrientation { get; set; }
public abstract OMV.Quaternion ForceOrientation { get; set; } public abstract OMV.Quaternion ForceOrientation { get; set; }

View File

@ -59,7 +59,7 @@ public class BSPlugin : IPhysicsPlugin
{ {
if (_mScene == null) if (_mScene == null)
{ {
_mScene = new BSScene(sceneIdentifier); _mScene = new BSScene(GetName(), sceneIdentifier);
} }
return (_mScene); return (_mScene);
} }

View File

@ -50,7 +50,10 @@ public sealed class BSPrim : BSPhysObject
private bool _grabbed; private bool _grabbed;
private bool _isSelected; private bool _isSelected;
private bool _isVolumeDetect; private bool _isVolumeDetect;
// _position is what the simulator thinks the positions of the prim is.
private OMV.Vector3 _position; private OMV.Vector3 _position;
private float _mass; // the mass of this object private float _mass; // the mass of this object
private float _density; private float _density;
private OMV.Vector3 _force; private OMV.Vector3 _force;
@ -204,6 +207,10 @@ public sealed class BSPrim : BSPhysObject
} }
} }
} }
public override bool IsSelected
{
get { return _isSelected; }
}
public override void CrossingFailure() { return; } public override void CrossingFailure() { return; }
// link me to the specified parent // link me to the specified parent
@ -290,7 +297,7 @@ public sealed class BSPrim : BSPhysObject
*/ */
// don't do the GetObjectPosition for root elements because this function is called a zillion times. // don't do the GetObjectPosition for root elements because this function is called a zillion times.
// _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody); // _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody) - PositionDisplacement;
return _position; return _position;
} }
set { set {
@ -316,18 +323,37 @@ public sealed class BSPrim : BSPhysObject
} }
public override OMV.Vector3 ForcePosition { public override OMV.Vector3 ForcePosition {
get { get {
_position = PhysicsScene.PE.GetPosition(PhysBody); _position = PhysicsScene.PE.GetPosition(PhysBody) - PositionDisplacement;
return _position; return _position;
} }
set { set {
_position = value; _position = value;
if (PhysBody.HasPhysicalBody) if (PhysBody.HasPhysicalBody)
{ {
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
ActivateIfPhysical(false); ActivateIfPhysical(false);
} }
} }
} }
// Override to have position displacement immediately update the physical position.
// A feeble attempt to keep the sim and physical positions in sync
// Must be called at taint time.
public override OMV.Vector3 PositionDisplacement
{
get
{
return base.PositionDisplacement;
}
set
{
base.PositionDisplacement = value;
PhysicsScene.TaintedObject(PhysicsScene.InTaintTime, "BSPrim.setPosition", delegate()
{
if (PhysBody.HasPhysicalBody)
PhysicsScene.PE.SetTranslation(PhysBody, _position + base.PositionDisplacement, _orientation);
});
}
}
// Check that the current position is sane and, if not, modify the position to make it so. // Check that the current position is sane and, if not, modify the position to make it so.
// Check for being below terrain and being out of bounds. // Check for being below terrain and being out of bounds.
@ -336,7 +362,7 @@ public sealed class BSPrim : BSPhysObject
{ {
bool ret = false; bool ret = false;
if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
{ {
// The physical object is out of the known/simulated area. // The physical object is out of the known/simulated area.
// Upper levels of code will handle the transition to other areas so, for // Upper levels of code will handle the transition to other areas so, for
@ -350,8 +376,11 @@ public sealed class BSPrim : BSPhysObject
{ {
DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
float targetHeight = terrainHeight + (Size.Z / 2f); float targetHeight = terrainHeight + (Size.Z / 2f);
// Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. // If the object is below ground it just has to be moved up because pushing will
upForce.Z = (terrainHeight - RawPosition.Z) * 1f; // not get it through the terrain
_position.Z = targetHeight;
if (!inTaintTime)
ForcePosition = _position;
ret = true; ret = true;
} }
@ -363,20 +392,15 @@ public sealed class BSPrim : BSPhysObject
{ {
// Upforce proportional to the distance away from the water. Correct the error in 1 sec. // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
upForce.Z = (waterHeight - RawPosition.Z) * 1f; upForce.Z = (waterHeight - RawPosition.Z) * 1f;
// Apply upforce and overcome gravity.
OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
AddForce(correctionForce, false, inTaintTime);
ret = true; ret = true;
} }
} }
// The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
// TODO: This should be intergrated with a geneal physics action mechanism.
// TODO: This should be moderated with PID'ness.
if (ret)
{
// Apply upforce and overcome gravity.
OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
AddForce(correctionForce, false, inTaintTime);
}
return ret; return ret;
} }
@ -410,7 +434,7 @@ public sealed class BSPrim : BSPhysObject
} }
else else
{ {
OMV.Vector3 grav = ComputeGravity(); OMV.Vector3 grav = ComputeGravity(Buoyancy);
if (inWorld) if (inWorld)
{ {
@ -445,12 +469,12 @@ public sealed class BSPrim : BSPhysObject
} }
// Return what gravity should be set to this very moment // Return what gravity should be set to this very moment
private OMV.Vector3 ComputeGravity() public OMV.Vector3 ComputeGravity(float buoyancy)
{ {
OMV.Vector3 ret = PhysicsScene.DefaultGravity; OMV.Vector3 ret = PhysicsScene.DefaultGravity;
if (!IsStatic) if (!IsStatic)
ret *= (1f - Buoyancy); ret *= (1f - buoyancy);
return ret; return ret;
} }
@ -586,6 +610,7 @@ public sealed class BSPrim : BSPhysObject
_velocity = value; _velocity = value;
if (PhysBody.HasPhysicalBody) if (PhysBody.HasPhysicalBody)
{ {
DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity);
PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
ActivateIfPhysical(false); ActivateIfPhysical(false);
} }
@ -650,12 +675,7 @@ public sealed class BSPrim : BSPhysObject
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
{ {
if (PhysBody.HasPhysicalBody) ForceOrientation = _orientation;
{
// _position = PhysicsScene.PE.GetObjectPosition(PhysicsScene.World, BSBody);
// DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
}
}); });
} }
} }
@ -670,7 +690,8 @@ public sealed class BSPrim : BSPhysObject
set set
{ {
_orientation = value; _orientation = value;
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); if (PhysBody.HasPhysicalBody)
PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
} }
} }
public override int PhysicsActorType { public override int PhysicsActorType {
@ -809,7 +830,7 @@ public sealed class BSPrim : BSPhysObject
// PhysicsScene.PE.ClearAllForces(BSBody); // PhysicsScene.PE.ClearAllForces(BSBody);
// For good measure, make sure the transform is set through to the motion state // For good measure, make sure the transform is set through to the motion state
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
// Center of mass is at the center of the object // Center of mass is at the center of the object
// DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation); // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation);
@ -1153,33 +1174,70 @@ public sealed class BSPrim : BSPhysObject
// This added force will only last the next simulation tick. // This added force will only last the next simulation tick.
public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
// for an object, doesn't matter if force is a pushforce or not // for an object, doesn't matter if force is a pushforce or not
if (!IsStatic && force.IsFinite()) if (!IsStatic)
{ {
float magnitude = force.Length(); if (force.IsFinite())
if (magnitude > BSParam.MaxAddForceMagnitude)
{ {
// Force has a limit float magnitude = force.Length();
force = force / magnitude * BSParam.MaxAddForceMagnitude; if (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
DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
if (PhysBody.HasPhysicalBody)
{ {
PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); // Force has a limit
ActivateIfPhysical(false); 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
DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
if (PhysBody.HasPhysicalBody)
{
PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce);
ActivateIfPhysical(false);
}
});
}
else
{
m_log.WarnFormat("{0}: AddForce: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
return;
}
} }
else }
public void AddForceImpulse(OMV.Vector3 impulse, bool pushforce, bool inTaintTime) {
// for an object, doesn't matter if force is a pushforce or not
if (!IsStatic)
{ {
m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); if (impulse.IsFinite())
return; {
float magnitude = impulse.Length();
if (magnitude > BSParam.MaxAddForceMagnitude)
{
// Force has a limit
impulse = impulse / magnitude * BSParam.MaxAddForceMagnitude;
}
// DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
OMV.Vector3 addImpulse = impulse;
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate()
{
// Bullet adds this impulse immediately to the velocity
DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
if (PhysBody.HasPhysicalBody)
{
PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
ActivateIfPhysical(false);
}
});
}
else
{
m_log.WarnFormat("{0}: AddForceImpulse: Got a NaN impulse applied to a prim. LocalID={1}", LogHeader, LocalID);
return;
}
} }
} }
@ -1561,21 +1619,6 @@ public sealed class BSPrim : BSPhysObject
// The physics engine says that properties have updated. Update same and inform // The physics engine says that properties have updated. Update same and inform
// the world that things have changed. // the world that things have changed.
// TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate()
enum UpdatedProperties {
Position = 1 << 0,
Rotation = 1 << 1,
Velocity = 1 << 2,
Acceleration = 1 << 3,
RotationalVel = 1 << 4
}
const float ROTATION_TOLERANCE = 0.01f;
const float VELOCITY_TOLERANCE = 0.001f;
const float POSITION_TOLERANCE = 0.05f;
const float ACCELERATION_TOLERANCE = 0.01f;
const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
public override void UpdateProperties(EntityProperties entprop) public override void UpdateProperties(EntityProperties entprop)
{ {
// Updates only for individual prims and for the root object of a linkset. // Updates only for individual prims and for the root object of a linkset.
@ -1588,7 +1631,8 @@ public sealed class BSPrim : BSPhysObject
entprop.RotationalVelocity = OMV.Vector3.Zero; entprop.RotationalVelocity = OMV.Vector3.Zero;
} }
// Assign directly to the local variables so the normal set action does not happen // Assign directly to the local variables so the normal set actions do not happen
entprop.Position -= PositionDisplacement;
_position = entprop.Position; _position = entprop.Position;
_orientation = entprop.Rotation; _orientation = entprop.Rotation;
_velocity = entprop.Velocity; _velocity = entprop.Velocity;

View File

@ -167,11 +167,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
public bool VehiclePhysicalLoggingEnabled { get; private set; } public bool VehiclePhysicalLoggingEnabled { get; private set; }
#region Construction and Initialization #region Construction and Initialization
public BSScene(string identifier) public BSScene(string engineType, string identifier)
{ {
m_initialized = false; m_initialized = false;
// we are passed the name of the region we're working for.
// The name of the region we're working for is passed to us. Keep for identification.
RegionName = identifier; RegionName = identifier;
// Set identifying variables in the PhysicsScene interface.
EngineType = engineType;
Name = EngineType + "/" + RegionName;
} }
public override void Initialise(IMesher meshmerizer, IConfigSource config) public override void Initialise(IMesher meshmerizer, IConfigSource config)
@ -486,6 +491,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
ProcessTaints(); ProcessTaints();
// Some of the physical objects requre individual, pre-step calls // Some of the physical objects requre individual, pre-step calls
// (vehicles and avatar movement, in particular)
TriggerPreStepEvent(timeStep); TriggerPreStepEvent(timeStep);
// the prestep actions might have added taints // the prestep actions might have added taints

View File

@ -906,7 +906,7 @@ public sealed class BSShapeCollection : IDisposable
} }
} }
// While we figure out the real problem, stick a simple native shape on the object. // While we figure out the real problem, stick in a simple box for the object.
BulletShape fillinShape = BulletShape fillinShape =
BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);

View File

@ -1,12 +1,17 @@
CURRENT PRIORITIES CURRENT PRIORITIES
================================================= =================================================
Avatars walking up stairs (HALF DONE) Nebadon vehicles turning funny in arena
Vehicle movement on terrain smoothness
limitMotorUp calibration (more down?) limitMotorUp calibration (more down?)
Preferred orientation angular correction fix Vehicle angular vertical attraction
Vehicle angular deflection
Preferred orientation angular correction fix
vehicle angular banking
Avatars walking up stairs (HALF DONE)
Radius of the capsule affects ability to climb edges.
Vehicle movement on terrain smoothness
Surfboard go wonky when turning Surfboard go wonky when turning
Angular motor direction is global coordinates rather than local coordinates? Angular motor direction is global coordinates rather than local coordinates?
Boats float low in the water Boats float low in the water (DONE)
Avatar movement Avatar movement
flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE) flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
walking up stairs is not calibrated correctly (stairs out of Kepler cabin) walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
@ -33,19 +38,15 @@ CRASHES
VEHICLES TODO LIST: VEHICLES TODO LIST:
================================================= =================================================
Angular motor direction is global coordinates rather than local coordinates
Border crossing with linked vehicle causes crash Border crossing with linked vehicle causes crash
Vehicles (Move smoothly) 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. 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
Happens on terrain and any other mesh object. Flat cubes are much smoother. Happens on terrain and any other mesh object. Flat cubes are much smoother.
This has been reduced but not eliminated. This has been reduced but not eliminated.
Implement referenceFrame for all the motion routines. Implement referenceFrame for all the motion routines.
For limitMotorUp, use raycast down to find if vehicle is in the air.
Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
Verify that angular motion specified around Z moves in the vehicle coordinates. Verify that angular motion specified around Z moves in the vehicle coordinates.
Verify llGetVel() is returning a smooth and good value for vehicle movement. Verify llGetVel() is returning a smooth and good value for vehicle movement.
@ -54,14 +55,13 @@ Implement function efficiency for lineaar and angular motion.
After getting off a vehicle, the root prim is phantom (can be walked through) After getting off a vehicle, the root prim is phantom (can be walked through)
Need to force a position update for the root prim after compound shape destruction Need to force a position update for the root prim after compound shape destruction
Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
For limitMotorUp, use raycast down to find if vehicle is in the air.
Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties(). Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
A kludge that isn't fixing the real problem of Bullet adding extra motion. A kludge that isn't fixing the real problem of Bullet adding extra motion.
Incorporate inter-relationship of angular corrections. For instance, angularDeflection Incorporate inter-relationship of angular corrections. For instance, angularDeflection
and angularMotorUp will compute same X or Y correction. When added together and angularMotorUp will compute same X or Y correction. When added together
creates over-correction and over-shoot and wabbling. creates over-correction and over-shoot and wabbling.
BULLETSIM TODO LIST: GENERAL TODO LIST:
================================================= =================================================
Implement an avatar mesh shape. The Bullet capsule is way too limited. Implement an avatar mesh shape. The Bullet capsule is way too limited.
Consider just hand creating a vertex/index array in a new BSShapeAvatar. Consider just hand creating a vertex/index array in a new BSShapeAvatar.
@ -121,11 +121,9 @@ LinksetCompound: when one of the children changes orientation (like tires
Verify/think through scripts in children of linksets. What do they reference Verify/think through scripts in children of linksets. What do they reference
and return when getting position, velocity, ... and return when getting position, velocity, ...
Confirm constraint linksets still work after making all the changes for compound linksets. Confirm constraint linksets still work after making all the changes for compound linksets.
Use PostTaint callback to do rebuilds for constraint linksets to reduce rebuilding
Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt. Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt.
For compound linksets, add ability to remove or reposition individual child shapes. For compound linksets, add ability to remove or reposition individual child shapes.
Disable activity of passive linkset children.
Since the linkset is a compound object, the old prims are left lying
around and need to be phantomized so they don't collide, ...
Speed up creation of large physical linksets Speed up creation of large physical linksets
For instance, sitting in Neb's car (130 prims) takes several seconds to become physical. For instance, sitting in Neb's car (130 prims) takes several seconds to become physical.
REALLY bad for very large physical linksets (freezes the sim for many seconds). REALLY bad for very large physical linksets (freezes the sim for many seconds).
@ -138,25 +136,21 @@ MORE
Use the HACD convex hull routine in Bullet rather than the C# version. Use the HACD convex hull routine in Bullet rather than the C# version.
Do we need to do convex hulls all the time? Can complex meshes be left meshes? Do we need to do convex hulls all the time? Can complex meshes be left meshes?
There is some problem with meshes and collisions There is some problem with meshes and collisions
Test avatar walking up stairs. How does compare with SL. Hulls are not as detailed as meshes. Hulled vehicles insides are different shape.
Radius of the capsule affects ability to climb edges.
Debounce avatar contact so legs don't keep folding up when standing. Debounce avatar contact so legs don't keep folding up when standing.
Implement LSL physics controls. Like STATUS_ROTATE_X. Implement LSL physics controls. Like STATUS_ROTATE_X.
Add border extensions to terrain to help region crossings and objects leaving region. Add border extensions to terrain to help region crossings and objects leaving region.
Use a different capsule shape for avatar when sitting Use a different capsule shape for avatar when sitting
LL uses a pyrimidal shape scaled by the avatar's bounding box LL uses a pyrimidal shape scaled by the avatar's bounding box
http://wiki.secondlife.com/wiki/File:Avmeshforms.png http://wiki.secondlife.com/wiki/File:Avmeshforms.png
Performance test with lots of avatars. Can BulletSim support a thousand? Performance test with lots of avatars. Can BulletSim support a thousand?
Optimize collisions in C++: only send up to the object subscribed to collisions. Optimize collisions in C++: only send up to the object subscribed to collisions.
Use collision subscription and remove the collsion(A,B) and collision(B,A) Use collision subscription and remove the collsion(A,B) and collision(B,A)
Check whether SimMotionState needs large if statement (see TODO). Check whether SimMotionState needs large if statement (see TODO).
Implement 'top colliders' info. Implement 'top colliders' info.
Avatar jump Avatar jump
Performance measurement and changes to make quicker. Performance measurement and changes to make quicker.
Implement detailed physics stats (GetStats()). Implement detailed physics stats (GetStats()).
Measure performance improvement from hulls Measure performance improvement from hulls
Test not using ghost objects for volume detect implementation. Test not using ghost objects for volume detect implementation.
Performance of closures and delegates for taint processing Performance of closures and delegates for taint processing
@ -164,9 +158,7 @@ Performance of closures and delegates for taint processing
Is any slowdown introduced by the existing implementation significant? Is any slowdown introduced by the existing implementation significant?
Is there are more efficient method of implementing pre and post step actions? 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. 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]
@ -178,6 +170,8 @@ Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/3179
INTERNAL IMPROVEMENT/CLEANUP INTERNAL IMPROVEMENT/CLEANUP
================================================= =================================================
Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
BSScene.TaintedObject() could immediately execute the callback if already in taint time.
Create the physical wrapper classes (BulletBody, BulletShape) by methods on Create the physical wrapper classes (BulletBody, BulletShape) by methods on
BSAPITemplate and make their actual implementation Bullet engine specific. BSAPITemplate and make their actual implementation Bullet engine specific.
For the short term, just call the existing functions in ShapeCollection. For the short term, just call the existing functions in ShapeCollection.
@ -197,22 +191,19 @@ Generalize Dynamics and PID with standardized motors.
Generalize Linkset and vehicles into PropertyManagers Generalize Linkset and vehicles into PropertyManagers
Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
Potentially add events for shape destruction, etc. Potentially add events for shape destruction, etc.
Complete implemention of preStepActions Better mechanism for resetting linkset set and vehicle parameters when body rebuilt.
Replace vehicle step call with prestep event. BSPrim.CreateGeomAndObject is kludgy with the callbacks, etc.
Is there a need for postStepActions? postStepTaints?
Implement linkset by setting position of children when root updated. (LinksetManual) Implement linkset by setting position of children when root updated. (LinksetManual)
Linkset implementation using manual prim movement. Linkset implementation using manual prim movement.
LinkablePrim class? Would that simplify/centralize the linkset logic? LinkablePrim class? Would that simplify/centralize the linkset logic?
BSScene.UpdateParameterSet() is broken. How to set params on objects? BSScene.UpdateParameterSet() is broken. How to set params on objects?
Remove HeightmapInfo from terrain specification
Since C++ code does not need terrain height, this structure et al are not needed.
Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
bob at the water level. BSPrim.PositionSanityCheck(). bob at the water level. BSPrim.PositionSanityCheck()
Should taints check for existance or activeness of target? Should taints check for existance or activeness of target?
When destroying linksets/etc, taints can be generated for objects that are When destroying linksets/etc, taints can be generated for objects that are
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 an 'active' flag that is checked by the taint processor?
Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones) Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones)
Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'? Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'?
There are TOO MANY interfaces from BulletSim core to Bullet itself There are TOO MANY interfaces from BulletSim core to Bullet itself
@ -282,3 +273,18 @@ Redo BulletSimAPI to allow native C# implementation of Bullet option (DONE)
Meshes rendering as bounding boxes (DONE) Meshes rendering as bounding boxes (DONE)
(Resolution: Added test for mesh/sculpties in native shapes so it didn't think it was a box) (Resolution: Added test for mesh/sculpties in native shapes so it didn't think it was a box)
llMoveToTarget (Resolution: added simple motor to update the position.) llMoveToTarget (Resolution: added simple motor to update the position.)
Angular motor direction is global coordinates rather than local coordinates (DONE)
Add vehicle collisions so IsColliding is properly reported. (DONE)
Needed for banking, limitMotorUp, movementLimiting, ...
(Resolution: added CollisionFlags.BS_VEHICLE_COLLISION and code to use it)
VehicleAddForce is not scaled by the simulation step but it is only
applied for one step. Should it be scaled? (DONE)
(Resolution: use force for timed things, Impulse for immediate, non-timed things)
Complete implemention of preStepActions (DONE)
Replace vehicle step call with prestep event.
Is there a need for postStepActions? postStepTaints?
Disable activity of passive linkset children. (DONE)
Since the linkset is a compound object, the old prims are left lying
around and need to be phantomized so they don't collide, ...
Remove HeightmapInfo from terrain specification (DONE)
Since C++ code does not need terrain height, this structure et al are not needed.

View File

@ -97,13 +97,20 @@ namespace OpenSim.Region.Physics.Manager
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary> /// <summary>
/// Name of this scene. Useful in debug messages to distinguish one OdeScene instance from another. /// A unique identifying string for this instance of the physics engine.
/// Useful in debug messages to distinguish one OdeScene instance from another.
/// Usually set to include the region name that the physics engine is acting for.
/// </summary> /// </summary>
public string Name { get; protected set; } public string Name { get; protected set; }
/// <summary>
/// A string identifying the family of this physics engine. Most common values returned
/// are "OpenDynamicsEngine" and "BulletSim" but others are possible.
/// </summary>
public string EngineType { get; protected set; }
// The only thing that should register for this event is the SceneGraph // The only thing that should register for this event is the SceneGraph
// Anything else could cause problems. // Anything else could cause problems.
public event physicsCrash OnPhysicsCrash; public event physicsCrash OnPhysicsCrash;
public static PhysicsScene Null public static PhysicsScene Null

View File

@ -72,7 +72,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// http://opensimulator.org/mantis/view.php?id=2750). // http://opensimulator.org/mantis/view.php?id=2750).
d.InitODE(); d.InitODE();
m_scene = new OdeScene(sceneIdentifier); m_scene = new OdeScene(GetName(), sceneIdentifier);
} }
return m_scene; return m_scene;

View File

@ -526,11 +526,12 @@ namespace OpenSim.Region.Physics.OdePlugin
/// These settings need to be tweaked 'exactly' right or weird stuff happens. /// These settings need to be tweaked 'exactly' right or weird stuff happens.
/// </summary> /// </summary>
/// <param value="name">Name of the scene. Useful in debug messages.</param> /// <param value="name">Name of the scene. Useful in debug messages.</param>
public OdeScene(string name) public OdeScene(string engineType, string name)
{ {
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name); m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
Name = name; Name = name;
EngineType = engineType;
nearCallback = near; nearCallback = near;
triCallback = TriCallback; triCallback = TriCallback;

View File

@ -49,7 +49,7 @@ namespace OpenSim.Region.Physics.POSPlugin
public PhysicsScene GetScene(string sceneIdentifier) public PhysicsScene GetScene(string sceneIdentifier)
{ {
return new POSScene(sceneIdentifier); return new POSScene(GetName(), sceneIdentifier);
} }
public string GetName() public string GetName()

View File

@ -43,8 +43,10 @@ namespace OpenSim.Region.Physics.POSPlugin
//protected internal string sceneIdentifier; //protected internal string sceneIdentifier;
public POSScene(String _sceneIdentifier) public POSScene(string engineType, String _sceneIdentifier)
{ {
EngineType = engineType;
Name = EngineType + "/" + _sceneIdentifier;
//sceneIdentifier = _sceneIdentifier; //sceneIdentifier = _sceneIdentifier;
} }

View File

@ -254,11 +254,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
} }
// Returns of the function is allowed. Throws a script exception if not allowed.
public void CheckThreatLevel(ThreatLevel level, string function) public void CheckThreatLevel(ThreatLevel level, string function)
{ {
if (!m_OSFunctionsEnabled) if (!m_OSFunctionsEnabled)
OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws
string reasonWhyNot = CheckThreatLevelTest(level, function);
if (!String.IsNullOrEmpty(reasonWhyNot))
{
OSSLError(reasonWhyNot);
}
}
// Check to see if function is allowed. Returns an empty string if function permitted
// or a string explaining why this function can't be used.
private string CheckThreatLevelTest(ThreatLevel level, string function)
{
if (!m_FunctionPerms.ContainsKey(function)) if (!m_FunctionPerms.ContainsKey(function))
{ {
FunctionPerms perms = new FunctionPerms(); FunctionPerms perms = new FunctionPerms();
@ -338,10 +350,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
// Allow / disallow by threat level // Allow / disallow by threat level
if (level > m_MaxThreatLevel) if (level > m_MaxThreatLevel)
OSSLError( return
String.Format( String.Format(
"{0} permission denied. Allowed threat level is {1} but function threat level is {2}.", "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.",
function, m_MaxThreatLevel, level)); function, m_MaxThreatLevel, level);
} }
else else
{ {
@ -351,7 +363,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID)) if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID))
{ {
// prim owner is in the list of allowed owners // prim owner is in the list of allowed owners
return; return String.Empty;
} }
UUID ownerID = m_item.OwnerID; UUID ownerID = m_item.OwnerID;
@ -363,7 +375,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero) if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
{ {
return; return String.Empty;
} }
} }
@ -374,7 +386,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (land.LandData.OwnerID == ownerID) if (land.LandData.OwnerID == ownerID)
{ {
return; return String.Empty;
} }
} }
@ -384,7 +396,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
//Only Estate Managers may use the function //Only Estate Managers may use the function
if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
{ {
return; return String.Empty;
} }
} }
@ -393,25 +405,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
if (World.RegionInfo.EstateSettings.EstateOwner == ownerID) if (World.RegionInfo.EstateSettings.EstateOwner == ownerID)
{ {
return; return String.Empty;
} }
} }
if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID)) if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
OSSLError( return(
String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.",
function)); function));
if (m_item.CreatorID != ownerID) if (m_item.CreatorID != ownerID)
{ {
if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0) if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
OSSLError( return String.Format("{0} permission denied. Script permissions error.", function);
String.Format("{0} permission denied. Script permissions error.",
function));
} }
} }
} }
return String.Empty;
} }
internal void OSSLDeprecated(string function, string replacement) internal void OSSLDeprecated(string function, string replacement)
@ -1567,6 +1578,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
} }
public string osGetPhysicsEngineType()
{
// High because it can be used to target attacks to known weaknesses
// This would allow a new class of griefer scripts that don't even
// require their user to know what they are doing (see script
// kiddie)
// Because it would be nice if scripts didn't blow up if the information
// about the physics engine, this function returns an empty string if
// the user does not have permission to see it. This as opposed to
// throwing an exception.
m_host.AddScriptLPS(1);
string ret = String.Empty;
if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType")))
{
if (m_ScriptEngine.World.PhysicsScene != null)
{
ret = m_ScriptEngine.World.PhysicsScene.EngineType;
// An old physics engine might have an uninitialized engine type
if (ret == null)
ret = "unknown";
}
}
return ret;
}
public string osGetSimulatorVersion() public string osGetSimulatorVersion()
{ {
// High because it can be used to target attacks to known weaknesses // High because it can be used to target attacks to known weaknesses

View File

@ -259,6 +259,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
string osGetScriptEngineName(); string osGetScriptEngineName();
string osGetSimulatorVersion(); string osGetSimulatorVersion();
string osGetPhysicsEngineType();
Object osParseJSONNew(string JSON); Object osParseJSONNew(string JSON);
Hashtable osParseJSON(string JSON); Hashtable osParseJSON(string JSON);

View File

@ -420,6 +420,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osGetScriptEngineName(); return m_OSSL_Functions.osGetScriptEngineName();
} }
public string osGetPhysicsEngineType()
{
return m_OSSL_Functions.osGetPhysicsEngineType();
}
public string osGetSimulatorVersion() public string osGetSimulatorVersion()
{ {
return m_OSSL_Functions.osGetSimulatorVersion(); return m_OSSL_Functions.osGetSimulatorVersion();

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.