aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
diff options
context:
space:
mode:
authorRobert Adams2013-01-07 16:05:02 -0800
committerRobert Adams2013-01-07 16:05:02 -0800
commit8452c0a8702ccf7ea045740dd829c69a6f509845 (patch)
treea2c094fbded7a502dc997d1eb4252659eddbb003 /OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
parentBulletSim: fix exception when re-creating the terrain when loading an OAR file (diff)
downloadopensim-SC-8452c0a8702ccf7ea045740dd829c69a6f509845.zip
opensim-SC-8452c0a8702ccf7ea045740dd829c69a6f509845.tar.gz
opensim-SC-8452c0a8702ccf7ea045740dd829c69a6f509845.tar.bz2
opensim-SC-8452c0a8702ccf7ea045740dd829c69a6f509845.tar.xz
BulletSim: add function to push avatar up when hitting stairs.
It looks like BulletSim and ODE rely on penetration correction to cause the avatar to move up and thus allowing walking up stairs. Object penetration was minimized for walking and flying (so one doesn't go through walls) and this stopped stairs from working. This commit introduces avatar movement code to check for collisions at the feet while walking and attempts to raise the avatar for the steps. Not yet perfect but movement is better.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs97
1 files changed, 71 insertions, 26 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index fe48166..939d38a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -184,10 +184,6 @@ public sealed class BSCharacter : BSPhysObject
184 // standing as well as moving. Destruction of the avatar will destroy the pre-step action. 184 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
185 private void SetupMovementMotor() 185 private void SetupMovementMotor()
186 { 186 {
187
188 // Someday, use a PID motor for asymmetric speed up and slow down
189 // _velocityMotor = new BSPIDVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f);
190
191 // Infinite decay and timescale values so motor only changes current to target values. 187 // Infinite decay and timescale values so motor only changes current to target values.
192 _velocityMotor = new BSVMotor("BSCharacter.Velocity", 188 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
193 0.2f, // time scale 189 0.2f, // time scale
@@ -214,25 +210,68 @@ public sealed class BSCharacter : BSPhysObject
214 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. 210 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
215 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass; 211 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
216 212
217 /* 213 // Should we check for move force being small and forcing velocity to zero?
218 // If moveForce is very small, zero things so we don't keep sending microscopic updates to the user 214
219 float moveForceMagnitudeSquared = moveForce.LengthSquared(); 215 // Add special movement force to allow avatars to walk up stepped surfaces.
220 if (moveForceMagnitudeSquared < 0.0001) 216 moveForce += WalkUpStairs();
221 { 217
222 DetailLog("{0},BSCharacter.MoveMotor,zeroMovement,stepVel={1},vel={2},mass={3},magSq={4},moveForce={5}", 218 DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
223 LocalID, stepVelocity, _velocity, Mass, moveForceMagnitudeSquared, moveForce);
224 ForceVelocity = OMV.Vector3.Zero;
225 }
226 else
227 {
228 AddForce(moveForce, false, true);
229 }
230 */
231 // DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
232 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce); 219 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
233 }); 220 });
234 } 221 }
235 222
223 // Decide of the character is colliding with a low object and compute a force to pop the
224 // avatar up so it has a chance of walking up and over the low object.
225 private OMV.Vector3 WalkUpStairs()
226 {
227 OMV.Vector3 ret = OMV.Vector3.Zero;
228
229 // This test is done if moving forward, not flying and is colliding with something.
230 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
231 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
232 if (IsColliding && !Flying && TargetSpeed > 0.1f /* && ForwardSpeed < 0.1f */)
233 {
234 // The range near the character's feet where we will consider stairs
235 float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
236 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
237
238 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
239 foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
240 {
241 // Don't care about collisions with the terrain
242 if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
243 {
244 OMV.Vector3 touchPosition = kvp.Value.Position;
245 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
246 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
247 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
248 {
249 // This contact is within the 'near the feet' range.
250 // The normal should be our contact point to the object so it is pointing away
251 // thus the difference between our facing orientation and the normal should be small.
252 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
253 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
254 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
255 if (diff < BSParam.AvatarStepApproachFactor)
256 {
257 // Found the stairs contact point. Push up a little to raise the character.
258 float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
259 ret = new OMV.Vector3(0f, 0f, upForce);
260
261 // Also move the avatar up for the new height
262 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
263 ForcePosition = RawPosition + displacement;
264 }
265 DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
266 LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
267 }
268 }
269 }
270 }
271
272 return ret;
273 }
274
236 public override void RequestPhysicsterseUpdate() 275 public override void RequestPhysicsterseUpdate()
237 { 276 {
238 base.RequestPhysicsterseUpdate(); 277 base.RequestPhysicsterseUpdate();
@@ -342,13 +381,11 @@ public sealed class BSCharacter : BSPhysObject
342 } 381 }
343 set { 382 set {
344 _position = value; 383 _position = value;
345 PositionSanityCheck();
346 384
347 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 385 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
348 { 386 {
349 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 387 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
350 if (PhysBody.HasPhysicalBody) 388 ForcePosition = _position;
351 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
352 }); 389 });
353 } 390 }
354 } 391 }
@@ -359,8 +396,11 @@ public sealed class BSCharacter : BSPhysObject
359 } 396 }
360 set { 397 set {
361 _position = value; 398 _position = value;
362 PositionSanityCheck(); 399 if (PhysBody.HasPhysicalBody)
363 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 400 {
401 PositionSanityCheck();
402 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
403 }
364 } 404 }
365 } 405 }
366 406
@@ -373,7 +413,7 @@ public sealed class BSCharacter : BSPhysObject
373 bool ret = false; 413 bool ret = false;
374 414
375 // TODO: check for out of bounds 415 // TODO: check for out of bounds
376 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) 416 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
377 { 417 {
378 // The character is out of the known/simulated area. 418 // The character is out of the known/simulated area.
379 // Upper levels of code will handle the transition to other areas so, for 419 // Upper levels of code will handle the transition to other areas so, for
@@ -382,7 +422,7 @@ public sealed class BSCharacter : BSPhysObject
382 } 422 }
383 423
384 // If below the ground, move the avatar up 424 // If below the ground, move the avatar up
385 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 425 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
386 if (Position.Z < terrainHeight) 426 if (Position.Z < terrainHeight)
387 { 427 {
388 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 428 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
@@ -485,6 +525,11 @@ public sealed class BSCharacter : BSPhysObject
485 }); 525 });
486 } 526 }
487 } 527 }
528 public override OMV.Vector3 RawVelocity
529 {
530 get { return _velocity; }
531 set { _velocity = value; }
532 }
488 // Directly setting velocity means this is what the user really wants now. 533 // Directly setting velocity means this is what the user really wants now.
489 public override OMV.Vector3 Velocity { 534 public override OMV.Vector3 Velocity {
490 get { return _velocity; } 535 get { return _velocity; }