Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
0c7d6adef1
|
@ -165,8 +165,8 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||||
|
|
||||||
// Do this after the object has been added to the world
|
// Do this after the object has been added to the world
|
||||||
BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr,
|
BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr,
|
||||||
(uint)CollisionFilterGroups.AvatarFilter,
|
(uint)CollisionFilterGroups.AvatarGroup,
|
||||||
(uint)CollisionFilterGroups.AvatarMask);
|
(uint)CollisionFilterGroups.AvatarMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using log4net;
|
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
@ -100,7 +98,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
|
private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
|
||||||
private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
|
private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
|
||||||
private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
|
private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
|
||||||
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
|
private Vector3 m_lastAngularCorrection = Vector3.Zero;
|
||||||
private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
|
private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
|
||||||
|
|
||||||
//Deflection properties
|
//Deflection properties
|
||||||
|
@ -113,6 +111,7 @@ 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;
|
||||||
|
@ -127,7 +126,7 @@ 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 = 500f; // Timescale > 300 means no vert attractor.
|
private float m_verticalAttractionTimescale = 600f; // Timescale > 500 means no vert attractor.
|
||||||
|
|
||||||
public BSDynamics(BSScene myScene, BSPrim myPrim)
|
public BSDynamics(BSScene myScene, BSPrim myPrim)
|
||||||
{
|
{
|
||||||
|
@ -154,7 +153,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
|
m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
|
||||||
break;
|
break;
|
||||||
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
|
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
|
||||||
m_angularMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120));
|
m_angularMotorDecayTimescale = ClampInRange(0.01f, pValue, 120);
|
||||||
m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale;
|
m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale;
|
||||||
break;
|
break;
|
||||||
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
|
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
|
||||||
|
@ -162,7 +161,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_angularMotor.TimeScale = m_angularMotorTimescale;
|
m_angularMotor.TimeScale = m_angularMotorTimescale;
|
||||||
break;
|
break;
|
||||||
case Vehicle.BANKING_EFFICIENCY:
|
case Vehicle.BANKING_EFFICIENCY:
|
||||||
m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f));
|
m_bankingEfficiency = ClampInRange(-1f, pValue, 1f);
|
||||||
break;
|
break;
|
||||||
case Vehicle.BANKING_MIX:
|
case Vehicle.BANKING_MIX:
|
||||||
m_bankingMix = Math.Max(pValue, 0.01f);
|
m_bankingMix = Math.Max(pValue, 0.01f);
|
||||||
|
@ -171,10 +170,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_bankingTimescale = Math.Max(pValue, 0.01f);
|
m_bankingTimescale = Math.Max(pValue, 0.01f);
|
||||||
break;
|
break;
|
||||||
case Vehicle.BUOYANCY:
|
case Vehicle.BUOYANCY:
|
||||||
m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f));
|
m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
|
||||||
break;
|
break;
|
||||||
case Vehicle.HOVER_EFFICIENCY:
|
case Vehicle.HOVER_EFFICIENCY:
|
||||||
m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f));
|
m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
|
||||||
break;
|
break;
|
||||||
case Vehicle.HOVER_HEIGHT:
|
case Vehicle.HOVER_HEIGHT:
|
||||||
m_VhoverHeight = pValue;
|
m_VhoverHeight = pValue;
|
||||||
|
@ -189,7 +188,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
|
m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
|
||||||
break;
|
break;
|
||||||
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
|
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
|
||||||
m_linearMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120));
|
m_linearMotorDecayTimescale = ClampInRange(0.01f, pValue, 120);
|
||||||
m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale;
|
m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale;
|
||||||
break;
|
break;
|
||||||
case Vehicle.LINEAR_MOTOR_TIMESCALE:
|
case Vehicle.LINEAR_MOTOR_TIMESCALE:
|
||||||
|
@ -197,7 +196,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_linearMotor.TimeScale = m_linearMotorTimescale;
|
m_linearMotor.TimeScale = m_linearMotorTimescale;
|
||||||
break;
|
break;
|
||||||
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
|
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
|
||||||
m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f));
|
m_verticalAttractionEfficiency = ClampInRange(0.1f, pValue, 1f);
|
||||||
m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency;
|
m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency;
|
||||||
break;
|
break;
|
||||||
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
|
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
|
||||||
|
@ -242,9 +241,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
break;
|
break;
|
||||||
case Vehicle.ANGULAR_MOTOR_DIRECTION:
|
case Vehicle.ANGULAR_MOTOR_DIRECTION:
|
||||||
// Limit requested angular speed to 2 rps= 4 pi rads/sec
|
// Limit requested angular speed to 2 rps= 4 pi rads/sec
|
||||||
pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f));
|
pValue.X = ClampInRange(-12.56f, pValue.X, 12.56f);
|
||||||
pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f));
|
pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f);
|
||||||
pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f));
|
pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f);
|
||||||
m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
||||||
m_angularMotor.SetTarget(m_angularMotorDirection);
|
m_angularMotor.SetTarget(m_angularMotorDirection);
|
||||||
break;
|
break;
|
||||||
|
@ -330,6 +329,7 @@ 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,6 +364,7 @@ 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
|
||||||
|
@ -402,6 +403,7 @@ 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
|
||||||
|
@ -440,14 +442,15 @@ 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
|
||||||
| VehicleFlag.HOVER_GLOBAL_HEIGHT
|
| VehicleFlag.HOVER_GLOBAL_HEIGHT
|
||||||
| VehicleFlag.LIMIT_ROLL_ONLY
|
| VehicleFlag.LIMIT_ROLL_ONLY
|
||||||
| VehicleFlag.LIMIT_MOTOR_UP
|
|
||||||
| VehicleFlag.HOVER_UP_ONLY);
|
| VehicleFlag.HOVER_UP_ONLY);
|
||||||
m_flags |= (VehicleFlag.NO_DEFLECTION_UP
|
m_flags |= (VehicleFlag.NO_DEFLECTION_UP
|
||||||
|
| VehicleFlag.LIMIT_MOTOR_UP
|
||||||
| VehicleFlag.HOVER_WATER_ONLY);
|
| VehicleFlag.HOVER_WATER_ONLY);
|
||||||
break;
|
break;
|
||||||
case Vehicle.TYPE_AIRPLANE:
|
case Vehicle.TYPE_AIRPLANE:
|
||||||
|
@ -478,6 +481,7 @@ 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
|
||||||
|
@ -516,6 +520,8 @@ 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;
|
||||||
|
|
||||||
m_referenceFrame = Quaternion.Identity;
|
m_referenceFrame = Quaternion.Identity;
|
||||||
|
@ -558,9 +564,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
if (IsActive)
|
if (IsActive)
|
||||||
{
|
{
|
||||||
|
// Remember the mass so we don't have to fetch it every step
|
||||||
m_vehicleMass = Prim.Linkset.LinksetMass;
|
m_vehicleMass = Prim.Linkset.LinksetMass;
|
||||||
|
|
||||||
// Friction effects are handled by this vehicle code
|
// Friction affects are handled by this vehicle code
|
||||||
float friction = 0f;
|
float friction = 0f;
|
||||||
BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction);
|
BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction);
|
||||||
|
|
||||||
|
@ -574,6 +581,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// 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);
|
||||||
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
|
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
|
||||||
|
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);
|
||||||
|
@ -598,31 +606,167 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Known vehicle value functions
|
||||||
|
// Vehicle physical parameters that we buffer from constant getting and setting.
|
||||||
|
// The "m_known*" variables are initialized to 'null', fetched only if referenced
|
||||||
|
// and stored back into the physics engine only if updated.
|
||||||
|
// This does two things: 1) saves continuious calls into unmanaged code, and
|
||||||
|
// 2) signals when a physics property update must happen back to the simulator
|
||||||
|
// to update values modified for the vehicle.
|
||||||
|
private int m_knownChanged;
|
||||||
|
private float? m_knownTerrainHeight;
|
||||||
|
private float? m_knownWaterLevel;
|
||||||
|
private Vector3? m_knownPosition;
|
||||||
|
private Vector3? m_knownVelocity;
|
||||||
|
private Quaternion? m_knownOrientation;
|
||||||
|
private Vector3? m_knownRotationalVelocity;
|
||||||
|
|
||||||
|
private const int m_knownChangedPosition = 1 << 0;
|
||||||
|
private const int m_knownChangedVelocity = 1 << 1;
|
||||||
|
private const int m_knownChangedOrientation = 1 << 2;
|
||||||
|
private const int m_knownChangedRotationalVelocity = 1 << 3;
|
||||||
|
|
||||||
|
private void ForgetKnownVehicleProperties()
|
||||||
|
{
|
||||||
|
m_knownTerrainHeight = null;
|
||||||
|
m_knownWaterLevel = null;
|
||||||
|
m_knownPosition = null;
|
||||||
|
m_knownVelocity = null;
|
||||||
|
m_knownOrientation = null;
|
||||||
|
m_knownRotationalVelocity = null;
|
||||||
|
m_knownChanged = 0;
|
||||||
|
}
|
||||||
|
private void PushKnownChanged()
|
||||||
|
{
|
||||||
|
if (m_knownChanged != 0)
|
||||||
|
{
|
||||||
|
if ((m_knownChanged & m_knownChangedPosition) != 0)
|
||||||
|
Prim.ForcePosition = VehiclePosition;
|
||||||
|
if ((m_knownChanged & m_knownChangedOrientation) != 0)
|
||||||
|
Prim.ForceOrientation = VehicleOrientation;
|
||||||
|
if ((m_knownChanged & m_knownChangedVelocity) != 0)
|
||||||
|
Prim.ForceVelocity = VehicleVelocity;
|
||||||
|
if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
|
||||||
|
{
|
||||||
|
Prim.ForceRotationalVelocity = VehicleRotationalVelocity;
|
||||||
|
BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity);
|
||||||
|
}
|
||||||
|
// 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.
|
||||||
|
BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the computation of terrain height can be a little involved, this routine
|
||||||
|
// is used ot fetch the height only once for each vehicle simulation step.
|
||||||
|
private float GetTerrainHeight(Vector3 pos)
|
||||||
|
{
|
||||||
|
if (m_knownTerrainHeight == null)
|
||||||
|
m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
||||||
|
return (float)m_knownTerrainHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the computation of water level can be a little involved, this routine
|
||||||
|
// is used ot fetch the level only once for each vehicle simulation step.
|
||||||
|
private float GetWaterLevel(Vector3 pos)
|
||||||
|
{
|
||||||
|
if (m_knownWaterLevel == null)
|
||||||
|
m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos);
|
||||||
|
return (float)m_knownWaterLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector3 VehiclePosition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_knownPosition == null)
|
||||||
|
m_knownPosition = Prim.ForcePosition;
|
||||||
|
return (Vector3)m_knownPosition;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_knownPosition = value;
|
||||||
|
m_knownChanged |= m_knownChangedPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Quaternion VehicleOrientation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_knownOrientation == null)
|
||||||
|
m_knownOrientation = Prim.ForceOrientation;
|
||||||
|
return (Quaternion)m_knownOrientation;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_knownOrientation = value;
|
||||||
|
m_knownChanged |= m_knownChangedOrientation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector3 VehicleVelocity
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_knownVelocity == null)
|
||||||
|
m_knownVelocity = Prim.ForceVelocity;
|
||||||
|
return (Vector3)m_knownVelocity;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_knownVelocity = value;
|
||||||
|
m_knownChanged |= m_knownChangedVelocity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector3 VehicleRotationalVelocity
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_knownRotationalVelocity == null)
|
||||||
|
m_knownRotationalVelocity = Prim.ForceRotationalVelocity;
|
||||||
|
return (Vector3)m_knownRotationalVelocity;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_knownRotationalVelocity = value;
|
||||||
|
m_knownChanged |= m_knownChangedRotationalVelocity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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.
|
||||||
internal void Step(float pTimestep)
|
internal void Step(float pTimestep)
|
||||||
{
|
{
|
||||||
if (!IsActive) return;
|
if (!IsActive) return;
|
||||||
|
|
||||||
|
ForgetKnownVehicleProperties();
|
||||||
|
|
||||||
MoveLinear(pTimestep);
|
MoveLinear(pTimestep);
|
||||||
MoveAngular(pTimestep);
|
MoveAngular(pTimestep);
|
||||||
|
|
||||||
LimitRotation(pTimestep);
|
LimitRotation(pTimestep);
|
||||||
|
|
||||||
// remember the position so next step we can limit absolute movement effects
|
// remember the position so next step we can limit absolute movement effects
|
||||||
m_lastPositionVector = Prim.ForcePosition;
|
m_lastPositionVector = VehiclePosition;
|
||||||
|
|
||||||
|
// If we forced the changing of some vehicle parameters, update the values and
|
||||||
|
// for the physics engine to note the changes so an UpdateProperties event will happen.
|
||||||
|
PushKnownChanged();
|
||||||
|
|
||||||
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
|
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
|
||||||
Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
|
Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the effect of the linear motor.
|
// Apply the effect of the linear motor and other linear motions (like hover and float).
|
||||||
// Also does hover and float.
|
|
||||||
private void MoveLinear(float pTimestep)
|
private void MoveLinear(float pTimestep)
|
||||||
{
|
{
|
||||||
Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep);
|
Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep);
|
||||||
|
|
||||||
// Rotate new object velocity from vehicle relative to world coordinates
|
// The movement computed in the linear motor is relative to the vehicle
|
||||||
linearMotorContribution *= Prim.ForceOrientation;
|
// coordinates. Rotate the movement to world coordinates.
|
||||||
|
linearMotorContribution *= VehicleOrientation;
|
||||||
|
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
// Gravity and Buoyancy
|
// Gravity and Buoyancy
|
||||||
|
@ -630,16 +774,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
|
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
|
||||||
Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy);
|
Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy);
|
||||||
|
|
||||||
Vector3 pos = Prim.ForcePosition;
|
Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
|
||||||
float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
|
||||||
|
|
||||||
Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep, ref pos, terrainHeight);
|
Vector3 hoverContribution = ComputeLinearHover(pTimestep);
|
||||||
|
|
||||||
Vector3 hoverContribution = ComputeLinearHover(pTimestep, ref pos, terrainHeight);
|
ComputeLinearBlockingEndPoint(pTimestep);
|
||||||
|
|
||||||
ComputeLinearBlockingEndPoint(pTimestep, ref pos);
|
Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep);
|
||||||
|
|
||||||
Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep, pos, terrainHeight);
|
|
||||||
|
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
Vector3 newVelocity = linearMotorContribution
|
Vector3 newVelocity = linearMotorContribution
|
||||||
|
@ -667,42 +808,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
newVelocity = Vector3.Zero;
|
newVelocity = Vector3.Zero;
|
||||||
|
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
// Stuff new linear velocity into the vehicle
|
// Stuff new linear velocity into the vehicle.
|
||||||
Prim.ForceVelocity = newVelocity;
|
// Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us.
|
||||||
// Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG
|
VehicleVelocity = newVelocity;
|
||||||
|
|
||||||
// Other linear forces are applied as forces.
|
// Other linear forces are applied as forces.
|
||||||
Vector3 totalDownForce = grav * m_vehicleMass;
|
Vector3 totalDownForce = grav * m_vehicleMass * pTimestep;
|
||||||
if (totalDownForce != Vector3.Zero)
|
if (totalDownForce != Vector3.Zero)
|
||||||
{
|
{
|
||||||
Prim.AddForce(totalDownForce, false);
|
Prim.AddForce(totalDownForce, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}",
|
VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},linContrib={3},terrContrib={4},hoverContrib={5},limitContrib={6}",
|
||||||
Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector,
|
Prim.LocalID, newVelocity, totalDownForce,
|
||||||
newVelocity, Prim.Velocity, totalDownForce);
|
linearMotorContribution, terrainHeightContribution, hoverContribution, limitMotorUpContribution
|
||||||
|
);
|
||||||
|
|
||||||
} // end MoveLinear()
|
} // end MoveLinear()
|
||||||
|
|
||||||
public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep, ref Vector3 pos, float terrainHeight)
|
public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep)
|
||||||
{
|
{
|
||||||
Vector3 ret = Vector3.Zero;
|
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.
|
||||||
// Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
|
// TODO: Consider taking the rotated size of the object or possibly casting a ray.
|
||||||
// TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
|
if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
|
||||||
// Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
|
|
||||||
// if (rotatedSize.Z < terrainHeight)
|
|
||||||
if (pos.Z < terrainHeight)
|
|
||||||
{
|
{
|
||||||
// TODO: correct position by applying force rather than forcing position.
|
// TODO: correct position by applying force rather than forcing position.
|
||||||
pos.Z = terrainHeight + 2;
|
VehiclePosition += new Vector3(0f, 0f, GetTerrainHeight(VehiclePosition) + 2f);
|
||||||
Prim.ForcePosition = pos;
|
VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
|
||||||
VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 ComputeLinearHover(float pTimestep, ref Vector3 pos, float terrainHeight)
|
public Vector3 ComputeLinearHover(float pTimestep)
|
||||||
{
|
{
|
||||||
Vector3 ret = Vector3.Zero;
|
Vector3 ret = Vector3.Zero;
|
||||||
|
|
||||||
|
@ -713,11 +851,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// We should hover, get the target height
|
// We should hover, get the target height
|
||||||
if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
|
if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
|
||||||
{
|
{
|
||||||
m_VhoverTargetHeight = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos) + m_VhoverHeight;
|
m_VhoverTargetHeight = GetWaterLevel(VehiclePosition) + m_VhoverHeight;
|
||||||
}
|
}
|
||||||
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
||||||
{
|
{
|
||||||
m_VhoverTargetHeight = terrainHeight + m_VhoverHeight;
|
m_VhoverTargetHeight = GetTerrainHeight(VehiclePosition) + m_VhoverHeight;
|
||||||
}
|
}
|
||||||
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
||||||
{
|
{
|
||||||
|
@ -727,46 +865,44 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
|
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
|
||||||
{
|
{
|
||||||
// If body is already heigher, use its height as target height
|
// If body is already heigher, use its height as target height
|
||||||
if (pos.Z > m_VhoverTargetHeight)
|
if (VehiclePosition.Z > m_VhoverTargetHeight)
|
||||||
m_VhoverTargetHeight = pos.Z;
|
m_VhoverTargetHeight = VehiclePosition.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
|
if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
|
||||||
{
|
{
|
||||||
if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f)
|
if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
|
||||||
{
|
{
|
||||||
|
Vector3 pos = VehiclePosition;
|
||||||
pos.Z = m_VhoverTargetHeight;
|
pos.Z = m_VhoverTargetHeight;
|
||||||
Prim.ForcePosition = pos;
|
VehiclePosition = pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float verticalError = pos.Z - m_VhoverTargetHeight;
|
// Error is positive if below the target and negative if above.
|
||||||
// RA: where does the 50 come from?
|
float verticalError = m_VhoverTargetHeight - VehiclePosition.Z;
|
||||||
float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale);
|
float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
|
||||||
// Replace Vertical speed with correction figure if significant
|
|
||||||
if (verticalError > 0.01f)
|
// TODO: implement m_VhoverEfficiency correctly
|
||||||
|
if (Math.Abs(verticalError) > m_VhoverEfficiency)
|
||||||
{
|
{
|
||||||
ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
|
ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
|
||||||
//KF: m_VhoverEfficiency is not yet implemented
|
|
||||||
}
|
|
||||||
else if (verticalError < -0.01)
|
|
||||||
{
|
|
||||||
ret = new Vector3(0f, 0f, -verticalCorrectionVelocity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}",
|
VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}",
|
||||||
Prim.LocalID, pos, ret, m_VhoverHeight, m_VhoverTargetHeight);
|
Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ComputeLinearBlockingEndPoint(float pTimestep, ref Vector3 pos)
|
public bool ComputeLinearBlockingEndPoint(float pTimestep)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
Vector3 pos = VehiclePosition;
|
||||||
Vector3 posChange = pos - m_lastPositionVector;
|
Vector3 posChange = pos - m_lastPositionVector;
|
||||||
if (m_BlockingEndPoint != Vector3.Zero)
|
if (m_BlockingEndPoint != Vector3.Zero)
|
||||||
{
|
{
|
||||||
|
@ -797,8 +933,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
Prim.ForcePosition = pos;
|
VehiclePosition = pos;
|
||||||
VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
|
VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
|
||||||
Prim.LocalID, m_BlockingEndPoint, posChange, pos);
|
Prim.LocalID, m_BlockingEndPoint, posChange, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -812,13 +948,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// 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?
|
||||||
public Vector3 ComputeLinearMotorUp(float pTimestep, Vector3 pos, float terrainHeight)
|
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 - terrainHeight;
|
// float distanceAboveGround = pos.Z - Math.Max(GetTerrainHeight(pos), GetWaterLevel(pos));
|
||||||
|
float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
|
||||||
if (distanceAboveGround > 1f)
|
if (distanceAboveGround > 1f)
|
||||||
{
|
{
|
||||||
// downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
|
// downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
|
||||||
|
@ -830,7 +967,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// 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},downForce={2}",
|
VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
|
||||||
Prim.LocalID, distanceAboveGround, ret);
|
Prim.LocalID, distanceAboveGround, ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -839,36 +976,12 @@ 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.
|
||||||
|
// All the contributions are added together and the orientation of the vehicle
|
||||||
|
// is changed by all the contributed corrections.
|
||||||
private void MoveAngular(float pTimestep)
|
private void MoveAngular(float pTimestep)
|
||||||
{
|
{
|
||||||
// m_angularMotorDirection // angular velocity requested by LSL motor
|
// The user wants how many radians per second angular change?
|
||||||
// m_angularMotorVelocity // current angular motor velocity (ramps up and down)
|
|
||||||
// m_angularMotorTimescale // motor angular velocity ramp up time
|
|
||||||
// m_angularMotorDecayTimescale // motor angular velocity decay rate
|
|
||||||
// m_angularFrictionTimescale // body angular velocity decay rate
|
|
||||||
// m_lastAngularVelocity // what was last applied to body
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (m_angularMotorDirection.LengthSquared() > 0.0001)
|
|
||||||
{
|
|
||||||
Vector3 origVel = m_angularMotorVelocity;
|
|
||||||
Vector3 origDir = m_angularMotorDirection;
|
|
||||||
|
|
||||||
// new velocity += error / ( time to get there / step interval)
|
|
||||||
// requested direction - current vehicle direction
|
|
||||||
m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep);
|
|
||||||
// decay requested direction
|
|
||||||
m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale));
|
|
||||||
|
|
||||||
VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}",
|
|
||||||
Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_angularMotorVelocity = Vector3.Zero;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
|
Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
|
||||||
|
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
|
@ -881,24 +994,46 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
angularMotorContribution.X = 0f;
|
angularMotorContribution.X = 0f;
|
||||||
angularMotorContribution.Y = 0f;
|
angularMotorContribution.Y = 0f;
|
||||||
VDetailLog("{0},MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
|
VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(pTimestep);
|
Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction();
|
||||||
|
|
||||||
Vector3 deflectionContribution = ComputeAngularDeflection(pTimestep);
|
Vector3 deflectionContribution = ComputeAngularDeflection();
|
||||||
|
|
||||||
Vector3 bankingContribution = ComputeAngularBanking(pTimestep);
|
Vector3 bankingContribution = ComputeAngularBanking(angularMotorContribution.Z);
|
||||||
|
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
m_lastVertAttractor = verticalAttractionContribution;
|
m_lastVertAttractor = verticalAttractionContribution;
|
||||||
|
|
||||||
// Sum velocities
|
// Sum corrections
|
||||||
m_lastAngularVelocity = angularMotorContribution
|
m_lastAngularCorrection = angularMotorContribution
|
||||||
+ verticalAttractionContribution
|
+ verticalAttractionContribution
|
||||||
+ deflectionContribution
|
+ deflectionContribution
|
||||||
+ bankingContribution;
|
+ bankingContribution;
|
||||||
|
|
||||||
|
// ==================================================================
|
||||||
|
// The correction is applied to the current orientation.
|
||||||
|
if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f))
|
||||||
|
{
|
||||||
|
Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep;
|
||||||
|
|
||||||
|
VehicleRotationalVelocity = scaledCorrection;
|
||||||
|
|
||||||
|
VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}",
|
||||||
|
Prim.LocalID,
|
||||||
|
angularMotorContribution, verticalAttractionContribution,
|
||||||
|
bankingContribution, deflectionContribution,
|
||||||
|
m_lastAngularCorrection, scaledCorrection
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The vehicle is not adding anything velocity wise.
|
||||||
|
VehicleRotationalVelocity = Vector3.Zero;
|
||||||
|
VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID);
|
||||||
|
}
|
||||||
|
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
//Offset section
|
//Offset section
|
||||||
if (m_linearMotorOffset != Vector3.Zero)
|
if (m_linearMotorOffset != Vector3.Zero)
|
||||||
|
@ -927,53 +1062,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
torqueFromOffset.Z = 0;
|
torqueFromOffset.Z = 0;
|
||||||
torqueFromOffset *= m_vehicleMass;
|
torqueFromOffset *= m_vehicleMass;
|
||||||
Prim.ApplyTorqueImpulse(torqueFromOffset, true);
|
Prim.ApplyTorqueImpulse(torqueFromOffset, true);
|
||||||
VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
|
VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================================================================
|
|
||||||
if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
|
|
||||||
{
|
|
||||||
m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
|
|
||||||
// TODO: zeroing is good but it also sets values in unmanaged code. Remove the stores when idle.
|
|
||||||
VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
|
|
||||||
Prim.ZeroAngularMotion(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Apply to the body.
|
|
||||||
// The above calculates the absolute angular velocity needed. Angular velocity is massless.
|
|
||||||
// Since we are stuffing the angular velocity directly into the object, the computed
|
|
||||||
// velocity needs to be scaled by the timestep.
|
|
||||||
// Also remove any motion that is on the object so added motion is only from vehicle.
|
|
||||||
Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep)
|
|
||||||
- Prim.ForceRotationalVelocity);
|
|
||||||
// Unscale the force by the angular factor so it overwhelmes the Bullet additions.
|
|
||||||
Prim.ForceRotationalVelocity = applyAngularForce;
|
|
||||||
|
|
||||||
VDetailLog("{0},MoveAngular,done,angMotor={1},vertAttr={2},bank={3},deflect={4},newAngForce={5},lastAngular={6}",
|
|
||||||
Prim.LocalID,
|
|
||||||
angularMotorContribution, verticalAttractionContribution,
|
|
||||||
bankingContribution, deflectionContribution,
|
|
||||||
applyAngularForce, m_lastAngularVelocity
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 ComputeAngularVerticalAttraction(float pTimestep)
|
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 < 500)
|
||||||
{
|
{
|
||||||
Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
|
|
||||||
verticalError.Normalize();
|
|
||||||
m_verticalAttractionMotor.SetCurrent(verticalError);
|
|
||||||
m_verticalAttractionMotor.SetTarget(Vector3.UnitZ);
|
|
||||||
ret = m_verticalAttractionMotor.Step(pTimestep);
|
|
||||||
/*
|
|
||||||
// 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 * Prim.ForceOrientation;
|
Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
|
||||||
verticalError.Normalize();
|
verticalError.Normalize();
|
||||||
|
|
||||||
// If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
|
// If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
|
||||||
|
@ -991,63 +1093,70 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Y error means needed rotation around X axis and visa versa.
|
// Y error means needed rotation around X axis and visa versa.
|
||||||
verticalAttractionContribution.X = verticalError.Y;
|
ret.X = verticalError.Y;
|
||||||
verticalAttractionContribution.Y = - verticalError.X;
|
ret.Y = - verticalError.X;
|
||||||
verticalAttractionContribution.Z = 0f;
|
ret.Z = 0f;
|
||||||
|
|
||||||
// scale by the time scale and timestep
|
// scale by the time scale and timestep
|
||||||
Vector3 unscaledContrib = verticalAttractionContribution;
|
Vector3 unscaledContrib = ret;
|
||||||
verticalAttractionContribution /= m_verticalAttractionTimescale;
|
ret /= m_verticalAttractionTimescale;
|
||||||
verticalAttractionContribution *= pTimestep;
|
// This returns the angular correction desired. Timestep is added later.
|
||||||
|
// ret *= pTimestep;
|
||||||
|
|
||||||
// apply efficiency
|
// apply efficiency
|
||||||
Vector3 preEfficiencyContrib = verticalAttractionContribution;
|
Vector3 preEfficiencyContrib = ret;
|
||||||
|
// TODO: implement efficiency.
|
||||||
|
// Effenciency squared seems to give a more realistic effect
|
||||||
float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
|
float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
|
||||||
verticalAttractionContribution *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
|
// ret *= efficencySquared;
|
||||||
|
|
||||||
VDetailLog("{0},MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}",
|
VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}",
|
||||||
Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
|
Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
|
||||||
m_verticalAttractionEfficiency, efficencySquared,
|
m_verticalAttractionEfficiency, efficencySquared,
|
||||||
verticalAttractionContribution);
|
ret);
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 ComputeAngularDeflection(float pTimestep)
|
// Return the angular correction to correct the direction the vehicle is pointing to be
|
||||||
|
// the direction is should want to be pointing.
|
||||||
|
public Vector3 ComputeAngularDeflection()
|
||||||
{
|
{
|
||||||
Vector3 ret = Vector3.Zero;
|
Vector3 ret = Vector3.Zero;
|
||||||
|
|
||||||
if (m_angularDeflectionEfficiency != 0)
|
if (m_angularDeflectionEfficiency != 0)
|
||||||
{
|
{
|
||||||
// Compute a scaled vector that points in the preferred axis (X direction)
|
// Where the vehicle should want to point relative to the vehicle
|
||||||
Vector3 scaledDefaultDirection =
|
Vector3 preferredDirection = Vector3.UnitX * m_referenceFrame;
|
||||||
new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0);
|
|
||||||
// Adding the current vehicle orientation and reference frame displaces the orientation to the frame.
|
|
||||||
// Rotate the scaled default axix relative to the actual vehicle direction giving where it should point.
|
|
||||||
Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
|
|
||||||
|
|
||||||
// Scale by efficiency and timescale
|
// Where the vehicle is pointing relative to the vehicle.
|
||||||
ret = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep;
|
Vector3 currentDirection = Vector3.UnitX * Quaternion.Add(VehicleOrientation, m_referenceFrame);
|
||||||
|
|
||||||
VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", Prim.LocalID, preferredAxisOfMotion, ret);
|
// Difference between where vehicle is pointing and where it should wish to point
|
||||||
|
Vector3 directionCorrection = preferredDirection - currentDirection;
|
||||||
|
|
||||||
// This deflection computation is not correct.
|
// Scale the correction by recovery timescale and efficiency
|
||||||
ret = Vector3.Zero;
|
ret = directionCorrection * m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
|
||||||
|
|
||||||
|
VDetailLog("{0}, MoveAngular,Deflection,perfDir={1},currentDir={2},dirCorrection={3},ret={4}",
|
||||||
|
Prim.LocalID, preferredDirection, currentDirection, directionCorrection, ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 ComputeAngularBanking(float pTimestep)
|
// Return an angular change to tip the vehicle (around X axis) when turning (turned around Z).
|
||||||
|
// Remembers the last banking value calculated and returns the difference needed this tick.
|
||||||
|
// TurningFactor is rate going left or right (pos=left, neg=right, scale=0..1).
|
||||||
|
public Vector3 ComputeAngularBanking(float turningFactor)
|
||||||
{
|
{
|
||||||
Vector3 ret = Vector3.Zero;
|
Vector3 ret = Vector3.Zero;
|
||||||
|
Vector3 computedBanking = Vector3.Zero;
|
||||||
|
|
||||||
if (m_bankingEfficiency != 0)
|
if (m_bankingEfficiency != 0)
|
||||||
{
|
{
|
||||||
Vector3 dir = Vector3.One * Prim.ForceOrientation;
|
Vector3 currentDirection = Vector3.UnitX * VehicleOrientation;
|
||||||
|
|
||||||
float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1);
|
float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1);
|
||||||
//Changes which way it banks in and out of turns
|
|
||||||
|
|
||||||
//Use the square of the efficiency, as it looks much more how SL banking works
|
//Use the square of the efficiency, as it looks much more how SL banking works
|
||||||
float effSquared = (m_bankingEfficiency * m_bankingEfficiency);
|
float effSquared = (m_bankingEfficiency * m_bankingEfficiency);
|
||||||
|
@ -1055,58 +1164,34 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
effSquared *= -1; //Keep the negative!
|
effSquared *= -1; //Keep the negative!
|
||||||
|
|
||||||
float mix = Math.Abs(m_bankingMix);
|
float mix = Math.Abs(m_bankingMix);
|
||||||
if (m_angularMotorVelocity.X == 0)
|
// TODO: Must include reference frame.
|
||||||
|
float forwardSpeed = VehicleVelocity.X;
|
||||||
|
|
||||||
|
if (!Prim.IsColliding && forwardSpeed > mix)
|
||||||
{
|
{
|
||||||
// The vehicle is stopped
|
computedBanking.X = ClampInRange(-3f, turningFactor * (effSquared * mult), 3f);
|
||||||
/*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f))
|
|
||||||
{
|
|
||||||
Vector3 axisAngle;
|
|
||||||
float angle;
|
|
||||||
parent.Orientation.GetAxisAngle(out axisAngle, out angle);
|
|
||||||
Vector3 rotatedVel = parent.Velocity * parent.Orientation;
|
|
||||||
if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0))
|
|
||||||
m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10;
|
|
||||||
else
|
|
||||||
m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret.Z += (effSquared * (mult * mix)) * (m_angularMotorVelocity.X) * 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//If they are colliding, we probably shouldn't shove the prim around... probably
|
// 'computedBanking' is now how much banking that should be happening.
|
||||||
if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
|
ret = computedBanking - m_lastBanking;
|
||||||
{
|
|
||||||
float angVelZ = m_angularMotorVelocity.X * -1;
|
// Scale the correction by timescale and efficiency
|
||||||
/*if(angVelZ > mix)
|
ret /= m_bankingTimescale * m_bankingEfficiency;
|
||||||
angVelZ = mix;
|
|
||||||
else if(angVelZ < -mix)
|
VDetailLog("{0}, MoveAngular,Banking,computedB={1},lastB={2},bEff={3},effSq={4},mult={5},mix={6},banking={7}",
|
||||||
angVelZ = -mix;*/
|
Prim.LocalID, computedBanking, m_lastBanking, m_bankingEfficiency, effSquared, mult, mix, ret);
|
||||||
//This controls how fast and how far the banking occurs
|
|
||||||
Vector3 bankingRot = new Vector3(angVelZ * (effSquared * mult), 0, 0);
|
|
||||||
if (bankingRot.X > 3)
|
|
||||||
bankingRot.X = 3;
|
|
||||||
else if (bankingRot.X < -3)
|
|
||||||
bankingRot.X = -3;
|
|
||||||
bankingRot *= Prim.ForceOrientation;
|
|
||||||
ret += bankingRot;
|
|
||||||
}
|
|
||||||
m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency;
|
|
||||||
VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},effSq={3},mult={4},mix={5},banking={6}",
|
|
||||||
Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, effSquared, mult, mix, ret);
|
|
||||||
}
|
}
|
||||||
|
m_lastBanking = computedBanking;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This is from previous instantiations of XXXDynamics.cs.
|
// This is from previous instantiations of XXXDynamics.cs.
|
||||||
// Applies roll reference frame.
|
// Applies roll reference frame.
|
||||||
// TODO: is this the right way to separate the code to do this operation?
|
// TODO: is this the right way to separate the code to do this operation?
|
||||||
// Should this be in MoveAngular()?
|
// Should this be in MoveAngular()?
|
||||||
internal void LimitRotation(float timestep)
|
internal void LimitRotation(float timestep)
|
||||||
{
|
{
|
||||||
Quaternion rotq = Prim.ForceOrientation;
|
Quaternion rotq = VehicleOrientation;
|
||||||
Quaternion m_rot = rotq;
|
Quaternion m_rot = rotq;
|
||||||
if (m_RollreferenceFrame != Quaternion.Identity)
|
if (m_RollreferenceFrame != Quaternion.Identity)
|
||||||
{
|
{
|
||||||
|
@ -1134,12 +1219,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
if (rotq != m_rot)
|
if (rotq != m_rot)
|
||||||
{
|
{
|
||||||
Prim.ForceOrientation = m_rot;
|
VehicleOrientation = m_rot;
|
||||||
VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
|
VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float ClampInRange(float low, float val, float high)
|
||||||
|
{
|
||||||
|
return Math.Max(low, Math.Min(val, high));
|
||||||
|
}
|
||||||
|
|
||||||
// Invoke the detailed logger and output something if it's enabled.
|
// Invoke the detailed logger and output something if it's enabled.
|
||||||
private void VDetailLog(string msg, params Object[] args)
|
private void VDetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -8,7 +35,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
public abstract class BSMotor
|
public abstract class BSMotor
|
||||||
{
|
{
|
||||||
// Timescales and other things can be turned off by setting them to 'infinite'.
|
// Timescales and other things can be turned off by setting them to 'infinite'.
|
||||||
public const float Infinite = 10000f;
|
public const float Infinite = 12345f;
|
||||||
public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
|
public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
|
||||||
|
|
||||||
public BSMotor(string useName)
|
public BSMotor(string useName)
|
||||||
|
@ -19,7 +46,9 @@ public abstract class BSMotor
|
||||||
public virtual void Reset() { }
|
public virtual void Reset() { }
|
||||||
public virtual void Zero() { }
|
public virtual void Zero() { }
|
||||||
|
|
||||||
|
// A name passed at motor creation for easily identifyable debugging messages.
|
||||||
public string UseName { get; private set; }
|
public string UseName { get; private set; }
|
||||||
|
|
||||||
// Used only for outputting debug information. Might not be set so check for null.
|
// Used only for outputting debug information. Might not be set so check for null.
|
||||||
public BSScene PhysicsScene { get; set; }
|
public BSScene PhysicsScene { get; set; }
|
||||||
protected void MDetailLog(string msg, params Object[] parms)
|
protected void MDetailLog(string msg, params Object[] parms)
|
||||||
|
@ -34,10 +63,23 @@ public abstract class BSMotor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Can all the incremental stepping be replaced with motor classes?
|
// Can all the incremental stepping be replaced with motor classes?
|
||||||
|
|
||||||
|
// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
|
||||||
|
// The TargetValue is decays in TargetValueDecayTimeScale and
|
||||||
|
// the CurrentValue will be held back by FrictionTimeScale.
|
||||||
|
// TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay.
|
||||||
|
|
||||||
|
// For instance, if something is moving at speed X and the desired speed is Y,
|
||||||
|
// CurrentValue is X and TargetValue is Y. As the motor is stepped, new
|
||||||
|
// values of CurrentValue are returned that approach the TargetValue.
|
||||||
|
// The feature of decaying TargetValue is so vehicles will eventually
|
||||||
|
// come to a stop rather than run forever. This can be disabled by
|
||||||
|
// setting TargetValueDecayTimescale to 'infinite'.
|
||||||
|
// The change from CurrentValue to TargetValue is linear over TimeScale seconds.
|
||||||
public class BSVMotor : BSMotor
|
public class BSVMotor : BSMotor
|
||||||
{
|
{
|
||||||
public Vector3 FrameOfReference { get; set; }
|
// public Vector3 FrameOfReference { get; set; }
|
||||||
public Vector3 Offset { get; set; }
|
// public Vector3 Offset { get; set; }
|
||||||
|
|
||||||
public float TimeScale { get; set; }
|
public float TimeScale { get; set; }
|
||||||
public float TargetValueDecayTimeScale { get; set; }
|
public float TargetValueDecayTimeScale { get; set; }
|
||||||
|
@ -72,6 +114,14 @@ public class BSVMotor : BSMotor
|
||||||
{
|
{
|
||||||
TargetValue = target;
|
TargetValue = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A form of stepping that does not take the time quantum into account.
|
||||||
|
// The caller must do the right thing later.
|
||||||
|
public Vector3 Step()
|
||||||
|
{
|
||||||
|
return Step(1f);
|
||||||
|
}
|
||||||
|
|
||||||
public Vector3 Step(float timeStep)
|
public Vector3 Step(float timeStep)
|
||||||
{
|
{
|
||||||
Vector3 returnCurrent = Vector3.Zero;
|
Vector3 returnCurrent = Vector3.Zero;
|
||||||
|
@ -99,18 +149,19 @@ public class BSVMotor : BSMotor
|
||||||
if (FrictionTimescale != BSMotor.InfiniteVector)
|
if (FrictionTimescale != BSMotor.InfiniteVector)
|
||||||
{
|
{
|
||||||
// frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
|
// frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
|
||||||
|
// Individual friction components can be 'infinite' so compute each separately.
|
||||||
frictionFactor.X = FrictionTimescale.X == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.X) * timeStep;
|
frictionFactor.X = FrictionTimescale.X == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.X) * timeStep;
|
||||||
frictionFactor.Y = FrictionTimescale.Y == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Y) * timeStep;
|
frictionFactor.Y = FrictionTimescale.Y == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Y) * timeStep;
|
||||||
frictionFactor.Z = FrictionTimescale.Z == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Z) * timeStep;
|
frictionFactor.Z = FrictionTimescale.Z == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Z) * timeStep;
|
||||||
CurrentValue *= (Vector3.One - frictionFactor);
|
CurrentValue *= (Vector3.One - frictionFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
MDetailLog("{0},BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
|
MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
|
||||||
BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
|
BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
|
||||||
timeStep, TimeScale, addAmount,
|
timeStep, TimeScale, addAmount,
|
||||||
TargetValueDecayTimeScale, decayFactor,
|
TargetValueDecayTimeScale, decayFactor,
|
||||||
FrictionTimescale, frictionFactor);
|
FrictionTimescale, frictionFactor);
|
||||||
MDetailLog("{0},BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}",
|
MDetailLog("{0}, BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}",
|
||||||
BSScene.DetailLogZero, UseName, CurrentValue, TargetValue,
|
BSScene.DetailLogZero, UseName, CurrentValue, TargetValue,
|
||||||
addAmount, decayFactor, frictionFactor, returnCurrent);
|
addAmount, decayFactor, frictionFactor, returnCurrent);
|
||||||
}
|
}
|
||||||
|
@ -120,7 +171,7 @@ public class BSVMotor : BSMotor
|
||||||
CurrentValue = Vector3.Zero;
|
CurrentValue = Vector3.Zero;
|
||||||
TargetValue = Vector3.Zero;
|
TargetValue = Vector3.Zero;
|
||||||
|
|
||||||
MDetailLog("{0},BSVMotor.Step,zero,{1},curr={2},target={3},ret={4}",
|
MDetailLog("{0}, BSVMotor.Step,zero,{1},curr={2},target={3},ret={4}",
|
||||||
BSScene.DetailLogZero, UseName, TargetValue, CurrentValue, returnCurrent);
|
BSScene.DetailLogZero, UseName, TargetValue, CurrentValue, returnCurrent);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,7 +348,9 @@ public sealed class BSPrim : BSPhysObject
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
// Apply upforce and overcome gravity.
|
// Apply upforce and overcome gravity.
|
||||||
AddForce(upForce - PhysicsScene.DefaultGravity, false, inTaintTime);
|
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;
|
||||||
}
|
}
|
||||||
|
@ -644,9 +646,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||||
|
|
||||||
// Collision filter can be set only when the object is in the world
|
// Collision filter can be set only when the object is in the world
|
||||||
if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0)
|
if (PhysBody.collisionGroup != 0 || PhysBody.collisionMask != 0)
|
||||||
{
|
{
|
||||||
BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask);
|
if (!BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr, (uint)PhysBody.collisionGroup, (uint)PhysBody.collisionMask))
|
||||||
|
{
|
||||||
|
PhysicsScene.Logger.ErrorFormat("{0} Failure setting prim collision mask. localID={1}, grp={2:X}, mask={3:X}",
|
||||||
|
LogHeader, LocalID, PhysBody.collisionGroup, PhysBody.collisionMask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recompute any linkset parameters.
|
// Recompute any linkset parameters.
|
||||||
|
@ -685,11 +691,11 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// There can be special things needed for implementing linksets
|
// There can be special things needed for implementing linksets
|
||||||
Linkset.MakeStatic(this);
|
Linkset.MakeStatic(this);
|
||||||
// The activation state is 'disabled' so Bullet will not try to act on it.
|
// The activation state is 'disabled' so Bullet will not try to act on it.
|
||||||
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
|
// BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
// Start it out sleeping and physical actions could wake it up.
|
// Start it out sleeping and physical actions could wake it up.
|
||||||
// BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
|
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING);
|
||||||
|
|
||||||
PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
|
PhysBody.collisionGroup = CollisionFilterGroups.StaticObjectGroup;
|
||||||
PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -735,7 +741,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
|
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
|
||||||
// BulletSimAPI.Activate2(BSBody.ptr, true);
|
// BulletSimAPI.Activate2(BSBody.ptr, true);
|
||||||
|
|
||||||
PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
|
PhysBody.collisionGroup = CollisionFilterGroups.ObjectGroup;
|
||||||
PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
|
PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -763,7 +769,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
|
m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
|
||||||
}
|
}
|
||||||
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||||
PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
|
PhysBody.collisionGroup = CollisionFilterGroups.VolumeDetectGroup;
|
||||||
PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
|
PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -839,15 +845,6 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 RotationalVelocity {
|
public override OMV.Vector3 RotationalVelocity {
|
||||||
get {
|
get {
|
||||||
/*
|
|
||||||
OMV.Vector3 pv = OMV.Vector3.Zero;
|
|
||||||
// if close to zero, report zero
|
|
||||||
// This is copied from ODE but I'm not sure why it returns zero but doesn't
|
|
||||||
// zero the property in the physics engine.
|
|
||||||
if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
|
|
||||||
return pv;
|
|
||||||
*/
|
|
||||||
|
|
||||||
return _rotationalVelocity;
|
return _rotationalVelocity;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
|
@ -1409,7 +1406,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
LastEntityProperties = CurrentEntityProperties;
|
LastEntityProperties = CurrentEntityProperties;
|
||||||
CurrentEntityProperties = entprop;
|
CurrentEntityProperties = entprop;
|
||||||
|
|
||||||
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
|
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
|
||||||
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);
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
public long SimulationStep { get { return m_simulationStep; } }
|
public long SimulationStep { get { return m_simulationStep; } }
|
||||||
private int m_taintsToProcessPerStep;
|
private int m_taintsToProcessPerStep;
|
||||||
|
|
||||||
|
public delegate void PreStepAction(float timeStep);
|
||||||
|
public event PreStepAction BeforeStep;
|
||||||
|
|
||||||
// A value of the time now so all the collision and update routines do not have to get their own
|
// A value of the time now so all the collision and update routines do not have to get their own
|
||||||
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
||||||
public int SimulationNowTime { get; private set; }
|
public int SimulationNowTime { get; private set; }
|
||||||
|
@ -487,8 +490,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
ProcessTaints();
|
ProcessTaints();
|
||||||
|
|
||||||
// Some of the prims operate with special vehicle properties
|
// Some of the prims operate with special vehicle properties
|
||||||
ProcessVehicles(timeStep);
|
DoPreStepActions(timeStep);
|
||||||
ProcessTaints(); // the vehicles might have added taints
|
|
||||||
|
// the prestep actions might have added taints
|
||||||
|
ProcessTaints();
|
||||||
|
|
||||||
// step the physical world one interval
|
// step the physical world one interval
|
||||||
m_simulationStep++;
|
m_simulationStep++;
|
||||||
|
@ -496,7 +501,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
||||||
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||||
|
@ -505,7 +510,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
|
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
|
||||||
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
|
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
|
||||||
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
|
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
|
||||||
// if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -907,6 +912,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DoPreStepActions(float timeStep)
|
||||||
|
{
|
||||||
|
ProcessVehicles(timeStep);
|
||||||
|
|
||||||
|
PreStepAction actions = BeforeStep;
|
||||||
|
if (actions != null)
|
||||||
|
actions(timeStep);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Some prims have extra vehicle actions
|
// Some prims have extra vehicle actions
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void ProcessVehicles(float timeStep)
|
private void ProcessVehicles(float timeStep)
|
||||||
|
@ -971,6 +986,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// Should handle fetching the right type from the ini file and converting it.
|
// Should handle fetching the right type from the ini file and converting it.
|
||||||
// -- a delegate for getting the value as a float
|
// -- a delegate for getting the value as a float
|
||||||
// -- a delegate for setting the value from a float
|
// -- a delegate for setting the value from a float
|
||||||
|
// -- an optional delegate to update the value in the world. Most often used to
|
||||||
|
// push the new value to an in-world object.
|
||||||
//
|
//
|
||||||
// The single letter parameters for the delegates are:
|
// The single letter parameters for the delegates are:
|
||||||
// s = BSScene
|
// s = BSScene
|
||||||
|
|
|
@ -620,8 +620,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Pass false for physicalness as this creates some sort of bounding box which we don't need
|
meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
|
||||||
meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
|
|
||||||
|
|
||||||
if (meshData != null)
|
if (meshData != null)
|
||||||
{
|
{
|
||||||
|
@ -694,8 +693,8 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Build a new hull in the physical world
|
// Build a new hull in the physical world
|
||||||
// Pass false for physicalness as this creates some sort of bounding box which we don't need
|
// Pass true for physicalness as this creates some sort of bounding box which we don't need
|
||||||
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
|
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
|
||||||
if (meshData != null)
|
if (meshData != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -121,8 +121,8 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
|
||||||
// redo its bounding box now that it is in the world
|
// redo its bounding box now that it is in the world
|
||||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
|
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
|
||||||
|
|
||||||
BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr,
|
BulletSimAPI.SetCollisionGroupMask2(m_mapInfo.terrainBody.ptr,
|
||||||
(uint)CollisionFilterGroups.TerrainFilter,
|
(uint)CollisionFilterGroups.TerrainGroup,
|
||||||
(uint)CollisionFilterGroups.TerrainMask);
|
(uint)CollisionFilterGroups.TerrainMask);
|
||||||
|
|
||||||
// Make it so the terrain will not move or be considered for movement.
|
// Make it so the terrain will not move or be considered for movement.
|
||||||
|
|
|
@ -140,8 +140,8 @@ public sealed class BSTerrainManager
|
||||||
// Ground plane does not move
|
// Ground plane does not move
|
||||||
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
// Everything collides with the ground plane.
|
// Everything collides with the ground plane.
|
||||||
BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
|
BulletSimAPI.SetCollisionGroupMask2(m_groundPlane.ptr,
|
||||||
(uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
|
(uint)CollisionFilterGroups.GroundPlaneGroup, (uint)CollisionFilterGroups.GroundPlaneMask);
|
||||||
|
|
||||||
// Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
|
// Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
|
||||||
BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
|
BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
|
||||||
|
|
|
@ -130,8 +130,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
// Redo its bounding box now that it is in the world
|
// Redo its bounding box now that it is in the world
|
||||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
||||||
|
|
||||||
BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr,
|
BulletSimAPI.SetCollisionGroupMask2(m_terrainBody.ptr,
|
||||||
(uint)CollisionFilterGroups.TerrainFilter,
|
(uint)CollisionFilterGroups.TerrainGroup,
|
||||||
(uint)CollisionFilterGroups.TerrainMask);
|
(uint)CollisionFilterGroups.TerrainMask);
|
||||||
|
|
||||||
// Make it so the terrain will not move or be considered for movement.
|
// Make it so the terrain will not move or be considered for movement.
|
||||||
|
|
|
@ -57,12 +57,12 @@ public struct BulletBody
|
||||||
{
|
{
|
||||||
ID = id;
|
ID = id;
|
||||||
ptr = xx;
|
ptr = xx;
|
||||||
collisionFilter = 0;
|
collisionGroup = 0;
|
||||||
collisionMask = 0;
|
collisionMask = 0;
|
||||||
}
|
}
|
||||||
public IntPtr ptr;
|
public IntPtr ptr;
|
||||||
public uint ID;
|
public uint ID;
|
||||||
public CollisionFilterGroups collisionFilter;
|
public CollisionFilterGroups collisionGroup;
|
||||||
public CollisionFilterGroups collisionMask;
|
public CollisionFilterGroups collisionMask;
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
@ -71,10 +71,10 @@ public struct BulletBody
|
||||||
buff.Append(ID.ToString());
|
buff.Append(ID.ToString());
|
||||||
buff.Append(",p=");
|
buff.Append(",p=");
|
||||||
buff.Append(ptr.ToString("X"));
|
buff.Append(ptr.ToString("X"));
|
||||||
if (collisionFilter != 0 || collisionMask != 0)
|
if (collisionGroup != 0 || collisionMask != 0)
|
||||||
{
|
{
|
||||||
buff.Append(",f=");
|
buff.Append(",g=");
|
||||||
buff.Append(collisionFilter.ToString("X"));
|
buff.Append(collisionGroup.ToString("X"));
|
||||||
buff.Append(",m=");
|
buff.Append(",m=");
|
||||||
buff.Append(collisionMask.ToString("X"));
|
buff.Append(collisionMask.ToString("X"));
|
||||||
}
|
}
|
||||||
|
@ -376,36 +376,36 @@ public enum CollisionFilterGroups : uint
|
||||||
// Don't use the bit definitions!! Define the use in a
|
// Don't use the bit definitions!! Define the use in a
|
||||||
// filter/mask definition below. This way collision interactions
|
// filter/mask definition below. This way collision interactions
|
||||||
// are more easily debugged.
|
// are more easily debugged.
|
||||||
BNoneFilter = 0,
|
BNoneGroup = 0,
|
||||||
BDefaultFilter = 1 << 0,
|
BDefaultGroup = 1 << 0,
|
||||||
BStaticFilter = 1 << 1,
|
BStaticGroup = 1 << 1,
|
||||||
BKinematicFilter = 1 << 2,
|
BKinematicGroup = 1 << 2,
|
||||||
BDebrisFilter = 1 << 3,
|
BDebrisGroup = 1 << 3,
|
||||||
BSensorTrigger = 1 << 4,
|
BSensorTrigger = 1 << 4,
|
||||||
BCharacterFilter = 1 << 5,
|
BCharacterGroup = 1 << 5,
|
||||||
BAllFilter = 0xFFFFFFFF,
|
BAllGroup = 0xFFFFFFFF,
|
||||||
// Filter groups defined by BulletSim
|
// Filter groups defined by BulletSim
|
||||||
BGroundPlaneFilter = 1 << 10,
|
BGroundPlaneGroup = 1 << 10,
|
||||||
BTerrainFilter = 1 << 11,
|
BTerrainGroup = 1 << 11,
|
||||||
BRaycastFilter = 1 << 12,
|
BRaycastGroup = 1 << 12,
|
||||||
BSolidFilter = 1 << 13,
|
BSolidGroup = 1 << 13,
|
||||||
BLinksetFilter = 1 << 14,
|
BLinksetGroup = 1 << 14,
|
||||||
|
|
||||||
// The collsion filters and masked are defined in one place -- don't want them scattered
|
// The collsion filters and masked are defined in one place -- don't want them scattered
|
||||||
AvatarFilter = BCharacterFilter,
|
AvatarGroup = BCharacterGroup,
|
||||||
AvatarMask = BAllFilter,
|
AvatarMask = BAllGroup,
|
||||||
ObjectFilter = BSolidFilter,
|
ObjectGroup = BSolidGroup,
|
||||||
ObjectMask = BAllFilter,
|
ObjectMask = BAllGroup,
|
||||||
StaticObjectFilter = BStaticFilter,
|
StaticObjectGroup = BStaticGroup,
|
||||||
StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other
|
StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much
|
||||||
LinksetFilter = BLinksetFilter,
|
LinksetGroup = BLinksetGroup,
|
||||||
LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other
|
LinksetMask = BAllGroup & ~BLinksetGroup, // linkset objects don't collide with each other
|
||||||
VolumeDetectFilter = BSensorTrigger,
|
VolumeDetectGroup = BSensorTrigger,
|
||||||
VolumeDetectMask = ~BSensorTrigger,
|
VolumeDetectMask = ~BSensorTrigger,
|
||||||
TerrainFilter = BTerrainFilter,
|
TerrainGroup = BTerrainGroup,
|
||||||
TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide
|
TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide
|
||||||
GroundPlaneFilter = BGroundPlaneFilter,
|
GroundPlaneGroup = BGroundPlaneGroup,
|
||||||
GroundPlaneMask = BAllFilter
|
GroundPlaneMask = BAllGroup
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -945,7 +945,7 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
|
||||||
public static extern int GetNumConstraintRefs2(IntPtr obj);
|
public static extern int GetNumConstraintRefs2(IntPtr obj);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
|
public static extern bool SetCollisionGroupMask2(IntPtr body, uint filter, uint mask);
|
||||||
|
|
||||||
// =====================================================================================
|
// =====================================================================================
|
||||||
// btCollisionShape entries
|
// btCollisionShape entries
|
||||||
|
@ -1006,14 +1006,17 @@ public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
|
public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
|
public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpAllInfo2(IntPtr sim);
|
public static extern void DumpActivationInfo2(IntPtr sim);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
public static extern void DumpAllInfo2(IntPtr sim);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpPhysicsStatistics2(IntPtr sim);
|
public static extern void DumpPhysicsStatistics2(IntPtr sim);
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
CRASHES
|
||||||
|
=================================================
|
||||||
|
20121129.1411: editting/moving phys object across region boundries causes crash
|
||||||
|
getPos-> btRigidBody::upcast -> getBodyType -> BOOM
|
||||||
|
20121128.1600: mesh object not rezzing (no physics mesh).
|
||||||
|
Causes many errors. Doesn't stop after first error with box shape.
|
||||||
|
Eventually crashes when deleting the object.
|
||||||
|
|
||||||
|
BULLETSIM TODO LIST:
|
||||||
|
=================================================
|
||||||
|
Neb car jiggling left and right
|
||||||
|
Vehicles (Move smoothly)
|
||||||
|
Light cycle falling over when driving
|
||||||
|
Light cycle not banking
|
||||||
|
Do single prim vehicles don't seem to properly vehiclize.
|
||||||
|
Gun sending shooter flying
|
||||||
|
Collision margin (gap between physical objects lying on each other)
|
||||||
|
Boundry checking (crashes related to crossing boundry)
|
||||||
|
Add check for border edge position for avatars and objects.
|
||||||
|
Verify the events are created for border crossings.
|
||||||
|
Avatar rotation (check out changes to ScenePresence for physical rotation)
|
||||||
|
Avatar running (what does phys engine need to do?)
|
||||||
|
Small physical objects do not interact correctly
|
||||||
|
Create chain of .5x.5x.1 torui and make all but top physical so to hang.
|
||||||
|
The chain will fall apart and pairs will dance around on ground
|
||||||
|
Chains of 1x1x.2 will stay connected but will dance.
|
||||||
|
Chains above 2x2x.4 are move stable and get stablier as torui get larger.
|
||||||
|
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.
|
||||||
|
Add PID motor for avatar movement (slow to stop, ...)
|
||||||
|
Implement function efficiency for lineaar and angular motion.
|
||||||
|
|
||||||
|
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.
|
||||||
|
Test avatar walking up stairs. How does compare with SL.
|
||||||
|
Radius of the capsule affects ability to climb edges.
|
||||||
|
Tune terrain/object friction to be closer to SL.
|
||||||
|
Debounce avatar contact so legs don't keep folding up when standing.
|
||||||
|
Implement LSL physics controls. Like STATUS_ROTATE_X.
|
||||||
|
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
|
||||||
|
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?
|
||||||
|
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)
|
||||||
|
Check wheter SimMotionState needs large if statement (see TODO).
|
||||||
|
|
||||||
|
Implement 'top colliders' info.
|
||||||
|
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.
|
||||||
|
Implement detailed physics stats (GetStats()).
|
||||||
|
|
||||||
|
Eliminate collisions between objects in a linkset. (LinksetConstraint)
|
||||||
|
Have UserPointer point to struct with localID and linksetID?
|
||||||
|
Objects in original linkset still collide with each other?
|
||||||
|
|
||||||
|
Measure performance improvement from hulls
|
||||||
|
Test not using ghost objects for volume detect implementation.
|
||||||
|
Performance of closures and delegates for taint processing
|
||||||
|
Are there faster ways?
|
||||||
|
Is any slowdown introduced by the existing implementation significant?
|
||||||
|
Is there are more efficient method of implementing pre and post step actions?
|
||||||
|
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?
|
||||||
|
|
||||||
|
INTERNAL IMPROVEMENT/CLEANUP
|
||||||
|
=================================================
|
||||||
|
Remove unused fields from ShapeData (not used in API2)
|
||||||
|
Breakout code for mesh/hull/compound/native into separate BSShape* classes
|
||||||
|
Standardize access to building and reference code.
|
||||||
|
The skeleton classes are in the sources but are not complete or linked in.
|
||||||
|
Generalize Dynamics and PID with standardized motors.
|
||||||
|
Generalize Linkset and vehicles into PropertyManagers
|
||||||
|
Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
|
||||||
|
Possibly generalized a 'pre step action' registration.
|
||||||
|
Complete implemention of preStepActions
|
||||||
|
Replace vehicle step call with prestep event.
|
||||||
|
Is there a need for postStepActions? postStepTaints?
|
||||||
|
Implement linkset by setting position of children when root updated. (LinksetManual)
|
||||||
|
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?
|
||||||
|
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
|
||||||
|
bob at the water level. BSPrim.PositionSanityCheck().
|
||||||
|
|
||||||
|
DONE DONE DONE DONE
|
||||||
|
=================================================
|
||||||
|
Cleanup code in BSDynamics by using motors.
|
||||||
|
Consider implementing terrain with a mesh rather than heightmap.
|
||||||
|
Would have better and adjustable resolution.
|
||||||
|
NOTDONE: 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.
|
||||||
|
Terrain as mesh.
|
||||||
|
How are static linksets seen by the physics engine?
|
||||||
|
A: 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
|
||||||
|
Avatar pushing difficult (too heavy?)
|
||||||
|
Use asset service passed to BulletSim to get sculptie bodies, etc.
|
||||||
|
Vehicles (fix bouncing on terrain)
|
||||||
|
Remove old code in DLL (all non-API2 stuff).
|
||||||
|
Measurements of mega-physical prim performance (with graph)
|
||||||
|
Debug Bullet internal stats output (why is timing all wrong?)
|
||||||
|
Bullet stats logging only works with a single instance of Bullet (one region).
|
|
@ -36,6 +36,7 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
{
|
{
|
||||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
|
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
|
||||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
|
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
|
||||||
|
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values for level of detail to be passed to the mesher.
|
// Values for level of detail to be passed to the mesher.
|
||||||
|
|
|
@ -64,10 +64,15 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
{
|
{
|
||||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
||||||
{
|
{
|
||||||
return CreateMesh(primName, primShape, size, lod, false);
|
return CreateMesh(primName, primShape, size, lod, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
|
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
|
||||||
|
{
|
||||||
|
return CreateMesh(primName, primShape, size, lod, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
|
||||||
{
|
{
|
||||||
// Remove the reference to the encoded JPEG2000 data so it can be GCed
|
// Remove the reference to the encoded JPEG2000 data so it can be GCed
|
||||||
primShape.SculptData = OpenMetaverse.Utils.EmptyBytes;
|
primShape.SculptData = OpenMetaverse.Utils.EmptyBytes;
|
||||||
|
|
|
@ -702,11 +702,16 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
||||||
{
|
{
|
||||||
return CreateMesh(primName, primShape, size, lod, false);
|
return CreateMesh(primName, primShape, size, lod, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
|
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
|
||||||
{
|
{
|
||||||
|
return CreateMesh(primName, primShape, size, lod, isPhysical, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
|
||||||
|
{
|
||||||
#if SPAM
|
#if SPAM
|
||||||
m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
|
m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
|
||||||
#endif
|
#endif
|
||||||
|
@ -716,9 +721,12 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
// If this mesh has been created already, return it instead of creating another copy
|
// If this mesh has been created already, return it instead of creating another copy
|
||||||
// For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
|
// For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
|
||||||
|
if (shouldCache)
|
||||||
|
{
|
||||||
key = primShape.GetMeshKey(size, lod);
|
key = primShape.GetMeshKey(size, lod);
|
||||||
if (m_uniqueMeshes.TryGetValue(key, out mesh))
|
if (m_uniqueMeshes.TryGetValue(key, out mesh))
|
||||||
return mesh;
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
if (size.X < 0.01f) size.X = 0.01f;
|
if (size.X < 0.01f) size.X = 0.01f;
|
||||||
if (size.Y < 0.01f) size.Y = 0.01f;
|
if (size.Y < 0.01f) size.Y = 0.01f;
|
||||||
|
@ -741,8 +749,11 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
// trim the vertex and triangle lists to free up memory
|
// trim the vertex and triangle lists to free up memory
|
||||||
mesh.TrimExcess();
|
mesh.TrimExcess();
|
||||||
|
|
||||||
|
if (shouldCache)
|
||||||
|
{
|
||||||
m_uniqueMeshes.Add(key, mesh);
|
m_uniqueMeshes.Add(key, mesh);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue