BulletSim: make all the different angularVerticalAttraction algorithms

selectable from configuration paramters.
Changed default algorithm to "1" from previous default as it seems to
handle Y axis correction a little better.
Add config file independent enablement of vehicle angular forces to
make debugging easier (independent testing of forces).
cpu-performance
Robert Adams 2013-07-08 16:21:10 -07:00
parent 76b2b20f7e
commit fad4241e4e
4 changed files with 146 additions and 138 deletions

View File

@ -125,33 +125,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
static readonly float PIOverFour = ((float)Math.PI) / 4f; static readonly float PIOverFour = ((float)Math.PI) / 4f;
static readonly float PIOverTwo = ((float)Math.PI) / 2f; static readonly float PIOverTwo = ((float)Math.PI) / 2f;
// For debugging, flags to turn on and off individual corrections.
public bool enableAngularVerticalAttraction;
public bool enableAngularDeflection;
public bool enableAngularBanking;
public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName)
: base(myScene, myPrim, actorName) : base(myScene, myPrim, actorName)
{ {
ControllingPrim = myPrim; ControllingPrim = myPrim;
Type = Vehicle.TYPE_NONE; Type = Vehicle.TYPE_NONE;
m_haveRegisteredForSceneEvents = false; m_haveRegisteredForSceneEvents = false;
SetupVehicleDebugging();
}
// Stopgap debugging enablement. Allows source level debugging but still checking
// in changes by making enablement of debugging flags from INI file.
public void SetupVehicleDebugging()
{
enableAngularVerticalAttraction = true;
enableAngularDeflection = true;
enableAngularBanking = true;
if (BSParam.VehicleDebuggingEnable)
{
enableAngularVerticalAttraction = true;
enableAngularDeflection = false;
enableAngularBanking = false;
}
} }
// Return 'true' if this vehicle is doing vehicle things // Return 'true' if this vehicle is doing vehicle things
@ -556,10 +535,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} }
m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f); m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f);
m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) // m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f); m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) // m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
/* Not implemented /* Not implemented
m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
@ -1393,116 +1372,134 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
// If vertical attaction timescale is reasonable // If vertical attaction timescale is reasonable
if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
{ {
//Another formula to try got from : Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
//http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html switch (BSParam.VehicleAngularVerticalAttractionAlgorithm)
Vector3 VehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
// Flipping what was originally a timescale into a speed variable and then multiplying it by 2
// since only computing half the distance between the angles.
float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
// Make a prediction of where the up axis will be when this is applied rather then where it is now as
// this makes for a smoother adjustment and less fighting between the various forces.
Vector3 predictedUp = VehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
// This is only half the distance to the target so it will take 2 seconds to complete the turn.
Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
// Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed;
VehicleRotationalVelocity += vertContributionV;
VDetailLog("{0}, MoveAngular,verticalAttraction,UpAxis={1},PredictedUp={2},torqueVector={3},contrib={4}",
ControllingPrim.LocalID,
VehicleUpAxis,
predictedUp,
torqueVector,
vertContributionV);
//=====================================================================
/*
// Possible solution derived from a discussion at:
// http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
// Create a rotation that is only the vehicle's rotation around Z
Vector3 currentEuler = Vector3.Zero;
VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
// Create the axis that is perpendicular to the up vector and the rotated up vector.
Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
// Compute the angle between those to vectors.
double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
// 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
// Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
// TODO: add 'efficiency'.
differenceAngle /= m_verticalAttractionTimescale;
// Create the quaterian representing the correction angle
Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
// Turn that quaternion into Euler values to make it into velocities to apply.
Vector3 vertContributionV = Vector3.Zero;
correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
vertContributionV *= -1f;
VehicleRotationalVelocity += vertContributionV;
VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}",
ControllingPrim.LocalID,
differenceAxis,
differenceAngle,
correctionRotation,
vertContributionV);
*/
// ===================================================================
/*
Vector3 vertContributionV = Vector3.Zero;
Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
// Take a vector pointing up and convert it from world to vehicle relative coords.
Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
// If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
// is now:
// leaning to one side: rotated around the X axis with the Y value going
// from zero (nearly straight up) to one (completely to the side)) or
// leaning front-to-back: rotated around the Y axis with the value of X being between
// zero and one.
// The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
// Y error means needed rotation around X axis and visa versa.
// Since the error goes from zero to one, the asin is the corresponding angle.
vertContributionV.X = (float)Math.Asin(verticalError.Y);
// (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
vertContributionV.Y = -(float)Math.Asin(verticalError.X);
// If verticalError.Z is negative, the vehicle is upside down. Add additional push.
if (verticalError.Z < 0f)
{ {
vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; case 0:
// vertContribution.Y -= PIOverFour; {
//Another formula to try got from :
//http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
// Flipping what was originally a timescale into a speed variable and then multiplying it by 2
// since only computing half the distance between the angles.
float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
// Make a prediction of where the up axis will be when this is applied rather then where it is now as
// this makes for a smoother adjustment and less fighting between the various forces.
Vector3 predictedUp = vehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
// This is only half the distance to the target so it will take 2 seconds to complete the turn.
Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
// Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed;
VehicleRotationalVelocity += vertContributionV;
VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},PredictedUp={2},torqueVector={3},contrib={4}",
ControllingPrim.LocalID,
vehicleUpAxis,
predictedUp,
torqueVector,
vertContributionV);
break;
}
case 1:
{
// Possible solution derived from a discussion at:
// http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
// Create a rotation that is only the vehicle's rotation around Z
Vector3 currentEuler = Vector3.Zero;
VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
// Create the axis that is perpendicular to the up vector and the rotated up vector.
Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
// Compute the angle between those to vectors.
double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
// 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
// Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
// TODO: add 'efficiency'.
differenceAngle /= m_verticalAttractionTimescale;
// Create the quaterian representing the correction angle
Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
// Turn that quaternion into Euler values to make it into velocities to apply.
Vector3 vertContributionV = Vector3.Zero;
correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
vertContributionV *= -1f;
VehicleRotationalVelocity += vertContributionV;
VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}",
ControllingPrim.LocalID,
vehicleUpAxis,
differenceAxis,
differenceAngle,
correctionRotation,
vertContributionV);
break;
}
case 2:
{
Vector3 vertContributionV = Vector3.Zero;
Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
// Take a vector pointing up and convert it from world to vehicle relative coords.
Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
// If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
// is now:
// leaning to one side: rotated around the X axis with the Y value going
// from zero (nearly straight up) to one (completely to the side)) or
// leaning front-to-back: rotated around the Y axis with the value of X being between
// zero and one.
// The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
// Y error means needed rotation around X axis and visa versa.
// Since the error goes from zero to one, the asin is the corresponding angle.
vertContributionV.X = (float)Math.Asin(verticalError.Y);
// (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
vertContributionV.Y = -(float)Math.Asin(verticalError.X);
// If verticalError.Z is negative, the vehicle is upside down. Add additional push.
if (verticalError.Z < 0f)
{
vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour;
// vertContribution.Y -= PIOverFour;
}
// 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
// Correction happens over a number of seconds.
Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
// The correction happens over the user's time period
vertContributionV /= m_verticalAttractionTimescale;
// Rotate the vehicle rotation to the world coordinates.
VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
VDetailLog("{0}, MoveAngular,verticalAttraction,,upAxis={1},origRotVW={2},vertError={3},unscaledV={4},eff={5},ts={6},vertContribV={7}",
ControllingPrim.LocalID,
vehicleUpAxis,
origRotVelW,
verticalError,
unscaledContribVerticalErrorV,
m_verticalAttractionEfficiency,
m_verticalAttractionTimescale,
vertContributionV);
break;
}
default:
{
break;
}
} }
// 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
// Correction happens over a number of seconds.
Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
// The correction happens over the user's time period
vertContributionV /= m_verticalAttractionTimescale;
// Rotate the vehicle rotation to the world coordinates.
VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
*/
} }
} }
@ -1514,7 +1511,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
public void ComputeAngularDeflection() public void ComputeAngularDeflection()
{ {
if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
{ {
Vector3 deflectContributionV = Vector3.Zero; Vector3 deflectContributionV = Vector3.Zero;
@ -1593,7 +1590,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// make a sluggish vehicle by giving it a timescale of several seconds. // make a sluggish vehicle by giving it a timescale of several seconds.
public void ComputeAngularBanking() public void ComputeAngularBanking()
{ {
if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
{ {
Vector3 bankingContributionV = Vector3.Zero; Vector3 bankingContributionV = Vector3.Zero;

View File

@ -155,7 +155,10 @@ public static class BSParam
public static Vector3 VehicleInertiaFactor { get; private set; } public static Vector3 VehicleInertiaFactor { get; private set; }
public static float VehicleGroundGravityFudge { get; private set; } public static float VehicleGroundGravityFudge { get; private set; }
public static float VehicleAngularBankingTimescaleFudge { get; private set; } public static float VehicleAngularBankingTimescaleFudge { get; private set; }
public static bool VehicleDebuggingEnable { get; private set; } public static bool VehicleEnableAngularVerticalAttraction { get; private set; }
public static int VehicleAngularVerticalAttractionAlgorithm { get; private set; }
public static bool VehicleEnableAngularDeflection { get; private set; }
public static bool VehicleEnableAngularBanking { get; private set; }
// Convex Hulls // Convex Hulls
public static int CSHullMaxDepthSplit { get; private set; } public static int CSHullMaxDepthSplit { get; private set; }
@ -606,8 +609,14 @@ public static class BSParam
0.2f ), 0.2f ),
new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.", new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.",
60.0f ), 60.0f ),
new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging", new ParameterDefn<bool>("VehicleEnableAngularVerticalAttraction", "Turn on/off vehicle angular vertical attraction effect",
false ), true ),
new ParameterDefn<int>("VehicleAngularVerticalAttractionAlgorithm", "Select vertical attraction algo. You need to look at the source.",
1 ),
new ParameterDefn<bool>("VehicleEnableAngularDeflection", "Turn on/off vehicle angular deflection effect",
true ),
new ParameterDefn<bool>("VehicleEnableAngularBanking", "Turn on/off vehicle angular banking effect",
true ),
new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
0f, 0f,

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -648,7 +648,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
simTime = Util.EnvironmentTickCountSubtract(beforeTime); simTime = Util.EnvironmentTickCountSubtract(beforeTime);
if (PhysicsLogging.Enabled) if (PhysicsLogging.Enabled)
{ {
DetailLog("{0},DoPhysicsStep,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", DetailLog("{0},DoPhysicsStep,complete,frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
} }

View File

@ -57,6 +57,8 @@ public class BasicVehicles : OpenSimTestCase
public void Init() public void Init()
{ {
Dictionary<string, string> engineParams = new Dictionary<string, string>(); Dictionary<string, string> engineParams = new Dictionary<string, string>();
engineParams.Add("VehicleEnableAngularVerticalAttraction", "true");
engineParams.Add("VehicleAngularVerticalAttractionAlgorithm", "1");
PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams); PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams);
PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere(); PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere();
@ -119,7 +121,7 @@ public class BasicVehicles : OpenSimTestCase
{ {
vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency); vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency);
vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale); vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale);
vehicleActor.enableAngularVerticalAttraction = true; // vehicleActor.enableAngularVerticalAttraction = true;
TestVehicle.IsPhysical = true; TestVehicle.IsPhysical = true;
PhysicsScene.ProcessTaints(); PhysicsScene.ProcessTaints();