aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs218
1 files changed, 151 insertions, 67 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 2e6b2da..623ac8f 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,14 +86,18 @@ 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;
92 _avatarDensity = PhysicsScene.Params.avatarDensity;
88 93
89 // The dimensions of the avatar capsule are kept in the scale. 94 // The dimensions of the avatar capsule are kept in the scale.
90 // Physics creates a unit capsule which is scaled by the physics engine. 95 // Physics creates a unit capsule which is scaled by the physics engine.
91 ComputeAvatarScale(_size); 96 ComputeAvatarScale(_size);
92 _avatarDensity = PhysicsScene.Params.avatarDensity; 97 // set _avatarVolume and _mass based on capsule size, _density and Scale
93 // set _avatarVolume and _mass based on capsule size, _density and _scale
94 ComputeAvatarVolumeAndMass(); 98 ComputeAvatarVolumeAndMass();
99 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
100 LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw);
95 101
96 ShapeData shapeData = new ShapeData(); 102 ShapeData shapeData = new ShapeData();
97 shapeData.ID = LocalID; 103 shapeData.ID = LocalID;
@@ -99,28 +105,22 @@ public class BSCharacter : BSPhysObject
99 shapeData.Position = _position; 105 shapeData.Position = _position;
100 shapeData.Rotation = _orientation; 106 shapeData.Rotation = _orientation;
101 shapeData.Velocity = _velocity; 107 shapeData.Velocity = _velocity;
102 shapeData.Scale = _scale; 108 shapeData.Size = Scale;
109 shapeData.Scale = Scale;
103 shapeData.Mass = _mass; 110 shapeData.Mass = _mass;
104 shapeData.Buoyancy = _buoyancy; 111 shapeData.Buoyancy = _buoyancy;
105 shapeData.Static = ShapeData.numericFalse; 112 shapeData.Static = ShapeData.numericFalse;
106 shapeData.Friction = PhysicsScene.Params.avatarFriction; 113 shapeData.Friction = PhysicsScene.Params.avatarStandingFriction;
107 shapeData.Restitution = PhysicsScene.Params.avatarRestitution; 114 shapeData.Restitution = PhysicsScene.Params.avatarRestitution;
108 115
109 // do actual create at taint time 116 // do actual create at taint time
110 PhysicsScene.TaintedObject("BSCharacter.create", delegate() 117 PhysicsScene.TaintedObject("BSCharacter.create", delegate()
111 { 118 {
112 DetailLog("{0},BSCharacter.create,taint", LocalID); 119 DetailLog("{0},BSCharacter.create,taint", LocalID);
113 BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); 120 // New body and shape into BSBody and BSShape
121 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null);
114 122
115 // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. 123 SetPhysicalProperties();
116 // If not set at creation, the avatar will stop flying when created after crossing a region boundry.
117 BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy);
118
119 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID));
120
121 // This works here because CreateObject has already put the character into the physical world.
122 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr,
123 (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask);
124 }); 124 });
125 return; 125 return;
126 } 126 }
@@ -131,53 +131,85 @@ public class BSCharacter : BSPhysObject
131 DetailLog("{0},BSCharacter.Destroy", LocalID); 131 DetailLog("{0},BSCharacter.Destroy", LocalID);
132 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 132 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
133 { 133 {
134 BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); 134 PhysicsScene.Shapes.DereferenceBody(BSBody, true, null);
135 PhysicsScene.Shapes.DereferenceShape(BSShape, true, null);
135 }); 136 });
136 } 137 }
137 138
139 private void SetPhysicalProperties()
140 {
141 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
142
143 ZeroMotion();
144 ForcePosition = _position;
145 // Set the velocity and compute the proper friction
146 ForceVelocity = _velocity;
147 BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution);
148 BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
149 BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
150 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
151 {
152 BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
153 BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
154 }
155
156 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
157 BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
158
159 BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT);
160
161 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr);
162
163 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
164 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr);
165
166 // Do this after the object has been added to the world
167 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr,
168 (uint)CollisionFilterGroups.AvatarFilter,
169 (uint)CollisionFilterGroups.AvatarMask);
170 }
171
138 public override void RequestPhysicsterseUpdate() 172 public override void RequestPhysicsterseUpdate()
139 { 173 {
140 base.RequestPhysicsterseUpdate(); 174 base.RequestPhysicsterseUpdate();
141 } 175 }
142 // No one calls this method so I don't know what it could possibly mean 176 // No one calls this method so I don't know what it could possibly mean
143 public override bool Stopped { 177 public override bool Stopped { get { return false; } }
144 get { return false; }
145 }
146 public override OMV.Vector3 Size { 178 public override OMV.Vector3 Size {
147 get 179 get
148 { 180 {
149 // Avatar capsule size is kept in the scale parameter. 181 // Avatar capsule size is kept in the scale parameter.
150 return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); 182 return _size;
151 } 183 }
152 184
153 set { 185 set {
154 // When an avatar's size is set, only the height is changed 186 // When an avatar's size is set, only the height is changed.
155 // and that really only depends on the radius.
156 _size = value; 187 _size = value;
157 ComputeAvatarScale(_size); 188 ComputeAvatarScale(_size);
158
159 // TODO: something has to be done with the avatar's vertical position
160
161 ComputeAvatarVolumeAndMass(); 189 ComputeAvatarVolumeAndMass();
190 DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}",
191 LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw);
162 192
163 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 193 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
164 { 194 {
165 BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true); 195 BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
196 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
197 BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
166 }); 198 });
167 199
168 } 200 }
169 } 201 }
170 public override PrimitiveBaseShape Shape { 202 public override OMV.Vector3 Scale { get; set; }
171 set { _pbs = value; 203 public override PrimitiveBaseShape Shape
172 } 204 {
205 set { BaseShape = value; }
173 } 206 }
207
174 public override bool Grabbed { 208 public override bool Grabbed {
175 set { _grabbed = value; 209 set { _grabbed = value; }
176 }
177 } 210 }
178 public override bool Selected { 211 public override bool Selected {
179 set { _selected = value; 212 set { _selected = value; }
180 }
181 } 213 }
182 public override void CrossingFailure() { return; } 214 public override void CrossingFailure() { return; }
183 public override void link(PhysicsActor obj) { return; } 215 public override void link(PhysicsActor obj) { return; }
@@ -204,7 +236,7 @@ public class BSCharacter : BSPhysObject
204 236
205 public override OMV.Vector3 Position { 237 public override OMV.Vector3 Position {
206 get { 238 get {
207 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); 239 // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID);
208 return _position; 240 return _position;
209 } 241 }
210 set { 242 set {
@@ -214,7 +246,7 @@ public class BSCharacter : BSPhysObject
214 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 246 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
215 { 247 {
216 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 248 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
217 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); 249 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
218 }); 250 });
219 } 251 }
220 } 252 }
@@ -263,7 +295,7 @@ public class BSCharacter : BSPhysObject
263 // A version of the sanity check that also makes sure a new position value is 295 // A version of the sanity check that also makes sure a new position value is
264 // pushed back to the physics engine. This routine would be used by anyone 296 // pushed back to the physics engine. This routine would be used by anyone
265 // who is not already pushing the value. 297 // who is not already pushing the value.
266 private bool PositionSanityCheck2(bool inTaintTime) 298 private bool PositionSanityCheck(bool inTaintTime)
267 { 299 {
268 bool ret = false; 300 bool ret = false;
269 if (PositionSanityCheck()) 301 if (PositionSanityCheck())
@@ -273,7 +305,7 @@ public class BSCharacter : BSPhysObject
273 BSScene.TaintCallback sanityOperation = delegate() 305 BSScene.TaintCallback sanityOperation = delegate()
274 { 306 {
275 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 307 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
276 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); 308 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
277 }; 309 };
278 if (inTaintTime) 310 if (inTaintTime)
279 sanityOperation(); 311 sanityOperation();
@@ -284,11 +316,7 @@ public class BSCharacter : BSPhysObject
284 return ret; 316 return ret;
285 } 317 }
286 318
287 public override float Mass { 319 public override float Mass { get { return _mass; } }
288 get {
289 return _mass;
290 }
291 }
292 320
293 // used when we only want this prim's mass and not the linkset thing 321 // used when we only want this prim's mass and not the linkset thing
294 public override float MassRaw { get {return _mass; } } 322 public override float MassRaw { get {return _mass; } }
@@ -301,15 +329,13 @@ public class BSCharacter : BSPhysObject
301 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 329 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
302 { 330 {
303 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 331 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
304 BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force); 332 BulletSimAPI.SetObjectForce2(BSBody.ptr, _force);
305 }); 333 });
306 } 334 }
307 } 335 }
308 336
309 public override int VehicleType { 337 // Avatars don't do vehicles
310 get { return 0; } 338 public override int VehicleType { get { return 0; } set { return; } }
311 set { return; }
312 }
313 public override void VehicleFloatParam(int param, float value) { } 339 public override void VehicleFloatParam(int param, float value) { }
314 public override void VehicleVectorParam(int param, OMV.Vector3 value) {} 340 public override void VehicleVectorParam(int param, OMV.Vector3 value) {}
315 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } 341 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { }
@@ -328,15 +354,37 @@ public class BSCharacter : BSPhysObject
328 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 354 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
329 { 355 {
330 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 356 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
331 BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); 357 ForceVelocity = _velocity;
332 }); 358 });
333 } 359 }
334 } 360 }
335 public override OMV.Vector3 ForceVelocity { 361 public override OMV.Vector3 ForceVelocity {
336 get { return _velocity; } 362 get { return _velocity; }
337 set { 363 set {
364 // Depending on whether the avatar is moving or not, change the friction
365 // to keep the avatar from slipping around
366 if (_velocity.Length() == 0)
367 {
368 if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
369 {
370 _currentFriction = PhysicsScene.Params.avatarStandingFriction;
371 BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction);
372 }
373 }
374 else
375 {
376 if (_currentFriction != PhysicsScene.Params.avatarFriction)
377 {
378 _currentFriction = PhysicsScene.Params.avatarFriction;
379 BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction);
380 }
381 }
338 _velocity = value; 382 _velocity = value;
339 BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); 383 // Remember the set velocity so we can suppress the reduction by friction, ...
384 _appliedVelocity = value;
385
386 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
387 BulletSimAPI.Activate2(BSBody.ptr, true);
340 } 388 }
341 } 389 }
342 public override OMV.Vector3 Torque { 390 public override OMV.Vector3 Torque {
@@ -360,8 +408,8 @@ public class BSCharacter : BSPhysObject
360 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 408 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
361 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() 409 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
362 { 410 {
363 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); 411 // _position = BulletSimAPI.GetPosition2(BSBody.ptr);
364 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); 412 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
365 }); 413 });
366 } 414 }
367 } 415 }
@@ -389,12 +437,18 @@ public class BSCharacter : BSPhysObject
389 set { _isPhysical = value; 437 set { _isPhysical = value;
390 } 438 }
391 } 439 }
440 public override bool IsSolid {
441 get { return true; }
442 }
443 public override bool IsStatic {
444 get { return false; }
445 }
392 public override bool Flying { 446 public override bool Flying {
393 get { return _flying; } 447 get { return _flying; }
394 set { 448 set {
395 _flying = value; 449 _flying = value;
396 // simulate flying by changing the effect of gravity 450 // simulate flying by changing the effect of gravity
397 this.Buoyancy = ComputeBuoyancyFromFlying(_flying); 451 Buoyancy = ComputeBuoyancyFromFlying(_flying);
398 } 452 }
399 } 453 }
400 // Flying is implimented by changing the avatar's buoyancy. 454 // Flying is implimented by changing the avatar's buoyancy.
@@ -454,10 +508,19 @@ public class BSCharacter : BSPhysObject
454 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() 508 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
455 { 509 {
456 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 510 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
457 BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); 511 ForceBuoyancy = _buoyancy;
458 }); 512 });
459 } 513 }
460 } 514 }
515 public override float ForceBuoyancy {
516 get { return _buoyancy; }
517 set { _buoyancy = value;
518 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
519 // Buoyancy is faked by changing the gravity applied to the object
520 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
521 BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav));
522 }
523 }
461 524
462 // Used for MoveTo 525 // Used for MoveTo
463 public override OMV.Vector3 PIDTarget { 526 public override OMV.Vector3 PIDTarget {
@@ -518,27 +581,32 @@ public class BSCharacter : BSPhysObject
518 581
519 private void ComputeAvatarScale(OMV.Vector3 size) 582 private void ComputeAvatarScale(OMV.Vector3 size)
520 { 583 {
521 _scale.X = PhysicsScene.Params.avatarCapsuleRadius; 584 // The 'size' given by the simulator is the mid-point of the avatar
522 _scale.Y = PhysicsScene.Params.avatarCapsuleRadius; 585 // and X and Y are unspecified.
523 586
524 // The 1.15 came from ODE but it seems to cause the avatar to float off the ground 587 OMV.Vector3 newScale = OMV.Vector3.Zero;
525 // _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); 588 newScale.X = PhysicsScene.Params.avatarCapsuleRadius;
526 _scale.Z = (_size.Z) - (_scale.X + _scale.Y); 589 newScale.Y = PhysicsScene.Params.avatarCapsuleRadius;
590
591 // From the total height, remote the capsule half spheres that are at each end
592 newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y);
593 // newScale.Z = (size.Z * 2f);
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 }
@@ -553,7 +621,23 @@ public class BSCharacter : BSPhysObject
553 _acceleration = entprop.Acceleration; 621 _acceleration = entprop.Acceleration;
554 _rotationalVelocity = entprop.RotationalVelocity; 622 _rotationalVelocity = entprop.RotationalVelocity;
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 PositionSanityCheck(true);
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);
557 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();