aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs741
1 files changed, 309 insertions, 432 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index e56276a..15b7090 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
41 [Serializable] 41 [Serializable]
42public class BSPrim : BSPhysObject 42public class BSPrim : BSPhysObject
43{ 43{
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private static readonly string LogHeader = "[BULLETS PRIM]"; 45 private static readonly string LogHeader = "[BULLETS PRIM]";
46 46
47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. 47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
@@ -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,17 +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 VehicleActor; 68 // Keep a handle to the vehicle actor so it is easy to set parameters on same.
76 public string VehicleActorName = "BasicVehicle"; 69 public const string VehicleActorName = "BasicVehicle";
77
78 private BSVMotor _targetMotor;
79 private OMV.Vector3 _PIDTarget;
80 private float _PIDTau;
81 70
82 private BSFMotor _hoverMotor; 71 // Parameters for the hover actor
83 private float _PIDHoverHeight; 72 public const string HoverActorName = "BSPrim.HoverActor";
84 private PIDHoverType _PIDHoverType; 73 // Parameters for the axis lock actor
85 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";
86 80
87 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,
88 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 82 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
@@ -90,32 +84,34 @@ public class BSPrim : BSPhysObject
90 { 84 {
91 // 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);
92 _physicsActorType = (int)ActorTypes.Prim; 86 _physicsActorType = (int)ActorTypes.Prim;
93 _position = pos; 87 RawPosition = pos;
94 _size = size; 88 _size = size;
95 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).
96 _orientation = rotation; 90 RawOrientation = rotation;
97 _buoyancy = 0f; 91 _buoyancy = 0f;
98 _velocity = OMV.Vector3.Zero; 92 RawVelocity = OMV.Vector3.Zero;
99 _rotationalVelocity = OMV.Vector3.Zero; 93 _rotationalVelocity = OMV.Vector3.Zero;
100 BaseShape = pbs; 94 BaseShape = pbs;
101 _isPhysical = pisPhysical; 95 _isPhysical = pisPhysical;
102 _isVolumeDetect = false; 96 _isVolumeDetect = false;
103 97
104 VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); 98 // Add a dynamic vehicle to our set of actors that can move this prim.
105 PhysicalActors.Add(VehicleActorName, VehicleActor); 99 // PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName));
106 100
107 _mass = CalculateMass(); 101 _mass = CalculateMass();
108 102
109 // DetailLog("{0},BSPrim.constructor,call", LocalID); 103 // DetailLog("{0},BSPrim.constructor,call", LocalID);
110 // do the actual object creation at taint time 104 // do the actual object creation at taint time
111 PhysicsScene.TaintedObject("BSPrim.create", delegate() 105 PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate()
112 { 106 {
113 // Make sure the object is being created with some sanity. 107 // Make sure the object is being created with some sanity.
114 ExtremeSanityCheck(true /* inTaintTime */); 108 ExtremeSanityCheck(true /* inTaintTime */);
115 109
116 CreateGeomAndObject(true); 110 CreateGeomAndObject(true);
117 111
118 CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); 112 CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody);
113
114 IsInitialized = true;
119 }); 115 });
120 } 116 }
121 117
@@ -123,19 +119,21 @@ public class BSPrim : BSPhysObject
123 public override void Destroy() 119 public override void Destroy()
124 { 120 {
125 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 121 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
122 IsInitialized = false;
123
126 base.Destroy(); 124 base.Destroy();
127 125
128 // Undo any vehicle properties 126 // Undo any vehicle properties
129 this.VehicleType = (int)Vehicle.TYPE_NONE; 127 this.VehicleType = (int)Vehicle.TYPE_NONE;
130 128
131 PhysicsScene.TaintedObject("BSPrim.Destroy", delegate() 129 PhysScene.TaintedObject(LocalID, "BSPrim.Destroy", delegate()
132 { 130 {
133 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 131 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
134 // If there are physical body and shape, release my use of same. 132 // If there are physical body and shape, release my use of same.
135 PhysicsScene.Shapes.DereferenceBody(PhysBody, null); 133 PhysScene.Shapes.DereferenceBody(PhysBody, null);
136 PhysBody.Clear(); 134 PhysBody.Clear();
137 PhysicsScene.Shapes.DereferenceShape(PhysShape, null); 135 PhysShape.Dereference(PhysScene);
138 PhysShape.Clear(); 136 PhysShape = new BSShapeNull();
139 }); 137 });
140 } 138 }
141 139
@@ -161,25 +159,13 @@ public class BSPrim : BSPhysObject
161 ForceBodyShapeRebuild(false); 159 ForceBodyShapeRebuild(false);
162 } 160 }
163 } 161 }
164 // 'unknown' says to choose the best type
165 public override BSPhysicsShapeType PreferredPhysicalShape
166 { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
167
168 public override bool ForceBodyShapeRebuild(bool inTaintTime) 162 public override bool ForceBodyShapeRebuild(bool inTaintTime)
169 { 163 {
170 if (inTaintTime) 164 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ForceBodyShapeRebuild", delegate()
171 { 165 {
172 _mass = CalculateMass(); // changing the shape changes the mass 166 _mass = CalculateMass(); // changing the shape changes the mass
173 CreateGeomAndObject(true); 167 CreateGeomAndObject(true);
174 } 168 });
175 else
176 {
177 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
178 {
179 _mass = CalculateMass(); // changing the shape changes the mass
180 CreateGeomAndObject(true);
181 });
182 }
183 return true; 169 return true;
184 } 170 }
185 public override bool Grabbed { 171 public override bool Grabbed {
@@ -192,7 +178,7 @@ public class BSPrim : BSPhysObject
192 if (value != _isSelected) 178 if (value != _isSelected)
193 { 179 {
194 _isSelected = value; 180 _isSelected = value;
195 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 181 PhysScene.TaintedObject(LocalID, "BSPrim.setSelected", delegate()
196 { 182 {
197 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 183 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
198 SetObjectDynamic(false); 184 SetObjectDynamic(false);
@@ -233,28 +219,28 @@ public class BSPrim : BSPhysObject
233 // Called at taint time! 219 // Called at taint time!
234 public override void ZeroMotion(bool inTaintTime) 220 public override void ZeroMotion(bool inTaintTime)
235 { 221 {
236 _velocity = OMV.Vector3.Zero; 222 RawVelocity = OMV.Vector3.Zero;
237 _acceleration = OMV.Vector3.Zero; 223 _acceleration = OMV.Vector3.Zero;
238 _rotationalVelocity = OMV.Vector3.Zero; 224 _rotationalVelocity = OMV.Vector3.Zero;
239 225
240 // Zero some other properties in the physics engine 226 // Zero some other properties in the physics engine
241 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 227 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
242 { 228 {
243 if (PhysBody.HasPhysicalBody) 229 if (PhysBody.HasPhysicalBody)
244 PhysicsScene.PE.ClearAllForces(PhysBody); 230 PhysScene.PE.ClearAllForces(PhysBody);
245 }); 231 });
246 } 232 }
247 public override void ZeroAngularMotion(bool inTaintTime) 233 public override void ZeroAngularMotion(bool inTaintTime)
248 { 234 {
249 _rotationalVelocity = OMV.Vector3.Zero; 235 _rotationalVelocity = OMV.Vector3.Zero;
250 // Zero some other properties in the physics engine 236 // Zero some other properties in the physics engine
251 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 237 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
252 { 238 {
253 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); 239 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
254 if (PhysBody.HasPhysicalBody) 240 if (PhysBody.HasPhysicalBody)
255 { 241 {
256 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 242 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
257 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 243 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
258 } 244 }
259 }); 245 });
260 } 246 }
@@ -268,64 +254,58 @@ public class BSPrim : BSPhysObject
268 if (axis.X != 1) locking.X = 0f; 254 if (axis.X != 1) locking.X = 0f;
269 if (axis.Y != 1) locking.Y = 0f; 255 if (axis.Y != 1) locking.Y = 0f;
270 if (axis.Z != 1) locking.Z = 0f; 256 if (axis.Z != 1) locking.Z = 0f;
271 LockedAxis = locking; 257 LockedAngularAxis = locking;
272 258
273 if (LockedAxis != LockedAxisFree) 259 EnableActor(LockedAngularAxis != LockedAxisFree, LockedAxisActorName, delegate()
274 { 260 {
275 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() 261 return new BSActorLockAxis(PhysScene, this, LockedAxisActorName);
276 { 262 });
277 // If there is not already an axis locker, make one 263
278 if (!PhysicalActors.HasActor(LockedAxisActorName)) 264 // Update parameters so the new actor's Refresh() action is called at the right time.
279 { 265 PhysScene.TaintedObject(LocalID, "BSPrim.LockAngularMotion", delegate()
280 DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID); 266 {
281 PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName)); 267 UpdatePhysicalParameters();
282 } 268 });
283 UpdatePhysicalParameters(); 269
284 });
285 }
286 return; 270 return;
287 } 271 }
288 272
289 public override OMV.Vector3 RawPosition
290 {
291 get { return _position; }
292 set { _position = value; }
293 }
294 public override OMV.Vector3 Position { 273 public override OMV.Vector3 Position {
295 get { 274 get {
296 // don't do the GetObjectPosition for root elements because this function is called a zillion times. 275 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
297 // _position = ForcePosition; 276 // RawPosition = ForcePosition;
298 return _position; 277 return RawPosition;
299 } 278 }
300 set { 279 set {
301 // If the position must be forced into the physics engine, use ForcePosition. 280 // If the position must be forced into the physics engine, use ForcePosition.
302 // All positions are given in world positions. 281 // All positions are given in world positions.
303 if (_position == value) 282 if (RawPosition == value)
304 { 283 {
305 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); 284 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
306 return; 285 return;
307 } 286 }
308 _position = value; 287 RawPosition = value;
309 PositionSanityCheck(false); 288 PositionSanityCheck(false);
310 289
311 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 290 PhysScene.TaintedObject(LocalID, "BSPrim.setPosition", delegate()
312 { 291 {
313 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 292 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
314 ForcePosition = _position; 293 ForcePosition = RawPosition;
315 }); 294 });
316 } 295 }
317 } 296 }
318 297
298 // NOTE: overloaded by BSPrimDisplaced to handle offset for center-of-gravity.
319 public override OMV.Vector3 ForcePosition { 299 public override OMV.Vector3 ForcePosition {
320 get { 300 get {
321 _position = PhysicsScene.PE.GetPosition(PhysBody); 301 RawPosition = PhysScene.PE.GetPosition(PhysBody);
322 return _position; 302 return RawPosition;
323 } 303 }
324 set { 304 set {
325 _position = value; 305 RawPosition = value;
326 if (PhysBody.HasPhysicalBody) 306 if (PhysBody.HasPhysicalBody)
327 { 307 {
328 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 308 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
329 ActivateIfPhysical(false); 309 ActivateIfPhysical(false);
330 } 310 }
331 } 311 }
@@ -342,7 +322,7 @@ public class BSPrim : BSPhysObject
342 if (!IsPhysicallyActive) 322 if (!IsPhysicallyActive)
343 return ret; 323 return ret;
344 324
345 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 325 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
346 { 326 {
347 // The physical object is out of the known/simulated area. 327 // The physical object is out of the known/simulated area.
348 // Upper levels of code will handle the transition to other areas so, for 328 // Upper levels of code will handle the transition to other areas so, for
@@ -350,7 +330,7 @@ public class BSPrim : BSPhysObject
350 return ret; 330 return ret;
351 } 331 }
352 332
353 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 333 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
354 OMV.Vector3 upForce = OMV.Vector3.Zero; 334 OMV.Vector3 upForce = OMV.Vector3.Zero;
355 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); 335 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z));
356 if ((RawPosition.Z + approxSize / 2f) < terrainHeight) 336 if ((RawPosition.Z + approxSize / 2f) < terrainHeight)
@@ -359,10 +339,10 @@ public class BSPrim : BSPhysObject
359 float targetHeight = terrainHeight + (Size.Z / 2f); 339 float targetHeight = terrainHeight + (Size.Z / 2f);
360 // If the object is below ground it just has to be moved up because pushing will 340 // If the object is below ground it just has to be moved up because pushing will
361 // not get it through the terrain 341 // not get it through the terrain
362 _position.Z = targetHeight; 342 RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, targetHeight);
363 if (inTaintTime) 343 if (inTaintTime)
364 { 344 {
365 ForcePosition = _position; 345 ForcePosition = RawPosition;
366 } 346 }
367 // If we are throwing the object around, zero its other forces 347 // If we are throwing the object around, zero its other forces
368 ZeroMotion(inTaintTime); 348 ZeroMotion(inTaintTime);
@@ -371,7 +351,7 @@ public class BSPrim : BSPhysObject
371 351
372 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 352 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
373 { 353 {
374 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 354 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
375 // TODO: a floating motor so object will bob in the water 355 // TODO: a floating motor so object will bob in the water
376 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) 356 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
377 { 357 {
@@ -379,8 +359,8 @@ public class BSPrim : BSPhysObject
379 upForce.Z = (waterHeight - RawPosition.Z) * 1f; 359 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
380 360
381 // Apply upforce and overcome gravity. 361 // Apply upforce and overcome gravity.
382 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; 362 OMV.Vector3 correctionForce = upForce - PhysScene.DefaultGravity;
383 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); 363 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, RawPosition, upForce, correctionForce);
384 AddForce(correctionForce, false, inTaintTime); 364 AddForce(correctionForce, false, inTaintTime);
385 ret = true; 365 ret = true;
386 } 366 }
@@ -399,17 +379,17 @@ public class BSPrim : BSPhysObject
399 uint wayOutThere = Constants.RegionSize * Constants.RegionSize; 379 uint wayOutThere = Constants.RegionSize * Constants.RegionSize;
400 // There have been instances of objects getting thrown way out of bounds and crashing 380 // There have been instances of objects getting thrown way out of bounds and crashing
401 // the border crossing code. 381 // the border crossing code.
402 if ( _position.X < -Constants.RegionSize || _position.X > wayOutThere 382 if ( RawPosition.X < -Constants.RegionSize || RawPosition.X > wayOutThere
403 || _position.Y < -Constants.RegionSize || _position.Y > wayOutThere 383 || RawPosition.Y < -Constants.RegionSize || RawPosition.Y > wayOutThere
404 || _position.Z < -Constants.RegionSize || _position.Z > wayOutThere) 384 || RawPosition.Z < -Constants.RegionSize || RawPosition.Z > wayOutThere)
405 { 385 {
406 _position = new OMV.Vector3(10, 10, 50); 386 RawPosition = new OMV.Vector3(10, 10, 50);
407 ZeroMotion(inTaintTime); 387 ZeroMotion(inTaintTime);
408 ret = true; 388 ret = true;
409 } 389 }
410 if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) 390 if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity)
411 { 391 {
412 _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); 392 RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity);
413 ret = true; 393 ret = true;
414 } 394 }
415 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) 395 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared)
@@ -434,7 +414,7 @@ public class BSPrim : BSPhysObject
434 get { return _mass; } 414 get { return _mass; }
435 } 415 }
436 // used when we only want this prim's mass and not the linkset thing 416 // used when we only want this prim's mass and not the linkset thing
437 public override float RawMass { 417 public override float RawMass {
438 get { return _mass; } 418 get { return _mass; }
439 } 419 }
440 // Set the physical mass to the passed mass. 420 // Set the physical mass to the passed mass.
@@ -445,10 +425,10 @@ public class BSPrim : BSPhysObject
445 { 425 {
446 if (IsStatic) 426 if (IsStatic)
447 { 427 {
448 PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); 428 PhysScene.PE.SetGravity(PhysBody, PhysScene.DefaultGravity);
449 Inertia = OMV.Vector3.Zero; 429 Inertia = OMV.Vector3.Zero;
450 PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); 430 PhysScene.PE.SetMassProps(PhysBody, 0f, Inertia);
451 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 431 PhysScene.PE.UpdateInertiaTensor(PhysBody);
452 } 432 }
453 else 433 else
454 { 434 {
@@ -457,16 +437,19 @@ public class BSPrim : BSPhysObject
457 // Changing interesting properties doesn't change proxy and collision cache 437 // Changing interesting properties doesn't change proxy and collision cache
458 // information. The Bullet solution is to re-add the object to the world 438 // information. The Bullet solution is to re-add the object to the world
459 // after parameters are changed. 439 // after parameters are changed.
460 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 440 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
461 } 441 }
462 442
463 // The computation of mass props requires gravity to be set on the object. 443 // The computation of mass props requires gravity to be set on the object.
464 Gravity = ComputeGravity(Buoyancy); 444 Gravity = ComputeGravity(Buoyancy);
465 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 445 PhysScene.PE.SetGravity(PhysBody, Gravity);
446
447 // OMV.Vector3 currentScale = PhysScene.PE.GetLocalScaling(PhysShape.physShapeInfo); // DEBUG DEBUG
448 // DetailLog("{0},BSPrim.UpdateMassProperties,currentScale{1},shape={2}", LocalID, currentScale, PhysShape.physShapeInfo); // DEBUG DEBUG
466 449
467 Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 450 Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
468 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); 451 PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia);
469 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 452 PhysScene.PE.UpdateInertiaTensor(PhysBody);
470 453
471 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", 454 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}",
472 LocalID, physMass, Inertia, Gravity, inWorld); 455 LocalID, physMass, Inertia, Gravity, inWorld);
@@ -482,7 +465,7 @@ public class BSPrim : BSPhysObject
482 // Return what gravity should be set to this very moment 465 // Return what gravity should be set to this very moment
483 public OMV.Vector3 ComputeGravity(float buoyancy) 466 public OMV.Vector3 ComputeGravity(float buoyancy)
484 { 467 {
485 OMV.Vector3 ret = PhysicsScene.DefaultGravity; 468 OMV.Vector3 ret = PhysScene.DefaultGravity;
486 469
487 if (!IsStatic) 470 if (!IsStatic)
488 { 471 {
@@ -506,83 +489,121 @@ public class BSPrim : BSPhysObject
506 } 489 }
507 490
508 public override OMV.Vector3 Force { 491 public override OMV.Vector3 Force {
509 get { return _force; } 492 get { return RawForce; }
510 set { 493 set {
511 _force = value; 494 RawForce = value;
512 if (_force != OMV.Vector3.Zero) 495 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
513 { 496 {
514 // If the force is non-zero, it must be reapplied each tick because 497 return new BSActorSetForce(PhysScene, this, SetForceActorName);
515 // Bullet clears the forces applied last frame. 498 });
516 RegisterPreStepAction("BSPrim.setForce", LocalID, 499 }
517 delegate(float timeStep) 500 }
518 {
519 if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
520 {
521 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
522 return;
523 }
524 501
525 DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); 502 // Find and return a handle to the current vehicle actor.
526 if (PhysBody.HasPhysicalBody) 503 // Return 'null' if there is no vehicle actor.
527 { 504 public BSDynamics GetVehicleActor(bool createIfNone)
528 PhysicsScene.PE.ApplyCentralForce(PhysBody, _force); 505 {
529 ActivateIfPhysical(false); 506 BSDynamics ret = null;
530 } 507 BSActor actor;
531 } 508 if (PhysicalActors.TryGetActor(VehicleActorName, out actor))
532 ); 509 {
533 } 510 ret = actor as BSDynamics;
534 else 511 }
512 else
513 {
514 if (createIfNone)
535 { 515 {
536 UnRegisterPreStepAction("BSPrim.setForce", LocalID); 516 ret = new BSDynamics(PhysScene, this, VehicleActorName);
517 PhysicalActors.Add(ret.ActorName, ret);
537 } 518 }
538 } 519 }
520 return ret;
539 } 521 }
540 522
541 public override int VehicleType { 523 public override int VehicleType {
542 get { 524 get {
543 return (int)VehicleActor.Type; // if we are a vehicle, return that type 525 int ret = (int)Vehicle.TYPE_NONE;
526 BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */);
527 if (vehicleActor != null)
528 ret = (int)vehicleActor.Type;
529 return ret;
544 } 530 }
545 set { 531 set {
546 Vehicle type = (Vehicle)value; 532 Vehicle type = (Vehicle)value;
547 533
548 PhysicsScene.TaintedObject("setVehicleType", delegate() 534 PhysScene.TaintedObject(LocalID, "setVehicleType", delegate()
549 { 535 {
550 // Done at taint time so we're sure the physics engine is not using the variables 536 // Some vehicle scripts change vehicle type on the fly as an easy way to
551 // Vehicle code changes the parameters for this vehicle type. 537 // change all the parameters. Like a plane changing to CAR when on the
552 VehicleActor.ProcessTypeChange(type); 538 // ground. In this case, don't want to zero motion.
553 ActivateIfPhysical(false); 539 // ZeroMotion(true /* inTaintTime */);
540 if (type == Vehicle.TYPE_NONE)
541 {
542 // Vehicle type is 'none' so get rid of any actor that may have been allocated.
543 BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */);
544 if (vehicleActor != null)
545 {
546 PhysicalActors.RemoveAndRelease(vehicleActor.ActorName);
547 }
548 }
549 else
550 {
551 // Vehicle type is not 'none' so create an actor and set it running.
552 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
553 if (vehicleActor != null)
554 {
555 vehicleActor.ProcessTypeChange(type);
556 ActivateIfPhysical(false);
557 }
558 }
554 }); 559 });
555 } 560 }
556 } 561 }
557 public override void VehicleFloatParam(int param, float value) 562 public override void VehicleFloatParam(int param, float value)
558 { 563 {
559 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 564 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFloatParam", delegate()
560 { 565 {
561 VehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); 566 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
562 ActivateIfPhysical(false); 567 if (vehicleActor != null)
568 {
569 vehicleActor.ProcessFloatVehicleParam((Vehicle)param, value);
570 ActivateIfPhysical(false);
571 }
563 }); 572 });
564 } 573 }
565 public override void VehicleVectorParam(int param, OMV.Vector3 value) 574 public override void VehicleVectorParam(int param, OMV.Vector3 value)
566 { 575 {
567 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 576 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleVectorParam", delegate()
568 { 577 {
569 VehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); 578 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
570 ActivateIfPhysical(false); 579 if (vehicleActor != null)
580 {
581 vehicleActor.ProcessVectorVehicleParam((Vehicle)param, value);
582 ActivateIfPhysical(false);
583 }
571 }); 584 });
572 } 585 }
573 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 586 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
574 { 587 {
575 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 588 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleRotationParam", delegate()
576 { 589 {
577 VehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); 590 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
578 ActivateIfPhysical(false); 591 if (vehicleActor != null)
592 {
593 vehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation);
594 ActivateIfPhysical(false);
595 }
579 }); 596 });
580 } 597 }
581 public override void VehicleFlags(int param, bool remove) 598 public override void VehicleFlags(int param, bool remove)
582 { 599 {
583 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() 600 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFlags", delegate()
584 { 601 {
585 VehicleActor.ProcessVehicleFlags(param, remove); 602 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
603 if (vehicleActor != null)
604 {
605 vehicleActor.ProcessVehicleFlags(param, remove);
606 }
586 }); 607 });
587 } 608 }
588 609
@@ -592,7 +613,7 @@ public class BSPrim : BSPhysObject
592 if (_isVolumeDetect != newValue) 613 if (_isVolumeDetect != newValue)
593 { 614 {
594 _isVolumeDetect = newValue; 615 _isVolumeDetect = newValue;
595 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 616 PhysScene.TaintedObject(LocalID, "BSPrim.SetVolumeDetect", delegate()
596 { 617 {
597 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); 618 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
598 SetObjectDynamic(true); 619 SetObjectDynamic(true);
@@ -600,10 +621,14 @@ public class BSPrim : BSPhysObject
600 } 621 }
601 return; 622 return;
602 } 623 }
624 public override bool IsVolumeDetect
625 {
626 get { return _isVolumeDetect; }
627 }
603 public override void SetMaterial(int material) 628 public override void SetMaterial(int material)
604 { 629 {
605 base.SetMaterial(material); 630 base.SetMaterial(material);
606 PhysicsScene.TaintedObject("BSPrim.SetMaterial", delegate() 631 PhysScene.TaintedObject(LocalID, "BSPrim.SetMaterial", delegate()
607 { 632 {
608 UpdatePhysicalParameters(); 633 UpdatePhysicalParameters();
609 }); 634 });
@@ -616,7 +641,7 @@ public class BSPrim : BSPhysObject
616 if (base.Friction != value) 641 if (base.Friction != value)
617 { 642 {
618 base.Friction = value; 643 base.Friction = value;
619 PhysicsScene.TaintedObject("BSPrim.setFriction", delegate() 644 PhysScene.TaintedObject(LocalID, "BSPrim.setFriction", delegate()
620 { 645 {
621 UpdatePhysicalParameters(); 646 UpdatePhysicalParameters();
622 }); 647 });
@@ -631,7 +656,7 @@ public class BSPrim : BSPhysObject
631 if (base.Restitution != value) 656 if (base.Restitution != value)
632 { 657 {
633 base.Restitution = value; 658 base.Restitution = value;
634 PhysicsScene.TaintedObject("BSPrim.setRestitution", delegate() 659 PhysScene.TaintedObject(LocalID, "BSPrim.setRestitution", delegate()
635 { 660 {
636 UpdatePhysicalParameters(); 661 UpdatePhysicalParameters();
637 }); 662 });
@@ -648,7 +673,7 @@ public class BSPrim : BSPhysObject
648 if (base.Density != value) 673 if (base.Density != value)
649 { 674 {
650 base.Density = value; 675 base.Density = value;
651 PhysicsScene.TaintedObject("BSPrim.setDensity", delegate() 676 PhysScene.TaintedObject(LocalID, "BSPrim.setDensity", delegate()
652 { 677 {
653 UpdatePhysicalParameters(); 678 UpdatePhysicalParameters();
654 }); 679 });
@@ -663,93 +688,66 @@ public class BSPrim : BSPhysObject
663 if (base.GravModifier != value) 688 if (base.GravModifier != value)
664 { 689 {
665 base.GravModifier = value; 690 base.GravModifier = value;
666 PhysicsScene.TaintedObject("BSPrim.setGravityModifier", delegate() 691 PhysScene.TaintedObject(LocalID, "BSPrim.setGravityModifier", delegate()
667 { 692 {
668 UpdatePhysicalParameters(); 693 UpdatePhysicalParameters();
669 }); 694 });
670 } 695 }
671 } 696 }
672 } 697 }
673 public override OMV.Vector3 RawVelocity
674 {
675 get { return _velocity; }
676 set { _velocity = value; }
677 }
678 public override OMV.Vector3 Velocity { 698 public override OMV.Vector3 Velocity {
679 get { return _velocity; } 699 get { return RawVelocity; }
680 set { 700 set {
681 _velocity = value; 701 RawVelocity = value;
682 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 702 PhysScene.TaintedObject(LocalID, "BSPrim.setVelocity", delegate()
683 { 703 {
684 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 704 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
685 ForceVelocity = _velocity; 705 ForceVelocity = RawVelocity;
686 }); 706 });
687 } 707 }
688 } 708 }
689 public override OMV.Vector3 ForceVelocity { 709 public override OMV.Vector3 ForceVelocity {
690 get { return _velocity; } 710 get { return RawVelocity; }
691 set { 711 set {
692 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); 712 PhysScene.AssertInTaintTime("BSPrim.ForceVelocity");
693 713
694 _velocity = Util.ClampV(value, BSParam.MaxLinearVelocity); 714 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
695 if (PhysBody.HasPhysicalBody) 715 if (PhysBody.HasPhysicalBody)
696 { 716 {
697 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity); 717 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
698 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 718 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
699 ActivateIfPhysical(false); 719 ActivateIfPhysical(false);
700 } 720 }
701 } 721 }
702 } 722 }
703 public override OMV.Vector3 Torque { 723 public override OMV.Vector3 Torque {
704 get { return _torque; } 724 get { return RawTorque; }
705 set { 725 set {
706 _torque = value; 726 RawTorque = value;
707 if (_torque != OMV.Vector3.Zero) 727 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
708 {
709 // If the torque is non-zero, it must be reapplied each tick because
710 // Bullet clears the forces applied last frame.
711 RegisterPreStepAction("BSPrim.setTorque", LocalID,
712 delegate(float timeStep)
713 {
714 if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
715 {
716 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
717 return;
718 }
719
720 if (PhysBody.HasPhysicalBody)
721 AddAngularForce(_torque, false, true);
722 }
723 );
724 }
725 else
726 { 728 {
727 UnRegisterPreStepAction("BSPrim.setTorque", LocalID); 729 return new BSActorSetTorque(PhysScene, this, SetTorqueActorName);
728 } 730 });
729 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 731 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
730 } 732 }
731 } 733 }
732 public override OMV.Vector3 Acceleration { 734 public override OMV.Vector3 Acceleration {
733 get { return _acceleration; } 735 get { return _acceleration; }
734 set { _acceleration = value; } 736 set { _acceleration = value; }
735 } 737 }
736 public override OMV.Quaternion RawOrientation 738
737 {
738 get { return _orientation; }
739 set { _orientation = value; }
740 }
741 public override OMV.Quaternion Orientation { 739 public override OMV.Quaternion Orientation {
742 get { 740 get {
743 return _orientation; 741 return RawOrientation;
744 } 742 }
745 set { 743 set {
746 if (_orientation == value) 744 if (RawOrientation == value)
747 return; 745 return;
748 _orientation = value; 746 RawOrientation = value;
749 747
750 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 748 PhysScene.TaintedObject(LocalID, "BSPrim.setOrientation", delegate()
751 { 749 {
752 ForceOrientation = _orientation; 750 ForceOrientation = RawOrientation;
753 }); 751 });
754 } 752 }
755 } 753 }
@@ -758,14 +756,14 @@ public class BSPrim : BSPhysObject
758 { 756 {
759 get 757 get
760 { 758 {
761 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 759 RawOrientation = PhysScene.PE.GetOrientation(PhysBody);
762 return _orientation; 760 return RawOrientation;
763 } 761 }
764 set 762 set
765 { 763 {
766 _orientation = value; 764 RawOrientation = value;
767 if (PhysBody.HasPhysicalBody) 765 if (PhysBody.HasPhysicalBody)
768 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 766 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
769 } 767 }
770 } 768 }
771 public override int PhysicsActorType { 769 public override int PhysicsActorType {
@@ -778,7 +776,7 @@ public class BSPrim : BSPhysObject
778 if (_isPhysical != value) 776 if (_isPhysical != value)
779 { 777 {
780 _isPhysical = value; 778 _isPhysical = value;
781 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 779 PhysScene.TaintedObject(LocalID, "BSPrim.setIsPhysical", delegate()
782 { 780 {
783 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 781 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
784 SetObjectDynamic(true); 782 SetObjectDynamic(true);
@@ -822,24 +820,24 @@ public class BSPrim : BSPhysObject
822 // isSolid: other objects bounce off of this object 820 // isSolid: other objects bounce off of this object
823 // isVolumeDetect: other objects pass through but can generate collisions 821 // isVolumeDetect: other objects pass through but can generate collisions
824 // collisionEvents: whether this object returns collision events 822 // collisionEvents: whether this object returns collision events
823 // NOTE: overloaded by BSPrimLinkable to also update linkset physical parameters.
825 public virtual void UpdatePhysicalParameters() 824 public virtual void UpdatePhysicalParameters()
826 { 825 {
827 if (!PhysBody.HasPhysicalBody) 826 if (!PhysBody.HasPhysicalBody)
828 { 827 {
829 // This would only happen if updates are called for during initialization when the body is not set up yet. 828 // This would only happen if updates are called for during initialization when the body is not set up yet.
830 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); 829 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID);
831 return; 830 return;
832 } 831 }
833 832
834 // Mangling all the physical properties requires the object not be in the physical world. 833 // Mangling all the physical properties requires the object not be in the physical world.
835 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 834 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
836 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 835 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
837 836
838 // Set up the object physicalness (does gravity and collisions move this object) 837 // Set up the object physicalness (does gravity and collisions move this object)
839 MakeDynamic(IsStatic); 838 MakeDynamic(IsStatic);
840 839
841 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) 840 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
842 VehicleActor.Refresh();
843 PhysicalActors.Refresh(); 841 PhysicalActors.Refresh();
844 842
845 // Arrange for collision events if the simulator wants them 843 // Arrange for collision events if the simulator wants them
@@ -851,10 +849,11 @@ public class BSPrim : BSPhysObject
851 AddObjectToPhysicalWorld(); 849 AddObjectToPhysicalWorld();
852 850
853 // Rebuild its shape 851 // Rebuild its shape
854 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 852 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
855 853
856 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", 854 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
857 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); 855 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(),
856 CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
858 } 857 }
859 858
860 // "Making dynamic" means changing to and from static. 859 // "Making dynamic" means changing to and from static.
@@ -867,28 +866,28 @@ public class BSPrim : BSPhysObject
867 if (makeStatic) 866 if (makeStatic)
868 { 867 {
869 // Become a Bullet 'static' object type 868 // Become a Bullet 'static' object type
870 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 869 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
871 // Stop all movement 870 // Stop all movement
872 ZeroMotion(true); 871 ZeroMotion(true);
873 872
874 // Set various physical properties so other object interact properly 873 // Set various physical properties so other object interact properly
875 PhysicsScene.PE.SetFriction(PhysBody, Friction); 874 PhysScene.PE.SetFriction(PhysBody, Friction);
876 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 875 PhysScene.PE.SetRestitution(PhysBody, Restitution);
877 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 876 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
878 877
879 // Mass is zero which disables a bunch of physics stuff in Bullet 878 // Mass is zero which disables a bunch of physics stuff in Bullet
880 UpdatePhysicalMassProperties(0f, false); 879 UpdatePhysicalMassProperties(0f, false);
881 // Set collision detection parameters 880 // Set collision detection parameters
882 if (BSParam.CcdMotionThreshold > 0f) 881 if (BSParam.CcdMotionThreshold > 0f)
883 { 882 {
884 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 883 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
885 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 884 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
886 } 885 }
887 886
888 // The activation state is 'disabled' so Bullet will not try to act on it. 887 // The activation state is 'disabled' so Bullet will not try to act on it.
889 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); 888 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION);
890 // Start it out sleeping and physical actions could wake it up. 889 // Start it out sleeping and physical actions could wake it up.
891 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); 890 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING);
892 891
893 // This collides like a static object 892 // This collides like a static object
894 PhysBody.collisionType = CollisionType.Static; 893 PhysBody.collisionType = CollisionType.Static;
@@ -896,11 +895,11 @@ public class BSPrim : BSPhysObject
896 else 895 else
897 { 896 {
898 // Not a Bullet static object 897 // Not a Bullet static object
899 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 898 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
900 899
901 // Set various physical properties so other object interact properly 900 // Set various physical properties so other object interact properly
902 PhysicsScene.PE.SetFriction(PhysBody, Friction); 901 PhysScene.PE.SetFriction(PhysBody, Friction);
903 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 902 PhysScene.PE.SetRestitution(PhysBody, Restitution);
904 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); 903 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution);
905 904
906 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 905 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
@@ -908,8 +907,8 @@ public class BSPrim : BSPhysObject
908 // PhysicsScene.PE.ClearAllForces(BSBody); 907 // PhysicsScene.PE.ClearAllForces(BSBody);
909 908
910 // For good measure, make sure the transform is set through to the motion state 909 // For good measure, make sure the transform is set through to the motion state
911 ForcePosition = _position; 910 ForcePosition = RawPosition;
912 ForceVelocity = _velocity; 911 ForceVelocity = RawVelocity;
913 ForceRotationalVelocity = _rotationalVelocity; 912 ForceRotationalVelocity = _rotationalVelocity;
914 913
915 // A dynamic object has mass 914 // A dynamic object has mass
@@ -918,22 +917,22 @@ public class BSPrim : BSPhysObject
918 // Set collision detection parameters 917 // Set collision detection parameters
919 if (BSParam.CcdMotionThreshold > 0f) 918 if (BSParam.CcdMotionThreshold > 0f)
920 { 919 {
921 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 920 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
922 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 921 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
923 } 922 }
924 923
925 // Various values for simulation limits 924 // Various values for simulation limits
926 PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); 925 PhysScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping);
927 PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); 926 PhysScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime);
928 PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); 927 PhysScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
929 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 928 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
930 929
931 // This collides like an object. 930 // This collides like an object.
932 PhysBody.collisionType = CollisionType.Dynamic; 931 PhysBody.collisionType = CollisionType.Dynamic;
933 932
934 // Force activation of the object so Bullet will act on it. 933 // Force activation of the object so Bullet will act on it.
935 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 934 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
936 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 935 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
937 } 936 }
938 } 937 }
939 938
@@ -943,7 +942,7 @@ public class BSPrim : BSPhysObject
943 // the functions after this one set up the state of a possibly newly created collision body. 942 // the functions after this one set up the state of a possibly newly created collision body.
944 private void MakeSolid(bool makeSolid) 943 private void MakeSolid(bool makeSolid)
945 { 944 {
946 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); 945 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysScene.PE.GetBodyType(PhysBody);
947 if (makeSolid) 946 if (makeSolid)
948 { 947 {
949 // Verify the previous code created the correct shape for this type of thing. 948 // Verify the previous code created the correct shape for this type of thing.
@@ -951,7 +950,7 @@ public class BSPrim : BSPhysObject
951 { 950 {
952 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 951 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
953 } 952 }
954 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 953 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
955 } 954 }
956 else 955 else
957 { 956 {
@@ -959,32 +958,23 @@ public class BSPrim : BSPhysObject
959 { 958 {
960 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 959 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
961 } 960 }
962 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 961 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
963 962
964 // Change collision info from a static object to a ghosty collision object 963 // Change collision info from a static object to a ghosty collision object
965 PhysBody.collisionType = CollisionType.VolumeDetect; 964 PhysBody.collisionType = CollisionType.VolumeDetect;
966 } 965 }
967 } 966 }
968 967
969 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
970 // they need waking up when parameters are changed.
971 // Called in taint-time!!
972 private void ActivateIfPhysical(bool forceIt)
973 {
974 if (IsPhysical && PhysBody.HasPhysicalBody)
975 PhysicsScene.PE.Activate(PhysBody, forceIt);
976 }
977
978 // Turn on or off the flag controlling whether collision events are returned to the simulator. 968 // Turn on or off the flag controlling whether collision events are returned to the simulator.
979 private void EnableCollisions(bool wantsCollisionEvents) 969 private void EnableCollisions(bool wantsCollisionEvents)
980 { 970 {
981 if (wantsCollisionEvents) 971 if (wantsCollisionEvents)
982 { 972 {
983 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 973 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
984 } 974 }
985 else 975 else
986 { 976 {
987 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 977 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
988 } 978 }
989 } 979 }
990 980
@@ -995,7 +985,7 @@ public class BSPrim : BSPhysObject
995 { 985 {
996 if (PhysBody.HasPhysicalBody) 986 if (PhysBody.HasPhysicalBody)
997 { 987 {
998 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 988 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
999 } 989 }
1000 else 990 else
1001 { 991 {
@@ -1030,12 +1020,12 @@ public class BSPrim : BSPhysObject
1030 public override bool FloatOnWater { 1020 public override bool FloatOnWater {
1031 set { 1021 set {
1032 _floatOnWater = value; 1022 _floatOnWater = value;
1033 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 1023 PhysScene.TaintedObject(LocalID, "BSPrim.setFloatOnWater", delegate()
1034 { 1024 {
1035 if (_floatOnWater) 1025 if (_floatOnWater)
1036 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1026 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
1037 else 1027 else
1038 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1028 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
1039 }); 1029 });
1040 } 1030 }
1041 } 1031 }
@@ -1047,7 +1037,7 @@ public class BSPrim : BSPhysObject
1047 _rotationalVelocity = value; 1037 _rotationalVelocity = value;
1048 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); 1038 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
1049 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 1039 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
1050 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 1040 PhysScene.TaintedObject(LocalID, "BSPrim.setRotationalVelocity", delegate()
1051 { 1041 {
1052 ForceRotationalVelocity = _rotationalVelocity; 1042 ForceRotationalVelocity = _rotationalVelocity;
1053 }); 1043 });
@@ -1062,7 +1052,7 @@ public class BSPrim : BSPhysObject
1062 if (PhysBody.HasPhysicalBody) 1052 if (PhysBody.HasPhysicalBody)
1063 { 1053 {
1064 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 1054 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
1065 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 1055 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
1066 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 1056 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
1067 ActivateIfPhysical(false); 1057 ActivateIfPhysical(false);
1068 } 1058 }
@@ -1078,7 +1068,7 @@ public class BSPrim : BSPhysObject
1078 get { return _buoyancy; } 1068 get { return _buoyancy; }
1079 set { 1069 set {
1080 _buoyancy = value; 1070 _buoyancy = value;
1081 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() 1071 PhysScene.TaintedObject(LocalID, "BSPrim.setBuoyancy", delegate()
1082 { 1072 {
1083 ForceBuoyancy = _buoyancy; 1073 ForceBuoyancy = _buoyancy;
1084 }); 1074 });
@@ -1096,179 +1086,54 @@ public class BSPrim : BSPhysObject
1096 } 1086 }
1097 } 1087 }
1098 1088
1099 // Used for MoveTo
1100 public override OMV.Vector3 PIDTarget {
1101 set
1102 {
1103 // TODO: add a sanity check -- don't move more than a region or something like that.
1104 _PIDTarget = value;
1105 }
1106 }
1107 public override float PIDTau {
1108 set { _PIDTau = value; }
1109 }
1110 public override bool PIDActive { 1089 public override bool PIDActive {
1111 set { 1090 set {
1112 if (value) 1091 base.MoveToTargetActive = value;
1092 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
1113 { 1093 {
1114 // We're taking over after this. 1094 return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName);
1115 ZeroMotion(true); 1095 });
1116 1096 }
1117 _targetMotor = new BSVMotor("BSPrim.PIDTarget", 1097 }
1118 _PIDTau, // timeScale
1119 BSMotor.Infinite, // decay time scale
1120 BSMotor.InfiniteVector, // friction timescale
1121 1f // efficiency
1122 );
1123 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1124 _targetMotor.SetTarget(_PIDTarget);
1125 _targetMotor.SetCurrent(RawPosition);
1126 /*
1127 _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget");
1128 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1129
1130 _targetMotor.SetTarget(_PIDTarget);
1131 _targetMotor.SetCurrent(RawPosition);
1132 _targetMotor.TimeScale = _PIDTau;
1133 _targetMotor.Efficiency = 1f;
1134 */
1135
1136 RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep)
1137 {
1138 if (!IsPhysicallyActive)
1139 {
1140 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
1141 return;
1142 }
1143
1144 OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below)
1145
1146 // 'movePosition' is where we'd like the prim to be at this moment.
1147 OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep);
1148 1098
1149 // If we are very close to our target, turn off the movement motor. 1099 public override OMV.Vector3 PIDTarget
1150 if (_targetMotor.ErrorIsZero()) 1100 {
1151 { 1101 set
1152 DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", 1102 {
1153 LocalID, movePosition, RawPosition, Mass); 1103 base.PIDTarget = value;
1154 ForcePosition = _targetMotor.TargetValue; 1104 BSActor actor;
1155 _targetMotor.Enabled = false; 1105 if (PhysicalActors.TryGetActor(MoveToTargetActorName, out actor))
1156 }
1157 else
1158 {
1159 _position = movePosition;
1160 PositionSanityCheck(true /* intaintTime */);
1161 ForcePosition = _position;
1162 }
1163 DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
1164 });
1165 }
1166 else
1167 { 1106 {
1168 // Stop any targetting 1107 // if the actor exists, tell it to refresh its values.
1169 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); 1108 actor.Refresh();
1170 } 1109 }
1110
1171 } 1111 }
1172 } 1112 }
1173
1174 // Used for llSetHoverHeight and maybe vehicle height 1113 // Used for llSetHoverHeight and maybe vehicle height
1175 // Hover Height will override MoveTo target's Z 1114 // Hover Height will override MoveTo target's Z
1176 public override bool PIDHoverActive { 1115 public override bool PIDHoverActive {
1177 set { 1116 set {
1178 if (value) 1117 base.HoverActive = value;
1118 EnableActor(HoverActive, HoverActorName, delegate()
1179 { 1119 {
1180 // Turning the target on 1120 return new BSActorHover(PhysScene, this, HoverActorName);
1181 _hoverMotor = new BSFMotor("BSPrim.Hover", 1121 });
1182 _PIDHoverTau, // timeScale
1183 BSMotor.Infinite, // decay time scale
1184 BSMotor.Infinite, // friction timescale
1185 1f // efficiency
1186 );
1187 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1188 _hoverMotor.SetCurrent(RawPosition.Z);
1189 _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1190
1191 RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep)
1192 {
1193 // Don't do hovering while the object is selected.
1194 if (!IsPhysicallyActive)
1195 return;
1196
1197 _hoverMotor.SetCurrent(RawPosition.Z);
1198 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1199 float targetHeight = _hoverMotor.Step(timeStep);
1200
1201 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
1202 // Compute the amount of force to push us there.
1203 float moveForce = (targetHeight - RawPosition.Z) * Mass;
1204 // Undo anything the object thinks it's doing at the moment
1205 moveForce = -RawVelocity.Z * Mass;
1206
1207 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce));
1208 DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass);
1209 });
1210 }
1211 else
1212 {
1213 UnRegisterPreStepAction("BSPrim.Hover", LocalID);
1214 }
1215 }
1216 }
1217 public override float PIDHoverHeight {
1218 set { _PIDHoverHeight = value; }
1219 }
1220 public override PIDHoverType PIDHoverType {
1221 set { _PIDHoverType = value; }
1222 }
1223 public override float PIDHoverTau {
1224 set { _PIDHoverTau = value; }
1225 }
1226 // Based on current position, determine what we should be hovering at now.
1227 // Must recompute often. What if we walked offa cliff>
1228 private float ComputeCurrentPIDHoverHeight()
1229 {
1230 float ret = _PIDHoverHeight;
1231 float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
1232
1233 switch (_PIDHoverType)
1234 {
1235 case PIDHoverType.Ground:
1236 ret = groundHeight + _PIDHoverHeight;
1237 break;
1238 case PIDHoverType.GroundAndWater:
1239 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
1240 if (groundHeight > waterHeight)
1241 {
1242 ret = groundHeight + _PIDHoverHeight;
1243 }
1244 else
1245 {
1246 ret = waterHeight + _PIDHoverHeight;
1247 }
1248 break;
1249 } 1122 }
1250 return ret;
1251 } 1123 }
1252 1124
1253
1254 // For RotLookAt
1255 public override OMV.Quaternion APIDTarget { set { return; } }
1256 public override bool APIDActive { set { return; } }
1257 public override float APIDStrength { set { return; } }
1258 public override float APIDDamping { set { return; } }
1259
1260 public override void AddForce(OMV.Vector3 force, bool pushforce) { 1125 public override void AddForce(OMV.Vector3 force, bool pushforce) {
1261 // Per documentation, max force is limited. 1126 // Per documentation, max force is limited.
1262 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 1127 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1263 1128
1264 // Since this force is being applied in only one step, make this a force per second. 1129 // Since this force is being applied in only one step, make this a force per second.
1265 addForce /= PhysicsScene.LastTimeStep; 1130 addForce /= PhysScene.LastTimeStep;
1266 AddForce(addForce, pushforce, false /* inTaintTime */); 1131 AddForce(addForce, pushforce, false /* inTaintTime */);
1267 } 1132 }
1268 1133
1269 // Applying a force just adds this to the total force on the object. 1134 // Applying a force just adds this to the total force on the object.
1270 // This added force will only last the next simulation tick. 1135 // This added force will only last the next simulation tick.
1271 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1136 public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
1272 // for an object, doesn't matter if force is a pushforce or not 1137 // for an object, doesn't matter if force is a pushforce or not
1273 if (IsPhysicallyActive) 1138 if (IsPhysicallyActive)
1274 { 1139 {
@@ -1277,13 +1142,15 @@ public class BSPrim : BSPhysObject
1277 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1142 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1278 1143
1279 OMV.Vector3 addForce = force; 1144 OMV.Vector3 addForce = force;
1280 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1145 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddForce", delegate()
1281 { 1146 {
1282 // Bullet adds this central force to the total force for this tick 1147 // Bullet adds this central force to the total force for this tick.
1148 // Deep down in Bullet:
1149 // linearVelocity += totalForce / mass * timeStep;
1283 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); 1150 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1284 if (PhysBody.HasPhysicalBody) 1151 if (PhysBody.HasPhysicalBody)
1285 { 1152 {
1286 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 1153 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
1287 ActivateIfPhysical(false); 1154 ActivateIfPhysical(false);
1288 } 1155 }
1289 }); 1156 });
@@ -1305,13 +1172,13 @@ public class BSPrim : BSPhysObject
1305 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); 1172 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
1306 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); 1173 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1307 1174
1308 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() 1175 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddImpulse", delegate()
1309 { 1176 {
1310 // Bullet adds this impulse immediately to the velocity 1177 // Bullet adds this impulse immediately to the velocity
1311 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); 1178 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
1312 if (PhysBody.HasPhysicalBody) 1179 if (PhysBody.HasPhysicalBody)
1313 { 1180 {
1314 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); 1181 PhysScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
1315 ActivateIfPhysical(false); 1182 ActivateIfPhysical(false);
1316 } 1183 }
1317 }); 1184 });
@@ -1324,20 +1191,18 @@ public class BSPrim : BSPhysObject
1324 } 1191 }
1325 } 1192 }
1326 1193
1327 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 1194 // BSPhysObject.AddAngularForce()
1328 AddAngularForce(force, pushforce, false); 1195 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1329 }
1330 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1331 { 1196 {
1332 if (force.IsFinite()) 1197 if (force.IsFinite())
1333 { 1198 {
1334 OMV.Vector3 angForce = force; 1199 OMV.Vector3 angForce = force;
1335 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() 1200 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddAngularForce", delegate()
1336 { 1201 {
1337 if (PhysBody.HasPhysicalBody) 1202 if (PhysBody.HasPhysicalBody)
1338 { 1203 {
1339 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); 1204 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
1340 PhysicsScene.PE.ApplyTorque(PhysBody, angForce); 1205 PhysScene.PE.ApplyTorque(PhysBody, angForce);
1341 ActivateIfPhysical(false); 1206 ActivateIfPhysical(false);
1342 } 1207 }
1343 }); 1208 });
@@ -1356,11 +1221,11 @@ public class BSPrim : BSPhysObject
1356 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1221 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1357 { 1222 {
1358 OMV.Vector3 applyImpulse = impulse; 1223 OMV.Vector3 applyImpulse = impulse;
1359 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1224 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ApplyTorqueImpulse", delegate()
1360 { 1225 {
1361 if (PhysBody.HasPhysicalBody) 1226 if (PhysBody.HasPhysicalBody)
1362 { 1227 {
1363 PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); 1228 PhysScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse);
1364 ActivateIfPhysical(false); 1229 ActivateIfPhysical(false);
1365 } 1230 }
1366 }); 1231 });
@@ -1649,6 +1514,8 @@ public class BSPrim : BSPhysObject
1649 1514
1650 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); 1515 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
1651 // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass); 1516 // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass);
1517 DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3},pathB={4},pathE={5},profB={6},profE={7},siz={8}",
1518 LocalID, Density, volume, returnMass, pathBegin, pathEnd, profileBegin, profileEnd, _size);
1652 1519
1653 return returnMass; 1520 return returnMass;
1654 }// end CalculateMass 1521 }// end CalculateMass
@@ -1661,13 +1528,14 @@ public class BSPrim : BSPhysObject
1661 { 1528 {
1662 // Create the correct physical representation for this type of object. 1529 // Create the correct physical representation for this type of object.
1663 // Updates base.PhysBody and base.PhysShape with the new information. 1530 // Updates base.PhysBody and base.PhysShape with the new information.
1664 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1531 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
1665 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) 1532 PhysScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysScene.World, this, delegate(BulletBody pBody, BulletShape pShape)
1666 { 1533 {
1667 // Called if the current prim body is about to be destroyed. 1534 // Called if the current prim body is about to be destroyed.
1668 // Remove all the physical dependencies on the old body. 1535 // Remove all the physical dependencies on the old body.
1669 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) 1536 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
1670 RemoveBodyDependencies(); 1537 // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints.
1538 RemoveDependencies();
1671 }); 1539 });
1672 1540
1673 // Make sure the properties are set on the new object 1541 // Make sure the properties are set on the new object
@@ -1675,27 +1543,45 @@ public class BSPrim : BSPhysObject
1675 return; 1543 return;
1676 } 1544 }
1677 1545
1678 protected virtual void RemoveBodyDependencies() 1546 // Called at taint-time
1547 protected virtual void RemoveDependencies()
1548 {
1549 PhysicalActors.RemoveDependencies();
1550 }
1551
1552 #region Extension
1553 public override object Extension(string pFunct, params object[] pParams)
1679 { 1554 {
1680 VehicleActor.RemoveBodyDependencies(); 1555 DetailLog("{0} BSPrim.Extension,op={1}", LocalID, pFunct);
1681 PhysicalActors.RemoveBodyDependencies(); 1556 object ret = null;
1557 switch (pFunct)
1558 {
1559 default:
1560 ret = base.Extension(pFunct, pParams);
1561 break;
1562 }
1563 return ret;
1682 } 1564 }
1565 #endregion // Extension
1683 1566
1684 // The physics engine says that properties have updated. Update same and inform 1567 // The physics engine says that properties have updated. Update same and inform
1685 // the world that things have changed. 1568 // the world that things have changed.
1569 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims.
1570 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimDisplaced which handles mapping physical position to simulator position.
1686 public override void UpdateProperties(EntityProperties entprop) 1571 public override void UpdateProperties(EntityProperties entprop)
1687 { 1572 {
1573 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
1688 TriggerPreUpdatePropertyAction(ref entprop); 1574 TriggerPreUpdatePropertyAction(ref entprop);
1689 1575
1690 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG 1576 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
1691 1577
1692 // Assign directly to the local variables so the normal set actions do not happen 1578 // Assign directly to the local variables so the normal set actions do not happen
1693 _position = entprop.Position; 1579 RawPosition = entprop.Position;
1694 _orientation = entprop.Rotation; 1580 RawOrientation = entprop.Rotation;
1695 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be 1581 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
1696 // very sensitive to velocity changes. 1582 // very sensitive to velocity changes.
1697 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold)) 1583 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold))
1698 _velocity = entprop.Velocity; 1584 RawVelocity = entprop.Velocity;
1699 _acceleration = entprop.Acceleration; 1585 _acceleration = entprop.Acceleration;
1700 _rotationalVelocity = entprop.RotationalVelocity; 1586 _rotationalVelocity = entprop.RotationalVelocity;
1701 1587
@@ -1704,29 +1590,20 @@ public class BSPrim : BSPhysObject
1704 // The sanity check can change the velocity and/or position. 1590 // The sanity check can change the velocity and/or position.
1705 if (PositionSanityCheck(true /* inTaintTime */ )) 1591 if (PositionSanityCheck(true /* inTaintTime */ ))
1706 { 1592 {
1707 entprop.Position = _position; 1593 entprop.Position = RawPosition;
1708 entprop.Velocity = _velocity; 1594 entprop.Velocity = RawVelocity;
1709 entprop.RotationalVelocity = _rotationalVelocity; 1595 entprop.RotationalVelocity = _rotationalVelocity;
1710 entprop.Acceleration = _acceleration; 1596 entprop.Acceleration = _acceleration;
1711 } 1597 }
1712 1598
1713 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG 1599 OMV.Vector3 direction = OMV.Vector3.UnitX * RawOrientation; // DEBUG DEBUG DEBUG
1714 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); 1600 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction);
1715 1601
1716 // remember the current and last set values 1602 // remember the current and last set values
1717 LastEntityProperties = CurrentEntityProperties; 1603 LastEntityProperties = CurrentEntityProperties;
1718 CurrentEntityProperties = entprop; 1604 CurrentEntityProperties = entprop;
1719 1605
1720 base.RequestPhysicsterseUpdate(); 1606 PhysScene.PostUpdate(this);
1721 /*
1722 else
1723 {
1724 // For debugging, report the movement of children
1725 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1726 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1727 entprop.Acceleration, entprop.RotationalVelocity);
1728 }
1729 */
1730 } 1607 }
1731} 1608}
1732} 1609}