diff options
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 30 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 143 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs | 26 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | 32 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 13 |
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 |