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.cs271
1 files changed, 41 insertions, 230 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 25be416..a0d58d3 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -46,9 +46,6 @@ public sealed class BSCharacter : BSPhysObject
46 private OMV.Vector3 _position; 46 private OMV.Vector3 _position;
47 private float _mass; 47 private float _mass;
48 private float _avatarVolume; 48 private float _avatarVolume;
49 private OMV.Vector3 _force;
50 private OMV.Vector3 _velocity;
51 private OMV.Vector3 _torque;
52 private float _collisionScore; 49 private float _collisionScore;
53 private OMV.Vector3 _acceleration; 50 private OMV.Vector3 _acceleration;
54 private OMV.Quaternion _orientation; 51 private OMV.Quaternion _orientation;
@@ -61,17 +58,13 @@ public sealed class BSCharacter : BSPhysObject
61 private OMV.Vector3 _rotationalVelocity; 58 private OMV.Vector3 _rotationalVelocity;
62 private bool _kinematic; 59 private bool _kinematic;
63 private float _buoyancy; 60 private float _buoyancy;
64 private bool _isStationaryStanding; // true is standing on a stationary object
65 61
66 private BSVMotor _velocityMotor; 62 private BSActorAvatarMove m_moveActor;
63 private const string AvatarMoveActorName = "BSCharacter.AvatarMove";
67 64
68 private OMV.Vector3 _PIDTarget; 65 private OMV.Vector3 _PIDTarget;
69 private bool _usePID; 66 private bool _usePID;
70 private float _PIDTau; 67 private float _PIDTau;
71 private bool _useHoverPID;
72 private float _PIDHoverHeight;
73 private PIDHoverType _PIDHoverType;
74 private float _PIDHoverTao;
75 68
76 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) 69 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
77 : base(parent_scene, localID, avName, "BSCharacter") 70 : base(parent_scene, localID, avName, "BSCharacter")
@@ -81,11 +74,10 @@ public sealed class BSCharacter : BSPhysObject
81 74
82 _flying = isFlying; 75 _flying = isFlying;
83 _orientation = OMV.Quaternion.Identity; 76 _orientation = OMV.Quaternion.Identity;
84 _velocity = OMV.Vector3.Zero; 77 RawVelocity = OMV.Vector3.Zero;
85 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 78 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
86 Friction = BSParam.AvatarStandingFriction; 79 Friction = BSParam.AvatarStandingFriction;
87 Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; 80 Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
88 _isStationaryStanding = false;
89 81
90 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 82 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
91 // replace with the default values. 83 // replace with the default values.
@@ -99,7 +91,12 @@ public sealed class BSCharacter : BSPhysObject
99 // set _avatarVolume and _mass based on capsule size, _density and Scale 91 // set _avatarVolume and _mass based on capsule size, _density and Scale
100 ComputeAvatarVolumeAndMass(); 92 ComputeAvatarVolumeAndMass();
101 93
102 SetupMovementMotor(); 94 // The avatar's movement is controlled by this motor that speeds up and slows down
95 // the avatar seeking to reach the motor's target speed.
96 // This motor runs as a prestep action for the avatar so it will keep the avatar
97 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
98 m_moveActor = new BSActorAvatarMove(PhysicsScene, this, AvatarMoveActorName);
99 PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
103 100
104 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", 101 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
105 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 102 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
@@ -139,10 +136,10 @@ public sealed class BSCharacter : BSPhysObject
139 ForcePosition = _position; 136 ForcePosition = _position;
140 137
141 // Set the velocity 138 // Set the velocity
142 _velocityMotor.Reset(); 139 if (m_moveActor != null)
143 _velocityMotor.SetTarget(_velocity); 140 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false);
144 _velocityMotor.SetCurrent(_velocity); 141
145 ForceVelocity = _velocity; 142 ForceVelocity = RawVelocity;
146 143
147 // This will enable or disable the flying buoyancy of the avatar. 144 // This will enable or disable the flying buoyancy of the avatar.
148 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 145 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
@@ -163,6 +160,9 @@ public sealed class BSCharacter : BSPhysObject
163 // Make so capsule does not fall over 160 // Make so capsule does not fall over
164 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); 161 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
165 162
163 // The avatar mover sets some parameters.
164 PhysicalActors.Refresh();
165
166 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); 166 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
167 167
168 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 168 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody);
@@ -176,162 +176,6 @@ public sealed class BSCharacter : BSPhysObject
176 PhysBody.ApplyCollisionMask(PhysicsScene); 176 PhysBody.ApplyCollisionMask(PhysicsScene);
177 } 177 }
178 178
179 // The avatar's movement is controlled by this motor that speeds up and slows down
180 // the avatar seeking to reach the motor's target speed.
181 // This motor runs as a prestep action for the avatar so it will keep the avatar
182 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
183 private void SetupMovementMotor()
184 {
185 // Infinite decay and timescale values so motor only changes current to target values.
186 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
187 0.2f, // time scale
188 BSMotor.Infinite, // decay time scale
189 BSMotor.InfiniteVector, // friction timescale
190 1f // efficiency
191 );
192 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
193
194 RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep)
195 {
196 // TODO: Decide if the step parameters should be changed depending on the avatar's
197 // state (flying, colliding, ...). There is code in ODE to do this.
198
199 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
200 // specified for the avatar is the one that should be used. For falling, if the avatar
201 // is not flying and is not colliding then it is presumed to be falling and the Z
202 // component is not fooled with (thus allowing gravity to do its thing).
203 // When the avatar is standing, though, the user has specified a velocity of zero and
204 // the avatar should be standing. But if the avatar is pushed by something in the world
205 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
206 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
207 // errors can creap in and the avatar will slowly float off in some direction.
208 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
209 // from real pushing.
210 // The code below uses whether the collider is static or moving to decide whether to zero motion.
211
212 _velocityMotor.Step(timeStep);
213 _isStationaryStanding = false;
214
215 // If we're not supposed to be moving, make sure things are zero.
216 if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero)
217 {
218 // The avatar shouldn't be moving
219 _velocityMotor.Zero();
220
221 if (IsColliding)
222 {
223 // If we are colliding with a stationary object, presume we're standing and don't move around
224 if (!ColliderIsMoving)
225 {
226 DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
227 _isStationaryStanding = true;
228 ZeroMotion(true /* inTaintTime */);
229 }
230
231 // Standing has more friction on the ground
232 if (Friction != BSParam.AvatarStandingFriction)
233 {
234 Friction = BSParam.AvatarStandingFriction;
235 PhysicsScene.PE.SetFriction(PhysBody, Friction);
236 }
237 }
238 else
239 {
240 if (Flying)
241 {
242 // Flying and not collising and velocity nearly zero.
243 ZeroMotion(true /* inTaintTime */);
244 }
245 }
246
247 DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
248 }
249 else
250 {
251 // Supposed to be moving.
252 OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue;
253
254 if (Friction != BSParam.AvatarFriction)
255 {
256 // Probably starting up walking. Set friction to moving friction.
257 Friction = BSParam.AvatarFriction;
258 PhysicsScene.PE.SetFriction(PhysBody, Friction);
259 }
260
261 // If falling, we keep the world's downward vector no matter what the other axis specify.
262 // The check for _velocity.Z < 0 makes jumping work (temporary upward force).
263 if (!Flying && !IsColliding)
264 {
265 if (_velocity.Z < 0)
266 stepVelocity.Z = _velocity.Z;
267 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
268 }
269
270 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
271 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
272
273 // Should we check for move force being small and forcing velocity to zero?
274
275 // Add special movement force to allow avatars to walk up stepped surfaces.
276 moveForce += WalkUpStairs();
277
278 DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
279 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
280 }
281 });
282 }
283
284 // Decide if the character is colliding with a low object and compute a force to pop the
285 // avatar up so it can walk up and over the low objects.
286 private OMV.Vector3 WalkUpStairs()
287 {
288 OMV.Vector3 ret = OMV.Vector3.Zero;
289
290 // This test is done if moving forward, not flying and is colliding with something.
291 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
292 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
293 if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
294 {
295 // The range near the character's feet where we will consider stairs
296 float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
297 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
298
299 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
300 foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
301 {
302 // Don't care about collisions with the terrain
303 if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
304 {
305 OMV.Vector3 touchPosition = kvp.Value.Position;
306 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
307 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
308 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
309 {
310 // This contact is within the 'near the feet' range.
311 // The normal should be our contact point to the object so it is pointing away
312 // thus the difference between our facing orientation and the normal should be small.
313 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
314 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
315 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
316 if (diff < BSParam.AvatarStepApproachFactor)
317 {
318 // Found the stairs contact point. Push up a little to raise the character.
319 float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
320 ret = new OMV.Vector3(0f, 0f, upForce);
321
322 // Also move the avatar up for the new height
323 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
324 ForcePosition = RawPosition + displacement;
325 }
326 DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
327 LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
328 }
329 }
330 }
331 }
332
333 return ret;
334 }
335 179
336 public override void RequestPhysicsterseUpdate() 180 public override void RequestPhysicsterseUpdate()
337 { 181 {
@@ -403,7 +247,7 @@ public sealed class BSCharacter : BSPhysObject
403 // Called at taint time! 247 // Called at taint time!
404 public override void ZeroMotion(bool inTaintTime) 248 public override void ZeroMotion(bool inTaintTime)
405 { 249 {
406 _velocity = OMV.Vector3.Zero; 250 RawVelocity = OMV.Vector3.Zero;
407 _acceleration = OMV.Vector3.Zero; 251 _acceleration = OMV.Vector3.Zero;
408 _rotationalVelocity = OMV.Vector3.Zero; 252 _rotationalVelocity = OMV.Vector3.Zero;
409 253
@@ -542,15 +386,15 @@ public sealed class BSCharacter : BSPhysObject
542 } 386 }
543 387
544 public override OMV.Vector3 Force { 388 public override OMV.Vector3 Force {
545 get { return _force; } 389 get { return RawForce; }
546 set { 390 set {
547 _force = value; 391 RawForce = value;
548 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 392 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
549 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 393 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
550 { 394 {
551 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 395 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
552 if (PhysBody.HasPhysicalBody) 396 if (PhysBody.HasPhysicalBody)
553 PhysicsScene.PE.SetObjectForce(PhysBody, _force); 397 PhysicsScene.PE.SetObjectForce(PhysBody, RawForce);
554 }); 398 });
555 } 399 }
556 } 400 }
@@ -573,7 +417,7 @@ public sealed class BSCharacter : BSPhysObject
573 { 417 {
574 get 418 get
575 { 419 {
576 return m_targetVelocity; 420 return base.m_targetVelocity;
577 } 421 }
578 set 422 set
579 { 423 {
@@ -583,51 +427,39 @@ public sealed class BSCharacter : BSPhysObject
583 if (_setAlwaysRun) 427 if (_setAlwaysRun)
584 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); 428 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f);
585 429
586 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() 430 if (m_moveActor != null)
587 { 431 m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */);
588 _velocityMotor.Reset();
589 _velocityMotor.SetTarget(targetVel);
590 _velocityMotor.SetCurrent(_velocity);
591 _velocityMotor.Enabled = true;
592 });
593 } 432 }
594 } 433 }
595 public override OMV.Vector3 RawVelocity
596 {
597 get { return _velocity; }
598 set { _velocity = value; }
599 }
600 // Directly setting velocity means this is what the user really wants now. 434 // Directly setting velocity means this is what the user really wants now.
601 public override OMV.Vector3 Velocity { 435 public override OMV.Vector3 Velocity {
602 get { return _velocity; } 436 get { return RawVelocity; }
603 set { 437 set {
604 _velocity = value; 438 RawVelocity = value;
605 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 439 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
606 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 440 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
607 { 441 {
608 _velocityMotor.Reset(); 442 if (m_moveActor != null)
609 _velocityMotor.SetCurrent(_velocity); 443 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
610 _velocityMotor.SetTarget(_velocity);
611 _velocityMotor.Enabled = false;
612 444
613 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 445 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity);
614 ForceVelocity = _velocity; 446 ForceVelocity = RawVelocity;
615 }); 447 });
616 } 448 }
617 } 449 }
618 public override OMV.Vector3 ForceVelocity { 450 public override OMV.Vector3 ForceVelocity {
619 get { return _velocity; } 451 get { return RawVelocity; }
620 set { 452 set {
621 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); 453 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
622 454
623 _velocity = value; 455 RawVelocity = value;
624 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 456 PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
625 PhysicsScene.PE.Activate(PhysBody, true); 457 PhysicsScene.PE.Activate(PhysBody, true);
626 } 458 }
627 } 459 }
628 public override OMV.Vector3 Torque { 460 public override OMV.Vector3 Torque {
629 get { return _torque; } 461 get { return RawTorque; }
630 set { _torque = value; 462 set { RawTorque = value;
631 } 463 }
632 } 464 }
633 public override float CollisionScore { 465 public override float CollisionScore {
@@ -783,27 +615,6 @@ public sealed class BSCharacter : BSPhysObject
783 set { _PIDTau = value; } 615 set { _PIDTau = value; }
784 } 616 }
785 617
786 // Used for llSetHoverHeight and maybe vehicle height
787 // Hover Height will override MoveTo target's Z
788 public override bool PIDHoverActive {
789 set { _useHoverPID = value; }
790 }
791 public override float PIDHoverHeight {
792 set { _PIDHoverHeight = value; }
793 }
794 public override PIDHoverType PIDHoverType {
795 set { _PIDHoverType = value; }
796 }
797 public override float PIDHoverTau {
798 set { _PIDHoverTao = value; }
799 }
800
801 // For RotLookAt
802 public override OMV.Quaternion APIDTarget { set { return; } }
803 public override bool APIDActive { set { return; } }
804 public override float APIDStrength { set { return; } }
805 public override float APIDDamping { set { return; } }
806
807 public override void AddForce(OMV.Vector3 force, bool pushforce) 618 public override void AddForce(OMV.Vector3 force, bool pushforce)
808 { 619 {
809 // Since this force is being applied in only one step, make this a force per second. 620 // Since this force is being applied in only one step, make this a force per second.
@@ -833,7 +644,7 @@ public sealed class BSCharacter : BSPhysObject
833 } 644 }
834 } 645 }
835 646
836 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 647 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
837 } 648 }
838 public override void SetMomentum(OMV.Vector3 momentum) { 649 public override void SetMomentum(OMV.Vector3 momentum) {
839 } 650 }
@@ -887,7 +698,7 @@ public sealed class BSCharacter : BSPhysObject
887 public override void UpdateProperties(EntityProperties entprop) 698 public override void UpdateProperties(EntityProperties entprop)
888 { 699 {
889 // Don't change position if standing on a stationary object. 700 // Don't change position if standing on a stationary object.
890 if (!_isStationaryStanding) 701 if (!IsStationary)
891 _position = entprop.Position; 702 _position = entprop.Position;
892 703
893 _orientation = entprop.Rotation; 704 _orientation = entprop.Rotation;
@@ -896,8 +707,8 @@ public sealed class BSCharacter : BSPhysObject
896 // and will send agent updates to the clients if velocity changes by more than 707 // and will send agent updates to the clients if velocity changes by more than
897 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many 708 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
898 // extra updates. 709 // extra updates.
899 if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) 710 if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f))
900 _velocity = entprop.Velocity; 711 RawVelocity = entprop.Velocity;
901 712
902 _acceleration = entprop.Acceleration; 713 _acceleration = entprop.Acceleration;
903 _rotationalVelocity = entprop.RotationalVelocity; 714 _rotationalVelocity = entprop.RotationalVelocity;
@@ -920,7 +731,7 @@ public sealed class BSCharacter : BSPhysObject
920 // base.RequestPhysicsterseUpdate(); 731 // base.RequestPhysicsterseUpdate();
921 732
922 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 733 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
923 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 734 LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity);
924 } 735 }
925} 736}
926} 737}