aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs323
1 files changed, 186 insertions, 137 deletions
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
index 83fc3a6..d182c34 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
@@ -40,7 +40,6 @@ public sealed class BSCharacter : BSPhysObject
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 // private bool _stopped; 42 // private bool _stopped;
43 private OMV.Vector3 _size;
44 private bool _grabbed; 43 private bool _grabbed;
45 private bool _selected; 44 private bool _selected;
46 private float _mass; 45 private float _mass;
@@ -53,19 +52,21 @@ public sealed class BSCharacter : BSPhysObject
53 private bool _setAlwaysRun; 52 private bool _setAlwaysRun;
54 private bool _throttleUpdates; 53 private bool _throttleUpdates;
55 private bool _floatOnWater; 54 private bool _floatOnWater;
56 private OMV.Vector3 _rotationalVelocity;
57 private bool _kinematic; 55 private bool _kinematic;
58 private float _buoyancy; 56 private float _buoyancy;
59 57
58 private OMV.Vector3 _size;
59 private float _footOffset;
60
60 private BSActorAvatarMove m_moveActor; 61 private BSActorAvatarMove m_moveActor;
61 private const string AvatarMoveActorName = "BSCharacter.AvatarMove"; 62 private const string AvatarMoveActorName = "BSCharacter.AvatarMove";
62 63
63 private OMV.Vector3 _PIDTarget; 64 private OMV.Vector3 _PIDTarget;
64 private float _PIDTau; 65 private float _PIDTau;
65 66
66// public override OMV.Vector3 RawVelocity 67// public override OMV.Vector3 RawVelocity
67// { get { return base.RawVelocity; } 68// { get { return base.RawVelocity; }
68// set { 69// set {
69// if (value != base.RawVelocity) 70// if (value != base.RawVelocity)
70// Util.PrintCallStack(); 71// Util.PrintCallStack();
71// Console.WriteLine("Set rawvel to {0}", value); 72// Console.WriteLine("Set rawvel to {0}", value);
@@ -76,12 +77,12 @@ public sealed class BSCharacter : BSPhysObject
76 public override bool IsIncomplete { get { return false; } } 77 public override bool IsIncomplete { get { return false; } }
77 78
78 public BSCharacter( 79 public BSCharacter(
79 uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 vel, OMV.Vector3 size, bool isFlying) 80 uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 vel, OMV.Vector3 size, float footOffset, bool isFlying)
80 81
81 : base(parent_scene, localID, avName, "BSCharacter") 82 : base(parent_scene, localID, avName, "BSCharacter")
82 { 83 {
83 _physicsActorType = (int)ActorTypes.Agent; 84 _physicsActorType = (int)ActorTypes.Agent;
84 RawPosition = pos; 85 RawPosition = pos;
85 86
86 _flying = isFlying; 87 _flying = isFlying;
87 RawOrientation = OMV.Quaternion.Identity; 88 RawOrientation = OMV.Quaternion.Identity;
@@ -89,22 +90,15 @@ public sealed class BSCharacter : BSPhysObject
89 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 90 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
90 Friction = BSParam.AvatarStandingFriction; 91 Friction = BSParam.AvatarStandingFriction;
91 Density = BSParam.AvatarDensity; 92 Density = BSParam.AvatarDensity;
93 _isPhysical = true;
92 94
93 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 95 // Adjustments for zero X and Y made in Size()
94 // replace with the default values. 96 // This also computes avatar scale, volume, and mass
95 _size = size; 97 SetAvatarSize(size, footOffset, true /* initializing */);
96 if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
97 if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
98
99 // The dimensions of the physical capsule are kept in the scale.
100 // Physics creates a unit capsule which is scaled by the physics engine.
101 Scale = ComputeAvatarScale(_size);
102 // set _avatarVolume and _mass based on capsule size, _density and Scale
103 ComputeAvatarVolumeAndMass();
104 98
105 DetailLog( 99 DetailLog(
106 "{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6},vel={7}", 100 "{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6},vel={7}",
107 LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos, vel); 101 LocalID, Size, Scale, Density, _avatarVolume, RawMass, pos, vel);
108 102
109 // do actual creation in taint time 103 // do actual creation in taint time
110 PhysScene.TaintedObject(LocalID, "BSCharacter.create", delegate() 104 PhysScene.TaintedObject(LocalID, "BSCharacter.create", delegate()
@@ -208,45 +202,68 @@ public sealed class BSCharacter : BSPhysObject
208 public override OMV.Vector3 Size { 202 public override OMV.Vector3 Size {
209 get 203 get
210 { 204 {
211 // Avatar capsule size is kept in the scale parameter.
212 return _size; 205 return _size;
213 } 206 }
214 207
215 set { 208 set {
216 // This is how much the avatar size is changing. Positive means getting bigger. 209 setAvatarSize(value, _footOffset);
217 // The avatar altitude must be adjusted for this change. 210 }
218 float heightChange = value.Z - _size.Z; 211 }
212
213 // OpenSim 0.9 introduces a common avatar size computation
214 public override void setAvatarSize(OMV.Vector3 size, float feetOffset)
215 {
216 SetAvatarSize(size, feetOffset, false /* initializing */);
217 }
219 218
220 _size = value; 219 // Internal version that, if initializing, doesn't do all the updating of the physics engine
220 public void SetAvatarSize(OMV.Vector3 size, float feetOffset, bool initializing)
221 {
222 OMV.Vector3 newSize = size;
223 if (newSize.IsFinite())
224 {
221 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 225 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
222 // replace with the default values. 226 // replace with the default values.
223 if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth; 227 if (newSize.X == 0f) newSize.X = BSParam.AvatarCapsuleDepth;
224 if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth; 228 if (newSize.Y == 0f) newSize.Y = BSParam.AvatarCapsuleWidth;
225 229
226 Scale = ComputeAvatarScale(_size); 230 if (newSize.X < 0.01f) newSize.X = 0.01f;
227 ComputeAvatarVolumeAndMass(); 231 if (newSize.Y < 0.01f) newSize.Y = 0.01f;
228 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", 232 if (newSize.Z < 0.01f) newSize.Z = BSParam.AvatarCapsuleHeight;
229 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 233 }
234 else
235 {
236 newSize = new OMV.Vector3(BSParam.AvatarCapsuleDepth, BSParam.AvatarCapsuleWidth, BSParam.AvatarCapsuleHeight);
237 }
230 238
231 PhysScene.TaintedObject(LocalID, "BSCharacter.setSize", delegate() 239 // This is how much the avatar size is changing. Positive means getting bigger.
232 { 240 // The avatar altitude must be adjusted for this change.
233 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape) 241 float heightChange = newSize.Z - Size.Z;
234 {
235 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
236 UpdatePhysicalMassProperties(RawMass, true);
237 242
238 // Adjust the avatar's position to account for the increase/decrease in size 243 _size = newSize;
239 ForcePosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, RawPosition.Z + heightChange / 2f);
240 244
241 // Make sure this change appears as a property update event 245 Scale = ComputeAvatarScale(Size);
242 PhysScene.PE.PushUpdate(PhysBody); 246 ComputeAvatarVolumeAndMass();
243 } 247 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
244 }); 248 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
245 249
246 } 250 PhysScene.TaintedObject(LocalID, "BSCharacter.setSize", delegate()
251 {
252 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
253 {
254 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
255 UpdatePhysicalMassProperties(RawMass, true);
256
257 // Adjust the avatar's position to account for the increase/decrease in size
258 ForcePosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, RawPosition.Z + heightChange / 2f);
259
260 // Make sure this change appears as a property update event
261 PhysScene.PE.PushUpdate(PhysBody);
262 }
263 });
247 } 264 }
248 265
249 public override PrimitiveBaseShape Shape 266 public override PrimitiveBaseShape Shape
250 { 267 {
251 set { BaseShape = value; } 268 set { BaseShape = value; }
252 } 269 }
@@ -273,7 +290,7 @@ public sealed class BSCharacter : BSPhysObject
273 { 290 {
274 RawVelocity = OMV.Vector3.Zero; 291 RawVelocity = OMV.Vector3.Zero;
275 _acceleration = OMV.Vector3.Zero; 292 _acceleration = OMV.Vector3.Zero;
276 _rotationalVelocity = OMV.Vector3.Zero; 293 RawRotationalVelocity = OMV.Vector3.Zero;
277 294
278 // Zero some other properties directly into the physics engine 295 // Zero some other properties directly into the physics engine
279 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate() 296 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
@@ -285,7 +302,7 @@ public sealed class BSCharacter : BSPhysObject
285 302
286 public override void ZeroAngularMotion(bool inTaintTime) 303 public override void ZeroAngularMotion(bool inTaintTime)
287 { 304 {
288 _rotationalVelocity = OMV.Vector3.Zero; 305 RawRotationalVelocity = OMV.Vector3.Zero;
289 306
290 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate() 307 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
291 { 308 {
@@ -300,7 +317,7 @@ public sealed class BSCharacter : BSPhysObject
300 } 317 }
301 318
302 319
303 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 320 public override void LockAngularMotion(byte axislocks) { return; }
304 321
305 public override OMV.Vector3 Position { 322 public override OMV.Vector3 Position {
306 get { 323 get {
@@ -333,7 +350,6 @@ public sealed class BSCharacter : BSPhysObject
333 } 350 }
334 } 351 }
335 352
336
337 // Check that the current position is sane and, if not, modify the position to make it so. 353 // Check that the current position is sane and, if not, modify the position to make it so.
338 // Check for being below terrain or on water. 354 // Check for being below terrain or on water.
339 // Returns 'true' of the position was made sane by some action. 355 // Returns 'true' of the position was made sane by some action.
@@ -433,6 +449,7 @@ public sealed class BSCharacter : BSPhysObject
433 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } 449 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
434 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } 450 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
435 451
452 // PhysicsActor.TargetVelocity
436 // Sets the target in the motor. This starts the changing of the avatar's velocity. 453 // Sets the target in the motor. This starts the changing of the avatar's velocity.
437 public override OMV.Vector3 TargetVelocity 454 public override OMV.Vector3 TargetVelocity
438 { 455 {
@@ -443,43 +460,51 @@ public sealed class BSCharacter : BSPhysObject
443 set 460 set
444 { 461 {
445 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value); 462 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value);
446 m_targetVelocity = value;
447 OMV.Vector3 targetVel = value; 463 OMV.Vector3 targetVel = value;
448 if (_setAlwaysRun && !_flying) 464 if (!_flying)
449 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 1f); 465 {
466 if (_setAlwaysRun)
467 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 1f);
468 else
469 if (BSParam.AvatarWalkVelocityFactor != 1f)
470 targetVel *= new OMV.Vector3(BSParam.AvatarWalkVelocityFactor, BSParam.AvatarWalkVelocityFactor, 1f);
471 }
472 base.m_targetVelocity = targetVel;
450 473
451 if (m_moveActor != null) 474 if (m_moveActor != null)
452 m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */); 475 m_moveActor.SetVelocityAndTarget(RawVelocity, base.m_targetVelocity, false /* inTaintTime */);
453 } 476 }
454 } 477 }
455 // Directly setting velocity means this is what the user really wants now. 478 // Directly setting velocity means this is what the user really wants now.
456 public override OMV.Vector3 Velocity { 479 public override OMV.Vector3 Velocity {
457 get { return RawVelocity; } 480 get { return RawVelocity; }
458 set { 481 set {
459 RawVelocity = value; 482 if (m_moveActor != null)
460 OMV.Vector3 vel = RawVelocity;
461
462 DetailLog("{0}: set Velocity = {1}", LocalID, value);
463
464 PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
465 { 483 {
466 if (m_moveActor != null) 484 // m_moveActor.SetVelocityAndTarget(OMV.Vector3.Zero, OMV.Vector3.Zero, false /* inTaintTime */);
467 m_moveActor.SetVelocityAndTarget(vel, vel, true /* inTaintTime */); 485 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false /* inTaintTime */);
486 }
487 base.Velocity = value;
488 }
489 }
468 490
469 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, vel); 491 // SetMomentum just sets the velocity without a target. We need to stop the movement actor if a character.
470 ForceVelocity = vel; 492 public override void SetMomentum(OMV.Vector3 momentum)
471 }); 493 {
494 if (m_moveActor != null)
495 {
496 // m_moveActor.SetVelocityAndTarget(OMV.Vector3.Zero, OMV.Vector3.Zero, false /* inTaintTime */);
497 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false /* inTaintTime */);
472 } 498 }
499 base.SetMomentum(momentum);
473 } 500 }
474 501
475 public override OMV.Vector3 ForceVelocity { 502 public override OMV.Vector3 ForceVelocity {
476 get { return RawVelocity; } 503 get { return RawVelocity; }
477 set { 504 set {
478 PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity"); 505 DetailLog("{0},BSCharacter.ForceVelocity.set={1}", LocalID, value);
479// Util.PrintCallStack();
480 DetailLog("{0}: set ForceVelocity = {1}", LocalID, value);
481 506
482 RawVelocity = value; 507 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
483 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity); 508 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
484 PhysScene.PE.Activate(PhysBody, true); 509 PhysScene.PE.Activate(PhysBody, true);
485 } 510 }
@@ -600,14 +625,6 @@ public sealed class BSCharacter : BSPhysObject
600 }); 625 });
601 } 626 }
602 } 627 }
603 public override OMV.Vector3 RotationalVelocity {
604 get { return _rotationalVelocity; }
605 set { _rotationalVelocity = value; }
606 }
607 public override OMV.Vector3 ForceRotationalVelocity {
608 get { return _rotationalVelocity; }
609 set { _rotationalVelocity = value; }
610 }
611 public override bool Kinematic { 628 public override bool Kinematic {
612 get { return _kinematic; } 629 get { return _kinematic; }
613 set { _kinematic = value; } 630 set { _kinematic = value; }
@@ -626,8 +643,6 @@ public sealed class BSCharacter : BSPhysObject
626 public override float ForceBuoyancy { 643 public override float ForceBuoyancy {
627 get { return _buoyancy; } 644 get { return _buoyancy; }
628 set { 645 set {
629 PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
630
631 _buoyancy = value; 646 _buoyancy = value;
632 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 647 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
633 // Buoyancy is faked by changing the gravity applied to the object 648 // Buoyancy is faked by changing the gravity applied to the object
@@ -652,14 +667,24 @@ public sealed class BSCharacter : BSPhysObject
652 public override void AddForce(OMV.Vector3 force, bool pushforce) 667 public override void AddForce(OMV.Vector3 force, bool pushforce)
653 { 668 {
654 // Since this force is being applied in only one step, make this a force per second. 669 // Since this force is being applied in only one step, make this a force per second.
655 OMV.Vector3 addForce = force / PhysScene.LastTimeStep; 670 OMV.Vector3 addForce = force;
656 AddForce(addForce, pushforce, false); 671
672 // The interaction of this force with the simulator rate and collision occurance is tricky.
673 // ODE multiplies the force by 100
674 // ubODE multiplies the force by 5.3
675 // BulletSim, after much in-world testing, thinks it gets a similar effect by multiplying mass*0.315f
676 // This number could be a feature of friction or timing, but it seems to move avatars the same as ubODE
677 addForce *= Mass * BSParam.AvatarAddForcePushFactor;
678
679 DetailLog("{0},BSCharacter.addForce,call,force={1},addForce={2},push={3},mass={4}", LocalID, force, addForce, pushforce, Mass);
680 AddForce(false, addForce);
657 } 681 }
658 public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 682
683 public override void AddForce(bool inTaintTime, OMV.Vector3 force) {
659 if (force.IsFinite()) 684 if (force.IsFinite())
660 { 685 {
661 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 686 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
662 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); 687 // DetailLog("{0},BSCharacter.addForce,call,force={1},push={2},inTaint={3}", LocalID, addForce, pushforce, inTaintTime);
663 688
664 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.AddForce", delegate() 689 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.AddForce", delegate()
665 { 690 {
@@ -667,7 +692,15 @@ public sealed class BSCharacter : BSPhysObject
667 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); 692 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
668 if (PhysBody.HasPhysicalBody) 693 if (PhysBody.HasPhysicalBody)
669 { 694 {
695 // Bullet adds this central force to the total force for this tick.
696 // Deep down in Bullet:
697 // linearVelocity += totalForce / mass * timeStep;
670 PhysScene.PE.ApplyCentralForce(PhysBody, addForce); 698 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
699 PhysScene.PE.Activate(PhysBody, true);
700 }
701 if (m_moveActor != null)
702 {
703 m_moveActor.SuppressStationayCheckUntilLowVelocity();
671 } 704 }
672 }); 705 });
673 } 706 }
@@ -678,65 +711,74 @@ public sealed class BSCharacter : BSPhysObject
678 } 711 }
679 } 712 }
680 713
681 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 714 public override void AddAngularForce(bool inTaintTime, OMV.Vector3 force) {
682 }
683 public override void SetMomentum(OMV.Vector3 momentum) {
684 } 715 }
685 716
717 // The avatar's physical shape (whether capsule or cube) is unit sized. BulletSim sets
718 // the scale of that unit shape to create the avatars full size.
686 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size) 719 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size)
687 { 720 {
688 OMV.Vector3 newScale = size; 721 OMV.Vector3 newScale = size;
689 722
690 // Bullet's capsule total height is the "passed height + radius * 2"; 723 if (BSParam.AvatarUseBefore09SizeComputation)
691 // The base capsule is 1 unit in diameter and 2 units in height (passed radius=0.5, passed height = 1) 724 {
692 // The number we pass in for 'scaling' is the multiplier to get that base
693 // shape to be the size desired.
694 // So, when creating the scale for the avatar height, we take the passed height
695 // (size.Z) and remove the caps.
696 // An oddity of the Bullet capsule implementation is that it presumes the Y
697 // dimension is the radius of the capsule. Even though some of the code allows
698 // for a asymmetrical capsule, other parts of the code presume it is cylindrical.
699 725
700 // Scale is multiplier of radius with one of "0.5" 726 // Bullet's capsule total height is the "passed height + radius * 2";
727 // The base capsule is 1 unit in diameter and 2 units in height (passed radius=0.5, passed height = 1)
728 // The number we pass in for 'scaling' is the multiplier to get that base
729 // shape to be the size desired.
730 // So, when creating the scale for the avatar height, we take the passed height
731 // (size.Z) and remove the caps.
732 // An oddity of the Bullet capsule implementation is that it presumes the Y
733 // dimension is the radius of the capsule. Even though some of the code allows
734 // for a asymmetrical capsule, other parts of the code presume it is cylindrical.
701 735
702 float heightAdjust = BSParam.AvatarHeightMidFudge; 736 // Scale is multiplier of radius with one of "0.5"
703 if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f) 737
704 { 738 float heightAdjust = BSParam.AvatarHeightMidFudge;
705 const float AVATAR_LOW = 1.1f; 739 if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f)
706 const float AVATAR_MID = 1.775f; // 1.87f
707 const float AVATAR_HI = 2.45f;
708 // An avatar is between 1.1 and 2.45 meters. Midpoint is 1.775m.
709 float midHeightOffset = size.Z - AVATAR_MID;
710 if (midHeightOffset < 0f)
711 { 740 {
712 // Small avatar. Add the adjustment based on the distance from midheight 741 const float AVATAR_LOW = 1.1f;
713 heightAdjust += ((-1f * midHeightOffset) / (AVATAR_MID - AVATAR_LOW)) * BSParam.AvatarHeightLowFudge; 742 const float AVATAR_MID = 1.775f; // 1.87f
743 const float AVATAR_HI = 2.45f;
744 // An avatar is between 1.1 and 2.45 meters. Midpoint is 1.775m.
745 float midHeightOffset = size.Z - AVATAR_MID;
746 if (midHeightOffset < 0f)
747 {
748 // Small avatar. Add the adjustment based on the distance from midheight
749 heightAdjust += ((-1f * midHeightOffset) / (AVATAR_MID - AVATAR_LOW)) * BSParam.AvatarHeightLowFudge;
750 }
751 else
752 {
753 // Large avatar. Add the adjustment based on the distance from midheight
754 heightAdjust += ((midHeightOffset) / (AVATAR_HI - AVATAR_MID)) * BSParam.AvatarHeightHighFudge;
755 }
756 }
757 if (BSParam.AvatarShape == BSShapeCollection.AvatarShapeCapsule)
758 {
759 newScale.X = size.X / 2f;
760 newScale.Y = size.Y / 2f;
761 // The total scale height is the central cylindar plus the caps on the two ends.
762 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2) + heightAdjust) / 2f;
714 } 763 }
715 else 764 else
716 { 765 {
717 // Large avatar. Add the adjustment based on the distance from midheight 766 newScale.Z = size.Z + heightAdjust;
718 heightAdjust += ((midHeightOffset) / (AVATAR_HI - AVATAR_MID)) * BSParam.AvatarHeightHighFudge;
719 } 767 }
720 } 768 // m_log.DebugFormat("{0} ComputeAvatarScale: size={1},adj={2},scale={3}", LogHeader, size, heightAdjust, newScale);
721 if (BSParam.AvatarShape == BSShapeCollection.AvatarShapeCapsule) 769
722 { 770 // If smaller than the endcaps, just fake like we're almost that small
723 newScale.X = size.X / 2f; 771 if (newScale.Z < 0)
724 newScale.Y = size.Y / 2f; 772 newScale.Z = 0.1f;
725 // The total scale height is the central cylindar plus the caps on the two ends. 773
726 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2) + heightAdjust) / 2f; 774 DetailLog("{0},BSCharacter.ComputeAvatarScale,size={1},lowF={2},midF={3},hiF={4},adj={5},newScale={6}",
775 LocalID, size, BSParam.AvatarHeightLowFudge, BSParam.AvatarHeightMidFudge, BSParam.AvatarHeightHighFudge, heightAdjust, newScale);
727 } 776 }
728 else 777 else
729 { 778 {
730 newScale.Z = size.Z + heightAdjust; 779 newScale.Z = size.Z + _footOffset;
780 DetailLog("{0},BSCharacter.ComputeAvatarScale,using newScale={1}, footOffset={2}", LocalID, newScale, _footOffset);
731 } 781 }
732 // m_log.DebugFormat("{0} ComputeAvatarScale: size={1},adj={2},scale={3}", LogHeader, size, heightAdjust, newScale);
733
734 // If smaller than the endcaps, just fake like we're almost that small
735 if (newScale.Z < 0)
736 newScale.Z = 0.1f;
737
738 DetailLog("{0},BSCharacter.ComputerAvatarScale,size={1},lowF={2},midF={3},hiF={4},adj={5},newScale={6}",
739 LocalID, size, BSParam.AvatarHeightLowFudge, BSParam.AvatarHeightMidFudge, BSParam.AvatarHeightHighFudge, heightAdjust, newScale);
740 782
741 return newScale; 783 return newScale;
742 } 784 }
@@ -744,17 +786,24 @@ public sealed class BSCharacter : BSPhysObject
744 // set _avatarVolume and _mass based on capsule size, _density and Scale 786 // set _avatarVolume and _mass based on capsule size, _density and Scale
745 private void ComputeAvatarVolumeAndMass() 787 private void ComputeAvatarVolumeAndMass()
746 { 788 {
747 _avatarVolume = (float)( 789 if (BSParam.AvatarShape == BSShapeCollection.AvatarShapeCapsule)
748 Math.PI 790 {
749 * Size.X / 2f 791 _avatarVolume = (float)(
750 * Size.Y / 2f // the area of capsule cylinder 792 Math.PI
751 * Size.Z // times height of capsule cylinder 793 * Size.X / 2f
752 + 1.33333333f 794 * Size.Y / 2f // the area of capsule cylinder
753 * Math.PI 795 * Size.Z // times height of capsule cylinder
754 * Size.X / 2f 796 + 1.33333333f
755 * Math.Min(Size.X, Size.Y) / 2 797 * Math.PI
756 * Size.Y / 2f // plus the volume of the capsule end caps 798 * Size.X / 2f
757 ); 799 * Math.Min(Size.X, Size.Y) / 2
800 * Size.Y / 2f // plus the volume of the capsule end caps
801 );
802 }
803 else
804 {
805 _avatarVolume = Size.X * Size.Y * Size.Z;
806 }
758 _mass = Density * BSParam.DensityScaleFactor * _avatarVolume; 807 _mass = Density * BSParam.DensityScaleFactor * _avatarVolume;
759 } 808 }
760 809
@@ -773,7 +822,7 @@ public sealed class BSCharacter : BSPhysObject
773 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many 822 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
774 // extra updates. 823 // extra updates.
775 // 824 //
776 // XXX: Contrary to the above comment, setting an update threshold here above 0.4 actually introduces jitter to 825 // XXX: Contrary to the above comment, setting an update threshold here above 0.4 actually introduces jitter to
777 // avatar movement rather than removes it. The larger the threshold, the bigger the jitter. 826 // avatar movement rather than removes it. The larger the threshold, the bigger the jitter.
778 // This is most noticeable in level flight and can be seen with 827 // This is most noticeable in level flight and can be seen with
779 // the "show updates" option in a viewer. With an update threshold, the RawVelocity cycles between a lower 828 // the "show updates" option in a viewer. With an update threshold, the RawVelocity cycles between a lower
@@ -787,7 +836,7 @@ public sealed class BSCharacter : BSPhysObject
787 RawVelocity = entprop.Velocity; 836 RawVelocity = entprop.Velocity;
788 837
789 _acceleration = entprop.Acceleration; 838 _acceleration = entprop.Acceleration;
790 _rotationalVelocity = entprop.RotationalVelocity; 839 RawRotationalVelocity = entprop.RotationalVelocity;
791 840
792 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. 841 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
793 if (PositionSanityCheck(true)) 842 if (PositionSanityCheck(true))
@@ -807,7 +856,7 @@ public sealed class BSCharacter : BSPhysObject
807 // PhysScene.PostUpdate(this); 856 // PhysScene.PostUpdate(this);
808 857
809 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 858 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
810 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity); 859 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, RawRotationalVelocity);
811 } 860 }
812} 861}
813} 862}