aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
authorRobert Adams2013-01-20 22:35:42 -0800
committerRobert Adams2013-01-20 23:09:54 -0800
commit52b341e2e24384395fddc7d32fd66358f5062468 (patch)
treea0b28ec5b79004b1a556db78d835e486b8040632 /OpenSim/Region/Physics/BulletSPlugin
parentBulletSim: fix problem of avatar sliding very slowly occasionally after stopp... (diff)
downloadopensim-SC_OLD-52b341e2e24384395fddc7d32fd66358f5062468.zip
opensim-SC_OLD-52b341e2e24384395fddc7d32fd66358f5062468.tar.gz
opensim-SC_OLD-52b341e2e24384395fddc7d32fd66358f5062468.tar.bz2
opensim-SC_OLD-52b341e2e24384395fddc7d32fd66358f5062468.tar.xz
BulletSim: More aggressive as setting character velocity to zero
when should be standing. Modify angular force routines to be the same pattern as linear force routines. BulletSim vehicle turning is scaled like SL and is DIFFERENT THAN ODE!! Fix some bugs in BSMotor dealing with the motor going to zero. Add a bunch of parameters: MaxLinearVelocity, MaxAngularVelocity, MaxAddForceMagnitude, VehicleMaxLinearVelocity, VehicleMaxAngularVelocity, and most of the values are defaulted to values that are larger than in SL. Use the new parameters in BSPrim, BSCharacter and BSDynamic.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs30
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs143
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs26
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs32
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs13
5 files changed, 153 insertions, 91 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index cd279e3..a9e16e6 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -200,20 +200,36 @@ public sealed class BSCharacter : BSPhysObject
200 // TODO: Decide if the step parameters should be changed depending on the avatar's 200 // TODO: Decide if the step parameters should be changed depending on the avatar's
201 // state (flying, colliding, ...). There is code in ODE to do this. 201 // state (flying, colliding, ...). There is code in ODE to do this.
202 202
203 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
204 // specified for the avatar is the one that should be used. For falling, if the avatar
205 // is not flying and is not colliding then it is presumed to be falling and the Z
206 // component is not fooled with (thus allowing gravity to do its thing).
207 // When the avatar is standing, though, the user has specified a velocity of zero and
208 // the avatar should be standing. But if the avatar is pushed by something in the world
209 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
210 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
211 // errors can creap in and the avatar will slowly float off in some direction.
212 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
213 // from real pushing.OMV.Vector3.Zero;
214 // The code below keeps setting the velocity to zero hoping the world will keep pushing.
215
203 _velocityMotor.Step(timeStep); 216 _velocityMotor.Step(timeStep);
204 217
205 // If we're not supposed to be moving, make sure things are zero. 218 // If we're not supposed to be moving, make sure things are zero.
206 if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f)) 219 if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero && IsColliding)
207 { 220 {
208 if (_wasWalking) 221 // The avatar shouldn't be moving
222 _velocityMotor.Zero();
223 ZeroMotion(true /* inTaintTime */);
224
225 // Standing has more friction on the ground
226 if (_currentFriction != BSParam.AvatarStandingFriction)
209 { 227 {
210 _velocityMotor.Zero();
211 _velocity = OMV.Vector3.Zero;
212 PhysicsScene.PE.SetLinearVelocity(PhysBody, OMV.Vector3.Zero);
213 _currentFriction = BSParam.AvatarStandingFriction; 228 _currentFriction = BSParam.AvatarStandingFriction;
214 PhysicsScene.PE.SetFriction(PhysBody, _currentFriction); 229 PhysicsScene.PE.SetFriction(PhysBody, _currentFriction);
215 // DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1}", LocalID, _velocityMotor.TargetValue);
216 } 230 }
231 DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1}", LocalID, _velocityMotor.TargetValue);
232
217 _wasWalking = false; 233 _wasWalking = false;
218 } 234 }
219 else 235 else
@@ -242,7 +258,7 @@ public sealed class BSCharacter : BSPhysObject
242 // Add special movement force to allow avatars to walk up stepped surfaces. 258 // Add special movement force to allow avatars to walk up stepped surfaces.
243 moveForce += WalkUpStairs(); 259 moveForce += WalkUpStairs();
244 260
245 // DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce); 261 DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
246 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce); 262 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
247 _wasWalking = true; 263 _wasWalking = true;
248 } 264 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 388d4f9..f8fc3de 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -231,6 +231,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
231 break; 231 break;
232 case Vehicle.ANGULAR_MOTOR_DIRECTION: 232 case Vehicle.ANGULAR_MOTOR_DIRECTION:
233 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 233 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
234 m_angularMotor.Zero();
234 m_angularMotor.SetTarget(m_angularMotorDirection); 235 m_angularMotor.SetTarget(m_angularMotorDirection);
235 break; 236 break;
236 case Vehicle.LINEAR_FRICTION_TIMESCALE: 237 case Vehicle.LINEAR_FRICTION_TIMESCALE:
@@ -264,6 +265,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
264 pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f); 265 pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f);
265 pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f); 266 pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f);
266 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 267 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
268 m_angularMotor.Zero();
267 m_angularMotor.SetTarget(m_angularMotorDirection); 269 m_angularMotor.SetTarget(m_angularMotorDirection);
268 break; 270 break;
269 case Vehicle.LINEAR_FRICTION_TIMESCALE: 271 case Vehicle.LINEAR_FRICTION_TIMESCALE:
@@ -945,10 +947,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
945 // ================================================================== 947 // ==================================================================
946 // Clamp high or low velocities 948 // Clamp high or low velocities
947 float newVelocityLengthSq = VehicleVelocity.LengthSquared(); 949 float newVelocityLengthSq = VehicleVelocity.LengthSquared();
948 if (newVelocityLengthSq > 1000f) 950 if (newVelocityLengthSq > BSParam.VehicleMaxLinearVelocity)
949 { 951 {
950 VehicleVelocity /= VehicleVelocity.Length(); 952 VehicleVelocity /= VehicleVelocity.Length();
951 VehicleVelocity *= 1000f; 953 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
952 } 954 }
953 else if (newVelocityLengthSq < 0.001f) 955 else if (newVelocityLengthSq < 0.001f)
954 VehicleVelocity = Vector3.Zero; 956 VehicleVelocity = Vector3.Zero;
@@ -1190,63 +1192,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1190 // set directly on the vehicle. 1192 // set directly on the vehicle.
1191 private void MoveAngular(float pTimestep) 1193 private void MoveAngular(float pTimestep)
1192 { 1194 {
1193 // The user wants this many radians per second angular change? 1195 VehicleRotationalVelocity = Vector3.Zero;
1194 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
1195 angularMotorContribution = m_angularMotor.CurrentValue;
1196 1196
1197 // ================================================================== 1197 ComputeAngularTurning(pTimestep);
1198 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1199 // This flag prevents linear deflection parallel to world z-axis. This is useful
1200 // for preventing ground vehicles with large linear deflection, like bumper cars,
1201 // from climbing their linear deflection into the sky.
1202 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1203 // TODO: This is here because this is where ODE put it but documentation says it
1204 // is a linear effect. Where should this check go?
1205 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1206 {
1207 angularMotorContribution.X = 0f;
1208 angularMotorContribution.Y = 0f;
1209 VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
1210 }
1211 1198
1212 Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(); 1199 ComputeAngularVerticalAttraction();
1213 1200
1214 Vector3 deflectionContribution = ComputeAngularDeflection(); 1201 ComputeAngularDeflection();
1215 1202
1216 Vector3 bankingContribution = ComputeAngularBanking(); 1203 ComputeAngularBanking();
1217 1204
1218 // ================================================================== 1205 // ==================================================================
1219 m_lastVertAttractor = verticalAttractionContribution;
1220
1221 m_lastAngularVelocity = angularMotorContribution
1222 + verticalAttractionContribution
1223 + deflectionContribution
1224 + bankingContribution;
1225
1226 // All of the above computation are made relative to vehicle coordinates. 1206 // All of the above computation are made relative to vehicle coordinates.
1227 // Convert to world coordinates. 1207 // Convert to world coordinates.
1228 m_lastAngularVelocity *= VehicleOrientation; 1208 // TODO: Should this be applied as an angular force (torque)?
1209 VehicleRotationalVelocity *= VehicleOrientation;
1229 1210
1230 // ================================================================== 1211 // ==================================================================
1231 // Apply the correction velocity. 1212 if (VehicleRotationalVelocity.ApproxEquals(Vector3.Zero, 0.01f))
1232 // TODO: Should this be applied as an angular force (torque)?
1233 if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
1234 {
1235 VehicleRotationalVelocity = m_lastAngularVelocity;
1236
1237 VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5}",
1238 Prim.LocalID,
1239 angularMotorContribution, verticalAttractionContribution,
1240 bankingContribution, deflectionContribution,
1241 m_lastAngularVelocity
1242 );
1243 }
1244 else
1245 { 1213 {
1246 // The vehicle is not adding anything angular wise. 1214 // The vehicle is not adding anything angular wise.
1247 VehicleRotationalVelocity = Vector3.Zero; 1215 VehicleRotationalVelocity = Vector3.Zero;
1248 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); 1216 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID);
1249 } 1217 }
1218 else
1219 {
1220 VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", Prim.LocalID, VehicleRotationalVelocity);
1221 }
1250 1222
1251 // ================================================================== 1223 // ==================================================================
1252 //Offset section 1224 //Offset section
@@ -1280,6 +1252,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1280 } 1252 }
1281 1253
1282 } 1254 }
1255
1256 private void ComputeAngularTurning(float pTimestep)
1257 {
1258 // The user wants this many radians per second angular change?
1259 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
1260
1261 // ==================================================================
1262 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1263 // This flag prevents linear deflection parallel to world z-axis. This is useful
1264 // for preventing ground vehicles with large linear deflection, like bumper cars,
1265 // from climbing their linear deflection into the sky.
1266 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1267 // TODO: This is here because this is where ODE put it but documentation says it
1268 // is a linear effect. Where should this check go?
1269 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1270 {
1271 angularMotorContribution.X = 0f;
1272 angularMotorContribution.Y = 0f;
1273 }
1274
1275 VehicleRotationalVelocity += angularMotorContribution;
1276 VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
1277 }
1278
1283 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: 1279 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1284 // Some vehicles, like boats, should always keep their up-side up. This can be done by 1280 // Some vehicles, like boats, should always keep their up-side up. This can be done by
1285 // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to 1281 // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to
@@ -1288,13 +1284,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1288 // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An 1284 // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An
1289 // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an 1285 // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an
1290 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. 1286 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
1291 public Vector3 ComputeAngularVerticalAttraction() 1287 public void ComputeAngularVerticalAttraction()
1292 { 1288 {
1293 Vector3 ret = Vector3.Zero;
1294
1295 // If vertical attaction timescale is reasonable 1289 // If vertical attaction timescale is reasonable
1296 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1290 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1297 { 1291 {
1292 Vector3 vertContribution = Vector3.Zero;
1293
1298 // Take a vector pointing up and convert it from world to vehicle relative coords. 1294 // Take a vector pointing up and convert it from world to vehicle relative coords.
1299 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; 1295 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
1300 1296
@@ -1308,37 +1304,36 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1308 1304
1309 // Y error means needed rotation around X axis and visa versa. 1305 // Y error means needed rotation around X axis and visa versa.
1310 // Since the error goes from zero to one, the asin is the corresponding angle. 1306 // Since the error goes from zero to one, the asin is the corresponding angle.
1311 ret.X = (float)Math.Asin(verticalError.Y); 1307 vertContribution.X = (float)Math.Asin(verticalError.Y);
1312 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) 1308 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1313 ret.Y = -(float)Math.Asin(verticalError.X); 1309 vertContribution.Y = -(float)Math.Asin(verticalError.X);
1314 1310
1315 // If verticalError.Z is negative, the vehicle is upside down. Add additional push. 1311 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1316 if (verticalError.Z < 0f) 1312 if (verticalError.Z < 0f)
1317 { 1313 {
1318 ret.X += PIOverFour; 1314 vertContribution.X += PIOverFour;
1319 ret.Y += PIOverFour; 1315 vertContribution.Y += PIOverFour;
1320 } 1316 }
1321 1317
1322 // 'ret' is now the necessary velocity to correct tilt in one second. 1318 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1323 // Correction happens over a number of seconds. 1319 // Correction happens over a number of seconds.
1324 Vector3 unscaledContrib = ret; 1320 Vector3 unscaledContrib = vertContribution; // DEBUG DEBUG
1325 ret /= m_verticalAttractionTimescale; 1321 vertContribution /= m_verticalAttractionTimescale;
1322
1323 VehicleRotationalVelocity += vertContribution;
1326 1324
1327 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}", 1325 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}",
1328 Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, ret); 1326 Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContribution);
1329 } 1327 }
1330 return ret;
1331 } 1328 }
1332 1329
1333 // Return the angular correction to correct the direction the vehicle is pointing to be 1330 // Angular correction to correct the direction the vehicle is pointing to be
1334 // the direction is should want to be pointing. 1331 // the direction is should want to be pointing.
1335 // The vehicle is moving in some direction and correct its orientation to it is pointing 1332 // The vehicle is moving in some direction and correct its orientation to it is pointing
1336 // in that direction. 1333 // in that direction.
1337 // TODO: implement reference frame. 1334 // TODO: implement reference frame.
1338 public Vector3 ComputeAngularDeflection() 1335 public void ComputeAngularDeflection()
1339 { 1336 {
1340 Vector3 ret = Vector3.Zero;
1341
1342 // Since angularMotorUp and angularDeflection are computed independently, they will calculate 1337 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1343 // approximately the same X or Y correction. When added together (when contributions are combined) 1338 // approximately the same X or Y correction. When added together (when contributions are combined)
1344 // this creates an over-correction and then wabbling as the target is overshot. 1339 // this creates an over-correction and then wabbling as the target is overshot.
@@ -1346,6 +1341,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1346 1341
1347 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) 1342 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1348 { 1343 {
1344 Vector3 deflectContribution = Vector3.Zero;
1345
1349 // The direction the vehicle is moving 1346 // The direction the vehicle is moving
1350 Vector3 movingDirection = VehicleVelocity; 1347 Vector3 movingDirection = VehicleVelocity;
1351 movingDirection.Normalize(); 1348 movingDirection.Normalize();
@@ -1371,18 +1368,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1371 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); 1368 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1372 1369
1373 // Scale the correction by recovery timescale and efficiency 1370 // Scale the correction by recovery timescale and efficiency
1374 ret = (-deflectionError) * m_angularDeflectionEfficiency; 1371 deflectContribution = (-deflectionError) * m_angularDeflectionEfficiency;
1375 ret /= m_angularDeflectionTimescale; 1372 deflectContribution /= m_angularDeflectionTimescale;
1373
1374 VehicleRotationalVelocity += deflectContribution;
1376 1375
1377 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", 1376 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1378 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret); 1377 Prim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContribution);
1379 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", 1378 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}",
1380 Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); 1379 Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale);
1381 } 1380 }
1382 return ret;
1383 } 1381 }
1384 1382
1385 // Return an angular change to rotate the vehicle around the Z axis when the vehicle 1383 // Angular change to rotate the vehicle around the Z axis when the vehicle
1386 // is tipped around the X axis. 1384 // is tipped around the X axis.
1387 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: 1385 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1388 // The vertical attractor feature must be enabled in order for the banking behavior to 1386 // The vertical attractor feature must be enabled in order for the banking behavior to
@@ -1413,12 +1411,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1413 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to 1411 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1414 // bank quickly then give it a banking timescale of about a second or less, otherwise you can 1412 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1415 // make a sluggish vehicle by giving it a timescale of several seconds. 1413 // make a sluggish vehicle by giving it a timescale of several seconds.
1416 public Vector3 ComputeAngularBanking() 1414 public void ComputeAngularBanking()
1417 { 1415 {
1418 Vector3 ret = Vector3.Zero;
1419
1420 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1416 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1421 { 1417 {
1418 Vector3 bankingContribution = Vector3.Zero;
1419
1422 // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented. 1420 // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented.
1423 // As the vehicle rolls to the right or left, the Y value will increase from 1421 // As the vehicle rolls to the right or left, the Y value will increase from
1424 // zero (straight up) to 1 or -1 (full tilt right or left) 1422 // zero (straight up) to 1 or -1 (full tilt right or left)
@@ -1435,15 +1433,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1435 mixedYawAngle = ClampInRange(-20f, mixedYawAngle, 20f); 1433 mixedYawAngle = ClampInRange(-20f, mixedYawAngle, 20f);
1436 1434
1437 // Build the force vector to change rotation from what it is to what it should be 1435 // Build the force vector to change rotation from what it is to what it should be
1438 ret.Z = -mixedYawAngle; 1436 bankingContribution.Z = -mixedYawAngle;
1439 1437
1440 // Don't do it all at once. 1438 // Don't do it all at once.
1441 ret /= m_bankingTimescale; 1439 bankingContribution /= m_bankingTimescale;
1440
1441 VehicleRotationalVelocity += bankingContribution;
1442 1442
1443 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", 1443 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}",
1444 Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, ret); 1444 Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContribution);
1445 } 1445 }
1446 return ret;
1447 } 1446 }
1448 1447
1449 // This is from previous instantiations of XXXDynamics.cs. 1448 // This is from previous instantiations of XXXDynamics.cs.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index 82fd2d2..9501e2d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -149,6 +149,7 @@ public class BSVMotor : BSMotor
149 149
150 Vector3 correction = Vector3.Zero; 150 Vector3 correction = Vector3.Zero;
151 Vector3 error = TargetValue - CurrentValue; 151 Vector3 error = TargetValue - CurrentValue;
152 LastError = error;
152 if (!ErrorIsZero(error)) 153 if (!ErrorIsZero(error))
153 { 154 {
154 correction = StepError(timeStep, error); 155 correction = StepError(timeStep, error);
@@ -188,9 +189,15 @@ public class BSVMotor : BSMotor
188 else 189 else
189 { 190 {
190 // Difference between what we have and target is small. Motor is done. 191 // Difference between what we have and target is small. Motor is done.
191 CurrentValue = TargetValue = Vector3.Zero; 192 if (TargetValue.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
192 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}", 193 {
193 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); 194 // The target can step down to nearly zero but not get there. If close to zero
195 // it is really zero.
196 TargetValue = Vector3.Zero;
197 }
198 CurrentValue = TargetValue;
199 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},currTgt={4},currCurr={5}",
200 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, TargetValue, CurrentValue);
194 } 201 }
195 202
196 return correction; 203 return correction;
@@ -205,9 +212,8 @@ public class BSVMotor : BSMotor
205 { 212 {
206 if (!Enabled) return Vector3.Zero; 213 if (!Enabled) return Vector3.Zero;
207 214
208 LastError = error;
209 Vector3 returnCorrection = Vector3.Zero; 215 Vector3 returnCorrection = Vector3.Zero;
210 if (!ErrorIsZero()) 216 if (!ErrorIsZero(error))
211 { 217 {
212 // correction = error / secondsItShouldTakeToCorrect 218 // correction = error / secondsItShouldTakeToCorrect
213 Vector3 correctionAmount; 219 Vector3 correctionAmount;
@@ -309,6 +315,7 @@ public class BSFMotor : BSMotor
309 315
310 float correction = 0f; 316 float correction = 0f;
311 float error = TargetValue - CurrentValue; 317 float error = TargetValue - CurrentValue;
318 LastError = error;
312 if (!ErrorIsZero(error)) 319 if (!ErrorIsZero(error))
313 { 320 {
314 correction = StepError(timeStep, error); 321 correction = StepError(timeStep, error);
@@ -346,6 +353,12 @@ public class BSFMotor : BSMotor
346 else 353 else
347 { 354 {
348 // Difference between what we have and target is small. Motor is done. 355 // Difference between what we have and target is small. Motor is done.
356 if (Util.InRange<float>(TargetValue, -ErrorZeroThreshold, ErrorZeroThreshold))
357 {
358 // The target can step down to nearly zero but not get there. If close to zero
359 // it is really zero.
360 TargetValue = 0f;
361 }
349 CurrentValue = TargetValue; 362 CurrentValue = TargetValue;
350 MDetailLog("{0}, BSFMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}", 363 MDetailLog("{0}, BSFMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}",
351 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); 364 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue);
@@ -358,9 +371,8 @@ public class BSFMotor : BSMotor
358 { 371 {
359 if (!Enabled) return 0f; 372 if (!Enabled) return 0f;
360 373
361 LastError = error;
362 float returnCorrection = 0f; 374 float returnCorrection = 0f;
363 if (!ErrorIsZero()) 375 if (!ErrorIsZero(error))
364 { 376 {
365 // correction = error / secondsItShouldTakeToCorrect 377 // correction = error / secondsItShouldTakeToCorrect
366 float correctionAmount; 378 float correctionAmount;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 3e80aa4..6a92365 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -45,6 +45,9 @@ public static class BSParam
45 45
46 public static float MinimumObjectMass { get; private set; } 46 public static float MinimumObjectMass { get; private set; }
47 public static float MaximumObjectMass { get; private set; } 47 public static float MaximumObjectMass { get; private set; }
48 public static float MaxLinearVelocity { get; private set; }
49 public static float MaxAngularVelocity { get; private set; }
50 public static float MaxAddForceMagnitude { get; private set; }
48 51
49 public static float LinearDamping { get; private set; } 52 public static float LinearDamping { get; private set; }
50 public static float AngularDamping { get; private set; } 53 public static float AngularDamping { get; private set; }
@@ -79,6 +82,8 @@ public static class BSParam
79 public static float AvatarStepApproachFactor { get; private set; } 82 public static float AvatarStepApproachFactor { get; private set; }
80 public static float AvatarStepForceFactor { get; private set; } 83 public static float AvatarStepForceFactor { get; private set; }
81 84
85 public static float VehicleMaxLinearVelocity { get; private set; }
86 public static float VehicleMaxAngularVelocity { get; private set; }
82 public static float VehicleAngularDamping { get; private set; } 87 public static float VehicleAngularDamping { get; private set; }
83 public static float VehicleDebuggingEnabled { get; private set; } 88 public static float VehicleDebuggingEnabled { get; private set; }
84 89
@@ -103,7 +108,6 @@ public static class BSParam
103 public const float MaxDensity = 22587f; 108 public const float MaxDensity = 22587f;
104 public const float MinRestitution = 0f; 109 public const float MinRestitution = 0f;
105 public const float MaxRestitution = 1f; 110 public const float MaxRestitution = 1f;
106 public const float MaxAddForceMagnitude = 20f;
107 111
108 // =========================================================================== 112 // ===========================================================================
109 public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 113 public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
@@ -247,6 +251,22 @@ public static class BSParam
247 (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); }, 251 (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
248 (s) => { return (float)MaximumObjectMass; }, 252 (s) => { return (float)MaximumObjectMass; },
249 (s,p,l,v) => { MaximumObjectMass = v; } ), 253 (s,p,l,v) => { MaximumObjectMass = v; } ),
254 new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
255 1000.0f,
256 (s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
257 (s) => { return (float)MaxLinearVelocity; },
258 (s,p,l,v) => { MaxLinearVelocity = v; } ),
259 new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
260 1000.0f,
261 (s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
262 (s) => { return (float)MaxAngularVelocity; },
263 (s,p,l,v) => { MaxAngularVelocity = v; } ),
264 // LL documentation says thie number should be 20f
265 new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
266 200.0f,
267 (s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
268 (s) => { return (float)MaxAddForceMagnitude; },
269 (s,p,l,v) => { MaxAddForceMagnitude = v; } ),
250 270
251 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 271 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
252 2200f, 272 2200f,
@@ -423,6 +443,16 @@ public static class BSParam
423 (s) => { return AvatarStepForceFactor; }, 443 (s) => { return AvatarStepForceFactor; },
424 (s,p,l,v) => { AvatarStepForceFactor = v; } ), 444 (s,p,l,v) => { AvatarStepForceFactor = v; } ),
425 445
446 new ParameterDefn("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
447 1000.0f,
448 (s,cf,p,v) => { VehicleMaxLinearVelocity = cf.GetFloat(p, v); },
449 (s) => { return (float)VehicleMaxLinearVelocity; },
450 (s,p,l,v) => { VehicleMaxLinearVelocity = v; } ),
451 new ParameterDefn("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
452 12.0f,
453 (s,cf,p,v) => { VehicleMaxAngularVelocity = cf.GetFloat(p, v); },
454 (s) => { return (float)VehicleMaxAngularVelocity; },
455 (s,p,l,v) => { VehicleMaxAngularVelocity = v; } ),
426 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", 456 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
427 0.95f, 457 0.95f,
428 (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); }, 458 (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 22afdc9..b63523c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -989,10 +989,10 @@ public sealed class BSPrim : BSPhysObject
989 } 989 }
990 set { 990 set {
991 _rotationalVelocity = value; 991 _rotationalVelocity = value;
992 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
992 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 993 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
993 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 994 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
994 { 995 {
995 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
996 ForceRotationalVelocity = _rotationalVelocity; 996 ForceRotationalVelocity = _rotationalVelocity;
997 }); 997 });
998 } 998 }
@@ -1005,6 +1005,7 @@ public sealed class BSPrim : BSPhysObject
1005 _rotationalVelocity = value; 1005 _rotationalVelocity = value;
1006 if (PhysBody.HasPhysicalBody) 1006 if (PhysBody.HasPhysicalBody)
1007 { 1007 {
1008 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
1008 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 1009 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
1009 ActivateIfPhysical(false); 1010 ActivateIfPhysical(false);
1010 } 1011 }
@@ -1193,10 +1194,14 @@ public sealed class BSPrim : BSPhysObject
1193 public override float APIDDamping { set { return; } } 1194 public override float APIDDamping { set { return; } }
1194 1195
1195 public override void AddForce(OMV.Vector3 force, bool pushforce) { 1196 public override void AddForce(OMV.Vector3 force, bool pushforce) {
1197 // Per documentation, max force is limited.
1198 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1199
1196 // Since this force is being applied in only one step, make this a force per second. 1200 // Since this force is being applied in only one step, make this a force per second.
1197 OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; 1201 addForce /= PhysicsScene.LastTimeStep;
1198 AddForce(addForce, pushforce, false); 1202 AddForce(addForce, pushforce, false /* inTaintTime */);
1199 } 1203 }
1204
1200 // Applying a force just adds this to the total force on the object. 1205 // Applying a force just adds this to the total force on the object.
1201 // This added force will only last the next simulation tick. 1206 // This added force will only last the next simulation tick.
1202 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1207 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
@@ -1205,9 +1210,9 @@ public sealed class BSPrim : BSPhysObject
1205 { 1210 {
1206 if (force.IsFinite()) 1211 if (force.IsFinite())
1207 { 1212 {
1208 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1209 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1213 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1210 1214
1215 OMV.Vector3 addForce = force;
1211 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1216 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
1212 { 1217 {
1213 // Bullet adds this central force to the total force for this tick 1218 // Bullet adds this central force to the total force for this tick