diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 182 |
1 files changed, 133 insertions, 49 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2e6b2da..7c2f856 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -41,8 +41,6 @@ public class BSCharacter : BSPhysObject | |||
41 | 41 | ||
42 | // private bool _stopped; | 42 | // private bool _stopped; |
43 | private OMV.Vector3 _size; | 43 | private OMV.Vector3 _size; |
44 | private OMV.Vector3 _scale; | ||
45 | private PrimitiveBaseShape _pbs; | ||
46 | private bool _grabbed; | 44 | private bool _grabbed; |
47 | private bool _selected; | 45 | private bool _selected; |
48 | private OMV.Vector3 _position; | 46 | private OMV.Vector3 _position; |
@@ -67,6 +65,10 @@ public class BSCharacter : BSPhysObject | |||
67 | private bool _kinematic; | 65 | private bool _kinematic; |
68 | private float _buoyancy; | 66 | private float _buoyancy; |
69 | 67 | ||
68 | // The friction and velocity of the avatar is modified depending on whether walking or not. | ||
69 | private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar | ||
70 | private float _currentFriction; // the friction currently being used (changed by setVelocity). | ||
71 | |||
70 | private OMV.Vector3 _PIDTarget; | 72 | private OMV.Vector3 _PIDTarget; |
71 | private bool _usePID; | 73 | private bool _usePID; |
72 | private float _PIDTau; | 74 | private float _PIDTau; |
@@ -84,13 +86,15 @@ public class BSCharacter : BSPhysObject | |||
84 | _flying = isFlying; | 86 | _flying = isFlying; |
85 | _orientation = OMV.Quaternion.Identity; | 87 | _orientation = OMV.Quaternion.Identity; |
86 | _velocity = OMV.Vector3.Zero; | 88 | _velocity = OMV.Vector3.Zero; |
89 | _appliedVelocity = OMV.Vector3.Zero; | ||
87 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); | 90 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); |
91 | _currentFriction = PhysicsScene.Params.avatarStandingFriction; | ||
88 | 92 | ||
89 | // The dimensions of the avatar capsule are kept in the scale. | 93 | // The dimensions of the avatar capsule are kept in the scale. |
90 | // Physics creates a unit capsule which is scaled by the physics engine. | 94 | // Physics creates a unit capsule which is scaled by the physics engine. |
91 | ComputeAvatarScale(_size); | 95 | ComputeAvatarScale(_size); |
92 | _avatarDensity = PhysicsScene.Params.avatarDensity; | 96 | _avatarDensity = PhysicsScene.Params.avatarDensity; |
93 | // set _avatarVolume and _mass based on capsule size, _density and _scale | 97 | // set _avatarVolume and _mass based on capsule size, _density and Scale |
94 | ComputeAvatarVolumeAndMass(); | 98 | ComputeAvatarVolumeAndMass(); |
95 | 99 | ||
96 | ShapeData shapeData = new ShapeData(); | 100 | ShapeData shapeData = new ShapeData(); |
@@ -99,24 +103,24 @@ public class BSCharacter : BSPhysObject | |||
99 | shapeData.Position = _position; | 103 | shapeData.Position = _position; |
100 | shapeData.Rotation = _orientation; | 104 | shapeData.Rotation = _orientation; |
101 | shapeData.Velocity = _velocity; | 105 | shapeData.Velocity = _velocity; |
102 | shapeData.Scale = _scale; | 106 | shapeData.Scale = Scale; |
103 | shapeData.Mass = _mass; | 107 | shapeData.Mass = _mass; |
104 | shapeData.Buoyancy = _buoyancy; | 108 | shapeData.Buoyancy = _buoyancy; |
105 | shapeData.Static = ShapeData.numericFalse; | 109 | shapeData.Static = ShapeData.numericFalse; |
106 | shapeData.Friction = PhysicsScene.Params.avatarFriction; | 110 | shapeData.Friction = PhysicsScene.Params.avatarStandingFriction; |
107 | shapeData.Restitution = PhysicsScene.Params.avatarRestitution; | 111 | shapeData.Restitution = PhysicsScene.Params.avatarRestitution; |
108 | 112 | ||
109 | // do actual create at taint time | 113 | // do actual create at taint time |
110 | PhysicsScene.TaintedObject("BSCharacter.create", delegate() | 114 | PhysicsScene.TaintedObject("BSCharacter.create", delegate() |
111 | { | 115 | { |
112 | DetailLog("{0},BSCharacter.create,taint", LocalID); | 116 | DetailLog("{0},BSCharacter.create,taint", LocalID); |
113 | BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); | 117 | PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); |
118 | |||
119 | SetPhysicalProperties(); | ||
114 | 120 | ||
115 | // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. | 121 | // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. |
116 | // If not set at creation, the avatar will stop flying when created after crossing a region boundry. | 122 | // If not set at creation, the avatar will stop flying when created after crossing a region boundry. |
117 | BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); | 123 | ForceBuoyancy = _buoyancy; |
118 | |||
119 | BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); | ||
120 | 124 | ||
121 | // This works here because CreateObject has already put the character into the physical world. | 125 | // This works here because CreateObject has already put the character into the physical world. |
122 | BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, | 126 | BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, |
@@ -131,10 +135,40 @@ public class BSCharacter : BSPhysObject | |||
131 | DetailLog("{0},BSCharacter.Destroy", LocalID); | 135 | DetailLog("{0},BSCharacter.Destroy", LocalID); |
132 | PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() | 136 | PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() |
133 | { | 137 | { |
134 | BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); | 138 | PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); |
139 | PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); | ||
135 | }); | 140 | }); |
136 | } | 141 | } |
137 | 142 | ||
143 | private void SetPhysicalProperties() | ||
144 | { | ||
145 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); | ||
146 | |||
147 | ZeroMotion(); | ||
148 | |||
149 | OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); | ||
150 | BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); | ||
151 | |||
152 | // Set the velocity and compute the proper friction | ||
153 | ForceVelocity = _velocity; | ||
154 | |||
155 | BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); | ||
156 | BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); | ||
157 | |||
158 | BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); | ||
159 | BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | ||
160 | |||
161 | if (PhysicsScene.Params.ccdMotionThreshold > 0f) | ||
162 | { | ||
163 | BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | ||
164 | BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | ||
165 | } | ||
166 | |||
167 | BulletSimAPI.SetActivationState2(BSBody.ptr, (int)ActivationState.DISABLE_DEACTIVATION); | ||
168 | |||
169 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); | ||
170 | } | ||
171 | |||
138 | public override void RequestPhysicsterseUpdate() | 172 | public override void RequestPhysicsterseUpdate() |
139 | { | 173 | { |
140 | base.RequestPhysicsterseUpdate(); | 174 | base.RequestPhysicsterseUpdate(); |
@@ -147,7 +181,7 @@ public class BSCharacter : BSPhysObject | |||
147 | get | 181 | get |
148 | { | 182 | { |
149 | // Avatar capsule size is kept in the scale parameter. | 183 | // Avatar capsule size is kept in the scale parameter. |
150 | return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); | 184 | return new OMV.Vector3(Scale.X * 2, Scale.Y * 2, Scale.Z); |
151 | } | 185 | } |
152 | 186 | ||
153 | set { | 187 | set { |
@@ -162,22 +196,25 @@ public class BSCharacter : BSPhysObject | |||
162 | 196 | ||
163 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() | 197 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() |
164 | { | 198 | { |
165 | BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true); | 199 | BulletSimAPI.SetLocalScaling2(BSBody.ptr, Scale); |
200 | OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); | ||
201 | BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); | ||
166 | }); | 202 | }); |
167 | 203 | ||
168 | } | 204 | } |
169 | } | 205 | } |
170 | public override PrimitiveBaseShape Shape { | 206 | public override OMV.Vector3 Scale { get; set; } |
171 | set { _pbs = value; | 207 | private PrimitiveBaseShape _pbs; |
172 | } | 208 | public override PrimitiveBaseShape Shape |
209 | { | ||
210 | set { _pbs = value;} | ||
173 | } | 211 | } |
212 | |||
174 | public override bool Grabbed { | 213 | public override bool Grabbed { |
175 | set { _grabbed = value; | 214 | set { _grabbed = value; } |
176 | } | ||
177 | } | 215 | } |
178 | public override bool Selected { | 216 | public override bool Selected { |
179 | set { _selected = value; | 217 | set { _selected = value; } |
180 | } | ||
181 | } | 218 | } |
182 | public override void CrossingFailure() { return; } | 219 | public override void CrossingFailure() { return; } |
183 | public override void link(PhysicsActor obj) { return; } | 220 | public override void link(PhysicsActor obj) { return; } |
@@ -204,7 +241,7 @@ public class BSCharacter : BSPhysObject | |||
204 | 241 | ||
205 | public override OMV.Vector3 Position { | 242 | public override OMV.Vector3 Position { |
206 | get { | 243 | get { |
207 | // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); | 244 | // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); |
208 | return _position; | 245 | return _position; |
209 | } | 246 | } |
210 | set { | 247 | set { |
@@ -214,7 +251,7 @@ public class BSCharacter : BSPhysObject | |||
214 | PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() | 251 | PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() |
215 | { | 252 | { |
216 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 253 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
217 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); | 254 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); |
218 | }); | 255 | }); |
219 | } | 256 | } |
220 | } | 257 | } |
@@ -273,7 +310,7 @@ public class BSCharacter : BSPhysObject | |||
273 | BSScene.TaintCallback sanityOperation = delegate() | 310 | BSScene.TaintCallback sanityOperation = delegate() |
274 | { | 311 | { |
275 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 312 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
276 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); | 313 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); |
277 | }; | 314 | }; |
278 | if (inTaintTime) | 315 | if (inTaintTime) |
279 | sanityOperation(); | 316 | sanityOperation(); |
@@ -284,11 +321,7 @@ public class BSCharacter : BSPhysObject | |||
284 | return ret; | 321 | return ret; |
285 | } | 322 | } |
286 | 323 | ||
287 | public override float Mass { | 324 | public override float Mass { get { return _mass; } } |
288 | get { | ||
289 | return _mass; | ||
290 | } | ||
291 | } | ||
292 | 325 | ||
293 | // used when we only want this prim's mass and not the linkset thing | 326 | // used when we only want this prim's mass and not the linkset thing |
294 | public override float MassRaw { get {return _mass; } } | 327 | public override float MassRaw { get {return _mass; } } |
@@ -301,15 +334,13 @@ public class BSCharacter : BSPhysObject | |||
301 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() | 334 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() |
302 | { | 335 | { |
303 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); | 336 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); |
304 | BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force); | 337 | BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); |
305 | }); | 338 | }); |
306 | } | 339 | } |
307 | } | 340 | } |
308 | 341 | ||
309 | public override int VehicleType { | 342 | // Avatars don't do vehicles |
310 | get { return 0; } | 343 | public override int VehicleType { get { return 0; } set { return; } } |
311 | set { return; } | ||
312 | } | ||
313 | public override void VehicleFloatParam(int param, float value) { } | 344 | public override void VehicleFloatParam(int param, float value) { } |
314 | public override void VehicleVectorParam(int param, OMV.Vector3 value) {} | 345 | public override void VehicleVectorParam(int param, OMV.Vector3 value) {} |
315 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } | 346 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } |
@@ -328,15 +359,35 @@ public class BSCharacter : BSPhysObject | |||
328 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() | 359 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() |
329 | { | 360 | { |
330 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); | 361 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); |
331 | BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); | 362 | ForceVelocity = _velocity; |
332 | }); | 363 | }); |
333 | } | 364 | } |
334 | } | 365 | } |
335 | public override OMV.Vector3 ForceVelocity { | 366 | public override OMV.Vector3 ForceVelocity { |
336 | get { return _velocity; } | 367 | get { return _velocity; } |
337 | set { | 368 | set { |
369 | // Depending on whether the avatar is moving or not, change the friction | ||
370 | // to keep the avatar from slipping around | ||
371 | if (_velocity.Length() == 0) | ||
372 | { | ||
373 | if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) | ||
374 | { | ||
375 | _currentFriction = PhysicsScene.Params.avatarStandingFriction; | ||
376 | BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); | ||
377 | } | ||
378 | } | ||
379 | else | ||
380 | { | ||
381 | if (_currentFriction == 999f) | ||
382 | { | ||
383 | _currentFriction = PhysicsScene.Params.avatarFriction; | ||
384 | BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); | ||
385 | } | ||
386 | } | ||
338 | _velocity = value; | 387 | _velocity = value; |
339 | BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); | 388 | _appliedVelocity = value; |
389 | BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); | ||
390 | BulletSimAPI.Activate2(BSBody.ptr, true); | ||
340 | } | 391 | } |
341 | } | 392 | } |
342 | public override OMV.Vector3 Torque { | 393 | public override OMV.Vector3 Torque { |
@@ -360,8 +411,8 @@ public class BSCharacter : BSPhysObject | |||
360 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); | 411 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); |
361 | PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() | 412 | PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() |
362 | { | 413 | { |
363 | // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); | 414 | // _position = BulletSimAPI.GetPosition2(BSBody.ptr); |
364 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); | 415 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); |
365 | }); | 416 | }); |
366 | } | 417 | } |
367 | } | 418 | } |
@@ -389,12 +440,18 @@ public class BSCharacter : BSPhysObject | |||
389 | set { _isPhysical = value; | 440 | set { _isPhysical = value; |
390 | } | 441 | } |
391 | } | 442 | } |
443 | public override bool IsSolid { | ||
444 | get { return true; } | ||
445 | } | ||
446 | public override bool IsStatic { | ||
447 | get { return false; } | ||
448 | } | ||
392 | public override bool Flying { | 449 | public override bool Flying { |
393 | get { return _flying; } | 450 | get { return _flying; } |
394 | set { | 451 | set { |
395 | _flying = value; | 452 | _flying = value; |
396 | // simulate flying by changing the effect of gravity | 453 | // simulate flying by changing the effect of gravity |
397 | this.Buoyancy = ComputeBuoyancyFromFlying(_flying); | 454 | Buoyancy = ComputeBuoyancyFromFlying(_flying); |
398 | } | 455 | } |
399 | } | 456 | } |
400 | // Flying is implimented by changing the avatar's buoyancy. | 457 | // Flying is implimented by changing the avatar's buoyancy. |
@@ -454,10 +511,19 @@ public class BSCharacter : BSPhysObject | |||
454 | PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() | 511 | PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() |
455 | { | 512 | { |
456 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 513 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
457 | BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); | 514 | ForceBuoyancy = _buoyancy; |
458 | }); | 515 | }); |
459 | } | 516 | } |
460 | } | 517 | } |
518 | public override float ForceBuoyancy { | ||
519 | get { return _buoyancy; } | ||
520 | set { _buoyancy = value; | ||
521 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | ||
522 | // Buoyancy is faked by changing the gravity applied to the object | ||
523 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | ||
524 | BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); | ||
525 | } | ||
526 | } | ||
461 | 527 | ||
462 | // Used for MoveTo | 528 | // Used for MoveTo |
463 | public override OMV.Vector3 PIDTarget { | 529 | public override OMV.Vector3 PIDTarget { |
@@ -518,27 +584,29 @@ public class BSCharacter : BSPhysObject | |||
518 | 584 | ||
519 | private void ComputeAvatarScale(OMV.Vector3 size) | 585 | private void ComputeAvatarScale(OMV.Vector3 size) |
520 | { | 586 | { |
521 | _scale.X = PhysicsScene.Params.avatarCapsuleRadius; | 587 | OMV.Vector3 newScale = OMV.Vector3.Zero; |
522 | _scale.Y = PhysicsScene.Params.avatarCapsuleRadius; | 588 | newScale.X = PhysicsScene.Params.avatarCapsuleRadius; |
589 | newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; | ||
523 | 590 | ||
524 | // The 1.15 came from ODE but it seems to cause the avatar to float off the ground | 591 | // The 1.15 came from ODE but it seems to cause the avatar to float off the ground |
525 | // _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); | 592 | // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); |
526 | _scale.Z = (_size.Z) - (_scale.X + _scale.Y); | 593 | newScale.Z = (_size.Z) - (Scale.X + Scale.Y); |
594 | Scale = newScale; | ||
527 | } | 595 | } |
528 | 596 | ||
529 | // set _avatarVolume and _mass based on capsule size, _density and _scale | 597 | // set _avatarVolume and _mass based on capsule size, _density and Scale |
530 | private void ComputeAvatarVolumeAndMass() | 598 | private void ComputeAvatarVolumeAndMass() |
531 | { | 599 | { |
532 | _avatarVolume = (float)( | 600 | _avatarVolume = (float)( |
533 | Math.PI | 601 | Math.PI |
534 | * _scale.X | 602 | * Scale.X |
535 | * _scale.Y // the area of capsule cylinder | 603 | * Scale.Y // the area of capsule cylinder |
536 | * _scale.Z // times height of capsule cylinder | 604 | * Scale.Z // times height of capsule cylinder |
537 | + 1.33333333f | 605 | + 1.33333333f |
538 | * Math.PI | 606 | * Math.PI |
539 | * _scale.X | 607 | * Scale.X |
540 | * Math.Min(_scale.X, _scale.Y) | 608 | * Math.Min(Scale.X, Scale.Y) |
541 | * _scale.Y // plus the volume of the capsule end caps | 609 | * Scale.Y // plus the volume of the capsule end caps |
542 | ); | 610 | ); |
543 | _mass = _avatarDensity * _avatarVolume; | 611 | _mass = _avatarDensity * _avatarVolume; |
544 | } | 612 | } |
@@ -555,6 +623,22 @@ public class BSCharacter : BSPhysObject | |||
555 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. | 623 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. |
556 | PositionSanityCheck2(true); | 624 | PositionSanityCheck2(true); |
557 | 625 | ||
626 | // remember the current and last set values | ||
627 | LastEntityProperties = CurrentEntityProperties; | ||
628 | CurrentEntityProperties = entprop; | ||
629 | |||
630 | if (entprop.Velocity != LastEntityProperties.Velocity) | ||
631 | { | ||
632 | // Changes in the velocity are suppressed in avatars. | ||
633 | // That's just the way they are defined. | ||
634 | OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); | ||
635 | _velocity = avVel; | ||
636 | BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); | ||
637 | } | ||
638 | |||
639 | // Tell the linkset about this | ||
640 | Linkset.UpdateProperties(this); | ||
641 | |||
558 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. | 642 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. |
559 | // base.RequestPhysicsterseUpdate(); | 643 | // base.RequestPhysicsterseUpdate(); |
560 | 644 | ||