diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 432 |
1 files changed, 137 insertions, 295 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 90c2d9c..48f842e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
@@ -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; |
@@ -62,15 +59,12 @@ public sealed class BSCharacter : BSPhysObject | |||
62 | private bool _kinematic; | 59 | private bool _kinematic; |
63 | private float _buoyancy; | 60 | private float _buoyancy; |
64 | 61 | ||
65 | private BSVMotor _velocityMotor; | 62 | private BSActorAvatarMove m_moveActor; |
63 | private const string AvatarMoveActorName = "BSCharacter.AvatarMove"; | ||
66 | 64 | ||
67 | private OMV.Vector3 _PIDTarget; | 65 | private OMV.Vector3 _PIDTarget; |
68 | private bool _usePID; | 66 | private bool _usePID; |
69 | private float _PIDTau; | 67 | private float _PIDTau; |
70 | private bool _useHoverPID; | ||
71 | private float _PIDHoverHeight; | ||
72 | private PIDHoverType _PIDHoverType; | ||
73 | private float _PIDHoverTao; | ||
74 | 68 | ||
75 | 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) |
76 | : base(parent_scene, localID, avName, "BSCharacter") | 70 | : base(parent_scene, localID, avName, "BSCharacter") |
@@ -80,7 +74,7 @@ public sealed class BSCharacter : BSPhysObject | |||
80 | 74 | ||
81 | _flying = isFlying; | 75 | _flying = isFlying; |
82 | _orientation = OMV.Quaternion.Identity; | 76 | _orientation = OMV.Quaternion.Identity; |
83 | _velocity = OMV.Vector3.Zero; | 77 | RawVelocity = OMV.Vector3.Zero; |
84 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); | 78 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); |
85 | Friction = BSParam.AvatarStandingFriction; | 79 | Friction = BSParam.AvatarStandingFriction; |
86 | Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; | 80 | Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; |
@@ -97,17 +91,22 @@ public sealed class BSCharacter : BSPhysObject | |||
97 | // set _avatarVolume and _mass based on capsule size, _density and Scale | 91 | // set _avatarVolume and _mass based on capsule size, _density and Scale |
98 | ComputeAvatarVolumeAndMass(); | 92 | ComputeAvatarVolumeAndMass(); |
99 | 93 | ||
100 | 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(PhysScene, this, AvatarMoveActorName); | ||
99 | PhysicalActors.Add(AvatarMoveActorName, m_moveActor); | ||
101 | 100 | ||
102 | 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}", |
103 | LocalID, _size, Scale, Density, _avatarVolume, RawMass); | 102 | LocalID, _size, Scale, Density, _avatarVolume, RawMass); |
104 | 103 | ||
105 | // do actual creation in taint time | 104 | // do actual creation in taint time |
106 | PhysicsScene.TaintedObject("BSCharacter.create", delegate() | 105 | PhysScene.TaintedObject("BSCharacter.create", delegate() |
107 | { | 106 | { |
108 | DetailLog("{0},BSCharacter.create,taint", LocalID); | 107 | DetailLog("{0},BSCharacter.create,taint", LocalID); |
109 | // New body and shape into PhysBody and PhysShape | 108 | // New body and shape into PhysBody and PhysShape |
110 | PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this); | 109 | PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this); |
111 | 110 | ||
112 | SetPhysicalProperties(); | 111 | SetPhysicalProperties(); |
113 | }); | 112 | }); |
@@ -120,214 +119,63 @@ public sealed class BSCharacter : BSPhysObject | |||
120 | base.Destroy(); | 119 | base.Destroy(); |
121 | 120 | ||
122 | DetailLog("{0},BSCharacter.Destroy", LocalID); | 121 | DetailLog("{0},BSCharacter.Destroy", LocalID); |
123 | PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() | 122 | PhysScene.TaintedObject("BSCharacter.destroy", delegate() |
124 | { | 123 | { |
125 | PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); | 124 | PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); |
126 | PhysBody.Clear(); | 125 | PhysBody.Clear(); |
127 | PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */); | 126 | PhysShape.Dereference(PhysScene); |
128 | PhysShape.Clear(); | 127 | PhysShape = new BSShapeNull(); |
129 | }); | 128 | }); |
130 | } | 129 | } |
131 | 130 | ||
132 | private void SetPhysicalProperties() | 131 | private void SetPhysicalProperties() |
133 | { | 132 | { |
134 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); | 133 | PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody); |
135 | 134 | ||
136 | ZeroMotion(true); | 135 | ZeroMotion(true); |
137 | ForcePosition = _position; | 136 | ForcePosition = _position; |
138 | 137 | ||
139 | // Set the velocity | 138 | // Set the velocity |
140 | _velocityMotor.Reset(); | 139 | if (m_moveActor != null) |
141 | _velocityMotor.SetTarget(_velocity); | 140 | m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false); |
142 | _velocityMotor.SetCurrent(_velocity); | 141 | |
143 | ForceVelocity = _velocity; | 142 | ForceVelocity = RawVelocity; |
144 | 143 | ||
145 | // This will enable or disable the flying buoyancy of the avatar. | 144 | // This will enable or disable the flying buoyancy of the avatar. |
146 | // 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. |
147 | Flying = _flying; | 146 | Flying = _flying; |
148 | 147 | ||
149 | PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); | 148 | PhysScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); |
150 | PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin); | 149 | PhysScene.PE.SetMargin(PhysShape.physShapeInfo, PhysScene.Params.collisionMargin); |
151 | PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); | 150 | PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale); |
152 | PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); | 151 | PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); |
153 | if (BSParam.CcdMotionThreshold > 0f) | 152 | if (BSParam.CcdMotionThreshold > 0f) |
154 | { | 153 | { |
155 | PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); | 154 | PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); |
156 | PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); | 155 | PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); |
157 | } | 156 | } |
158 | 157 | ||
159 | UpdatePhysicalMassProperties(RawMass, false); | 158 | UpdatePhysicalMassProperties(RawMass, false); |
160 | 159 | ||
161 | // Make so capsule does not fall over | 160 | // Make so capsule does not fall over |
162 | PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); | 161 | PhysScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); |
162 | |||
163 | // The avatar mover sets some parameters. | ||
164 | PhysicalActors.Refresh(); | ||
163 | 165 | ||
164 | PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); | 166 | PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); |
165 | 167 | ||
166 | PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); | 168 | PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody); |
167 | 169 | ||
168 | // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); | 170 | // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); |
169 | PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION); | 171 | PhysScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION); |
170 | PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); | 172 | PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody); |
171 | 173 | ||
172 | // Do this after the object has been added to the world | 174 | // Do this after the object has been added to the world |
173 | PhysBody.collisionType = CollisionType.Avatar; | 175 | PhysBody.collisionType = CollisionType.Avatar; |
174 | PhysBody.ApplyCollisionMask(PhysicsScene); | 176 | PhysBody.ApplyCollisionMask(PhysScene); |
175 | } | ||
176 | |||
177 | // The avatar's movement is controlled by this motor that speeds up and slows down | ||
178 | // the avatar seeking to reach the motor's target speed. | ||
179 | // This motor runs as a prestep action for the avatar so it will keep the avatar | ||
180 | // standing as well as moving. Destruction of the avatar will destroy the pre-step action. | ||
181 | private void SetupMovementMotor() | ||
182 | { | ||
183 | // Infinite decay and timescale values so motor only changes current to target values. | ||
184 | _velocityMotor = new BSVMotor("BSCharacter.Velocity", | ||
185 | 0.2f, // time scale | ||
186 | BSMotor.Infinite, // decay time scale | ||
187 | BSMotor.InfiniteVector, // friction timescale | ||
188 | 1f // efficiency | ||
189 | ); | ||
190 | // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
191 | |||
192 | RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep) | ||
193 | { | ||
194 | // TODO: Decide if the step parameters should be changed depending on the avatar's | ||
195 | // state (flying, colliding, ...). There is code in ODE to do this. | ||
196 | |||
197 | // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity | ||
198 | // specified for the avatar is the one that should be used. For falling, if the avatar | ||
199 | // is not flying and is not colliding then it is presumed to be falling and the Z | ||
200 | // component is not fooled with (thus allowing gravity to do its thing). | ||
201 | // When the avatar is standing, though, the user has specified a velocity of zero and | ||
202 | // the avatar should be standing. But if the avatar is pushed by something in the world | ||
203 | // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to | ||
204 | // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity | ||
205 | // errors can creap in and the avatar will slowly float off in some direction. | ||
206 | // So, the problem is that, when an avatar is standing, we cannot tell creaping error | ||
207 | // from real pushing. | ||
208 | // The code below uses whether the collider is static or moving to decide whether to zero motion. | ||
209 | |||
210 | _velocityMotor.Step(timeStep); | ||
211 | |||
212 | // If we're not supposed to be moving, make sure things are zero. | ||
213 | if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero) | ||
214 | { | ||
215 | // The avatar shouldn't be moving | ||
216 | _velocityMotor.Zero(); | ||
217 | |||
218 | if (IsColliding) | ||
219 | { | ||
220 | // If we are colliding with a stationary object, presume we're standing and don't move around | ||
221 | if (!ColliderIsMoving) | ||
222 | { | ||
223 | DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID); | ||
224 | ZeroMotion(true /* inTaintTime */); | ||
225 | } | ||
226 | |||
227 | // Standing has more friction on the ground | ||
228 | if (Friction != BSParam.AvatarStandingFriction) | ||
229 | { | ||
230 | Friction = BSParam.AvatarStandingFriction; | ||
231 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | ||
232 | } | ||
233 | } | ||
234 | else | ||
235 | { | ||
236 | if (Flying) | ||
237 | { | ||
238 | // Flying and not collising and velocity nearly zero. | ||
239 | ZeroMotion(true /* inTaintTime */); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding); | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | // Supposed to be moving. | ||
248 | OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue; | ||
249 | |||
250 | if (Friction != BSParam.AvatarFriction) | ||
251 | { | ||
252 | // Probably starting up walking. Set friction to moving friction. | ||
253 | Friction = BSParam.AvatarFriction; | ||
254 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | ||
255 | } | ||
256 | |||
257 | // If falling, we keep the world's downward vector no matter what the other axis specify. | ||
258 | // The check for _velocity.Z < 0 makes jumping work (temporary upward force). | ||
259 | if (!Flying && !IsColliding) | ||
260 | { | ||
261 | if (_velocity.Z < 0) | ||
262 | stepVelocity.Z = _velocity.Z; | ||
263 | // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); | ||
264 | } | ||
265 | |||
266 | // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. | ||
267 | OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass; | ||
268 | |||
269 | // Should we check for move force being small and forcing velocity to zero? | ||
270 | |||
271 | // Add special movement force to allow avatars to walk up stepped surfaces. | ||
272 | moveForce += WalkUpStairs(); | ||
273 | |||
274 | DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce); | ||
275 | PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce); | ||
276 | } | ||
277 | }); | ||
278 | } | 177 | } |
279 | 178 | ||
280 | // Decide if the character is colliding with a low object and compute a force to pop the | ||
281 | // avatar up so it can walk up and over the low objects. | ||
282 | private OMV.Vector3 WalkUpStairs() | ||
283 | { | ||
284 | OMV.Vector3 ret = OMV.Vector3.Zero; | ||
285 | |||
286 | // This test is done if moving forward, not flying and is colliding with something. | ||
287 | // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", | ||
288 | // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); | ||
289 | if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) | ||
290 | { | ||
291 | // The range near the character's feet where we will consider stairs | ||
292 | float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f; | ||
293 | float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight; | ||
294 | |||
295 | // Look for a collision point that is near the character's feet and is oriented the same as the charactor is | ||
296 | foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList) | ||
297 | { | ||
298 | // Don't care about collisions with the terrain | ||
299 | if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID) | ||
300 | { | ||
301 | OMV.Vector3 touchPosition = kvp.Value.Position; | ||
302 | // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", | ||
303 | // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); | ||
304 | if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) | ||
305 | { | ||
306 | // This contact is within the 'near the feet' range. | ||
307 | // The normal should be our contact point to the object so it is pointing away | ||
308 | // thus the difference between our facing orientation and the normal should be small. | ||
309 | OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation; | ||
310 | OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); | ||
311 | float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); | ||
312 | if (diff < BSParam.AvatarStepApproachFactor) | ||
313 | { | ||
314 | // Found the stairs contact point. Push up a little to raise the character. | ||
315 | float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor; | ||
316 | ret = new OMV.Vector3(0f, 0f, upForce); | ||
317 | |||
318 | // Also move the avatar up for the new height | ||
319 | OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f); | ||
320 | ForcePosition = RawPosition + displacement; | ||
321 | } | ||
322 | DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}", | ||
323 | LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret); | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | |||
329 | return ret; | ||
330 | } | ||
331 | 179 | ||
332 | public override void RequestPhysicsterseUpdate() | 180 | public override void RequestPhysicsterseUpdate() |
333 | { | 181 | { |
@@ -355,14 +203,14 @@ public sealed class BSCharacter : BSPhysObject | |||
355 | DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", | 203 | DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", |
356 | LocalID, _size, Scale, Density, _avatarVolume, RawMass); | 204 | LocalID, _size, Scale, Density, _avatarVolume, RawMass); |
357 | 205 | ||
358 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() | 206 | PhysScene.TaintedObject("BSCharacter.setSize", delegate() |
359 | { | 207 | { |
360 | if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) | 208 | if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape) |
361 | { | 209 | { |
362 | PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); | 210 | PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale); |
363 | UpdatePhysicalMassProperties(RawMass, true); | 211 | UpdatePhysicalMassProperties(RawMass, true); |
364 | // Make sure this change appears as a property update event | 212 | // Make sure this change appears as a property update event |
365 | PhysicsScene.PE.PushUpdate(PhysBody); | 213 | PhysScene.PE.PushUpdate(PhysBody); |
366 | } | 214 | } |
367 | }); | 215 | }); |
368 | 216 | ||
@@ -373,11 +221,6 @@ public sealed class BSCharacter : BSPhysObject | |||
373 | { | 221 | { |
374 | set { BaseShape = value; } | 222 | set { BaseShape = value; } |
375 | } | 223 | } |
376 | // I want the physics engine to make an avatar capsule | ||
377 | public override BSPhysicsShapeType PreferredPhysicalShape | ||
378 | { | ||
379 | get {return BSPhysicsShapeType.SHAPE_CAPSULE; } | ||
380 | } | ||
381 | 224 | ||
382 | public override bool Grabbed { | 225 | public override bool Grabbed { |
383 | set { _grabbed = value; } | 226 | set { _grabbed = value; } |
@@ -399,29 +242,29 @@ public sealed class BSCharacter : BSPhysObject | |||
399 | // Called at taint time! | 242 | // Called at taint time! |
400 | public override void ZeroMotion(bool inTaintTime) | 243 | public override void ZeroMotion(bool inTaintTime) |
401 | { | 244 | { |
402 | _velocity = OMV.Vector3.Zero; | 245 | RawVelocity = OMV.Vector3.Zero; |
403 | _acceleration = OMV.Vector3.Zero; | 246 | _acceleration = OMV.Vector3.Zero; |
404 | _rotationalVelocity = OMV.Vector3.Zero; | 247 | _rotationalVelocity = OMV.Vector3.Zero; |
405 | 248 | ||
406 | // Zero some other properties directly into the physics engine | 249 | // Zero some other properties directly into the physics engine |
407 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() | 250 | PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() |
408 | { | 251 | { |
409 | if (PhysBody.HasPhysicalBody) | 252 | if (PhysBody.HasPhysicalBody) |
410 | PhysicsScene.PE.ClearAllForces(PhysBody); | 253 | PhysScene.PE.ClearAllForces(PhysBody); |
411 | }); | 254 | }); |
412 | } | 255 | } |
413 | public override void ZeroAngularMotion(bool inTaintTime) | 256 | public override void ZeroAngularMotion(bool inTaintTime) |
414 | { | 257 | { |
415 | _rotationalVelocity = OMV.Vector3.Zero; | 258 | _rotationalVelocity = OMV.Vector3.Zero; |
416 | 259 | ||
417 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() | 260 | PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() |
418 | { | 261 | { |
419 | if (PhysBody.HasPhysicalBody) | 262 | if (PhysBody.HasPhysicalBody) |
420 | { | 263 | { |
421 | PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero); | 264 | PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero); |
422 | PhysicsScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero); | 265 | PhysScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero); |
423 | // The next also get rid of applied linear force but the linear velocity is untouched. | 266 | // The next also get rid of applied linear force but the linear velocity is untouched. |
424 | PhysicsScene.PE.ClearForces(PhysBody); | 267 | PhysScene.PE.ClearForces(PhysBody); |
425 | } | 268 | } |
426 | }); | 269 | }); |
427 | } | 270 | } |
@@ -443,7 +286,7 @@ public sealed class BSCharacter : BSPhysObject | |||
443 | set { | 286 | set { |
444 | _position = value; | 287 | _position = value; |
445 | 288 | ||
446 | PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() | 289 | PhysScene.TaintedObject("BSCharacter.setPosition", delegate() |
447 | { | 290 | { |
448 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 291 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
449 | PositionSanityCheck(); | 292 | PositionSanityCheck(); |
@@ -453,14 +296,14 @@ public sealed class BSCharacter : BSPhysObject | |||
453 | } | 296 | } |
454 | public override OMV.Vector3 ForcePosition { | 297 | public override OMV.Vector3 ForcePosition { |
455 | get { | 298 | get { |
456 | _position = PhysicsScene.PE.GetPosition(PhysBody); | 299 | _position = PhysScene.PE.GetPosition(PhysBody); |
457 | return _position; | 300 | return _position; |
458 | } | 301 | } |
459 | set { | 302 | set { |
460 | _position = value; | 303 | _position = value; |
461 | if (PhysBody.HasPhysicalBody) | 304 | if (PhysBody.HasPhysicalBody) |
462 | { | 305 | { |
463 | PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); | 306 | PhysScene.PE.SetTranslation(PhysBody, _position, _orientation); |
464 | } | 307 | } |
465 | } | 308 | } |
466 | } | 309 | } |
@@ -474,18 +317,18 @@ public sealed class BSCharacter : BSPhysObject | |||
474 | bool ret = false; | 317 | bool ret = false; |
475 | 318 | ||
476 | // TODO: check for out of bounds | 319 | // TODO: check for out of bounds |
477 | if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) | 320 | if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) |
478 | { | 321 | { |
479 | // The character is out of the known/simulated area. | 322 | // The character is out of the known/simulated area. |
480 | // Force the avatar position to be within known. ScenePresence will use the position | 323 | // Force the avatar position to be within known. ScenePresence will use the position |
481 | // plus the velocity to decide if the avatar is moving out of the region. | 324 | // plus the velocity to decide if the avatar is moving out of the region. |
482 | RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); | 325 | RawPosition = PhysScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); |
483 | DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); | 326 | DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); |
484 | return true; | 327 | return true; |
485 | } | 328 | } |
486 | 329 | ||
487 | // If below the ground, move the avatar up | 330 | // If below the ground, move the avatar up |
488 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | 331 | float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); |
489 | if (Position.Z < terrainHeight) | 332 | if (Position.Z < terrainHeight) |
490 | { | 333 | { |
491 | DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); | 334 | DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); |
@@ -494,7 +337,7 @@ public sealed class BSCharacter : BSPhysObject | |||
494 | } | 337 | } |
495 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | 338 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) |
496 | { | 339 | { |
497 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); | 340 | float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(_position); |
498 | if (Position.Z < waterHeight) | 341 | if (Position.Z < waterHeight) |
499 | { | 342 | { |
500 | _position.Z = waterHeight; | 343 | _position.Z = waterHeight; |
@@ -515,7 +358,7 @@ public sealed class BSCharacter : BSPhysObject | |||
515 | { | 358 | { |
516 | // The new position value must be pushed into the physics engine but we can't | 359 | // The new position value must be pushed into the physics engine but we can't |
517 | // just assign to "Position" because of potential call loops. | 360 | // just assign to "Position" because of potential call loops. |
518 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() | 361 | PhysScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() |
519 | { | 362 | { |
520 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 363 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
521 | ForcePosition = _position; | 364 | ForcePosition = _position; |
@@ -528,25 +371,25 @@ public sealed class BSCharacter : BSPhysObject | |||
528 | public override float Mass { get { return _mass; } } | 371 | public override float Mass { get { return _mass; } } |
529 | 372 | ||
530 | // used when we only want this prim's mass and not the linkset thing | 373 | // used when we only want this prim's mass and not the linkset thing |
531 | public override float RawMass { | 374 | public override float RawMass { |
532 | get {return _mass; } | 375 | get {return _mass; } |
533 | } | 376 | } |
534 | public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) | 377 | public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) |
535 | { | 378 | { |
536 | OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); | 379 | OMV.Vector3 localInertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass); |
537 | PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia); | 380 | PhysScene.PE.SetMassProps(PhysBody, physMass, localInertia); |
538 | } | 381 | } |
539 | 382 | ||
540 | public override OMV.Vector3 Force { | 383 | public override OMV.Vector3 Force { |
541 | get { return _force; } | 384 | get { return RawForce; } |
542 | set { | 385 | set { |
543 | _force = value; | 386 | RawForce = value; |
544 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); | 387 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); |
545 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() | 388 | PhysScene.TaintedObject("BSCharacter.SetForce", delegate() |
546 | { | 389 | { |
547 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); | 390 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce); |
548 | if (PhysBody.HasPhysicalBody) | 391 | if (PhysBody.HasPhysicalBody) |
549 | PhysicsScene.PE.SetObjectForce(PhysBody, _force); | 392 | PhysScene.PE.SetObjectForce(PhysBody, RawForce); |
550 | }); | 393 | }); |
551 | } | 394 | } |
552 | } | 395 | } |
@@ -569,61 +412,49 @@ public sealed class BSCharacter : BSPhysObject | |||
569 | { | 412 | { |
570 | get | 413 | get |
571 | { | 414 | { |
572 | return m_targetVelocity; | 415 | return base.m_targetVelocity; |
573 | } | 416 | } |
574 | set | 417 | set |
575 | { | 418 | { |
576 | DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value); | 419 | DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value); |
577 | m_targetVelocity = value; | 420 | m_targetVelocity = value; |
578 | OMV.Vector3 targetVel = value; | 421 | OMV.Vector3 targetVel = value; |
579 | if (_setAlwaysRun) | 422 | if (_setAlwaysRun && !_flying) |
580 | targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); | 423 | targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); |
581 | 424 | ||
582 | PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() | 425 | if (m_moveActor != null) |
583 | { | 426 | m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */); |
584 | _velocityMotor.Reset(); | ||
585 | _velocityMotor.SetTarget(targetVel); | ||
586 | _velocityMotor.SetCurrent(_velocity); | ||
587 | _velocityMotor.Enabled = true; | ||
588 | }); | ||
589 | } | 427 | } |
590 | } | 428 | } |
591 | public override OMV.Vector3 RawVelocity | ||
592 | { | ||
593 | get { return _velocity; } | ||
594 | set { _velocity = value; } | ||
595 | } | ||
596 | // Directly setting velocity means this is what the user really wants now. | 429 | // Directly setting velocity means this is what the user really wants now. |
597 | public override OMV.Vector3 Velocity { | 430 | public override OMV.Vector3 Velocity { |
598 | get { return _velocity; } | 431 | get { return RawVelocity; } |
599 | set { | 432 | set { |
600 | _velocity = value; | 433 | RawVelocity = value; |
601 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); | 434 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity); |
602 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() | 435 | PhysScene.TaintedObject("BSCharacter.setVelocity", delegate() |
603 | { | 436 | { |
604 | _velocityMotor.Reset(); | 437 | if (m_moveActor != null) |
605 | _velocityMotor.SetCurrent(_velocity); | 438 | m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */); |
606 | _velocityMotor.SetTarget(_velocity); | ||
607 | _velocityMotor.Enabled = false; | ||
608 | 439 | ||
609 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); | 440 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity); |
610 | ForceVelocity = _velocity; | 441 | ForceVelocity = RawVelocity; |
611 | }); | 442 | }); |
612 | } | 443 | } |
613 | } | 444 | } |
614 | public override OMV.Vector3 ForceVelocity { | 445 | public override OMV.Vector3 ForceVelocity { |
615 | get { return _velocity; } | 446 | get { return RawVelocity; } |
616 | set { | 447 | set { |
617 | PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); | 448 | PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity"); |
618 | 449 | ||
619 | _velocity = value; | 450 | RawVelocity = value; |
620 | PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); | 451 | PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity); |
621 | PhysicsScene.PE.Activate(PhysBody, true); | 452 | PhysScene.PE.Activate(PhysBody, true); |
622 | } | 453 | } |
623 | } | 454 | } |
624 | public override OMV.Vector3 Torque { | 455 | public override OMV.Vector3 Torque { |
625 | get { return _torque; } | 456 | get { return RawTorque; } |
626 | set { _torque = value; | 457 | set { RawTorque = value; |
627 | } | 458 | } |
628 | } | 459 | } |
629 | public override float CollisionScore { | 460 | public override float CollisionScore { |
@@ -648,9 +479,19 @@ public sealed class BSCharacter : BSPhysObject | |||
648 | if (_orientation != value) | 479 | if (_orientation != value) |
649 | { | 480 | { |
650 | _orientation = value; | 481 | _orientation = value; |
651 | PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() | 482 | PhysScene.TaintedObject("BSCharacter.setOrientation", delegate() |
652 | { | 483 | { |
653 | ForceOrientation = _orientation; | 484 | // Bullet assumes we know what we are doing when forcing orientation |
485 | // so it lets us go against all the rules and just compensates for them later. | ||
486 | // This forces rotation to be only around the Z axis and doesn't change any of the other axis. | ||
487 | // This keeps us from flipping the capsule over which the veiwer does not understand. | ||
488 | float oRoll, oPitch, oYaw; | ||
489 | _orientation.GetEulerAngles(out oRoll, out oPitch, out oYaw); | ||
490 | OMV.Quaternion trimmedOrientation = OMV.Quaternion.CreateFromEulers(0f, 0f, oYaw); | ||
491 | // DetailLog("{0},BSCharacter.setOrientation,taint,val={1},valDir={2},conv={3},convDir={4}", | ||
492 | // LocalID, _orientation, OMV.Vector3.UnitX * _orientation, | ||
493 | // trimmedOrientation, OMV.Vector3.UnitX * trimmedOrientation); | ||
494 | ForceOrientation = trimmedOrientation; | ||
654 | }); | 495 | }); |
655 | } | 496 | } |
656 | } | 497 | } |
@@ -660,7 +501,7 @@ public sealed class BSCharacter : BSPhysObject | |||
660 | { | 501 | { |
661 | get | 502 | get |
662 | { | 503 | { |
663 | _orientation = PhysicsScene.PE.GetOrientation(PhysBody); | 504 | _orientation = PhysScene.PE.GetOrientation(PhysBody); |
664 | return _orientation; | 505 | return _orientation; |
665 | } | 506 | } |
666 | set | 507 | set |
@@ -669,7 +510,7 @@ public sealed class BSCharacter : BSPhysObject | |||
669 | if (PhysBody.HasPhysicalBody) | 510 | if (PhysBody.HasPhysicalBody) |
670 | { | 511 | { |
671 | // _position = PhysicsScene.PE.GetPosition(BSBody); | 512 | // _position = PhysicsScene.PE.GetPosition(BSBody); |
672 | PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); | 513 | PhysScene.PE.SetTranslation(PhysBody, _position, _orientation); |
673 | } | 514 | } |
674 | } | 515 | } |
675 | } | 516 | } |
@@ -718,14 +559,14 @@ public sealed class BSCharacter : BSPhysObject | |||
718 | public override bool FloatOnWater { | 559 | public override bool FloatOnWater { |
719 | set { | 560 | set { |
720 | _floatOnWater = value; | 561 | _floatOnWater = value; |
721 | PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() | 562 | PhysScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() |
722 | { | 563 | { |
723 | if (PhysBody.HasPhysicalBody) | 564 | if (PhysBody.HasPhysicalBody) |
724 | { | 565 | { |
725 | if (_floatOnWater) | 566 | if (_floatOnWater) |
726 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); | 567 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); |
727 | else | 568 | else |
728 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); | 569 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); |
729 | } | 570 | } |
730 | }); | 571 | }); |
731 | } | 572 | } |
@@ -746,7 +587,7 @@ public sealed class BSCharacter : BSPhysObject | |||
746 | public override float Buoyancy { | 587 | public override float Buoyancy { |
747 | get { return _buoyancy; } | 588 | get { return _buoyancy; } |
748 | set { _buoyancy = value; | 589 | set { _buoyancy = value; |
749 | PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() | 590 | PhysScene.TaintedObject("BSCharacter.setBuoyancy", delegate() |
750 | { | 591 | { |
751 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 592 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
752 | ForceBuoyancy = _buoyancy; | 593 | ForceBuoyancy = _buoyancy; |
@@ -755,8 +596,8 @@ public sealed class BSCharacter : BSPhysObject | |||
755 | } | 596 | } |
756 | public override float ForceBuoyancy { | 597 | public override float ForceBuoyancy { |
757 | get { return _buoyancy; } | 598 | get { return _buoyancy; } |
758 | set { | 599 | set { |
759 | PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); | 600 | PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); |
760 | 601 | ||
761 | _buoyancy = value; | 602 | _buoyancy = value; |
762 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 603 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
@@ -764,7 +605,7 @@ public sealed class BSCharacter : BSPhysObject | |||
764 | float grav = BSParam.Gravity * (1f - _buoyancy); | 605 | float grav = BSParam.Gravity * (1f - _buoyancy); |
765 | Gravity = new OMV.Vector3(0f, 0f, grav); | 606 | Gravity = new OMV.Vector3(0f, 0f, grav); |
766 | if (PhysBody.HasPhysicalBody) | 607 | if (PhysBody.HasPhysicalBody) |
767 | PhysicsScene.PE.SetGravity(PhysBody, Gravity); | 608 | PhysScene.PE.SetGravity(PhysBody, Gravity); |
768 | } | 609 | } |
769 | } | 610 | } |
770 | 611 | ||
@@ -779,31 +620,10 @@ public sealed class BSCharacter : BSPhysObject | |||
779 | set { _PIDTau = value; } | 620 | set { _PIDTau = value; } |
780 | } | 621 | } |
781 | 622 | ||
782 | // Used for llSetHoverHeight and maybe vehicle height | ||
783 | // Hover Height will override MoveTo target's Z | ||
784 | public override bool PIDHoverActive { | ||
785 | set { _useHoverPID = value; } | ||
786 | } | ||
787 | public override float PIDHoverHeight { | ||
788 | set { _PIDHoverHeight = value; } | ||
789 | } | ||
790 | public override PIDHoverType PIDHoverType { | ||
791 | set { _PIDHoverType = value; } | ||
792 | } | ||
793 | public override float PIDHoverTau { | ||
794 | set { _PIDHoverTao = value; } | ||
795 | } | ||
796 | |||
797 | // For RotLookAt | ||
798 | public override OMV.Quaternion APIDTarget { set { return; } } | ||
799 | public override bool APIDActive { set { return; } } | ||
800 | public override float APIDStrength { set { return; } } | ||
801 | public override float APIDDamping { set { return; } } | ||
802 | |||
803 | public override void AddForce(OMV.Vector3 force, bool pushforce) | 623 | public override void AddForce(OMV.Vector3 force, bool pushforce) |
804 | { | 624 | { |
805 | // Since this force is being applied in only one step, make this a force per second. | 625 | // Since this force is being applied in only one step, make this a force per second. |
806 | OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; | 626 | OMV.Vector3 addForce = force / PhysScene.LastTimeStep; |
807 | AddForce(addForce, pushforce, false); | 627 | AddForce(addForce, pushforce, false); |
808 | } | 628 | } |
809 | private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { | 629 | private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
@@ -812,13 +632,13 @@ public sealed class BSCharacter : BSPhysObject | |||
812 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); | 632 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); |
813 | // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); | 633 | // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); |
814 | 634 | ||
815 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() | 635 | PhysScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() |
816 | { | 636 | { |
817 | // Bullet adds this central force to the total force for this tick | 637 | // Bullet adds this central force to the total force for this tick |
818 | // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); | 638 | // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); |
819 | if (PhysBody.HasPhysicalBody) | 639 | if (PhysBody.HasPhysicalBody) |
820 | { | 640 | { |
821 | PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); | 641 | PhysScene.PE.ApplyCentralForce(PhysBody, addForce); |
822 | } | 642 | } |
823 | }); | 643 | }); |
824 | } | 644 | } |
@@ -829,7 +649,7 @@ public sealed class BSCharacter : BSPhysObject | |||
829 | } | 649 | } |
830 | } | 650 | } |
831 | 651 | ||
832 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 652 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
833 | } | 653 | } |
834 | public override void SetMomentum(OMV.Vector3 momentum) { | 654 | public override void SetMomentum(OMV.Vector3 momentum) { |
835 | } | 655 | } |
@@ -837,14 +657,14 @@ public sealed class BSCharacter : BSPhysObject | |||
837 | private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size) | 657 | private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size) |
838 | { | 658 | { |
839 | OMV.Vector3 newScale; | 659 | OMV.Vector3 newScale; |
840 | 660 | ||
841 | // Bullet's capsule total height is the "passed height + radius * 2"; | 661 | // Bullet's capsule total height is the "passed height + radius * 2"; |
842 | // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1) | 662 | // The base capsule is 1 unit in diameter and 2 units in height (passed radius=0.5, passed height = 1) |
843 | // The number we pass in for 'scaling' is the multiplier to get that base | 663 | // The number we pass in for 'scaling' is the multiplier to get that base |
844 | // shape to be the size desired. | 664 | // shape to be the size desired. |
845 | // So, when creating the scale for the avatar height, we take the passed height | 665 | // So, when creating the scale for the avatar height, we take the passed height |
846 | // (size.Z) and remove the caps. | 666 | // (size.Z) and remove the caps. |
847 | // Another oddity of the Bullet capsule implementation is that it presumes the Y | 667 | // An oddity of the Bullet capsule implementation is that it presumes the Y |
848 | // dimension is the radius of the capsule. Even though some of the code allows | 668 | // dimension is the radius of the capsule. Even though some of the code allows |
849 | // for a asymmetrical capsule, other parts of the code presume it is cylindrical. | 669 | // for a asymmetrical capsule, other parts of the code presume it is cylindrical. |
850 | 670 | ||
@@ -852,8 +672,27 @@ public sealed class BSCharacter : BSPhysObject | |||
852 | newScale.X = size.X / 2f; | 672 | newScale.X = size.X / 2f; |
853 | newScale.Y = size.Y / 2f; | 673 | newScale.Y = size.Y / 2f; |
854 | 674 | ||
675 | float heightAdjust = BSParam.AvatarHeightMidFudge; | ||
676 | if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f) | ||
677 | { | ||
678 | // An avatar is between 1.61 and 2.12 meters. Midpoint is 1.87m. | ||
679 | // The "times 4" relies on the fact that the difference from the midpoint to the extremes is exactly 0.25 | ||
680 | float midHeightOffset = size.Z - 1.87f; | ||
681 | if (midHeightOffset < 0f) | ||
682 | { | ||
683 | // Small avatar. Add the adjustment based on the distance from midheight | ||
684 | heightAdjust += -1f * midHeightOffset * 4f * BSParam.AvatarHeightLowFudge; | ||
685 | } | ||
686 | else | ||
687 | { | ||
688 | // Large avatar. Add the adjustment based on the distance from midheight | ||
689 | heightAdjust += midHeightOffset * 4f * BSParam.AvatarHeightHighFudge; | ||
690 | } | ||
691 | } | ||
855 | // The total scale height is the central cylindar plus the caps on the two ends. | 692 | // The total scale height is the central cylindar plus the caps on the two ends. |
856 | newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2)) / 2f; | 693 | newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2) + heightAdjust) / 2f; |
694 | // m_log.DebugFormat("{0} ComputeAvatarScale: size={1},adj={2},scale={3}", LogHeader, size, heightAdjust, newScale); | ||
695 | |||
857 | // If smaller than the endcaps, just fake like we're almost that small | 696 | // If smaller than the endcaps, just fake like we're almost that small |
858 | if (newScale.Z < 0) | 697 | if (newScale.Z < 0) |
859 | newScale.Z = 0.1f; | 698 | newScale.Z = 0.1f; |
@@ -882,15 +721,18 @@ public sealed class BSCharacter : BSPhysObject | |||
882 | // the world that things have changed. | 721 | // the world that things have changed. |
883 | public override void UpdateProperties(EntityProperties entprop) | 722 | public override void UpdateProperties(EntityProperties entprop) |
884 | { | 723 | { |
885 | _position = entprop.Position; | 724 | // Don't change position if standing on a stationary object. |
725 | if (!IsStationary) | ||
726 | _position = entprop.Position; | ||
727 | |||
886 | _orientation = entprop.Rotation; | 728 | _orientation = entprop.Rotation; |
887 | 729 | ||
888 | // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar | 730 | // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar |
889 | // and will send agent updates to the clients if velocity changes by more than | 731 | // and will send agent updates to the clients if velocity changes by more than |
890 | // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many | 732 | // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many |
891 | // extra updates. | 733 | // extra updates. |
892 | if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) | 734 | if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f)) |
893 | _velocity = entprop.Velocity; | 735 | RawVelocity = entprop.Velocity; |
894 | 736 | ||
895 | _acceleration = entprop.Acceleration; | 737 | _acceleration = entprop.Acceleration; |
896 | _rotationalVelocity = entprop.RotationalVelocity; | 738 | _rotationalVelocity = entprop.RotationalVelocity; |
@@ -913,7 +755,7 @@ public sealed class BSCharacter : BSPhysObject | |||
913 | // base.RequestPhysicsterseUpdate(); | 755 | // base.RequestPhysicsterseUpdate(); |
914 | 756 | ||
915 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 757 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
916 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 758 | LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity); |
917 | } | 759 | } |
918 | } | 760 | } |
919 | } | 761 | } |