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

0.7.5-pf-bulletsim
Justin Clark-Casey (justincc) 2012-12-07 00:53:47 +00:00
commit 4e622f6816
11 changed files with 461 additions and 358 deletions

View File

@ -24,21 +24,10 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to * are Copyright (c) 2009 Linden Research, Inc and are used under their license
* call the BulletSim system. * of Creative Commons Attribution-Share Alike 3.0
*/ * (http://creativecommons.org/licenses/by-sa/3.0/).
/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
* ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
* ODEPrim.cs contains methods dealing with Prim editing, Prim
* characteristics and Kinetic motion.
* ODEDynamics.cs contains methods dealing with Prim Physical motion
* (dynamics) and the associated settings. Old Linear and angular
* motors for dynamic motion have been replace with MoveLinear()
* and MoveAngular(); 'Physical' is used only to switch ODE dynamic
* simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
* switch between 'VEHICLE' parameter use and general dynamics
* settings use.
*/ */
using System; using System;
@ -111,7 +100,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private float m_bankingEfficiency = 0; private float m_bankingEfficiency = 0;
private float m_bankingMix = 0; private float m_bankingMix = 0;
private float m_bankingTimescale = 0; private float m_bankingTimescale = 0;
private Vector3 m_lastBanking = Vector3.Zero;
//Hover and Buoyancy properties //Hover and Buoyancy properties
private float m_VhoverHeight = 0f; private float m_VhoverHeight = 0f;
@ -125,8 +113,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
//Attractor properties //Attractor properties
private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
private float m_verticalAttractionEfficiency = 1.0f; // damped private float m_verticalAttractionEfficiency = 1.0f; // damped
private float m_verticalAttractionTimescale = 600f; // Timescale > 500 means no vert attractor. private float m_verticalAttractionCutoff = 500f; // per the documentation
// Timescale > cutoff means no vert attractor.
private float m_verticalAttractionTimescale = 510f;
public BSDynamics(BSScene myScene, BSPrim myPrim) public BSDynamics(BSScene myScene, BSPrim myPrim)
{ {
@ -329,7 +319,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_bankingEfficiency = 0; m_bankingEfficiency = 0;
m_bankingTimescale = 1000; m_bankingTimescale = 1000;
m_bankingMix = 1; m_bankingMix = 1;
m_lastBanking = Vector3.Zero;
m_referenceFrame = Quaternion.Identity; m_referenceFrame = Quaternion.Identity;
m_flags = (VehicleFlag)0; m_flags = (VehicleFlag)0;
@ -364,7 +353,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_bankingEfficiency = 0; m_bankingEfficiency = 0;
m_bankingTimescale = 10; m_bankingTimescale = 10;
m_bankingMix = 1; m_bankingMix = 1;
m_lastBanking = Vector3.Zero;
m_referenceFrame = Quaternion.Identity; m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@ -374,6 +362,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_flags |= (VehicleFlag.NO_DEFLECTION_UP m_flags |= (VehicleFlag.NO_DEFLECTION_UP
| VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_ROLL_ONLY
| VehicleFlag.LIMIT_MOTOR_UP); | VehicleFlag.LIMIT_MOTOR_UP);
break; break;
case Vehicle.TYPE_CAR: case Vehicle.TYPE_CAR:
m_linearMotorDirection = Vector3.Zero; m_linearMotorDirection = Vector3.Zero;
@ -403,7 +392,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_bankingEfficiency = -0.2f; m_bankingEfficiency = -0.2f;
m_bankingMix = 1; m_bankingMix = 1;
m_bankingTimescale = 1; m_bankingTimescale = 1;
m_lastBanking = Vector3.Zero;
m_referenceFrame = Quaternion.Identity; m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@ -442,7 +430,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_bankingEfficiency = -0.3f; m_bankingEfficiency = -0.3f;
m_bankingMix = 0.8f; m_bankingMix = 0.8f;
m_bankingTimescale = 1; m_bankingTimescale = 1;
m_lastBanking = Vector3.Zero;
m_referenceFrame = Quaternion.Identity; m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
@ -481,7 +468,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_bankingEfficiency = 1; m_bankingEfficiency = 1;
m_bankingMix = 0.7f; m_bankingMix = 0.7f;
m_bankingTimescale = 2; m_bankingTimescale = 2;
m_lastBanking = Vector3.Zero;
m_referenceFrame = Quaternion.Identity; m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@ -520,7 +506,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_bankingEfficiency = 0; m_bankingEfficiency = 0;
m_bankingMix = 0.7f; m_bankingMix = 0.7f;
m_bankingTimescale = 5; m_bankingTimescale = 5;
m_lastBanking = Vector3.Zero;
m_referenceFrame = Quaternion.Identity; m_referenceFrame = Quaternion.Identity;
@ -554,8 +539,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// 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)
// m_bankingMotor = new BSVMotor("BankingMotor", ...);
} }
// Some of the properties of this prim may have changed. // Some of the properties of this prim may have changed.
@ -577,15 +560,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
float angularDamping = PhysicsScene.Params.vehicleAngularDamping; float angularDamping = PhysicsScene.Params.vehicleAngularDamping;
BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping);
// Vehicles report collision events so we know when it's on the ground
BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
// DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
// Vector3 localInertia = new Vector3(1f, 1f, 1f); // Vector3 localInertia = new Vector3(1f, 1f, 1f);
Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass); // Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass);
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}", VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
Prim.LocalID, friction, localInertia, angularDamping); Prim.LocalID, friction, localInertia, angularDamping);
} }
else
{
BulletSimAPI.RemoveFromCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
}
} }
public bool RemoveBodyDependencies(BSPhysObject prim) public bool RemoveBodyDependencies(BSPhysObject prim)
@ -618,13 +609,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private float? m_knownWaterLevel; private float? m_knownWaterLevel;
private Vector3? m_knownPosition; private Vector3? m_knownPosition;
private Vector3? m_knownVelocity; private Vector3? m_knownVelocity;
private Vector3 m_knownForce;
private Quaternion? m_knownOrientation; private Quaternion? m_knownOrientation;
private Vector3? m_knownRotationalVelocity; private Vector3? m_knownRotationalVelocity;
private Vector3 m_knownRotationalForce;
private float? m_knownForwardSpeed;
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_knownChangedOrientation = 1 << 2; private const int m_knownChangedForce = 1 << 2;
private const int m_knownChangedRotationalVelocity = 1 << 3; private const int m_knownChangedOrientation = 1 << 3;
private const int m_knownChangedRotationalVelocity = 1 << 4;
private const int m_knownChangedRotationalForce = 1 << 5;
private void ForgetKnownVehicleProperties() private void ForgetKnownVehicleProperties()
{ {
@ -632,8 +628,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_knownWaterLevel = null; m_knownWaterLevel = null;
m_knownPosition = null; m_knownPosition = null;
m_knownVelocity = null; m_knownVelocity = null;
m_knownForce = Vector3.Zero;
m_knownOrientation = null; m_knownOrientation = null;
m_knownRotationalVelocity = null; m_knownRotationalVelocity = null;
m_knownRotationalForce = Vector3.Zero;
m_knownForwardSpeed = null;
m_knownChanged = 0; m_knownChanged = 0;
} }
private void PushKnownChanged() private void PushKnownChanged()
@ -645,12 +644,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if ((m_knownChanged & m_knownChangedOrientation) != 0) if ((m_knownChanged & m_knownChangedOrientation) != 0)
Prim.ForceOrientation = VehicleOrientation; Prim.ForceOrientation = VehicleOrientation;
if ((m_knownChanged & m_knownChangedVelocity) != 0) if ((m_knownChanged & m_knownChangedVelocity) != 0)
{
Prim.ForceVelocity = VehicleVelocity; Prim.ForceVelocity = VehicleVelocity;
BulletSimAPI.SetInterpolationLinearVelocity2(Prim.PhysBody.ptr, VehicleVelocity);
}
if ((m_knownChanged & m_knownChangedForce) != 0)
Prim.AddForce((Vector3)m_knownForce, false, true);
if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
{ {
Prim.ForceRotationalVelocity = VehicleRotationalVelocity; Prim.ForceRotationalVelocity = VehicleRotationalVelocity;
// Fake out Bullet by making it think the velocity is the same as last time.
BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity); BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity);
} }
if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true);
// 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.
BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr);
@ -720,6 +729,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} }
} }
private void VehicleAddForce(Vector3 aForce)
{
m_knownForce += aForce;
m_knownChanged |= m_knownChangedForce;
}
private Vector3 VehicleRotationalVelocity private Vector3 VehicleRotationalVelocity
{ {
get get
@ -734,6 +749,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_knownChanged |= m_knownChangedRotationalVelocity; m_knownChanged |= m_knownChangedRotationalVelocity;
} }
} }
private void VehicleAddAngularForce(Vector3 aForce)
{
m_knownRotationalForce += aForce;
m_knownChanged |= m_knownChangedRotationalForce;
}
private float VehicleForwardSpeed
{
get
{
if (m_knownForwardSpeed == null)
m_knownForwardSpeed = (VehicleVelocity * Quaternion.Inverse(VehicleOrientation)).X;
return (float)m_knownForwardSpeed;
}
}
#endregion // Known vehicle value functions #endregion // Known vehicle value functions
// One step of the vehicle properties for the next 'pTimestep' seconds. // One step of the vehicle properties for the next 'pTimestep' seconds.
@ -769,10 +799,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
linearMotorContribution *= VehicleOrientation; linearMotorContribution *= VehicleOrientation;
// ================================================================== // ==================================================================
// Gravity and Buoyancy // Buoyancy: force to overcome gravity.
// There is some gravity, make a gravity force vector that is applied after object velocity.
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); // 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 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
@ -797,14 +827,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
newVelocity.Z = 0; newVelocity.Z = 0;
// ================================================================== // ==================================================================
// Clamp REALLY high or low velocities // Clamp high or low velocities
float newVelocityLengthSq = newVelocity.LengthSquared(); float newVelocityLengthSq = newVelocity.LengthSquared();
if (newVelocityLengthSq > 1e6f) // if (newVelocityLengthSq > 1e6f)
if (newVelocityLengthSq > 1000f)
{ {
newVelocity /= newVelocity.Length(); newVelocity /= newVelocity.Length();
newVelocity *= 1000f; newVelocity *= 1000f;
} }
else if (newVelocityLengthSq < 1e-6f) // else if (newVelocityLengthSq < 1e-6f)
else if (newVelocityLengthSq < 0.001f)
newVelocity = Vector3.Zero; newVelocity = Vector3.Zero;
// ================================================================== // ==================================================================
@ -813,15 +845,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
VehicleVelocity = newVelocity; VehicleVelocity = newVelocity;
// Other linear forces are applied as forces. // Other linear forces are applied as forces.
Vector3 totalDownForce = grav * m_vehicleMass * pTimestep; Vector3 totalDownForce = buoyancyContribution * m_vehicleMass;
if (totalDownForce != Vector3.Zero) if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
{ {
Prim.AddForce(totalDownForce, false); VehicleAddForce(totalDownForce);
} }
VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},linContrib={3},terrContrib={4},hoverContrib={5},limitContrib={6}", VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}",
Prim.LocalID, newVelocity, totalDownForce, Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding);
linearMotorContribution, terrainHeightContribution, hoverContribution, limitMotorUpContribution 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()
@ -942,21 +977,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} }
// From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
// Prevent ground vehicles from motoring into the sky.This flag has a subtle effect when // Prevent ground vehicles from motoring into the sky. This flag has a subtle effect when
// used with conjunction with banking: the strength of the banking will decay when the // used with conjunction with banking: the strength of the banking will decay when the
// vehicle no longer experiences collisions. The decay timescale is the same as // vehicle no longer experiences collisions. The decay timescale is the same as
// VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
// when they are in mid jump. // when they are in mid jump.
// TODO: this code is wrong. Also, what should it do for boats? // 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
// a downward raycast to find what is below.
public Vector3 ComputeLinearMotorUp(float pTimestep) public Vector3 ComputeLinearMotorUp(float pTimestep)
{ {
Vector3 ret = Vector3.Zero; Vector3 ret = Vector3.Zero;
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
{ {
// If the vehicle is motoring into the sky, get it going back down. // If the vehicle is motoring into the sky, get it going back down.
// float distanceAboveGround = pos.Z - Math.Max(GetTerrainHeight(pos), GetWaterLevel(pos));
float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition); float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
if (distanceAboveGround > 1f) // Not colliding if the vehicle is off the ground
if (!Prim.IsColliding)
{ {
// downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
// downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
@ -977,8 +1015,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// ======================================================================= // =======================================================================
// Apply the effect of the angular motor. // Apply the effect of the angular motor.
// The 'contribution' is how much angular correction velocity each function wants. // The 'contribution' is how much angular correction velocity each function wants.
// All the contributions are added together and the orientation of the vehicle // All the contributions are added together and the resulting velocity is
// is changed by all the contributed corrections. // set directly on the vehicle.
private void MoveAngular(float pTimestep) private void MoveAngular(float pTimestep)
{ {
// The user wants how many radians per second angular change? // The user wants how many radians per second angular change?
@ -1001,7 +1039,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
Vector3 deflectionContribution = ComputeAngularDeflection(); Vector3 deflectionContribution = ComputeAngularDeflection();
Vector3 bankingContribution = ComputeAngularBanking(angularMotorContribution.Z); Vector3 bankingContribution = ComputeAngularBanking();
// ================================================================== // ==================================================================
m_lastVertAttractor = verticalAttractionContribution; m_lastVertAttractor = verticalAttractionContribution;
@ -1013,11 +1051,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
+ bankingContribution; + bankingContribution;
// ================================================================== // ==================================================================
// The correction is applied to the current orientation. // Apply the correction velocity.
// TODO: Should this be applied as an angular force (torque)?
if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f)) if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f))
{ {
Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep; Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep;
VehicleRotationalVelocity = scaledCorrection; VehicleRotationalVelocity = scaledCorrection;
VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}", VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}",
@ -1029,7 +1067,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} }
else else
{ {
// The vehicle is not adding anything velocity wise. // The vehicle is not adding anything angular wise.
VehicleRotationalVelocity = Vector3.Zero; VehicleRotationalVelocity = Vector3.Zero;
VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID);
} }
@ -1060,19 +1098,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
torqueFromOffset.Y = 0; torqueFromOffset.Y = 0;
if (float.IsNaN(torqueFromOffset.Z)) if (float.IsNaN(torqueFromOffset.Z))
torqueFromOffset.Z = 0; torqueFromOffset.Z = 0;
torqueFromOffset *= m_vehicleMass;
Prim.ApplyTorqueImpulse(torqueFromOffset, true); VehicleAddAngularForce(torqueFromOffset * m_vehicleMass);
VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
} }
} }
// From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
// Some vehicles, like boats, should always keep their up-side up. This can be done by
// enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to
// the world z-axis (a.k.a. "up"). To take advantage of this feature you would set the
// VEHICLE_VERTICAL_ATTRACTION_TIMESCALE to control the period of the spring frequency,
// and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An
// efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an
// efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
public Vector3 ComputeAngularVerticalAttraction() public Vector3 ComputeAngularVerticalAttraction()
{ {
Vector3 ret = Vector3.Zero; Vector3 ret = Vector3.Zero;
// If vertical attaction timescale is reasonable and we applied an angular force last time... // If vertical attaction timescale is reasonable and we applied an angular force last time...
if (m_verticalAttractionTimescale < 500) if (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;
@ -1097,91 +1142,121 @@ namespace OpenSim.Region.Physics.BulletSPlugin
ret.Y = - verticalError.X; ret.Y = - verticalError.X;
ret.Z = 0f; ret.Z = 0f;
// scale by the time scale and timestep // Scale the correction force by how far we're off from vertical.
// Z error of one says little error. As Z gets smaller, the vehicle is leaning farther over.
float clampedSqrZError = ClampInRange(0.01f, verticalError.Z * verticalError.Z, 1f);
float vertForce = 1f / clampedSqrZError;
ret *= vertForce;
// Correction happens over a number of seconds.
Vector3 unscaledContrib = ret; Vector3 unscaledContrib = ret;
ret /= m_verticalAttractionTimescale; ret /= m_verticalAttractionTimescale;
// This returns the angular correction desired. Timestep is added later.
// ret *= pTimestep;
// apply efficiency VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},vertForce={3},eff={4},vertAttr={5}",
Vector3 preEfficiencyContrib = ret; Prim.LocalID, verticalError, unscaledContrib, vertForce, m_verticalAttractionEfficiency, ret);
// TODO: implement efficiency.
// Effenciency squared seems to give a more realistic effect
float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
// ret *= efficencySquared;
VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}",
Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
m_verticalAttractionEfficiency, efficencySquared,
ret);
} }
return ret; return ret;
} }
// Return the angular correction to correct the direction the vehicle is pointing to be // Return the angular correction to correct the direction the vehicle is pointing to be
// the direction is should want to be pointing. // the direction is should want to be pointing.
// The vehicle is moving in some direction and correct its orientation to it is pointing
// in that direction.
// TODO: implement reference frame.
public Vector3 ComputeAngularDeflection() public Vector3 ComputeAngularDeflection()
{ {
Vector3 ret = Vector3.Zero; Vector3 ret = Vector3.Zero;
return ret; // DEBUG DEBUG DEBUG debug one force at a time
if (m_angularDeflectionEfficiency != 0) if (m_angularDeflectionEfficiency != 0)
{ {
// Where the vehicle should want to point relative to the vehicle // The direction the vehicle is moving
Vector3 preferredDirection = Vector3.UnitX * m_referenceFrame; Vector3 movingDirection = VehicleVelocity;
movingDirection.Normalize();
// Where the vehicle is pointing relative to the vehicle. // The direction the vehicle is pointing
Vector3 currentDirection = Vector3.UnitX * Quaternion.Add(VehicleOrientation, m_referenceFrame); Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
pointingDirection.Normalize();
// Difference between where vehicle is pointing and where it should wish to point // The difference between what is and what should be
Vector3 directionCorrection = preferredDirection - currentDirection; Vector3 deflectionError = movingDirection - pointingDirection;
// Scale the correction by recovery timescale and efficiency // Scale the correction by recovery timescale and efficiency
ret = directionCorrection * m_angularDeflectionEfficiency / m_angularDeflectionTimescale; ret = (-deflectionError * VehicleForwardSpeed) * m_angularDeflectionEfficiency;
ret /= m_angularDeflectionTimescale;
VDetailLog("{0}, MoveAngular,Deflection,perfDir={1},currentDir={2},dirCorrection={3},ret={4}", VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
Prim.LocalID, preferredDirection, currentDirection, directionCorrection, ret); Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret);
} }
return ret; return ret;
} }
// Return an angular change to tip the vehicle (around X axis) when turning (turned around Z). // Return an angular change to rotate the vehicle around the Z axis when the vehicle
// Remembers the last banking value calculated and returns the difference needed this tick. // is tipped around the X axis.
// TurningFactor is rate going left or right (pos=left, neg=right, scale=0..1). // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
public Vector3 ComputeAngularBanking(float turningFactor) // The vertical attractor feature must be enabled in order for the banking behavior to
// function. The way banking works is this: a rotation around the vehicle's roll-axis will
// produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
// of the yaw effect will be proportional to the
// VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
// velocity along its preferred axis of motion.
// The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
// positive rotation (by the right-hand rule) about the roll-axis will effect a
// (negative) torque around the yaw-axis, making it turn to the right--that is the
// vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
// Negating the banking coefficient will make it so that the vehicle leans to the
// outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
// The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
// banking vehicles do what you want rather than what the laws of physics allow.
// For example, consider a real motorcycle...it must be moving forward in order for
// it to turn while banking, however video-game motorcycles are often configured
// to turn in place when at a dead stop--because they are often easier to control
// that way using the limited interface of the keyboard or game controller. The
// VEHICLE_BANKING_MIX enables combinations of both realistic and non-realistic
// banking by functioning as a slider between a banking that is correspondingly
// totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
// banking effect depends only on the vehicle's rotation about its roll-axis compared
// to "dynamic" where the banking is also proportional to its velocity along its
// roll-axis. Finding the best value of the "mixture" will probably require trial and error.
// The time it takes for the banking behavior to defeat a preexisting angular velocity about the
// world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
// bank quickly then give it a banking timescale of about a second or less, otherwise you can
// make a sluggish vehicle by giving it a timescale of several seconds.
public Vector3 ComputeAngularBanking()
{ {
Vector3 ret = Vector3.Zero; Vector3 ret = Vector3.Zero;
Vector3 computedBanking = Vector3.Zero;
if (m_bankingEfficiency != 0) if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
{ {
Vector3 currentDirection = Vector3.UnitX * VehicleOrientation; // This works by rotating a unit vector to the orientation of the vehicle. The
// roll (tilt) will be Y component of a tilting Z vector (zero for no tilt
// up to one for full over).
Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation;
float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1); // Figure out the yaw value for this much roll.
float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency;
// Keep the sign
if (rollComponents.Y < 0f)
turnComponent = -turnComponent;
//Use the square of the efficiency, as it looks much more how SL banking works // TODO: there must be a better computation of the banking force.
float effSquared = (m_bankingEfficiency * m_bankingEfficiency); float bankingTurnForce = turnComponent;
if (m_bankingEfficiency < 0)
effSquared *= -1; //Keep the negative!
float mix = Math.Abs(m_bankingMix); // actual error = static turn error + dynamic turn error
// TODO: Must include reference frame. float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed;
float forwardSpeed = VehicleVelocity.X; // TODO: the banking effect should not go to infinity but what to limit it to?
mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f);
if (!Prim.IsColliding && forwardSpeed > mix) // Build the force vector to change rotation from what it is to what it should be
{ ret.Z = -mixedBankingError;
computedBanking.X = ClampInRange(-3f, turningFactor * (effSquared * mult), 3f);
}
// 'computedBanking' is now how much banking that should be happening. // Don't do it all at once.
ret = computedBanking - m_lastBanking; ret /= m_bankingTimescale;
// Scale the correction by timescale and efficiency VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}",
ret /= m_bankingTimescale * m_bankingEfficiency; Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret);
VDetailLog("{0}, MoveAngular,Banking,computedB={1},lastB={2},bEff={3},effSq={4},mult={5},mix={6},banking={7}",
Prim.LocalID, computedBanking, m_lastBanking, m_bankingEfficiency, effSquared, mult, mix, ret);
} }
m_lastBanking = computedBanking;
return ret; return ret;
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -53,24 +53,19 @@ public struct MaterialAttributes
// Names must be in the order of the above enum. // Names must be in the order of the above enum.
public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
"Flesh", "Plastic", "Rubber", "Light", "Avatar" }; "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
public static string[] MaterialAttribs = { "Density", "Friction", "Restitution", public static string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
"ccdMotionThreshold", "ccdSweptSphereRadius" };
public MaterialAttributes(string t, float d, float f, float r, float ccdM, float ccdS) public MaterialAttributes(string t, float d, float f, float r)
{ {
type = t; type = t;
density = d; density = d;
friction = f; friction = f;
restitution = r; restitution = r;
ccdMotionThreshold = ccdM;
ccdSweptSphereRadius = ccdS;
} }
public string type; public string type;
public float density; public float density;
public float friction; public float friction;
public float restitution; public float restitution;
public float ccdMotionThreshold;
public float ccdSweptSphereRadius;
} }
public static class BSMaterials public static class BSMaterials
@ -86,50 +81,49 @@ public static class BSMaterials
// This is where all the default material attributes are defined. // This is where all the default material attributes are defined.
public static void InitializeFromDefaults(ConfigurationParameters parms) public static void InitializeFromDefaults(ConfigurationParameters parms)
{ {
// public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
// public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
// "Flesh", "Plastic", "Rubber", "Light", "Avatar" }; // "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
float dFriction = parms.defaultFriction; float dFriction = parms.defaultFriction;
float dRestitution = parms.defaultRestitution; float dRestitution = parms.defaultRestitution;
float dDensity = parms.defaultDensity; float dDensity = parms.defaultDensity;
float dCcdM = parms.ccdMotionThreshold;
float dCcdS = parms.ccdSweptSphereRadius;
Attributes[(int)MaterialAttributes.Material.Stone] = Attributes[(int)MaterialAttributes.Material.Stone] =
new MaterialAttributes("stone",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Metal] = Attributes[(int)MaterialAttributes.Material.Metal] =
new MaterialAttributes("metal",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("metal",dDensity, 0.3f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Glass] = Attributes[(int)MaterialAttributes.Material.Glass] =
new MaterialAttributes("glass",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("glass",dDensity, 0.2f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Wood] = Attributes[(int)MaterialAttributes.Material.Wood] =
new MaterialAttributes("wood",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("wood",dDensity, 0.6f, 0.5f);
Attributes[(int)MaterialAttributes.Material.Flesh] = Attributes[(int)MaterialAttributes.Material.Flesh] =
new MaterialAttributes("flesh",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f);
Attributes[(int)MaterialAttributes.Material.Plastic] = Attributes[(int)MaterialAttributes.Material.Plastic] =
new MaterialAttributes("plastic",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Rubber] = Attributes[(int)MaterialAttributes.Material.Rubber] =
new MaterialAttributes("rubber",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f);
Attributes[(int)MaterialAttributes.Material.Light] = Attributes[(int)MaterialAttributes.Material.Light] =
new MaterialAttributes("light",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("light",dDensity, dFriction, dRestitution);
Attributes[(int)MaterialAttributes.Material.Avatar] = Attributes[(int)MaterialAttributes.Material.Avatar] =
new MaterialAttributes("avatar",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("avatar",60f, 0.2f, 0f);
Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("stonePhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("metalPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("glassPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("woodPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f);
Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("fleshPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f);
Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("plasticPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("rubberPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f);
Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("lightPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("avatarPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f);
} }
// Under the [BulletSim] section, one can change the individual material // Under the [BulletSim] section, one can change the individual material

View File

@ -1010,6 +1010,9 @@ public sealed class BSPrim : BSPhysObject
}); });
} }
// A torque impulse. // A torque impulse.
// ApplyTorqueImpulse adds torque directly to the angularVelocity.
// AddAngularForce accumulates the force and applied it to the angular velocity all at once.
// Computed as: angularVelocity += impulse * inertia;
public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
{ {
OMV.Vector3 applyImpulse = impulse; OMV.Vector3 applyImpulse = impulse;
@ -1396,7 +1399,7 @@ public sealed class BSPrim : BSPhysObject
_rotationalVelocity = entprop.RotationalVelocity; _rotationalVelocity = entprop.RotationalVelocity;
// The sanity check can change the velocity and/or position. // The sanity check can change the velocity and/or position.
if (PositionSanityCheck(true)) if (IsPhysical && PositionSanityCheck(true))
{ {
entprop.Position = _position; entprop.Position = _position;
entprop.Velocity = _velocity; entprop.Velocity = _velocity;
@ -1410,8 +1413,6 @@ public sealed class BSPrim : BSPhysObject
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
// BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
base.RequestPhysicsterseUpdate(); base.RequestPhysicsterseUpdate();
} }
/* /*

View File

@ -65,9 +65,16 @@ public sealed class BSShapeCollection : IDisposable
private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>(); private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>(); private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
private bool DDetail = false;
public BSShapeCollection(BSScene physScene) public BSShapeCollection(BSScene physScene)
{ {
PhysicsScene = physScene; PhysicsScene = physScene;
// Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
// While detailed debugging is still active, this is better than commenting out all the
// DetailLog statements. When debugging slows down, this and the protected logging
// statements can be commented/removed.
DDetail = true;
} }
public void Dispose() public void Dispose()
@ -126,13 +133,13 @@ public sealed class BSShapeCollection : IDisposable
{ {
lock (m_collectionActivityLock) lock (m_collectionActivityLock)
{ {
DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
{ {
if (!BulletSimAPI.IsInWorld2(body.ptr)) if (!BulletSimAPI.IsInWorld2(body.ptr))
{ {
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
} }
}); });
} }
@ -149,7 +156,7 @@ public sealed class BSShapeCollection : IDisposable
{ {
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
{ {
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
body.ID, body, inTaintTime); body.ID, body, inTaintTime);
// If the caller needs to know the old body is going away, pass the event up. // If the caller needs to know the old body is going away, pass the event up.
if (bodyCallback != null) bodyCallback(body); if (bodyCallback != null) bodyCallback(body);
@ -157,7 +164,7 @@ public sealed class BSShapeCollection : IDisposable
if (BulletSimAPI.IsInWorld2(body.ptr)) if (BulletSimAPI.IsInWorld2(body.ptr))
{ {
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
} }
// Zero any reference to the shape so it is not freed when the body is deleted. // Zero any reference to the shape so it is not freed when the body is deleted.
@ -184,7 +191,7 @@ public sealed class BSShapeCollection : IDisposable
{ {
// There is an existing instance of this mesh. // There is an existing instance of this mesh.
meshDesc.referenceCount++; meshDesc.referenceCount++;
DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
} }
else else
@ -194,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable
meshDesc.shapeKey = shape.shapeKey; meshDesc.shapeKey = shape.shapeKey;
// We keep a reference to the underlying IMesh data so a hull can be built // We keep a reference to the underlying IMesh data so a hull can be built
meshDesc.referenceCount = 1; meshDesc.referenceCount = 1;
DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
ret = true; ret = true;
} }
@ -207,7 +214,7 @@ public sealed class BSShapeCollection : IDisposable
{ {
// There is an existing instance of this hull. // There is an existing instance of this hull.
hullDesc.referenceCount++; hullDesc.referenceCount++;
DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
} }
else else
@ -216,7 +223,7 @@ public sealed class BSShapeCollection : IDisposable
hullDesc.ptr = shape.ptr; hullDesc.ptr = shape.ptr;
hullDesc.shapeKey = shape.shapeKey; hullDesc.shapeKey = shape.shapeKey;
hullDesc.referenceCount = 1; hullDesc.referenceCount = 1;
DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
ret = true; ret = true;
@ -246,7 +253,7 @@ public sealed class BSShapeCollection : IDisposable
if (shape.isNativeShape) if (shape.isNativeShape)
{ {
// Native shapes are not tracked and are released immediately // Native shapes are not tracked and are released immediately
DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
if (shapeCallback != null) shapeCallback(shape); if (shapeCallback != null) shapeCallback(shape);
BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
@ -286,7 +293,7 @@ public sealed class BSShapeCollection : IDisposable
if (shapeCallback != null) shapeCallback(shape); if (shapeCallback != null) shapeCallback(shape);
meshDesc.lastReferenced = System.DateTime.Now; meshDesc.lastReferenced = System.DateTime.Now;
Meshes[shape.shapeKey] = meshDesc; Meshes[shape.shapeKey] = meshDesc;
DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
BSScene.DetailLogZero, shape, meshDesc.referenceCount); BSScene.DetailLogZero, shape, meshDesc.referenceCount);
} }
@ -307,7 +314,7 @@ public sealed class BSShapeCollection : IDisposable
hullDesc.lastReferenced = System.DateTime.Now; hullDesc.lastReferenced = System.DateTime.Now;
Hulls[shape.shapeKey] = hullDesc; Hulls[shape.shapeKey] = hullDesc;
DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
BSScene.DetailLogZero, shape, hullDesc.referenceCount); BSScene.DetailLogZero, shape, hullDesc.referenceCount);
} }
} }
@ -325,13 +332,13 @@ public sealed class BSShapeCollection : IDisposable
// Failed the sanity check!! // Failed the sanity check!!
PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
LogHeader, shape.type, shape.ptr.ToString("X")); LogHeader, shape.type, shape.ptr.ToString("X"));
DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X"));
return; return;
} }
int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);
DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
for (int ii = numChildren - 1; ii >= 0; ii--) for (int ii = numChildren - 1; ii >= 0; ii--)
{ {
@ -379,7 +386,7 @@ public sealed class BSShapeCollection : IDisposable
} }
} }
DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
{ {
@ -410,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable
// an avatar capsule is close to a native shape (it is not shared) // an avatar capsule is close to a native shape (it is not shared)
ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE,
FixedShapeKey.KEY_CAPSULE, shapeCallback); FixedShapeKey.KEY_CAPSULE, shapeCallback);
DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
ret = true; ret = true;
haveShape = true; haveShape = true;
} }
@ -420,7 +427,7 @@ public sealed class BSShapeCollection : IDisposable
if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
{ {
ret = GetReferenceToCompoundShape(prim, shapeCallback); ret = GetReferenceToCompoundShape(prim, shapeCallback);
DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
haveShape = true; haveShape = true;
} }
@ -465,7 +472,7 @@ public sealed class BSShapeCollection : IDisposable
{ {
ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
FixedShapeKey.KEY_SPHERE, shapeCallback); FixedShapeKey.KEY_SPHERE, shapeCallback);
DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
prim.LocalID, forceRebuild, prim.PhysShape); prim.LocalID, forceRebuild, prim.PhysShape);
} }
} }
@ -479,7 +486,7 @@ public sealed class BSShapeCollection : IDisposable
{ {
ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
FixedShapeKey.KEY_BOX, shapeCallback); FixedShapeKey.KEY_BOX, shapeCallback);
DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
prim.LocalID, forceRebuild, prim.PhysShape); prim.LocalID, forceRebuild, prim.PhysShape);
} }
} }
@ -504,13 +511,13 @@ public sealed class BSShapeCollection : IDisposable
{ {
// Update prim.BSShape to reference a hull of this shape. // Update prim.BSShape to reference a hull of this shape.
ret = GetReferenceToHull(prim,shapeCallback); ret = GetReferenceToHull(prim,shapeCallback);
DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
} }
else else
{ {
ret = GetReferenceToMesh(prim, shapeCallback); ret = GetReferenceToMesh(prim, shapeCallback);
DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
} }
return ret; return ret;
@ -528,7 +535,7 @@ public sealed class BSShapeCollection : IDisposable
BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
// Don't need to do a 'ReferenceShape()' here because native shapes are not shared. // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
prim.LocalID, newShape, prim.Scale); prim.LocalID, newShape, prim.Scale);
prim.PhysShape = newShape; prim.PhysShape = newShape;
@ -554,7 +561,7 @@ public sealed class BSShapeCollection : IDisposable
newShape = new BulletShape( newShape = new BulletShape(
BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
, shapeType); , shapeType);
DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
} }
else else
{ {
@ -589,7 +596,7 @@ public sealed class BSShapeCollection : IDisposable
if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
return false; return false;
DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
// Since we're recreating new, get rid of the reference to the previous shape // Since we're recreating new, get rid of the reference to the previous shape
@ -662,7 +669,7 @@ public sealed class BSShapeCollection : IDisposable
if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
return false; return false;
DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
// Remove usage of the previous shape. // Remove usage of the previous shape.
@ -808,7 +815,7 @@ public sealed class BSShapeCollection : IDisposable
// Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
CreateGeomMeshOrHull(prim, shapeCallback); CreateGeomMeshOrHull(prim, shapeCallback);
BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity);
DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
prim.LocalID, cShape, prim.PhysShape); prim.LocalID, cShape, prim.PhysShape);
prim.PhysShape = cShape; prim.PhysShape = cShape;
@ -935,13 +942,13 @@ public sealed class BSShapeCollection : IDisposable
{ {
bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
prim.LocalID, prim.RawPosition, prim.RawOrientation); prim.LocalID, prim.RawPosition, prim.RawOrientation);
DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
} }
else else
{ {
bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
prim.LocalID, prim.RawPosition, prim.RawOrientation); prim.LocalID, prim.RawPosition, prim.RawOrientation);
DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
} }
aBody = new BulletBody(prim.LocalID, bodyPtr); aBody = new BulletBody(prim.LocalID, bodyPtr);

View File

@ -360,6 +360,7 @@ public enum CollisionFlags : uint
// Following used by BulletSim to control collisions and updates // Following used by BulletSim to control collisions and updates
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
BS_FLOATS_ON_WATER = 1 << 11, BS_FLOATS_ON_WATER = 1 << 11,
BS_VEHICLE_COLLISIONS = 1 << 12,
BS_NONE = 0, BS_NONE = 0,
BS_ALL = 0xFFFFFFFF, BS_ALL = 0xFFFFFFFF,

View File

@ -6,14 +6,34 @@ CRASHES
Causes many errors. Doesn't stop after first error with box shape. Causes many errors. Doesn't stop after first error with box shape.
Eventually crashes when deleting the object. Eventually crashes when deleting the object.
BULLETSIM TODO LIST: VEHICLES TODO LIST:
================================================= =================================================
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.
Vehicles (Move smoothly) Vehicles (Move smoothly)
Light cycle falling over when driving Add vehicle collisions so IsColliding is properly reported.
Light cycle not banking Needed for banking, limitMotorUp, movementLimiting, ...
Do single prim vehicles don't seem to properly vehiclize. Some vehicles should not be able to turn if no speed or off ground.
Gun sending shooter flying For limitMotorUp, use raycast down to find if vehicle is in the air.
Implement function efficiency for lineaar and angular motion.
Should vehicle angular/linear movement friction happen after all the components
or does it only apply to the basic movement?
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
Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
Implement referenceFrame for all the motion routines.
Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
BULLETSIM TODO LIST:
=================================================
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, ...
Scenes with hundred of thousands of static objects take a lot of physics CPU time.
BSPrim.Force should set a continious force on the prim. The force should be
applied each tick. Some limits?
Single prim vehicles don't seem to properly vehiclize.
Gun sending shooter flying.
Collision margin (gap between physical objects lying on each other) Collision margin (gap between physical objects lying on each other)
Boundry checking (crashes related to crossing boundry) Boundry checking (crashes related to crossing boundry)
Add check for border edge position for avatars and objects. Add check for border edge position for avatars and objects.
@ -28,10 +48,11 @@ Small physical objects do not interact correctly
Add material type linkage and input all the material property definitions. Add material type linkage and input all the material property definitions.
Skeleton classes and table are in the sources but are not filled or used. Skeleton classes and table are in the sources but are not filled or used.
Add PID motor for avatar movement (slow to stop, ...) Add PID motor for avatar movement (slow to stop, ...)
Implement function efficiency for lineaar and angular motion. setForce should set a constant force. Different than AddImpulse.
Implement raycast.
Implement ShapeCollection.Dispose()
Implement water as a plain so raycasting and collisions can happen with same.
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
Find/remove avatar collision with ID=0. Find/remove avatar collision with ID=0.
Test avatar walking up stairs. How does compare with SL. Test avatar walking up stairs. How does compare with SL.
Radius of the capsule affects ability to climb edges. Radius of the capsule affects ability to climb edges.
@ -39,19 +60,16 @@ Tune terrain/object friction to be closer to SL.
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.
Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
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
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 wheter 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
Implement meshes or just verify that they work.
Do prim hash codes work for sculpties and meshes?
Performance measurement and changes to make quicker. Performance measurement and changes to make quicker.
Implement detailed physics stats (GetStats()). Implement detailed physics stats (GetStats()).
@ -67,8 +85,6 @@ Performance of closures and delegates for taint processing
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
Package Bullet source mods for Bullet internal stats output
Physics Arena central pyramid: why is one side permiable? Physics Arena central pyramid: why is one side permiable?
INTERNAL IMPROVEMENT/CLEANUP INTERNAL IMPROVEMENT/CLEANUP
@ -85,33 +101,42 @@ Complete implemention of preStepActions
Replace vehicle step call with prestep event. Replace vehicle step call with prestep event.
Is there a need for postStepActions? postStepTaints? 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.
LinkablePrim class? Would that simplify/centralize the linkset logic? LinkablePrim class? Would that simplify/centralize the linkset logic?
Linkset implementation using manual prim movement.
Linkset implementation using compound shapes.
Compound shapes will need the LocalID in the shapes and collision
processing to get it from there.
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. Remove HeightmapInfo from terrain specification.
Since C++ code does not need terrain height, this structure et al are not needed. 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().
THREADING
=================================================
Do taint action immediately if not actually executing Bullet.
Add lock around Bullet execution and just do taint actions if simulation is not happening.
DONE DONE DONE DONE DONE DONE DONE DONE
================================================= =================================================
Cleanup code in BSDynamics by using motors. Cleanup code in BSDynamics by using motors. (Resolution: started)
Consider implementing terrain with a mesh rather than heightmap. Consider implementing terrain with a mesh rather than heightmap. (Resolution: done)
Would have better and adjustable resolution. Would have better and adjustable resolution.
NOTDONE: Build terrain mesh so heighmap is height of the center of the square meter. Build terrain mesh so heighmap is height of the center of the square meter.
SL and ODE define meter square as being at one corner with one diagional. Resolution: NOT DONE: SL and ODE define meter square as being at one corner with one diagional.
Terrain as mesh. Terrain as mesh. (Resolution: done)
How are static linksets seen by the physics engine? How are static linksets seen by the physics engine?
A: they are not linked in physics. When moved, all the children are repositioned. Resolution: they are not linked in physics. When moved, all the children are repositioned.
Remember to remove BSScene.DetailLog Refresh call. Convert BSCharacter to use all API2 (Resolution: done)
Convert BSCharacter to use all API2
Avatar pushing difficult (too heavy?) Avatar pushing difficult (too heavy?)
Use asset service passed to BulletSim to get sculptie bodies, etc. Use asset service passed to BulletSim to get sculptie bodies, etc. (Resolution: done)
Vehicles (fix bouncing on terrain) Remove old code in DLL (all non-API2 stuff). (Resolution: done)
Remove old code in DLL (all non-API2 stuff). Measurements of mega-physical prim performance (with graph) (Resolution: done, email)
Measurements of mega-physical prim performance (with graph)
Debug Bullet internal stats output (why is timing all wrong?) Debug Bullet internal stats output (why is timing all wrong?)
Bullet stats logging only works with a single instance of Bullet (one region). Resolution: Bullet stats logging only works with a single instance of Bullet (one region).
Implement meshes or just verify that they work. (Resolution: they do!)
Do prim hash codes work for sculpties and meshes? (Resolution: yes)
Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound)
Compound shapes will need the LocalID in the shapes and collision
processing to get it from there.
Light cycle falling over when driving (Resolution: implemented VerticalAttractor)
Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.)
Package Bullet source mods for Bullet internal stats output
(Resolution: move code into WorldData.h rather than relying on patches)

View File

@ -1,5 +1,5 @@
<configuration> <configuration>
<dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet-2.1.5.0-dotnet-1.dylib" /> <dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet.dylib" />
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-x86_64" /> <dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-x86_64" />
<dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet" /> <dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet" />
</configuration> </configuration>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.