diff options
author | onefang | 2019-09-11 16:36:50 +1000 |
---|---|---|
committer | onefang | 2019-09-11 16:36:50 +1000 |
commit | 50cd1ffd32f69228e566f2b0b89f86ea0d9fe489 (patch) | |
tree | 52f2ab0c04f1a5d7d6ac5dc872981b4b156447e7 /OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs | |
parent | Renamed branch to SledjChisl. (diff) | |
parent | Bump to release flavour, build 0. (diff) | |
download | opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.zip opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.gz opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.bz2 opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.xz |
Merge branch 'SledjChisl'
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs | 323 |
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..6b32bf8 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 = 0; | ||
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 | } |