aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs99
1 files changed, 71 insertions, 28 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index c215e3a..939d38a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -58,8 +58,6 @@ public sealed class BSCharacter : BSPhysObject
58 private bool _flying; 58 private bool _flying;
59 private bool _setAlwaysRun; 59 private bool _setAlwaysRun;
60 private bool _throttleUpdates; 60 private bool _throttleUpdates;
61 private bool _isColliding;
62 private bool _collidingObj;
63 private bool _floatOnWater; 61 private bool _floatOnWater;
64 private OMV.Vector3 _rotationalVelocity; 62 private OMV.Vector3 _rotationalVelocity;
65 private bool _kinematic; 63 private bool _kinematic;
@@ -186,10 +184,6 @@ public sealed class BSCharacter : BSPhysObject
186 // 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.
187 private void SetupMovementMotor() 185 private void SetupMovementMotor()
188 { 186 {
189
190 // Someday, use a PID motor for asymmetric speed up and slow down
191 // _velocityMotor = new BSPIDVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f);
192
193 // 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.
194 _velocityMotor = new BSVMotor("BSCharacter.Velocity", 188 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
195 0.2f, // time scale 189 0.2f, // time scale
@@ -216,25 +210,68 @@ public sealed class BSCharacter : BSPhysObject
216 // '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.
217 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass; 211 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
218 212
219 /* 213 // Should we check for move force being small and forcing velocity to zero?
220 // If moveForce is very small, zero things so we don't keep sending microscopic updates to the user 214
221 float moveForceMagnitudeSquared = moveForce.LengthSquared(); 215 // Add special movement force to allow avatars to walk up stepped surfaces.
222 if (moveForceMagnitudeSquared < 0.0001) 216 moveForce += WalkUpStairs();
223 { 217
224 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);
225 LocalID, stepVelocity, _velocity, Mass, moveForceMagnitudeSquared, moveForce);
226 ForceVelocity = OMV.Vector3.Zero;
227 }
228 else
229 {
230 AddForce(moveForce, false, true);
231 }
232 */
233 // DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
234 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce); 219 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
235 }); 220 });
236 } 221 }
237 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
238 public override void RequestPhysicsterseUpdate() 275 public override void RequestPhysicsterseUpdate()
239 { 276 {
240 base.RequestPhysicsterseUpdate(); 277 base.RequestPhysicsterseUpdate();
@@ -344,13 +381,11 @@ public sealed class BSCharacter : BSPhysObject
344 } 381 }
345 set { 382 set {
346 _position = value; 383 _position = value;
347 PositionSanityCheck();
348 384
349 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 385 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
350 { 386 {
351 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);
352 if (PhysBody.HasPhysicalBody) 388 ForcePosition = _position;
353 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
354 }); 389 });
355 } 390 }
356 } 391 }
@@ -361,8 +396,11 @@ public sealed class BSCharacter : BSPhysObject
361 } 396 }
362 set { 397 set {
363 _position = value; 398 _position = value;
364 PositionSanityCheck(); 399 if (PhysBody.HasPhysicalBody)
365 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 400 {
401 PositionSanityCheck();
402 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
403 }
366 } 404 }
367 } 405 }
368 406
@@ -375,7 +413,7 @@ public sealed class BSCharacter : BSPhysObject
375 bool ret = false; 413 bool ret = false;
376 414
377 // TODO: check for out of bounds 415 // TODO: check for out of bounds
378 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) 416 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
379 { 417 {
380 // The character is out of the known/simulated area. 418 // The character is out of the known/simulated area.
381 // 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
@@ -384,7 +422,7 @@ public sealed class BSCharacter : BSPhysObject
384 } 422 }
385 423
386 // If below the ground, move the avatar up 424 // If below the ground, move the avatar up
387 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 425 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
388 if (Position.Z < terrainHeight) 426 if (Position.Z < terrainHeight)
389 { 427 {
390 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);
@@ -487,6 +525,11 @@ public sealed class BSCharacter : BSPhysObject
487 }); 525 });
488 } 526 }
489 } 527 }
528 public override OMV.Vector3 RawVelocity
529 {
530 get { return _velocity; }
531 set { _velocity = value; }
532 }
490 // 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.
491 public override OMV.Vector3 Velocity { 534 public override OMV.Vector3 Velocity {
492 get { return _velocity; } 535 get { return _velocity; }