diff options
author | Robert Adams | 2013-01-07 16:05:02 -0800 |
---|---|---|
committer | Robert Adams | 2013-01-07 16:05:02 -0800 |
commit | 8452c0a8702ccf7ea045740dd829c69a6f509845 (patch) | |
tree | a2c094fbded7a502dc997d1eb4252659eddbb003 /OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |
parent | BulletSim: fix exception when re-creating the terrain when loading an OAR file (diff) | |
download | opensim-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.cs | 97 |
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; } |