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.cs445
1 files changed, 271 insertions, 174 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index aeeb4dd..2b3fa25 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -25,8 +25,6 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28// Uncomment this it enable code to do all shape an body memory management
29// in the C# code.
30using System; 28using System;
31using System.Reflection; 29using System.Reflection;
32using System.Collections.Generic; 30using System.Collections.Generic;
@@ -49,7 +47,6 @@ public sealed class BSPrim : BSPhysObject
49 // _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.
50 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. 48 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
51 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 49 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
52 // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
53 50
54 private bool _grabbed; 51 private bool _grabbed;
55 private bool _isSelected; 52 private bool _isSelected;
@@ -90,13 +87,13 @@ public sealed class BSPrim : BSPhysObject
90 87
91 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 88 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
92 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 89 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
90 : base(parent_scene, localID, primName, "BSPrim")
93 { 91 {
94 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 92 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
95 base.BaseInitialize(parent_scene, localID, primName, "BSPrim");
96 _physicsActorType = (int)ActorTypes.Prim; 93 _physicsActorType = (int)ActorTypes.Prim;
97 _position = pos; 94 _position = pos;
98 _size = size; 95 _size = size;
99 Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type 96 Scale = size; // the scale will be set by CreateGeom depending on object type
100 _orientation = rotation; 97 _orientation = rotation;
101 _buoyancy = 1f; 98 _buoyancy = 1f;
102 _velocity = OMV.Vector3.Zero; 99 _velocity = OMV.Vector3.Zero;
@@ -111,8 +108,8 @@ public sealed class BSPrim : BSPhysObject
111 _mass = CalculateMass(); 108 _mass = CalculateMass();
112 109
113 // No body or shape yet 110 // No body or shape yet
114 BSBody = new BulletBody(LocalID, IntPtr.Zero); 111 PhysBody = new BulletBody(LocalID, IntPtr.Zero);
115 BSShape = new BulletShape(IntPtr.Zero); 112 PhysShape = new BulletShape(IntPtr.Zero);
116 113
117 DetailLog("{0},BSPrim.constructor,call", LocalID); 114 DetailLog("{0},BSPrim.constructor,call", LocalID);
118 // do the actual object creation at taint time 115 // do the actual object creation at taint time
@@ -120,7 +117,7 @@ public sealed class BSPrim : BSPhysObject
120 { 117 {
121 CreateGeomAndObject(true); 118 CreateGeomAndObject(true);
122 119
123 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.ptr); 120 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr);
124 }); 121 });
125 } 122 }
126 123
@@ -145,8 +142,8 @@ public sealed class BSPrim : BSPhysObject
145 { 142 {
146 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 143 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
147 // If there are physical body and shape, release my use of same. 144 // If there are physical body and shape, release my use of same.
148 PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); 145 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
149 PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); 146 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
150 }); 147 });
151 } 148 }
152 149
@@ -157,6 +154,8 @@ public sealed class BSPrim : BSPhysObject
157 public override OMV.Vector3 Size { 154 public override OMV.Vector3 Size {
158 get { return _size; } 155 get { return _size; }
159 set { 156 set {
157 // We presume the scale and size are the same. If scale must be changed for
158 // the physical shape, that is done when the geometry is built.
160 _size = value; 159 _size = value;
161 ForceBodyShapeRebuild(false); 160 ForceBodyShapeRebuild(false);
162 } 161 }
@@ -171,17 +170,18 @@ public sealed class BSPrim : BSPhysObject
171 ForceBodyShapeRebuild(false); 170 ForceBodyShapeRebuild(false);
172 } 171 }
173 } 172 }
173 // Whatever the linkset wants is what I want.
174 public override BSPhysicsShapeType PreferredPhysicalShape
175 { get { return Linkset.PreferredPhysicalShape(this); } }
176
174 public override bool ForceBodyShapeRebuild(bool inTaintTime) 177 public override bool ForceBodyShapeRebuild(bool inTaintTime)
175 { 178 {
176 BSScene.TaintCallback rebuildOperation = delegate() 179 LastAssetBuildFailed = false;
180 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
177 { 181 {
178 _mass = CalculateMass(); // changing the shape changes the mass 182 _mass = CalculateMass(); // changing the shape changes the mass
179 CreateGeomAndObject(true); 183 CreateGeomAndObject(true);
180 }; 184 });
181 if (inTaintTime)
182 rebuildOperation();
183 else
184 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation);
185 return true; 185 return true;
186 } 186 }
187 public override bool Grabbed { 187 public override bool Grabbed {
@@ -235,14 +235,27 @@ public sealed class BSPrim : BSPhysObject
235 // Do it to the properties so the values get set in the physics engine. 235 // Do it to the properties so the values get set in the physics engine.
236 // Push the setting of the values to the viewer. 236 // Push the setting of the values to the viewer.
237 // Called at taint time! 237 // Called at taint time!
238 public override void ZeroMotion() 238 public override void ZeroMotion(bool inTaintTime)
239 { 239 {
240 _velocity = OMV.Vector3.Zero; 240 _velocity = OMV.Vector3.Zero;
241 _acceleration = OMV.Vector3.Zero; 241 _acceleration = OMV.Vector3.Zero;
242 _rotationalVelocity = OMV.Vector3.Zero; 242 _rotationalVelocity = OMV.Vector3.Zero;
243 243
244 // Zero some other properties directly into the physics engine 244 // Zero some other properties in the physics engine
245 BulletSimAPI.ClearForces2(BSBody.ptr); 245 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
246 {
247 BulletSimAPI.ClearAllForces2(PhysBody.ptr);
248 });
249 }
250 public override void ZeroAngularMotion(bool inTaintTime)
251 {
252 _rotationalVelocity = OMV.Vector3.Zero;
253 // Zero some other properties in the physics engine
254 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
255 {
256 BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
257 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
258 });
246 } 259 }
247 260
248 public override void LockAngularMotion(OMV.Vector3 axis) 261 public override void LockAngularMotion(OMV.Vector3 axis)
@@ -251,97 +264,91 @@ public sealed class BSPrim : BSPhysObject
251 return; 264 return;
252 } 265 }
253 266
267 public override OMV.Vector3 RawPosition
268 {
269 get { return _position; }
270 set { _position = value; }
271 }
254 public override OMV.Vector3 Position { 272 public override OMV.Vector3 Position {
255 get { 273 get {
274 // child prims move around based on their parent. Need to get the latest location
256 if (!Linkset.IsRoot(this)) 275 if (!Linkset.IsRoot(this))
257 // child prims move around based on their parent. Need to get the latest location 276 _position = Linkset.Position(this);
258 _position = BulletSimAPI.GetPosition2(BSBody.ptr);
259 277
260 // don't do the GetObjectPosition for root elements because this function is called a zillion times 278 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
261 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 279 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
262 return _position; 280 return _position;
263 } 281 }
264 set { 282 set {
265 // If you must push the position into the physics engine, use ForcePosition. 283 // If the position must be forced into the physics engine, use ForcePosition.
266 if (_position == value) 284 if (_position == value)
267 { 285 {
268 return; 286 return;
269 } 287 }
270 _position = value; 288 _position = value;
271 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 289 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
272 PositionSanityCheck(); 290 PositionSanityCheck(false);
273 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 291 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
274 { 292 {
275 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 293 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
276 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 294 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
295 ActivateIfPhysical(false);
277 }); 296 });
278 } 297 }
279 } 298 }
280 public override OMV.Vector3 ForcePosition { 299 public override OMV.Vector3 ForcePosition {
281 get { 300 get {
282 _position = BulletSimAPI.GetPosition2(BSBody.ptr); 301 _position = BulletSimAPI.GetPosition2(PhysBody.ptr);
283 return _position; 302 return _position;
284 } 303 }
285 set { 304 set {
286 _position = value; 305 _position = value;
287 PositionSanityCheck(); 306 // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better.
288 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 307 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
308 ActivateIfPhysical(false);
289 } 309 }
290 } 310 }
291 311
292 // Check that the current position is sane and, if not, modify the position to make it so. 312 // Check that the current position is sane and, if not, modify the position to make it so.
293 // Check for being below terrain and being out of bounds. 313 // Check for being below terrain and being out of bounds.
294 // Returns 'true' of the position was made sane by some action. 314 // Returns 'true' of the position was made sane by some action.
295 private bool PositionSanityCheck() 315 private bool PositionSanityCheck(bool inTaintTime)
296 { 316 {
297 bool ret = false; 317 bool ret = false;
298 318
299 // If totally below the ground, move the prim up
300 // TODO: figure out the right solution for this... only for dynamic objects?
301 /*
302 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 319 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
320 OMV.Vector3 upForce = OMV.Vector3.Zero;
303 if (Position.Z < terrainHeight) 321 if (Position.Z < terrainHeight)
304 { 322 {
305 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 323 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
306 _position.Z = terrainHeight + 2.0f; 324 float targetHeight = terrainHeight + (Size.Z / 2f);
325 // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
326 upForce.Z = (terrainHeight - Position.Z) * 1f;
307 ret = true; 327 ret = true;
308 } 328 }
309 */ 329
310 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 330 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
311 { 331 {
312 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); 332 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
313 if (Position.Z < waterHeight) 333 // TODO: a floating motor so object will bob in the water
334 if (Math.Abs(Position.Z - waterHeight) > 0.1f)
314 { 335 {
315 _position.Z = waterHeight; 336 // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
337 upForce.Z = (waterHeight - Position.Z) * 1f;
316 ret = true; 338 ret = true;
317 } 339 }
318 } 340 }
319 341
320 // TODO: check for out of bounds 342 // TODO: check for out of bounds
321 return ret;
322 }
323 343
324 // A version of the sanity check that also makes sure a new position value is 344 // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
325 // pushed to the physics engine. This routine would be used by anyone 345 if (ret)
326 // who is not already pushing the value.
327 private bool PositionSanityCheck(bool inTaintTime)
328 {
329 bool ret = false;
330 if (PositionSanityCheck())
331 { 346 {
332 // The new position value must be pushed into the physics engine but we can't 347 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck:belowTerrain", delegate()
333 // just assign to "Position" because of potential call loops.
334 BSScene.TaintCallback sanityOperation = delegate()
335 { 348 {
336 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 349 // Apply upforce and overcome gravity.
337 ForcePosition = _position; 350 ForceVelocity = ForceVelocity + upForce - PhysicsScene.DefaultGravity;
338 }; 351 });
339 if (inTaintTime)
340 sanityOperation();
341 else
342 PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation);
343
344 ret = true;
345 } 352 }
346 return ret; 353 return ret;
347 } 354 }
@@ -352,13 +359,35 @@ public sealed class BSPrim : BSPhysObject
352 { 359 {
353 get 360 get
354 { 361 {
355 // return Linkset.LinksetMass; 362 return Linkset.LinksetMass;
356 return _mass; 363 // return _mass;
357 } 364 }
358 } 365 }
359 366
360 // used when we only want this prim's mass and not the linkset thing 367 // used when we only want this prim's mass and not the linkset thing
361 public override float MassRaw { get { return _mass; } } 368 public override float RawMass {
369 get { return _mass; }
370 }
371 // Set the physical mass to the passed mass.
372 // Note that this does not change _mass!
373 public override void UpdatePhysicalMassProperties(float physMass)
374 {
375 if (IsStatic)
376 {
377 Inertia = OMV.Vector3.Zero;
378 BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia);
379 BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
380 }
381 else
382 {
383 Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
384 BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
385 BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
386 // center of mass is at the zero of the object
387 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
388 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia);
389 }
390 }
362 391
363 // Is this used? 392 // Is this used?
364 public override OMV.Vector3 CenterOfMass 393 public override OMV.Vector3 CenterOfMass
@@ -379,7 +408,7 @@ public sealed class BSPrim : BSPhysObject
379 PhysicsScene.TaintedObject("BSPrim.setForce", delegate() 408 PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
380 { 409 {
381 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 410 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
382 BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); 411 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
383 }); 412 });
384 } 413 }
385 } 414 }
@@ -398,7 +427,8 @@ public sealed class BSPrim : BSPhysObject
398 { 427 {
399 // Done at taint time so we're sure the physics engine is not using the variables 428 // Done at taint time so we're sure the physics engine is not using the variables
400 // Vehicle code changes the parameters for this vehicle type. 429 // Vehicle code changes the parameters for this vehicle type.
401 this._vehicle.ProcessTypeChange(type); 430 _vehicle.ProcessTypeChange(type);
431 ActivateIfPhysical(false);
402 }); 432 });
403 } 433 }
404 } 434 }
@@ -407,6 +437,7 @@ public sealed class BSPrim : BSPhysObject
407 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 437 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
408 { 438 {
409 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 439 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
440 ActivateIfPhysical(false);
410 }); 441 });
411 } 442 }
412 public override void VehicleVectorParam(int param, OMV.Vector3 value) 443 public override void VehicleVectorParam(int param, OMV.Vector3 value)
@@ -414,6 +445,7 @@ public sealed class BSPrim : BSPhysObject
414 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 445 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
415 { 446 {
416 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 447 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
448 ActivateIfPhysical(false);
417 }); 449 });
418 } 450 }
419 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 451 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
@@ -421,6 +453,7 @@ public sealed class BSPrim : BSPhysObject
421 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 453 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
422 { 454 {
423 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 455 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
456 ActivateIfPhysical(false);
424 }); 457 });
425 } 458 }
426 public override void VehicleFlags(int param, bool remove) 459 public override void VehicleFlags(int param, bool remove)
@@ -435,9 +468,16 @@ public sealed class BSPrim : BSPhysObject
435 // Called from Scene when doing simulation step so we're in taint processing time. 468 // Called from Scene when doing simulation step so we're in taint processing time.
436 public override void StepVehicle(float timeStep) 469 public override void StepVehicle(float timeStep)
437 { 470 {
438 if (IsPhysical) 471 if (IsPhysical && _vehicle.IsActive)
439 { 472 {
440 _vehicle.Step(timeStep); 473 _vehicle.Step(timeStep);
474 /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step
475 PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate()
476 {
477 // This resets the interpolation values and recomputes the tensor variables
478 BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation);
479 });
480 */
441 } 481 }
442 } 482 }
443 483
@@ -462,7 +502,7 @@ public sealed class BSPrim : BSPhysObject
462 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 502 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
463 { 503 {
464 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 504 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
465 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); 505 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
466 }); 506 });
467 } 507 }
468 } 508 }
@@ -470,12 +510,14 @@ public sealed class BSPrim : BSPhysObject
470 get { return _velocity; } 510 get { return _velocity; }
471 set { 511 set {
472 _velocity = value; 512 _velocity = value;
473 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); 513 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
474 } 514 }
475 } 515 }
476 public override OMV.Vector3 Torque { 516 public override OMV.Vector3 Torque {
477 get { return _torque; } 517 get { return _torque; }
478 set { _torque = value; 518 set {
519 _torque = value;
520 AddAngularForce(_torque, false, false);
479 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 521 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
480 } 522 }
481 } 523 }
@@ -488,12 +530,17 @@ public sealed class BSPrim : BSPhysObject
488 get { return _acceleration; } 530 get { return _acceleration; }
489 set { _acceleration = value; } 531 set { _acceleration = value; }
490 } 532 }
533 public override OMV.Quaternion RawOrientation
534 {
535 get { return _orientation; }
536 set { _orientation = value; }
537 }
491 public override OMV.Quaternion Orientation { 538 public override OMV.Quaternion Orientation {
492 get { 539 get {
540 // Children move around because tied to parent. Get a fresh value.
493 if (!Linkset.IsRoot(this)) 541 if (!Linkset.IsRoot(this))
494 { 542 {
495 // Children move around because tied to parent. Get a fresh value. 543 _orientation = Linkset.Orientation(this);
496 _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
497 } 544 }
498 return _orientation; 545 return _orientation;
499 } 546 }
@@ -506,22 +553,22 @@ public sealed class BSPrim : BSPhysObject
506 { 553 {
507 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 554 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
508 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 555 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
509 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 556 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
510 }); 557 });
511 } 558 }
512 } 559 }
513 // Go directly to Bullet to get/set the value. 560 // Go directly to Bullet to get/set the value.
514 public override OMV.Quaternion ForceOrientation 561 public override OMV.Quaternion ForceOrientation
515 { 562 {
516 get 563 get
517 { 564 {
518 _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); 565 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr);
519 return _orientation; 566 return _orientation;
520 } 567 }
521 set 568 set
522 { 569 {
523 _orientation = value; 570 _orientation = value;
524 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 571 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
525 } 572 }
526 } 573 }
527 public override int PhysicsActorType { 574 public override int PhysicsActorType {
@@ -538,6 +585,8 @@ public sealed class BSPrim : BSPhysObject
538 { 585 {
539 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 586 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
540 SetObjectDynamic(true); 587 SetObjectDynamic(true);
588 // whether phys-to-static or static-to-phys, the object is not moving.
589 ZeroMotion(true);
541 }); 590 });
542 } 591 }
543 } 592 }
@@ -575,7 +624,7 @@ public sealed class BSPrim : BSPhysObject
575 624
576 // Mangling all the physical properties requires the object not be in the physical world. 625 // Mangling all the physical properties requires the object not be in the physical world.
577 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 626 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
578 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); 627 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
579 628
580 // Set up the object physicalness (does gravity and collisions move this object) 629 // Set up the object physicalness (does gravity and collisions move this object)
581 MakeDynamic(IsStatic); 630 MakeDynamic(IsStatic);
@@ -589,24 +638,25 @@ public sealed class BSPrim : BSPhysObject
589 // Make solid or not (do things bounce off or pass through this object). 638 // Make solid or not (do things bounce off or pass through this object).
590 MakeSolid(IsSolid); 639 MakeSolid(IsSolid);
591 640
592 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); 641 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
593 642
594 // Rebuild its shape 643 // Rebuild its shape
595 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); 644 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
596 645
597 // Collision filter can be set only when the object is in the world 646 // Collision filter can be set only when the object is in the world
598 if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0) 647 if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0)
599 { 648 {
600 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask); 649 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask);
601 } 650 }
602 651
603 // Recompute any linkset parameters. 652 // Recompute any linkset parameters.
604 // When going from non-physical to physical, this re-enables the constraints that 653 // When going from non-physical to physical, this re-enables the constraints that
605 // had been automatically disabled when the mass was set to zero. 654 // had been automatically disabled when the mass was set to zero.
606 Linkset.Refresh(this, true); 655 // For compound based linksets, this enables and disables interactions of the children.
656 Linkset.Refresh(this);
607 657
608 DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", 658 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
609 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); 659 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape);
610 } 660 }
611 661
612 // "Making dynamic" means changing to and from static. 662 // "Making dynamic" means changing to and from static.
@@ -619,75 +669,74 @@ public sealed class BSPrim : BSPhysObject
619 if (makeStatic) 669 if (makeStatic)
620 { 670 {
621 // Become a Bullet 'static' object type 671 // Become a Bullet 'static' object type
622 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 672 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
623 // Stop all movement 673 // Stop all movement
624 BulletSimAPI.ClearAllForces2(BSBody.ptr); 674 ZeroMotion(true);
625 // Center of mass is at the center of the object 675 // Center of mass is at the center of the object
626 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); 676 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
627 // Mass is zero which disables a bunch of physics stuff in Bullet 677 // Mass is zero which disables a bunch of physics stuff in Bullet
628 BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); 678 UpdatePhysicalMassProperties(0f);
629 // There is no inertia in a static object
630 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
631 // Set collision detection parameters 679 // Set collision detection parameters
632 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 680 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
633 { 681 {
634 BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 682 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
635 BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 683 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
636 } 684 }
637 // There can be special things needed for implementing linksets 685 // There can be special things needed for implementing linksets
638 Linkset.MakeStatic(this); 686 Linkset.MakeStatic(this);
639 // The activation state is 'disabled' so Bullet will not try to act on it. 687 // The activation state is 'disabled' so Bullet will not try to act on it.
640 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); 688 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
641 // Start it out sleeping and physical actions could wake it up. 689 // Start it out sleeping and physical actions could wake it up.
642 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); 690 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
643 691
644 BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; 692 PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
645 BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; 693 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
646 } 694 }
647 else 695 else
648 { 696 {
649 // Not a Bullet static object 697 // Not a Bullet static object
650 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 698 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
651 699
652 // Set various physical properties so internal dynamic properties will get computed correctly as they are set 700 // Set various physical properties so internal dynamic properties will get computed correctly as they are set
653 BulletSimAPI.SetFriction2(BSBody.ptr, PhysicsScene.Params.defaultFriction); 701 BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
654 BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution); 702 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
655 703
656 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 704 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
657 BulletSimAPI.ClearAllForces2(BSBody.ptr); 705 // Since this can be called multiple times, only zero forces when becoming physical
706 // BulletSimAPI.ClearAllForces2(BSBody.ptr);
658 707
659 // For good measure, make sure the transform is set through to the motion state 708 // For good measure, make sure the transform is set through to the motion state
660 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 709 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
710
711 // Center of mass is at the center of the object
712 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
661 713
662 // A dynamic object has mass 714 // A dynamic object has mass
663 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); 715 UpdatePhysicalMassProperties(RawMass);
664 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
665 BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia);
666 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
667 716
668 // Set collision detection parameters 717 // Set collision detection parameters
669 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 718 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
670 { 719 {
671 BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 720 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
672 BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 721 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
673 } 722 }
674 723
675 // Various values for simulation limits 724 // Various values for simulation limits
676 BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); 725 BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping);
677 BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime); 726 BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime);
678 BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); 727 BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
679 BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); 728 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
680 729
681 // There might be special things needed for implementing linksets. 730 // There might be special things needed for implementing linksets.
682 Linkset.MakeDynamic(this); 731 Linkset.MakeDynamic(this);
683 732
684 // Force activation of the object so Bullet will act on it. 733 // Force activation of the object so Bullet will act on it.
685 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 734 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
686 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); 735 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
687 // BulletSimAPI.Activate2(BSBody.ptr, true); 736 // BulletSimAPI.Activate2(BSBody.ptr, true);
688 737
689 BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; 738 PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
690 BSBody.collisionMask = CollisionFilterGroups.ObjectMask; 739 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
691 } 740 }
692 } 741 }
693 742
@@ -697,7 +746,7 @@ public sealed class BSPrim : BSPhysObject
697 // the functions after this one set up the state of a possibly newly created collision body. 746 // the functions after this one set up the state of a possibly newly created collision body.
698 private void MakeSolid(bool makeSolid) 747 private void MakeSolid(bool makeSolid)
699 { 748 {
700 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr); 749 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr);
701 if (makeSolid) 750 if (makeSolid)
702 { 751 {
703 // Verify the previous code created the correct shape for this type of thing. 752 // Verify the previous code created the correct shape for this type of thing.
@@ -705,7 +754,7 @@ public sealed class BSPrim : BSPhysObject
705 { 754 {
706 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 755 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
707 } 756 }
708 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 757 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
709 } 758 }
710 else 759 else
711 { 760 {
@@ -713,22 +762,31 @@ public sealed class BSPrim : BSPhysObject
713 { 762 {
714 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 763 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
715 } 764 }
716 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 765 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
717 BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; 766 PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
718 BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; 767 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
719 } 768 }
720 } 769 }
721 770
771 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
772 // they need waking up when parameters are changed.
773 // Called in taint-time!!
774 private void ActivateIfPhysical(bool forceIt)
775 {
776 if (IsPhysical)
777 BulletSimAPI.Activate2(PhysBody.ptr, forceIt);
778 }
779
722 // Turn on or off the flag controlling whether collision events are returned to the simulator. 780 // Turn on or off the flag controlling whether collision events are returned to the simulator.
723 private void EnableCollisions(bool wantsCollisionEvents) 781 private void EnableCollisions(bool wantsCollisionEvents)
724 { 782 {
725 if (wantsCollisionEvents) 783 if (wantsCollisionEvents)
726 { 784 {
727 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 785 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
728 } 786 }
729 else 787 else
730 { 788 {
731 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 789 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
732 } 790 }
733 } 791 }
734 792
@@ -768,14 +826,14 @@ public sealed class BSPrim : BSPhysObject
768 } 826 }
769 } 827 }
770 public override bool FloatOnWater { 828 public override bool FloatOnWater {
771 set { 829 set {
772 _floatOnWater = value; 830 _floatOnWater = value;
773 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 831 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
774 { 832 {
775 if (_floatOnWater) 833 if (_floatOnWater)
776 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); 834 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
777 else 835 else
778 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); 836 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
779 }); 837 });
780 } 838 }
781 } 839 }
@@ -797,8 +855,8 @@ public sealed class BSPrim : BSPhysObject
797 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 855 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
798 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 856 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
799 { 857 {
800 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 858 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
801 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); 859 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
802 }); 860 });
803 } 861 }
804 } 862 }
@@ -808,7 +866,7 @@ public sealed class BSPrim : BSPhysObject
808 } 866 }
809 set { 867 set {
810 _rotationalVelocity = value; 868 _rotationalVelocity = value;
811 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); 869 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
812 } 870 }
813 } 871 }
814 public override bool Kinematic { 872 public override bool Kinematic {
@@ -834,7 +892,7 @@ public sealed class BSPrim : BSPhysObject
834 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 892 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
835 // Buoyancy is faked by changing the gravity applied to the object 893 // Buoyancy is faked by changing the gravity applied to the object
836 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); 894 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
837 BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); 895 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
838 } 896 }
839 } 897 }
840 898
@@ -874,6 +932,7 @@ public sealed class BSPrim : BSPhysObject
874 public override void AddForce(OMV.Vector3 force, bool pushforce) { 932 public override void AddForce(OMV.Vector3 force, bool pushforce) {
875 AddForce(force, pushforce, false); 933 AddForce(force, pushforce, false);
876 } 934 }
935 // Applying a force just adds this to the total force on the object.
877 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 936 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
878 // for an object, doesn't matter if force is a pushforce or not 937 // for an object, doesn't matter if force is a pushforce or not
879 if (force.IsFinite()) 938 if (force.IsFinite())
@@ -887,7 +946,7 @@ public sealed class BSPrim : BSPhysObject
887 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 946 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
888 return; 947 return;
889 } 948 }
890 BSScene.TaintCallback addForceOperation = delegate() 949 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
891 { 950 {
892 OMV.Vector3 fSum = OMV.Vector3.Zero; 951 OMV.Vector3 fSum = OMV.Vector3.Zero;
893 lock (m_accumulatedForces) 952 lock (m_accumulatedForces)
@@ -899,20 +958,70 @@ public sealed class BSPrim : BSPhysObject
899 } 958 }
900 m_accumulatedForces.Clear(); 959 m_accumulatedForces.Clear();
901 } 960 }
902 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); 961 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
903 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. 962 if (fSum != OMV.Vector3.Zero)
904 BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); 963 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
905 }; 964 });
906 if (inTaintTime) 965 }
907 addForceOperation(); 966
908 else 967 // An impulse force is scaled by the mass of the object.
909 PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); 968 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
969 {
970 OMV.Vector3 applyImpulse = impulse;
971 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
972 {
973 DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
974 BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
975 });
910 } 976 }
911 977
978 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
912 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 979 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
913 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 980 AddAngularForce(force, pushforce, false);
914 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
915 } 981 }
982 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
983 {
984 if (force.IsFinite())
985 {
986 // _force += force;
987 lock (m_accumulatedAngularForces)
988 m_accumulatedAngularForces.Add(new OMV.Vector3(force));
989 }
990 else
991 {
992 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
993 return;
994 }
995 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
996 {
997 OMV.Vector3 fSum = OMV.Vector3.Zero;
998 lock (m_accumulatedAngularForces)
999 {
1000 // Sum the accumulated additional forces for one big force to apply once.
1001 foreach (OMV.Vector3 v in m_accumulatedAngularForces)
1002 {
1003 fSum += v;
1004 }
1005 m_accumulatedAngularForces.Clear();
1006 }
1007 DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
1008 if (fSum != OMV.Vector3.Zero)
1009 {
1010 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
1011 _torque = fSum;
1012 }
1013 });
1014 }
1015 // A torque impulse.
1016 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1017 {
1018 OMV.Vector3 applyImpulse = impulse;
1019 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1020 {
1021 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
1022 });
1023 }
1024
916 public override void SetMomentum(OMV.Vector3 momentum) { 1025 public override void SetMomentum(OMV.Vector3 momentum) {
917 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 1026 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
918 } 1027 }
@@ -971,7 +1080,7 @@ public sealed class BSPrim : BSPhysObject
971 if (hollowAmount > 0.0) 1080 if (hollowAmount > 0.0)
972 { 1081 {
973 hollowVolume *= hollowAmount; 1082 hollowVolume *= hollowAmount;
974 1083
975 switch (BaseShape.HollowShape) 1084 switch (BaseShape.HollowShape)
976 { 1085 {
977 case HollowShape.Square: 1086 case HollowShape.Square:
@@ -1194,9 +1303,7 @@ public sealed class BSPrim : BSPhysObject
1194 1303
1195 returnMass = _density * volume; 1304 returnMass = _density * volume;
1196 1305
1197 /* 1306 /* Comment out code that computes the mass of the linkset. That is done in the Linkset class.
1198 * This change means each object keeps its own mass and the Mass property
1199 * will return the sum if we're part of a linkset.
1200 if (IsRootOfLinkset) 1307 if (IsRootOfLinkset)
1201 { 1308 {
1202 foreach (BSPrim prim in _childrenPrims) 1309 foreach (BSPrim prim in _childrenPrims)
@@ -1216,48 +1323,27 @@ public sealed class BSPrim : BSPhysObject
1216 }// end CalculateMass 1323 }// end CalculateMass
1217 #endregion Mass Calculation 1324 #endregion Mass Calculation
1218 1325
1219 // Copy prim's info into the BulletSim shape description structure
1220 public void FillShapeInfo(out ShapeData shape)
1221 {
1222 shape.ID = LocalID;
1223 shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
1224 shape.Position = _position;
1225 shape.Rotation = _orientation;
1226 shape.Velocity = _velocity;
1227 shape.Size = _size;
1228 shape.Scale = Scale;
1229 shape.Mass = _isPhysical ? _mass : 0f;
1230 shape.Buoyancy = _buoyancy;
1231 shape.HullKey = 0;
1232 shape.MeshKey = 0;
1233 shape.Friction = _friction;
1234 shape.Restitution = _restitution;
1235 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
1236 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1237 shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue;
1238 }
1239 // Rebuild the geometry and object. 1326 // Rebuild the geometry and object.
1240 // This is called when the shape changes so we need to recreate the mesh/hull. 1327 // This is called when the shape changes so we need to recreate the mesh/hull.
1241 // Called at taint-time!!! 1328 // Called at taint-time!!!
1242 private void CreateGeomAndObject(bool forceRebuild) 1329 private void CreateGeomAndObject(bool forceRebuild)
1243 { 1330 {
1244 ShapeData shapeData;
1245 FillShapeInfo(out shapeData);
1246
1247 // If this prim is part of a linkset, we must remove and restore the physical 1331 // If this prim is part of a linkset, we must remove and restore the physical
1248 // links of the body is rebuilt. 1332 // links if the body is rebuilt.
1249 bool needToRestoreLinkset = false; 1333 bool needToRestoreLinkset = false;
1334 bool needToRestoreVehicle = false;
1250 1335
1251 // Create the correct physical representation for this type of object. 1336 // Create the correct physical representation for this type of object.
1252 // Updates BSBody and BSShape with the new information. 1337 // Updates PhysBody and PhysShape with the new information.
1253 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1338 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
1254 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, 1339 // Returns 'true' if either the body or the shape was changed.
1255 null, delegate(BulletBody dBody) 1340 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
1256 { 1341 {
1257 // Called if the current prim body is about to be destroyed. 1342 // Called if the current prim body is about to be destroyed.
1258 // Remove all the physical dependencies on the old body. 1343 // Remove all the physical dependencies on the old body.
1259 // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) 1344 // (Maybe someday make the changing of BSShape an event handled by BSLinkset.)
1260 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); 1345 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
1346 needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this);
1261 }); 1347 });
1262 1348
1263 if (needToRestoreLinkset) 1349 if (needToRestoreLinkset)
@@ -1265,6 +1351,11 @@ public sealed class BSPrim : BSPhysObject
1265 // If physical body dependencies were removed, restore them 1351 // If physical body dependencies were removed, restore them
1266 Linkset.RestoreBodyDependencies(this); 1352 Linkset.RestoreBodyDependencies(this);
1267 } 1353 }
1354 if (needToRestoreVehicle)
1355 {
1356 // If physical body dependencies were removed, restore them
1357 _vehicle.RestoreBodyDependencies(this);
1358 }
1268 1359
1269 // Make sure the properties are set on the new object 1360 // Make sure the properties are set on the new object
1270 UpdatePhysicalParameters(); 1361 UpdatePhysicalParameters();
@@ -1326,7 +1417,7 @@ public sealed class BSPrim : BSPhysObject
1326 if (changed != 0) 1417 if (changed != 0)
1327 { 1418 {
1328 // Only update the position of single objects and linkset roots 1419 // Only update the position of single objects and linkset roots
1329 if (this._parentPrim == null) 1420 if (Linkset.IsRoot(this))
1330 { 1421 {
1331 base.RequestPhysicsterseUpdate(); 1422 base.RequestPhysicsterseUpdate();
1332 } 1423 }
@@ -1338,23 +1429,29 @@ public sealed class BSPrim : BSPhysObject
1338 // Updates only for individual prims and for the root object of a linkset. 1429 // Updates only for individual prims and for the root object of a linkset.
1339 if (Linkset.IsRoot(this)) 1430 if (Linkset.IsRoot(this))
1340 { 1431 {
1341 // Assign to the local variables so the normal set action does not happen 1432 // Assign directly to the local variables so the normal set action does not happen
1342 _position = entprop.Position; 1433 _position = entprop.Position;
1343 _orientation = entprop.Rotation; 1434 _orientation = entprop.Rotation;
1344 _velocity = entprop.Velocity; 1435 _velocity = entprop.Velocity;
1345 _acceleration = entprop.Acceleration; 1436 _acceleration = entprop.Acceleration;
1346 _rotationalVelocity = entprop.RotationalVelocity; 1437 _rotationalVelocity = entprop.RotationalVelocity;
1347 1438
1439 // The sanity check can change the velocity and/or position.
1440 if (PositionSanityCheck(true))
1441 {
1442 entprop.Position = _position;
1443 entprop.Velocity = _velocity;
1444 }
1445
1348 // remember the current and last set values 1446 // remember the current and last set values
1349 LastEntityProperties = CurrentEntityProperties; 1447 LastEntityProperties = CurrentEntityProperties;
1350 CurrentEntityProperties = entprop; 1448 CurrentEntityProperties = entprop;
1351 1449
1352 PositionSanityCheck(true); 1450 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
1353 1451 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1354 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1452 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1355 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1356 1453
1357 // BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr); 1454 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
1358 1455
1359 base.RequestPhysicsterseUpdate(); 1456 base.RequestPhysicsterseUpdate();
1360 } 1457 }
@@ -1367,8 +1464,8 @@ public sealed class BSPrim : BSPhysObject
1367 entprop.Acceleration, entprop.RotationalVelocity); 1464 entprop.Acceleration, entprop.RotationalVelocity);
1368 } 1465 }
1369 */ 1466 */
1370 // The linkset implimentation might want to know about this.
1371 1467
1468 // The linkset implimentation might want to know about this.
1372 Linkset.UpdateProperties(this); 1469 Linkset.UpdateProperties(this);
1373 } 1470 }
1374} 1471}