aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs789
1 files changed, 281 insertions, 508 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 6a5461a..e92a1d2 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -51,15 +51,8 @@ public class BSPrim : BSPhysObject
51 private bool _isSelected; 51 private bool _isSelected;
52 private bool _isVolumeDetect; 52 private bool _isVolumeDetect;
53 53
54 // _position is what the simulator thinks the positions of the prim is.
55 private OMV.Vector3 _position;
56
57 private float _mass; // the mass of this object 54 private float _mass; // the mass of this object
58 private OMV.Vector3 _force;
59 private OMV.Vector3 _velocity;
60 private OMV.Vector3 _torque;
61 private OMV.Vector3 _acceleration; 55 private OMV.Vector3 _acceleration;
62 private OMV.Quaternion _orientation;
63 private int _physicsActorType; 56 private int _physicsActorType;
64 private bool _isPhysical; 57 private bool _isPhysical;
65 private bool _flying; 58 private bool _flying;
@@ -72,16 +65,18 @@ public class BSPrim : BSPhysObject
72 65
73 private int CrossingFailures { get; set; } 66 private int CrossingFailures { get; set; }
74 67
75 public BSDynamics VehicleController { get; private set; } 68 // Keep a handle to the vehicle actor so it is easy to set parameters on same.
76 69 public const string VehicleActorName = "BasicVehicle";
77 private BSVMotor _targetMotor;
78 private OMV.Vector3 _PIDTarget;
79 private float _PIDTau;
80 70
81 private BSFMotor _hoverMotor; 71 // Parameters for the hover actor
82 private float _PIDHoverHeight; 72 public const string HoverActorName = "BSPrim.HoverActor";
83 private PIDHoverType _PIDHoverType; 73 // Parameters for the axis lock actor
84 private float _PIDHoverTau; 74 public const String LockedAxisActorName = "BSPrim.LockedAxis";
75 // Parameters for the move to target actor
76 public const string MoveToTargetActorName = "BSPrim.MoveToTargetActor";
77 // Parameters for the setForce and setTorque actors
78 public const string SetForceActorName = "BSPrim.SetForceActor";
79 public const string SetTorqueActorName = "BSPrim.SetTorqueActor";
85 80
86 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 81 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
87 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 82 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
@@ -89,31 +84,32 @@ public class BSPrim : BSPhysObject
89 { 84 {
90 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 85 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
91 _physicsActorType = (int)ActorTypes.Prim; 86 _physicsActorType = (int)ActorTypes.Prim;
92 _position = pos; 87 RawPosition = pos;
93 _size = size; 88 _size = size;
94 Scale = size; // prims are the size the user wants them to be (different for BSCharactes). 89 Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
95 _orientation = rotation; 90 RawOrientation = rotation;
96 _buoyancy = 0f; 91 _buoyancy = 0f;
97 _velocity = OMV.Vector3.Zero; 92 RawVelocity = OMV.Vector3.Zero;
98 _rotationalVelocity = OMV.Vector3.Zero; 93 _rotationalVelocity = OMV.Vector3.Zero;
99 BaseShape = pbs; 94 BaseShape = pbs;
100 _isPhysical = pisPhysical; 95 _isPhysical = pisPhysical;
101 _isVolumeDetect = false; 96 _isVolumeDetect = false;
102 97
103 VehicleController = new BSDynamics(PhysicsScene, this); // add vehicleness 98 // Add a dynamic vehicle to our set of actors that can move this prim.
99 // PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName));
104 100
105 _mass = CalculateMass(); 101 _mass = CalculateMass();
106 102
107 DetailLog("{0},BSPrim.constructor,call", LocalID); 103 // DetailLog("{0},BSPrim.constructor,call", LocalID);
108 // do the actual object creation at taint time 104 // do the actual object creation at taint time
109 PhysicsScene.TaintedObject("BSPrim.create", delegate() 105 PhysScene.TaintedObject("BSPrim.create", delegate()
110 { 106 {
111 // Make sure the object is being created with some sanity. 107 // Make sure the object is being created with some sanity.
112 ExtremeSanityCheck(true /* inTaintTime */); 108 ExtremeSanityCheck(true /* inTaintTime */);
113 109
114 CreateGeomAndObject(true); 110 CreateGeomAndObject(true);
115 111
116 CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); 112 CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody);
117 }); 113 });
118 } 114 }
119 115
@@ -126,14 +122,14 @@ public class BSPrim : BSPhysObject
126 // Undo any vehicle properties 122 // Undo any vehicle properties
127 this.VehicleType = (int)Vehicle.TYPE_NONE; 123 this.VehicleType = (int)Vehicle.TYPE_NONE;
128 124
129 PhysicsScene.TaintedObject("BSPrim.destroy", delegate() 125 PhysScene.TaintedObject("BSPrim.Destroy", delegate()
130 { 126 {
131 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 127 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
132 // If there are physical body and shape, release my use of same. 128 // If there are physical body and shape, release my use of same.
133 PhysicsScene.Shapes.DereferenceBody(PhysBody, null); 129 PhysScene.Shapes.DereferenceBody(PhysBody, null);
134 PhysBody.Clear(); 130 PhysBody.Clear();
135 PhysicsScene.Shapes.DereferenceShape(PhysShape, null); 131 PhysShape.Dereference(PhysScene);
136 PhysShape.Clear(); 132 PhysShape = new BSShapeNull();
137 }); 133 });
138 } 134 }
139 135
@@ -159,25 +155,13 @@ public class BSPrim : BSPhysObject
159 ForceBodyShapeRebuild(false); 155 ForceBodyShapeRebuild(false);
160 } 156 }
161 } 157 }
162 // 'unknown' says to choose the best type
163 public override BSPhysicsShapeType PreferredPhysicalShape
164 { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
165
166 public override bool ForceBodyShapeRebuild(bool inTaintTime) 158 public override bool ForceBodyShapeRebuild(bool inTaintTime)
167 { 159 {
168 if (inTaintTime) 160 PhysScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
169 { 161 {
170 _mass = CalculateMass(); // changing the shape changes the mass 162 _mass = CalculateMass(); // changing the shape changes the mass
171 CreateGeomAndObject(true); 163 CreateGeomAndObject(true);
172 } 164 });
173 else
174 {
175 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
176 {
177 _mass = CalculateMass(); // changing the shape changes the mass
178 CreateGeomAndObject(true);
179 });
180 }
181 return true; 165 return true;
182 } 166 }
183 public override bool Grabbed { 167 public override bool Grabbed {
@@ -190,7 +174,7 @@ public class BSPrim : BSPhysObject
190 if (value != _isSelected) 174 if (value != _isSelected)
191 { 175 {
192 _isSelected = value; 176 _isSelected = value;
193 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 177 PhysScene.TaintedObject("BSPrim.setSelected", delegate()
194 { 178 {
195 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 179 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
196 SetObjectDynamic(false); 180 SetObjectDynamic(false);
@@ -231,165 +215,93 @@ public class BSPrim : BSPhysObject
231 // Called at taint time! 215 // Called at taint time!
232 public override void ZeroMotion(bool inTaintTime) 216 public override void ZeroMotion(bool inTaintTime)
233 { 217 {
234 _velocity = OMV.Vector3.Zero; 218 RawVelocity = OMV.Vector3.Zero;
235 _acceleration = OMV.Vector3.Zero; 219 _acceleration = OMV.Vector3.Zero;
236 _rotationalVelocity = OMV.Vector3.Zero; 220 _rotationalVelocity = OMV.Vector3.Zero;
237 221
238 // Zero some other properties in the physics engine 222 // Zero some other properties in the physics engine
239 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 223 PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
240 { 224 {
241 if (PhysBody.HasPhysicalBody) 225 if (PhysBody.HasPhysicalBody)
242 PhysicsScene.PE.ClearAllForces(PhysBody); 226 PhysScene.PE.ClearAllForces(PhysBody);
243 }); 227 });
244 } 228 }
245 public override void ZeroAngularMotion(bool inTaintTime) 229 public override void ZeroAngularMotion(bool inTaintTime)
246 { 230 {
247 _rotationalVelocity = OMV.Vector3.Zero; 231 _rotationalVelocity = OMV.Vector3.Zero;
248 // Zero some other properties in the physics engine 232 // Zero some other properties in the physics engine
249 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 233 PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
250 { 234 {
251 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); 235 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
252 if (PhysBody.HasPhysicalBody) 236 if (PhysBody.HasPhysicalBody)
253 { 237 {
254 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 238 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
255 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 239 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
256 } 240 }
257 }); 241 });
258 } 242 }
259 243
260 bool TryExperimentalLockAxisCode = false;
261 BSConstraint LockAxisConstraint = null;
262 public override void LockAngularMotion(OMV.Vector3 axis) 244 public override void LockAngularMotion(OMV.Vector3 axis)
263 { 245 {
264 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 246 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
265 247
266 // "1" means free, "0" means locked 248 // "1" means free, "0" means locked
267 OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f); 249 OMV.Vector3 locking = LockedAxisFree;
268 if (axis.X != 1) locking.X = 0f; 250 if (axis.X != 1) locking.X = 0f;
269 if (axis.Y != 1) locking.Y = 0f; 251 if (axis.Y != 1) locking.Y = 0f;
270 if (axis.Z != 1) locking.Z = 0f; 252 if (axis.Z != 1) locking.Z = 0f;
271 LockedAxis = locking; 253 LockedAngularAxis = locking;
272 254
273 if (TryExperimentalLockAxisCode && LockedAxis != LockedAxisFree) 255 EnableActor(LockedAngularAxis != LockedAxisFree, LockedAxisActorName, delegate()
274 { 256 {
275 // Lock that axis by creating a 6DOF constraint that has one end in the world and 257 return new BSActorLockAxis(PhysScene, this, LockedAxisActorName);
276 // the other in the object. 258 });
277 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
278 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
279
280 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
281 {
282 CleanUpLockAxisPhysicals(true /* inTaintTime */);
283
284 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(PhysicsScene.World, PhysBody,
285 OMV.Vector3.Zero, OMV.Quaternion.Inverse(RawOrientation),
286 true /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
287 LockAxisConstraint = axisConstrainer;
288 PhysicsScene.Constraints.AddConstraint(LockAxisConstraint);
289
290 // The constraint is tied to the world and oriented to the prim.
291
292 // Free to move linearly
293 OMV.Vector3 linearLow = OMV.Vector3.Zero;
294 OMV.Vector3 linearHigh = PhysicsScene.TerrainManager.DefaultRegionSize;
295 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
296
297 // Angular with some axis locked
298 float f2PI = (float)Math.PI * 2f;
299 OMV.Vector3 angularLow = new OMV.Vector3(-f2PI, -f2PI, -f2PI);
300 OMV.Vector3 angularHigh = new OMV.Vector3(f2PI, f2PI, f2PI);
301 if (LockedAxis.X != 1f)
302 {
303 angularLow.X = 0f;
304 angularHigh.X = 0f;
305 }
306 if (LockedAxis.Y != 1f)
307 {
308 angularLow.Y = 0f;
309 angularHigh.Y = 0f;
310 }
311 if (LockedAxis.Z != 1f)
312 {
313 angularLow.Z = 0f;
314 angularHigh.Z = 0f;
315 }
316 axisConstrainer.SetAngularLimits(angularLow, angularHigh);
317
318 DetailLog("{0},BSPrim.LockAngularMotion,create,linLow={1},linHi={2},angLow={3},angHi={4}",
319 LocalID, linearLow, linearHigh, angularLow, angularHigh);
320
321 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
322 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
323 259
324 axisConstrainer.RecomputeConstraintVariables(RawMass); 260 // Update parameters so the new actor's Refresh() action is called at the right time.
325 }); 261 PhysScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
326 }
327 else
328 { 262 {
329 // Everything seems unlocked 263 UpdatePhysicalParameters();
330 CleanUpLockAxisPhysicals(false /* inTaintTime */); 264 });
331 }
332 265
333 return; 266 return;
334 } 267 }
335 // Get rid of any constraint built for LockAxis
336 // Most often the constraint is removed when the constraint collection is cleaned for this prim.
337 private void CleanUpLockAxisPhysicals(bool inTaintTime)
338 {
339 if (LockAxisConstraint != null)
340 {
341 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.CleanUpLockAxisPhysicals", delegate()
342 {
343 if (LockAxisConstraint != null)
344 {
345 PhysicsScene.Constraints.RemoveAndDestroyConstraint(LockAxisConstraint);
346 LockAxisConstraint = null;
347 DetailLog("{0},BSPrim.CleanUpLockAxisPhysicals,destroyingConstraint", LocalID);
348 }
349 });
350 }
351 }
352 268
353 public override OMV.Vector3 RawPosition
354 {
355 get { return _position; }
356 set { _position = value; }
357 }
358 public override OMV.Vector3 Position { 269 public override OMV.Vector3 Position {
359 get { 270 get {
360 // don't do the GetObjectPosition for root elements because this function is called a zillion times. 271 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
361 // _position = ForcePosition; 272 // RawPosition = ForcePosition;
362 return _position; 273 return RawPosition;
363 } 274 }
364 set { 275 set {
365 // If the position must be forced into the physics engine, use ForcePosition. 276 // If the position must be forced into the physics engine, use ForcePosition.
366 // All positions are given in world positions. 277 // All positions are given in world positions.
367 if (_position == value) 278 if (RawPosition == value)
368 { 279 {
369 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); 280 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
370 return; 281 return;
371 } 282 }
372 _position = value; 283 RawPosition = value;
373 PositionSanityCheck(false); 284 PositionSanityCheck(false);
374 285
375 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 286 PhysScene.TaintedObject("BSPrim.setPosition", delegate()
376 { 287 {
377 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 288 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
378 ForcePosition = _position; 289 ForcePosition = RawPosition;
379 }); 290 });
380 } 291 }
381 } 292 }
382 293
294 // NOTE: overloaded by BSPrimDisplaced to handle offset for center-of-gravity.
383 public override OMV.Vector3 ForcePosition { 295 public override OMV.Vector3 ForcePosition {
384 get { 296 get {
385 _position = PhysicsScene.PE.GetPosition(PhysBody); 297 RawPosition = PhysScene.PE.GetPosition(PhysBody);
386 return _position; 298 return RawPosition;
387 } 299 }
388 set { 300 set {
389 _position = value; 301 RawPosition = value;
390 if (PhysBody.HasPhysicalBody) 302 if (PhysBody.HasPhysicalBody)
391 { 303 {
392 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 304 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
393 ActivateIfPhysical(false); 305 ActivateIfPhysical(false);
394 } 306 }
395 } 307 }
@@ -406,7 +318,7 @@ public class BSPrim : BSPhysObject
406 if (!IsPhysicallyActive) 318 if (!IsPhysicallyActive)
407 return ret; 319 return ret;
408 320
409 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 321 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
410 { 322 {
411 // The physical object is out of the known/simulated area. 323 // The physical object is out of the known/simulated area.
412 // Upper levels of code will handle the transition to other areas so, for 324 // Upper levels of code will handle the transition to other areas so, for
@@ -414,7 +326,7 @@ public class BSPrim : BSPhysObject
414 return ret; 326 return ret;
415 } 327 }
416 328
417 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 329 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
418 OMV.Vector3 upForce = OMV.Vector3.Zero; 330 OMV.Vector3 upForce = OMV.Vector3.Zero;
419 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); 331 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z));
420 if ((RawPosition.Z + approxSize / 2f) < terrainHeight) 332 if ((RawPosition.Z + approxSize / 2f) < terrainHeight)
@@ -423,10 +335,10 @@ public class BSPrim : BSPhysObject
423 float targetHeight = terrainHeight + (Size.Z / 2f); 335 float targetHeight = terrainHeight + (Size.Z / 2f);
424 // If the object is below ground it just has to be moved up because pushing will 336 // If the object is below ground it just has to be moved up because pushing will
425 // not get it through the terrain 337 // not get it through the terrain
426 _position.Z = targetHeight; 338 RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, targetHeight);
427 if (inTaintTime) 339 if (inTaintTime)
428 { 340 {
429 ForcePosition = _position; 341 ForcePosition = RawPosition;
430 } 342 }
431 // If we are throwing the object around, zero its other forces 343 // If we are throwing the object around, zero its other forces
432 ZeroMotion(inTaintTime); 344 ZeroMotion(inTaintTime);
@@ -435,7 +347,7 @@ public class BSPrim : BSPhysObject
435 347
436 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 348 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
437 { 349 {
438 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 350 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
439 // TODO: a floating motor so object will bob in the water 351 // TODO: a floating motor so object will bob in the water
440 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) 352 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
441 { 353 {
@@ -443,8 +355,8 @@ public class BSPrim : BSPhysObject
443 upForce.Z = (waterHeight - RawPosition.Z) * 1f; 355 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
444 356
445 // Apply upforce and overcome gravity. 357 // Apply upforce and overcome gravity.
446 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; 358 OMV.Vector3 correctionForce = upForce - PhysScene.DefaultGravity;
447 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); 359 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, RawPosition, upForce, correctionForce);
448 AddForce(correctionForce, false, inTaintTime); 360 AddForce(correctionForce, false, inTaintTime);
449 ret = true; 361 ret = true;
450 } 362 }
@@ -463,17 +375,17 @@ public class BSPrim : BSPhysObject
463 uint wayOutThere = Constants.RegionSize * Constants.RegionSize; 375 uint wayOutThere = Constants.RegionSize * Constants.RegionSize;
464 // There have been instances of objects getting thrown way out of bounds and crashing 376 // There have been instances of objects getting thrown way out of bounds and crashing
465 // the border crossing code. 377 // the border crossing code.
466 if ( _position.X < -Constants.RegionSize || _position.X > wayOutThere 378 if ( RawPosition.X < -Constants.RegionSize || RawPosition.X > wayOutThere
467 || _position.Y < -Constants.RegionSize || _position.Y > wayOutThere 379 || RawPosition.Y < -Constants.RegionSize || RawPosition.Y > wayOutThere
468 || _position.Z < -Constants.RegionSize || _position.Z > wayOutThere) 380 || RawPosition.Z < -Constants.RegionSize || RawPosition.Z > wayOutThere)
469 { 381 {
470 _position = new OMV.Vector3(10, 10, 50); 382 RawPosition = new OMV.Vector3(10, 10, 50);
471 ZeroMotion(inTaintTime); 383 ZeroMotion(inTaintTime);
472 ret = true; 384 ret = true;
473 } 385 }
474 if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) 386 if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity)
475 { 387 {
476 _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); 388 RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity);
477 ret = true; 389 ret = true;
478 } 390 }
479 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) 391 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared)
@@ -498,7 +410,7 @@ public class BSPrim : BSPhysObject
498 get { return _mass; } 410 get { return _mass; }
499 } 411 }
500 // used when we only want this prim's mass and not the linkset thing 412 // used when we only want this prim's mass and not the linkset thing
501 public override float RawMass { 413 public override float RawMass {
502 get { return _mass; } 414 get { return _mass; }
503 } 415 }
504 // Set the physical mass to the passed mass. 416 // Set the physical mass to the passed mass.
@@ -509,10 +421,10 @@ public class BSPrim : BSPhysObject
509 { 421 {
510 if (IsStatic) 422 if (IsStatic)
511 { 423 {
512 PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); 424 PhysScene.PE.SetGravity(PhysBody, PhysScene.DefaultGravity);
513 Inertia = OMV.Vector3.Zero; 425 Inertia = OMV.Vector3.Zero;
514 PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); 426 PhysScene.PE.SetMassProps(PhysBody, 0f, Inertia);
515 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 427 PhysScene.PE.UpdateInertiaTensor(PhysBody);
516 } 428 }
517 else 429 else
518 { 430 {
@@ -521,16 +433,19 @@ public class BSPrim : BSPhysObject
521 // Changing interesting properties doesn't change proxy and collision cache 433 // Changing interesting properties doesn't change proxy and collision cache
522 // information. The Bullet solution is to re-add the object to the world 434 // information. The Bullet solution is to re-add the object to the world
523 // after parameters are changed. 435 // after parameters are changed.
524 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 436 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
525 } 437 }
526 438
527 // The computation of mass props requires gravity to be set on the object. 439 // The computation of mass props requires gravity to be set on the object.
528 Gravity = ComputeGravity(Buoyancy); 440 Gravity = ComputeGravity(Buoyancy);
529 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 441 PhysScene.PE.SetGravity(PhysBody, Gravity);
442
443 // OMV.Vector3 currentScale = PhysScene.PE.GetLocalScaling(PhysShape.physShapeInfo); // DEBUG DEBUG
444 // DetailLog("{0},BSPrim.UpdateMassProperties,currentScale{1},shape={2}", LocalID, currentScale, PhysShape.physShapeInfo); // DEBUG DEBUG
530 445
531 Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 446 Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
532 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); 447 PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia);
533 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 448 PhysScene.PE.UpdateInertiaTensor(PhysBody);
534 449
535 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", 450 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}",
536 LocalID, physMass, Inertia, Gravity, inWorld); 451 LocalID, physMass, Inertia, Gravity, inWorld);
@@ -546,7 +461,7 @@ public class BSPrim : BSPhysObject
546 // Return what gravity should be set to this very moment 461 // Return what gravity should be set to this very moment
547 public OMV.Vector3 ComputeGravity(float buoyancy) 462 public OMV.Vector3 ComputeGravity(float buoyancy)
548 { 463 {
549 OMV.Vector3 ret = PhysicsScene.DefaultGravity; 464 OMV.Vector3 ret = PhysScene.DefaultGravity;
550 465
551 if (!IsStatic) 466 if (!IsStatic)
552 { 467 {
@@ -570,95 +485,121 @@ public class BSPrim : BSPhysObject
570 } 485 }
571 486
572 public override OMV.Vector3 Force { 487 public override OMV.Vector3 Force {
573 get { return _force; } 488 get { return RawForce; }
574 set { 489 set {
575 _force = value; 490 RawForce = value;
576 if (_force != OMV.Vector3.Zero) 491 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
577 { 492 {
578 // If the force is non-zero, it must be reapplied each tick because 493 return new BSActorSetForce(PhysScene, this, SetForceActorName);
579 // Bullet clears the forces applied last frame. 494 });
580 RegisterPreStepAction("BSPrim.setForce", LocalID, 495 }
581 delegate(float timeStep) 496 }
582 {
583 if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
584 {
585 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
586 return;
587 }
588 497
589 DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); 498 // Find and return a handle to the current vehicle actor.
590 if (PhysBody.HasPhysicalBody) 499 // Return 'null' if there is no vehicle actor.
591 { 500 public BSDynamics GetVehicleActor(bool createIfNone)
592 PhysicsScene.PE.ApplyCentralForce(PhysBody, _force); 501 {
593 ActivateIfPhysical(false); 502 BSDynamics ret = null;
594 } 503 BSActor actor;
595 } 504 if (PhysicalActors.TryGetActor(VehicleActorName, out actor))
596 ); 505 {
597 } 506 ret = actor as BSDynamics;
598 else 507 }
508 else
509 {
510 if (createIfNone)
599 { 511 {
600 UnRegisterPreStepAction("BSPrim.setForce", LocalID); 512 ret = new BSDynamics(PhysScene, this, VehicleActorName);
513 PhysicalActors.Add(ret.ActorName, ret);
601 } 514 }
602 } 515 }
516 return ret;
603 } 517 }
604 518
605 public override int VehicleType { 519 public override int VehicleType {
606 get { 520 get {
607 return (int)VehicleController.Type; // if we are a vehicle, return that type 521 int ret = (int)Vehicle.TYPE_NONE;
522 BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */);
523 if (vehicleActor != null)
524 ret = (int)vehicleActor.Type;
525 return ret;
608 } 526 }
609 set { 527 set {
610 Vehicle type = (Vehicle)value; 528 Vehicle type = (Vehicle)value;
611 529
612 PhysicsScene.TaintedObject("setVehicleType", delegate() 530 PhysScene.TaintedObject("setVehicleType", delegate()
613 { 531 {
614 // Done at taint time so we're sure the physics engine is not using the variables 532 // Some vehicle scripts change vehicle type on the fly as an easy way to
615 // Vehicle code changes the parameters for this vehicle type. 533 // change all the parameters. Like a plane changing to CAR when on the
616 VehicleController.ProcessTypeChange(type); 534 // ground. In this case, don't want to zero motion.
617 ActivateIfPhysical(false); 535 // ZeroMotion(true /* inTaintTime */);
618 536 if (type == Vehicle.TYPE_NONE)
619 // If an active vehicle, register the vehicle code to be called before each step
620 if (VehicleController.Type == Vehicle.TYPE_NONE)
621 { 537 {
622 UnRegisterPreStepAction("BSPrim.Vehicle", LocalID); 538 // Vehicle type is 'none' so get rid of any actor that may have been allocated.
623 UnRegisterPostStepAction("BSPrim.Vehicle", LocalID); 539 BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */);
540 if (vehicleActor != null)
541 {
542 PhysicalActors.RemoveAndRelease(vehicleActor.ActorName);
543 }
624 } 544 }
625 else 545 else
626 { 546 {
627 RegisterPreStepAction("BSPrim.Vehicle", LocalID, VehicleController.Step); 547 // Vehicle type is not 'none' so create an actor and set it running.
628 RegisterPostStepAction("BSPrim.Vehicle", LocalID, VehicleController.PostStep); 548 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
549 if (vehicleActor != null)
550 {
551 vehicleActor.ProcessTypeChange(type);
552 ActivateIfPhysical(false);
553 }
629 } 554 }
630 }); 555 });
631 } 556 }
632 } 557 }
633 public override void VehicleFloatParam(int param, float value) 558 public override void VehicleFloatParam(int param, float value)
634 { 559 {
635 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 560 PhysScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
636 { 561 {
637 VehicleController.ProcessFloatVehicleParam((Vehicle)param, value); 562 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
638 ActivateIfPhysical(false); 563 if (vehicleActor != null)
564 {
565 vehicleActor.ProcessFloatVehicleParam((Vehicle)param, value);
566 ActivateIfPhysical(false);
567 }
639 }); 568 });
640 } 569 }
641 public override void VehicleVectorParam(int param, OMV.Vector3 value) 570 public override void VehicleVectorParam(int param, OMV.Vector3 value)
642 { 571 {
643 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 572 PhysScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
644 { 573 {
645 VehicleController.ProcessVectorVehicleParam((Vehicle)param, value); 574 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
646 ActivateIfPhysical(false); 575 if (vehicleActor != null)
576 {
577 vehicleActor.ProcessVectorVehicleParam((Vehicle)param, value);
578 ActivateIfPhysical(false);
579 }
647 }); 580 });
648 } 581 }
649 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 582 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
650 { 583 {
651 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 584 PhysScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
652 { 585 {
653 VehicleController.ProcessRotationVehicleParam((Vehicle)param, rotation); 586 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
654 ActivateIfPhysical(false); 587 if (vehicleActor != null)
588 {
589 vehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation);
590 ActivateIfPhysical(false);
591 }
655 }); 592 });
656 } 593 }
657 public override void VehicleFlags(int param, bool remove) 594 public override void VehicleFlags(int param, bool remove)
658 { 595 {
659 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() 596 PhysScene.TaintedObject("BSPrim.VehicleFlags", delegate()
660 { 597 {
661 VehicleController.ProcessVehicleFlags(param, remove); 598 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
599 if (vehicleActor != null)
600 {
601 vehicleActor.ProcessVehicleFlags(param, remove);
602 }
662 }); 603 });
663 } 604 }
664 605
@@ -668,7 +609,7 @@ public class BSPrim : BSPhysObject
668 if (_isVolumeDetect != newValue) 609 if (_isVolumeDetect != newValue)
669 { 610 {
670 _isVolumeDetect = newValue; 611 _isVolumeDetect = newValue;
671 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 612 PhysScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
672 { 613 {
673 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); 614 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
674 SetObjectDynamic(true); 615 SetObjectDynamic(true);
@@ -679,7 +620,7 @@ public class BSPrim : BSPhysObject
679 public override void SetMaterial(int material) 620 public override void SetMaterial(int material)
680 { 621 {
681 base.SetMaterial(material); 622 base.SetMaterial(material);
682 PhysicsScene.TaintedObject("BSPrim.SetMaterial", delegate() 623 PhysScene.TaintedObject("BSPrim.SetMaterial", delegate()
683 { 624 {
684 UpdatePhysicalParameters(); 625 UpdatePhysicalParameters();
685 }); 626 });
@@ -692,7 +633,7 @@ public class BSPrim : BSPhysObject
692 if (base.Friction != value) 633 if (base.Friction != value)
693 { 634 {
694 base.Friction = value; 635 base.Friction = value;
695 PhysicsScene.TaintedObject("BSPrim.setFriction", delegate() 636 PhysScene.TaintedObject("BSPrim.setFriction", delegate()
696 { 637 {
697 UpdatePhysicalParameters(); 638 UpdatePhysicalParameters();
698 }); 639 });
@@ -707,7 +648,7 @@ public class BSPrim : BSPhysObject
707 if (base.Restitution != value) 648 if (base.Restitution != value)
708 { 649 {
709 base.Restitution = value; 650 base.Restitution = value;
710 PhysicsScene.TaintedObject("BSPrim.setRestitution", delegate() 651 PhysScene.TaintedObject("BSPrim.setRestitution", delegate()
711 { 652 {
712 UpdatePhysicalParameters(); 653 UpdatePhysicalParameters();
713 }); 654 });
@@ -724,7 +665,7 @@ public class BSPrim : BSPhysObject
724 if (base.Density != value) 665 if (base.Density != value)
725 { 666 {
726 base.Density = value; 667 base.Density = value;
727 PhysicsScene.TaintedObject("BSPrim.setDensity", delegate() 668 PhysScene.TaintedObject("BSPrim.setDensity", delegate()
728 { 669 {
729 UpdatePhysicalParameters(); 670 UpdatePhysicalParameters();
730 }); 671 });
@@ -739,93 +680,66 @@ public class BSPrim : BSPhysObject
739 if (base.GravModifier != value) 680 if (base.GravModifier != value)
740 { 681 {
741 base.GravModifier = value; 682 base.GravModifier = value;
742 PhysicsScene.TaintedObject("BSPrim.setGravityModifier", delegate() 683 PhysScene.TaintedObject("BSPrim.setGravityModifier", delegate()
743 { 684 {
744 UpdatePhysicalParameters(); 685 UpdatePhysicalParameters();
745 }); 686 });
746 } 687 }
747 } 688 }
748 } 689 }
749 public override OMV.Vector3 RawVelocity
750 {
751 get { return _velocity; }
752 set { _velocity = value; }
753 }
754 public override OMV.Vector3 Velocity { 690 public override OMV.Vector3 Velocity {
755 get { return _velocity; } 691 get { return RawVelocity; }
756 set { 692 set {
757 _velocity = value; 693 RawVelocity = value;
758 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 694 PhysScene.TaintedObject("BSPrim.setVelocity", delegate()
759 { 695 {
760 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 696 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
761 ForceVelocity = _velocity; 697 ForceVelocity = RawVelocity;
762 }); 698 });
763 } 699 }
764 } 700 }
765 public override OMV.Vector3 ForceVelocity { 701 public override OMV.Vector3 ForceVelocity {
766 get { return _velocity; } 702 get { return RawVelocity; }
767 set { 703 set {
768 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); 704 PhysScene.AssertInTaintTime("BSPrim.ForceVelocity");
769 705
770 _velocity = Util.ClampV(value, BSParam.MaxLinearVelocity); 706 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
771 if (PhysBody.HasPhysicalBody) 707 if (PhysBody.HasPhysicalBody)
772 { 708 {
773 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity); 709 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
774 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 710 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
775 ActivateIfPhysical(false); 711 ActivateIfPhysical(false);
776 } 712 }
777 } 713 }
778 } 714 }
779 public override OMV.Vector3 Torque { 715 public override OMV.Vector3 Torque {
780 get { return _torque; } 716 get { return RawTorque; }
781 set { 717 set {
782 _torque = value; 718 RawTorque = value;
783 if (_torque != OMV.Vector3.Zero) 719 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
784 { 720 {
785 // If the torque is non-zero, it must be reapplied each tick because 721 return new BSActorSetTorque(PhysScene, this, SetTorqueActorName);
786 // Bullet clears the forces applied last frame. 722 });
787 RegisterPreStepAction("BSPrim.setTorque", LocalID, 723 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
788 delegate(float timeStep)
789 {
790 if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
791 {
792 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
793 return;
794 }
795
796 if (PhysBody.HasPhysicalBody)
797 AddAngularForce(_torque, false, true);
798 }
799 );
800 }
801 else
802 {
803 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
804 }
805 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
806 } 724 }
807 } 725 }
808 public override OMV.Vector3 Acceleration { 726 public override OMV.Vector3 Acceleration {
809 get { return _acceleration; } 727 get { return _acceleration; }
810 set { _acceleration = value; } 728 set { _acceleration = value; }
811 } 729 }
812 public override OMV.Quaternion RawOrientation 730
813 {
814 get { return _orientation; }
815 set { _orientation = value; }
816 }
817 public override OMV.Quaternion Orientation { 731 public override OMV.Quaternion Orientation {
818 get { 732 get {
819 return _orientation; 733 return RawOrientation;
820 } 734 }
821 set { 735 set {
822 if (_orientation == value) 736 if (RawOrientation == value)
823 return; 737 return;
824 _orientation = value; 738 RawOrientation = value;
825 739
826 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 740 PhysScene.TaintedObject("BSPrim.setOrientation", delegate()
827 { 741 {
828 ForceOrientation = _orientation; 742 ForceOrientation = RawOrientation;
829 }); 743 });
830 } 744 }
831 } 745 }
@@ -834,14 +748,14 @@ public class BSPrim : BSPhysObject
834 { 748 {
835 get 749 get
836 { 750 {
837 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 751 RawOrientation = PhysScene.PE.GetOrientation(PhysBody);
838 return _orientation; 752 return RawOrientation;
839 } 753 }
840 set 754 set
841 { 755 {
842 _orientation = value; 756 RawOrientation = value;
843 if (PhysBody.HasPhysicalBody) 757 if (PhysBody.HasPhysicalBody)
844 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 758 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
845 } 759 }
846 } 760 }
847 public override int PhysicsActorType { 761 public override int PhysicsActorType {
@@ -854,7 +768,7 @@ public class BSPrim : BSPhysObject
854 if (_isPhysical != value) 768 if (_isPhysical != value)
855 { 769 {
856 _isPhysical = value; 770 _isPhysical = value;
857 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 771 PhysScene.TaintedObject("BSPrim.setIsPhysical", delegate()
858 { 772 {
859 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 773 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
860 SetObjectDynamic(true); 774 SetObjectDynamic(true);
@@ -898,24 +812,25 @@ public class BSPrim : BSPhysObject
898 // isSolid: other objects bounce off of this object 812 // isSolid: other objects bounce off of this object
899 // isVolumeDetect: other objects pass through but can generate collisions 813 // isVolumeDetect: other objects pass through but can generate collisions
900 // collisionEvents: whether this object returns collision events 814 // collisionEvents: whether this object returns collision events
815 // NOTE: overloaded by BSPrimLinkable to also update linkset physical parameters.
901 public virtual void UpdatePhysicalParameters() 816 public virtual void UpdatePhysicalParameters()
902 { 817 {
903 if (!PhysBody.HasPhysicalBody) 818 if (!PhysBody.HasPhysicalBody)
904 { 819 {
905 // This would only happen if updates are called for during initialization when the body is not set up yet. 820 // This would only happen if updates are called for during initialization when the body is not set up yet.
906 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); 821 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID);
907 return; 822 return;
908 } 823 }
909 824
910 // Mangling all the physical properties requires the object not be in the physical world. 825 // Mangling all the physical properties requires the object not be in the physical world.
911 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 826 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
912 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 827 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
913 828
914 // Set up the object physicalness (does gravity and collisions move this object) 829 // Set up the object physicalness (does gravity and collisions move this object)
915 MakeDynamic(IsStatic); 830 MakeDynamic(IsStatic);
916 831
917 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) 832 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
918 VehicleController.Refresh(); 833 PhysicalActors.Refresh();
919 834
920 // Arrange for collision events if the simulator wants them 835 // Arrange for collision events if the simulator wants them
921 EnableCollisions(SubscribedEvents()); 836 EnableCollisions(SubscribedEvents());
@@ -926,10 +841,11 @@ public class BSPrim : BSPhysObject
926 AddObjectToPhysicalWorld(); 841 AddObjectToPhysicalWorld();
927 842
928 // Rebuild its shape 843 // Rebuild its shape
929 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 844 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
930 845
931 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", 846 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
932 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); 847 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(),
848 CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
933 } 849 }
934 850
935 // "Making dynamic" means changing to and from static. 851 // "Making dynamic" means changing to and from static.
@@ -942,28 +858,28 @@ public class BSPrim : BSPhysObject
942 if (makeStatic) 858 if (makeStatic)
943 { 859 {
944 // Become a Bullet 'static' object type 860 // Become a Bullet 'static' object type
945 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 861 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
946 // Stop all movement 862 // Stop all movement
947 ZeroMotion(true); 863 ZeroMotion(true);
948 864
949 // Set various physical properties so other object interact properly 865 // Set various physical properties so other object interact properly
950 PhysicsScene.PE.SetFriction(PhysBody, Friction); 866 PhysScene.PE.SetFriction(PhysBody, Friction);
951 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 867 PhysScene.PE.SetRestitution(PhysBody, Restitution);
952 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 868 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
953 869
954 // Mass is zero which disables a bunch of physics stuff in Bullet 870 // Mass is zero which disables a bunch of physics stuff in Bullet
955 UpdatePhysicalMassProperties(0f, false); 871 UpdatePhysicalMassProperties(0f, false);
956 // Set collision detection parameters 872 // Set collision detection parameters
957 if (BSParam.CcdMotionThreshold > 0f) 873 if (BSParam.CcdMotionThreshold > 0f)
958 { 874 {
959 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 875 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
960 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 876 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
961 } 877 }
962 878
963 // The activation state is 'disabled' so Bullet will not try to act on it. 879 // The activation state is 'disabled' so Bullet will not try to act on it.
964 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); 880 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION);
965 // Start it out sleeping and physical actions could wake it up. 881 // Start it out sleeping and physical actions could wake it up.
966 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); 882 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING);
967 883
968 // This collides like a static object 884 // This collides like a static object
969 PhysBody.collisionType = CollisionType.Static; 885 PhysBody.collisionType = CollisionType.Static;
@@ -971,11 +887,11 @@ public class BSPrim : BSPhysObject
971 else 887 else
972 { 888 {
973 // Not a Bullet static object 889 // Not a Bullet static object
974 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 890 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
975 891
976 // Set various physical properties so other object interact properly 892 // Set various physical properties so other object interact properly
977 PhysicsScene.PE.SetFriction(PhysBody, Friction); 893 PhysScene.PE.SetFriction(PhysBody, Friction);
978 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 894 PhysScene.PE.SetRestitution(PhysBody, Restitution);
979 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); 895 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution);
980 896
981 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 897 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
@@ -983,8 +899,8 @@ public class BSPrim : BSPhysObject
983 // PhysicsScene.PE.ClearAllForces(BSBody); 899 // PhysicsScene.PE.ClearAllForces(BSBody);
984 900
985 // For good measure, make sure the transform is set through to the motion state 901 // For good measure, make sure the transform is set through to the motion state
986 ForcePosition = _position; 902 ForcePosition = RawPosition;
987 ForceVelocity = _velocity; 903 ForceVelocity = RawVelocity;
988 ForceRotationalVelocity = _rotationalVelocity; 904 ForceRotationalVelocity = _rotationalVelocity;
989 905
990 // A dynamic object has mass 906 // A dynamic object has mass
@@ -993,22 +909,22 @@ public class BSPrim : BSPhysObject
993 // Set collision detection parameters 909 // Set collision detection parameters
994 if (BSParam.CcdMotionThreshold > 0f) 910 if (BSParam.CcdMotionThreshold > 0f)
995 { 911 {
996 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 912 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
997 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 913 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
998 } 914 }
999 915
1000 // Various values for simulation limits 916 // Various values for simulation limits
1001 PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); 917 PhysScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping);
1002 PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); 918 PhysScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime);
1003 PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); 919 PhysScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
1004 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 920 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
1005 921
1006 // This collides like an object. 922 // This collides like an object.
1007 PhysBody.collisionType = CollisionType.Dynamic; 923 PhysBody.collisionType = CollisionType.Dynamic;
1008 924
1009 // Force activation of the object so Bullet will act on it. 925 // Force activation of the object so Bullet will act on it.
1010 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 926 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
1011 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 927 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
1012 } 928 }
1013 } 929 }
1014 930
@@ -1018,7 +934,7 @@ public class BSPrim : BSPhysObject
1018 // the functions after this one set up the state of a possibly newly created collision body. 934 // the functions after this one set up the state of a possibly newly created collision body.
1019 private void MakeSolid(bool makeSolid) 935 private void MakeSolid(bool makeSolid)
1020 { 936 {
1021 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); 937 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysScene.PE.GetBodyType(PhysBody);
1022 if (makeSolid) 938 if (makeSolid)
1023 { 939 {
1024 // Verify the previous code created the correct shape for this type of thing. 940 // Verify the previous code created the correct shape for this type of thing.
@@ -1026,7 +942,7 @@ public class BSPrim : BSPhysObject
1026 { 942 {
1027 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 943 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
1028 } 944 }
1029 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 945 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
1030 } 946 }
1031 else 947 else
1032 { 948 {
@@ -1034,32 +950,23 @@ public class BSPrim : BSPhysObject
1034 { 950 {
1035 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 951 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
1036 } 952 }
1037 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 953 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
1038 954
1039 // Change collision info from a static object to a ghosty collision object 955 // Change collision info from a static object to a ghosty collision object
1040 PhysBody.collisionType = CollisionType.VolumeDetect; 956 PhysBody.collisionType = CollisionType.VolumeDetect;
1041 } 957 }
1042 } 958 }
1043 959
1044 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
1045 // they need waking up when parameters are changed.
1046 // Called in taint-time!!
1047 private void ActivateIfPhysical(bool forceIt)
1048 {
1049 if (IsPhysical && PhysBody.HasPhysicalBody)
1050 PhysicsScene.PE.Activate(PhysBody, forceIt);
1051 }
1052
1053 // Turn on or off the flag controlling whether collision events are returned to the simulator. 960 // Turn on or off the flag controlling whether collision events are returned to the simulator.
1054 private void EnableCollisions(bool wantsCollisionEvents) 961 private void EnableCollisions(bool wantsCollisionEvents)
1055 { 962 {
1056 if (wantsCollisionEvents) 963 if (wantsCollisionEvents)
1057 { 964 {
1058 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 965 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
1059 } 966 }
1060 else 967 else
1061 { 968 {
1062 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 969 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
1063 } 970 }
1064 } 971 }
1065 972
@@ -1070,7 +977,7 @@ public class BSPrim : BSPhysObject
1070 { 977 {
1071 if (PhysBody.HasPhysicalBody) 978 if (PhysBody.HasPhysicalBody)
1072 { 979 {
1073 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 980 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
1074 } 981 }
1075 else 982 else
1076 { 983 {
@@ -1105,12 +1012,12 @@ public class BSPrim : BSPhysObject
1105 public override bool FloatOnWater { 1012 public override bool FloatOnWater {
1106 set { 1013 set {
1107 _floatOnWater = value; 1014 _floatOnWater = value;
1108 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 1015 PhysScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
1109 { 1016 {
1110 if (_floatOnWater) 1017 if (_floatOnWater)
1111 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1018 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
1112 else 1019 else
1113 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1020 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
1114 }); 1021 });
1115 } 1022 }
1116 } 1023 }
@@ -1122,7 +1029,7 @@ public class BSPrim : BSPhysObject
1122 _rotationalVelocity = value; 1029 _rotationalVelocity = value;
1123 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); 1030 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
1124 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 1031 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
1125 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 1032 PhysScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
1126 { 1033 {
1127 ForceRotationalVelocity = _rotationalVelocity; 1034 ForceRotationalVelocity = _rotationalVelocity;
1128 }); 1035 });
@@ -1137,7 +1044,7 @@ public class BSPrim : BSPhysObject
1137 if (PhysBody.HasPhysicalBody) 1044 if (PhysBody.HasPhysicalBody)
1138 { 1045 {
1139 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 1046 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
1140 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 1047 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
1141 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 1048 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
1142 ActivateIfPhysical(false); 1049 ActivateIfPhysical(false);
1143 } 1050 }
@@ -1153,7 +1060,7 @@ public class BSPrim : BSPhysObject
1153 get { return _buoyancy; } 1060 get { return _buoyancy; }
1154 set { 1061 set {
1155 _buoyancy = value; 1062 _buoyancy = value;
1156 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() 1063 PhysScene.TaintedObject("BSPrim.setBuoyancy", delegate()
1157 { 1064 {
1158 ForceBuoyancy = _buoyancy; 1065 ForceBuoyancy = _buoyancy;
1159 }); 1066 });
@@ -1171,179 +1078,54 @@ public class BSPrim : BSPhysObject
1171 } 1078 }
1172 } 1079 }
1173 1080
1174 // Used for MoveTo
1175 public override OMV.Vector3 PIDTarget {
1176 set
1177 {
1178 // TODO: add a sanity check -- don't move more than a region or something like that.
1179 _PIDTarget = value;
1180 }
1181 }
1182 public override float PIDTau {
1183 set { _PIDTau = value; }
1184 }
1185 public override bool PIDActive { 1081 public override bool PIDActive {
1186 set { 1082 set {
1187 if (value) 1083 base.MoveToTargetActive = value;
1084 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
1188 { 1085 {
1189 // We're taking over after this. 1086 return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName);
1190 ZeroMotion(true); 1087 });
1191 1088 }
1192 _targetMotor = new BSVMotor("BSPrim.PIDTarget", 1089 }
1193 _PIDTau, // timeScale
1194 BSMotor.Infinite, // decay time scale
1195 BSMotor.InfiniteVector, // friction timescale
1196 1f // efficiency
1197 );
1198 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1199 _targetMotor.SetTarget(_PIDTarget);
1200 _targetMotor.SetCurrent(RawPosition);
1201 /*
1202 _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget");
1203 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1204
1205 _targetMotor.SetTarget(_PIDTarget);
1206 _targetMotor.SetCurrent(RawPosition);
1207 _targetMotor.TimeScale = _PIDTau;
1208 _targetMotor.Efficiency = 1f;
1209 */
1210
1211 RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep)
1212 {
1213 if (!IsPhysicallyActive)
1214 {
1215 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
1216 return;
1217 }
1218
1219 OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below)
1220
1221 // 'movePosition' is where we'd like the prim to be at this moment.
1222 OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep);
1223 1090
1224 // If we are very close to our target, turn off the movement motor. 1091 public override OMV.Vector3 PIDTarget
1225 if (_targetMotor.ErrorIsZero()) 1092 {
1226 { 1093 set
1227 DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", 1094 {
1228 LocalID, movePosition, RawPosition, Mass); 1095 base.PIDTarget = value;
1229 ForcePosition = _targetMotor.TargetValue; 1096 BSActor actor;
1230 _targetMotor.Enabled = false; 1097 if (PhysicalActors.TryGetActor(MoveToTargetActorName, out actor))
1231 }
1232 else
1233 {
1234 _position = movePosition;
1235 PositionSanityCheck(true /* intaintTime */);
1236 ForcePosition = _position;
1237 }
1238 DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
1239 });
1240 }
1241 else
1242 { 1098 {
1243 // Stop any targetting 1099 // if the actor exists, tell it to refresh its values.
1244 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); 1100 actor.Refresh();
1245 } 1101 }
1102
1246 } 1103 }
1247 } 1104 }
1248
1249 // Used for llSetHoverHeight and maybe vehicle height 1105 // Used for llSetHoverHeight and maybe vehicle height
1250 // Hover Height will override MoveTo target's Z 1106 // Hover Height will override MoveTo target's Z
1251 public override bool PIDHoverActive { 1107 public override bool PIDHoverActive {
1252 set { 1108 set {
1253 if (value) 1109 base.HoverActive = value;
1254 { 1110 EnableActor(HoverActive, HoverActorName, delegate()
1255 // Turning the target on
1256 _hoverMotor = new BSFMotor("BSPrim.Hover",
1257 _PIDHoverTau, // timeScale
1258 BSMotor.Infinite, // decay time scale
1259 BSMotor.Infinite, // friction timescale
1260 1f // efficiency
1261 );
1262 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1263 _hoverMotor.SetCurrent(RawPosition.Z);
1264 _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1265
1266 RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep)
1267 {
1268 // Don't do hovering while the object is selected.
1269 if (!IsPhysicallyActive)
1270 return;
1271
1272 _hoverMotor.SetCurrent(RawPosition.Z);
1273 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1274 float targetHeight = _hoverMotor.Step(timeStep);
1275
1276 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
1277 // Compute the amount of force to push us there.
1278 float moveForce = (targetHeight - RawPosition.Z) * Mass;
1279 // Undo anything the object thinks it's doing at the moment
1280 moveForce = -RawVelocity.Z * Mass;
1281
1282 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce));
1283 DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass);
1284 });
1285 }
1286 else
1287 { 1111 {
1288 UnRegisterPreStepAction("BSPrim.Hover", LocalID); 1112 return new BSActorHover(PhysScene, this, HoverActorName);
1289 } 1113 });
1290 }
1291 }
1292 public override float PIDHoverHeight {
1293 set { _PIDHoverHeight = value; }
1294 }
1295 public override PIDHoverType PIDHoverType {
1296 set { _PIDHoverType = value; }
1297 }
1298 public override float PIDHoverTau {
1299 set { _PIDHoverTau = value; }
1300 }
1301 // Based on current position, determine what we should be hovering at now.
1302 // Must recompute often. What if we walked offa cliff>
1303 private float ComputeCurrentPIDHoverHeight()
1304 {
1305 float ret = _PIDHoverHeight;
1306 float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
1307
1308 switch (_PIDHoverType)
1309 {
1310 case PIDHoverType.Ground:
1311 ret = groundHeight + _PIDHoverHeight;
1312 break;
1313 case PIDHoverType.GroundAndWater:
1314 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
1315 if (groundHeight > waterHeight)
1316 {
1317 ret = groundHeight + _PIDHoverHeight;
1318 }
1319 else
1320 {
1321 ret = waterHeight + _PIDHoverHeight;
1322 }
1323 break;
1324 } 1114 }
1325 return ret;
1326 } 1115 }
1327 1116
1328
1329 // For RotLookAt
1330 public override OMV.Quaternion APIDTarget { set { return; } }
1331 public override bool APIDActive { set { return; } }
1332 public override float APIDStrength { set { return; } }
1333 public override float APIDDamping { set { return; } }
1334
1335 public override void AddForce(OMV.Vector3 force, bool pushforce) { 1117 public override void AddForce(OMV.Vector3 force, bool pushforce) {
1336 // Per documentation, max force is limited. 1118 // Per documentation, max force is limited.
1337 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 1119 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1338 1120
1339 // Since this force is being applied in only one step, make this a force per second. 1121 // Since this force is being applied in only one step, make this a force per second.
1340 addForce /= PhysicsScene.LastTimeStep; 1122 addForce /= PhysScene.LastTimeStep;
1341 AddForce(addForce, pushforce, false /* inTaintTime */); 1123 AddForce(addForce, pushforce, false /* inTaintTime */);
1342 } 1124 }
1343 1125
1344 // Applying a force just adds this to the total force on the object. 1126 // Applying a force just adds this to the total force on the object.
1345 // This added force will only last the next simulation tick. 1127 // This added force will only last the next simulation tick.
1346 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1128 public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
1347 // for an object, doesn't matter if force is a pushforce or not 1129 // for an object, doesn't matter if force is a pushforce or not
1348 if (IsPhysicallyActive) 1130 if (IsPhysicallyActive)
1349 { 1131 {
@@ -1352,13 +1134,15 @@ public class BSPrim : BSPhysObject
1352 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1134 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1353 1135
1354 OMV.Vector3 addForce = force; 1136 OMV.Vector3 addForce = force;
1355 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1137 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
1356 { 1138 {
1357 // Bullet adds this central force to the total force for this tick 1139 // Bullet adds this central force to the total force for this tick.
1140 // Deep down in Bullet:
1141 // linearVelocity += totalForce / mass * timeStep;
1358 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); 1142 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1359 if (PhysBody.HasPhysicalBody) 1143 if (PhysBody.HasPhysicalBody)
1360 { 1144 {
1361 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 1145 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
1362 ActivateIfPhysical(false); 1146 ActivateIfPhysical(false);
1363 } 1147 }
1364 }); 1148 });
@@ -1380,13 +1164,13 @@ public class BSPrim : BSPhysObject
1380 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); 1164 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
1381 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); 1165 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1382 1166
1383 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() 1167 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate()
1384 { 1168 {
1385 // Bullet adds this impulse immediately to the velocity 1169 // Bullet adds this impulse immediately to the velocity
1386 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); 1170 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
1387 if (PhysBody.HasPhysicalBody) 1171 if (PhysBody.HasPhysicalBody)
1388 { 1172 {
1389 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); 1173 PhysScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
1390 ActivateIfPhysical(false); 1174 ActivateIfPhysical(false);
1391 } 1175 }
1392 }); 1176 });
@@ -1399,20 +1183,18 @@ public class BSPrim : BSPhysObject
1399 } 1183 }
1400 } 1184 }
1401 1185
1402 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 1186 // BSPhysObject.AddAngularForce()
1403 AddAngularForce(force, pushforce, false); 1187 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1404 }
1405 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1406 { 1188 {
1407 if (force.IsFinite()) 1189 if (force.IsFinite())
1408 { 1190 {
1409 OMV.Vector3 angForce = force; 1191 OMV.Vector3 angForce = force;
1410 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() 1192 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
1411 { 1193 {
1412 if (PhysBody.HasPhysicalBody) 1194 if (PhysBody.HasPhysicalBody)
1413 { 1195 {
1414 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); 1196 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
1415 PhysicsScene.PE.ApplyTorque(PhysBody, angForce); 1197 PhysScene.PE.ApplyTorque(PhysBody, angForce);
1416 ActivateIfPhysical(false); 1198 ActivateIfPhysical(false);
1417 } 1199 }
1418 }); 1200 });
@@ -1431,11 +1213,11 @@ public class BSPrim : BSPhysObject
1431 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1213 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1432 { 1214 {
1433 OMV.Vector3 applyImpulse = impulse; 1215 OMV.Vector3 applyImpulse = impulse;
1434 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1216 PhysScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1435 { 1217 {
1436 if (PhysBody.HasPhysicalBody) 1218 if (PhysBody.HasPhysicalBody)
1437 { 1219 {
1438 PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); 1220 PhysScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse);
1439 ActivateIfPhysical(false); 1221 ActivateIfPhysical(false);
1440 } 1222 }
1441 }); 1223 });
@@ -1721,9 +1503,11 @@ public class BSPrim : BSPhysObject
1721 volume *= (profileEnd - profileBegin); 1503 volume *= (profileEnd - profileBegin);
1722 1504
1723 returnMass = Density * BSParam.DensityScaleFactor * volume; 1505 returnMass = Density * BSParam.DensityScaleFactor * volume;
1724 DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass);
1725 1506
1726 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); 1507 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
1508 // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass);
1509 DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3},pathB={4},pathE={5},profB={6},profE={7},siz={8}",
1510 LocalID, Density, volume, returnMass, pathBegin, pathEnd, profileBegin, profileEnd, _size);
1727 1511
1728 return returnMass; 1512 return returnMass;
1729 }// end CalculateMass 1513 }// end CalculateMass
@@ -1736,13 +1520,14 @@ public class BSPrim : BSPhysObject
1736 { 1520 {
1737 // Create the correct physical representation for this type of object. 1521 // Create the correct physical representation for this type of object.
1738 // Updates base.PhysBody and base.PhysShape with the new information. 1522 // Updates base.PhysBody and base.PhysShape with the new information.
1739 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1523 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
1740 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) 1524 PhysScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysScene.World, this, delegate(BulletBody pBody, BulletShape pShape)
1741 { 1525 {
1742 // Called if the current prim body is about to be destroyed. 1526 // Called if the current prim body is about to be destroyed.
1743 // Remove all the physical dependencies on the old body. 1527 // Remove all the physical dependencies on the old body.
1744 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) 1528 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
1745 RemoveBodyDependencies(); 1529 // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints.
1530 RemoveDependencies();
1746 }); 1531 });
1747 1532
1748 // Make sure the properties are set on the new object 1533 // Make sure the properties are set on the new object
@@ -1750,33 +1535,30 @@ public class BSPrim : BSPhysObject
1750 return; 1535 return;
1751 } 1536 }
1752 1537
1753 protected virtual void RemoveBodyDependencies() 1538 // Called at taint-time
1539 protected virtual void RemoveDependencies()
1754 { 1540 {
1755 VehicleController.RemoveBodyDependencies(this); 1541 PhysicalActors.RemoveDependencies();
1756 } 1542 }
1757 1543
1758 // The physics engine says that properties have updated. Update same and inform 1544 // The physics engine says that properties have updated. Update same and inform
1759 // the world that things have changed. 1545 // the world that things have changed.
1546 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims.
1547 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimDisplaced which handles mapping physical position to simulator position.
1760 public override void UpdateProperties(EntityProperties entprop) 1548 public override void UpdateProperties(EntityProperties entprop)
1761 { 1549 {
1550 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
1762 TriggerPreUpdatePropertyAction(ref entprop); 1551 TriggerPreUpdatePropertyAction(ref entprop);
1763 1552
1764 // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
1765 // TODO: handle physics introduced by Bullet with computed vehicle physics.
1766 if (VehicleController.IsActive)
1767 {
1768 entprop.RotationalVelocity = OMV.Vector3.Zero;
1769 }
1770
1771 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG 1553 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
1772 1554
1773 // Assign directly to the local variables so the normal set actions do not happen 1555 // Assign directly to the local variables so the normal set actions do not happen
1774 _position = entprop.Position; 1556 RawPosition = entprop.Position;
1775 _orientation = entprop.Rotation; 1557 RawOrientation = entprop.Rotation;
1776 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be 1558 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
1777 // very sensitive to velocity changes. 1559 // very sensitive to velocity changes.
1778 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold)) 1560 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold))
1779 _velocity = entprop.Velocity; 1561 RawVelocity = entprop.Velocity;
1780 _acceleration = entprop.Acceleration; 1562 _acceleration = entprop.Acceleration;
1781 _rotationalVelocity = entprop.RotationalVelocity; 1563 _rotationalVelocity = entprop.RotationalVelocity;
1782 1564
@@ -1785,29 +1567,20 @@ public class BSPrim : BSPhysObject
1785 // The sanity check can change the velocity and/or position. 1567 // The sanity check can change the velocity and/or position.
1786 if (PositionSanityCheck(true /* inTaintTime */ )) 1568 if (PositionSanityCheck(true /* inTaintTime */ ))
1787 { 1569 {
1788 entprop.Position = _position; 1570 entprop.Position = RawPosition;
1789 entprop.Velocity = _velocity; 1571 entprop.Velocity = RawVelocity;
1790 entprop.RotationalVelocity = _rotationalVelocity; 1572 entprop.RotationalVelocity = _rotationalVelocity;
1791 entprop.Acceleration = _acceleration; 1573 entprop.Acceleration = _acceleration;
1792 } 1574 }
1793 1575
1794 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG 1576 OMV.Vector3 direction = OMV.Vector3.UnitX * RawOrientation; // DEBUG DEBUG DEBUG
1795 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); 1577 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction);
1796 1578
1797 // remember the current and last set values 1579 // remember the current and last set values
1798 LastEntityProperties = CurrentEntityProperties; 1580 LastEntityProperties = CurrentEntityProperties;
1799 CurrentEntityProperties = entprop; 1581 CurrentEntityProperties = entprop;
1800 1582
1801 base.RequestPhysicsterseUpdate(); 1583 PhysScene.PostUpdate(this);
1802 /*
1803 else
1804 {
1805 // For debugging, report the movement of children
1806 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1807 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1808 entprop.Acceleration, entprop.RotationalVelocity);
1809 }
1810 */
1811 } 1584 }
1812} 1585}
1813} 1586}