diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 445 |
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. | ||
30 | using System; | 28 | using System; |
31 | using System.Reflection; | 29 | using System.Reflection; |
32 | using System.Collections.Generic; | 30 | using 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 | } |