aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs166
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs19
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs434
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs150
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs64
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs450
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs621
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs480
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs592
9 files changed, 1983 insertions, 993 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index e2f7af9..526dbad 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -34,13 +34,12 @@ using OpenSim.Region.Physics.Manager;
34 34
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public class BSCharacter : PhysicsActor 37public class BSCharacter : BSPhysObject
38{ 38{
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 private BSScene _scene; 42 public BSScene Scene { get; private set; }
43 public BSScene Scene { get { return _scene; } }
44 private String _avName; 43 private String _avName;
45 // private bool _stopped; 44 // private bool _stopped;
46 private Vector3 _size; 45 private Vector3 _size;
@@ -74,11 +73,9 @@ public class BSCharacter : PhysicsActor
74 private bool _kinematic; 73 private bool _kinematic;
75 private float _buoyancy; 74 private float _buoyancy;
76 75
77 private BulletBody m_body; 76 public override BulletBody BSBody { get; set; }
78 public BulletBody Body { 77 public override BulletShape BSShape { get; set; }
79 get { return m_body; } 78 public override BSLinkset Linkset { get; set; }
80 set { m_body = value; }
81 }
82 79
83 private int _subscribedEventsMs = 0; 80 private int _subscribedEventsMs = 0;
84 private int _nextCollisionOkTime = 0; 81 private int _nextCollisionOkTime = 0;
@@ -95,7 +92,8 @@ public class BSCharacter : PhysicsActor
95 { 92 {
96 _localID = localID; 93 _localID = localID;
97 _avName = avName; 94 _avName = avName;
98 _scene = parent_scene; 95 Scene = parent_scene;
96 _physicsActorType = (int)ActorTypes.Agent;
99 _position = pos; 97 _position = pos;
100 _size = size; 98 _size = size;
101 _flying = isFlying; 99 _flying = isFlying;
@@ -104,10 +102,12 @@ public class BSCharacter : PhysicsActor
104 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 102 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
105 // The dimensions of the avatar capsule are kept in the scale. 103 // The dimensions of the avatar capsule are kept in the scale.
106 // Physics creates a unit capsule which is scaled by the physics engine. 104 // Physics creates a unit capsule which is scaled by the physics engine.
107 _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); 105 _scale = new Vector3(Scene.Params.avatarCapsuleRadius, Scene.Params.avatarCapsuleRadius, size.Z);
108 _density = _scene.Params.avatarDensity; 106 _density = Scene.Params.avatarDensity;
109 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 107 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
110 108
109 Linkset = new BSLinkset(Scene, this);
110
111 ShapeData shapeData = new ShapeData(); 111 ShapeData shapeData = new ShapeData();
112 shapeData.ID = _localID; 112 shapeData.ID = _localID;
113 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; 113 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
@@ -118,29 +118,31 @@ public class BSCharacter : PhysicsActor
118 shapeData.Mass = _mass; 118 shapeData.Mass = _mass;
119 shapeData.Buoyancy = _buoyancy; 119 shapeData.Buoyancy = _buoyancy;
120 shapeData.Static = ShapeData.numericFalse; 120 shapeData.Static = ShapeData.numericFalse;
121 shapeData.Friction = _scene.Params.avatarFriction; 121 shapeData.Friction = Scene.Params.avatarFriction;
122 shapeData.Restitution = _scene.Params.avatarRestitution; 122 shapeData.Restitution = Scene.Params.avatarRestitution;
123 123
124 // do actual create at taint time 124 // do actual create at taint time
125 _scene.TaintedObject("BSCharacter.create", delegate() 125 Scene.TaintedObject("BSCharacter.create", delegate()
126 { 126 {
127 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); 127 DetailLog("{0},BSCharacter.create", _localID);
128 BulletSimAPI.CreateObject(Scene.WorldID, shapeData);
128 129
129 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 130 // Set the buoyancy for flying. This will be refactored when all the settings happen in C#
130 // avatars get all collisions no matter what 131 BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
131 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 132
133 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
132 }); 134 });
133 135
134 return; 136 return;
135 } 137 }
136 138
137 // called when this character is being destroyed and the resources should be released 139 // called when this character is being destroyed and the resources should be released
138 public void Destroy() 140 public override void Destroy()
139 { 141 {
140 // DetailLog("{0},BSCharacter.Destroy", LocalID); 142 DetailLog("{0},BSCharacter.Destroy", LocalID);
141 _scene.TaintedObject("BSCharacter.destroy", delegate() 143 Scene.TaintedObject("BSCharacter.destroy", delegate()
142 { 144 {
143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 145 BulletSimAPI.DestroyObject(Scene.WorldID, _localID);
144 }); 146 });
145 } 147 }
146 148
@@ -169,9 +171,9 @@ public class BSCharacter : PhysicsActor
169 171
170 ComputeAvatarVolumeAndMass(); 172 ComputeAvatarVolumeAndMass();
171 173
172 _scene.TaintedObject("BSCharacter.setSize", delegate() 174 Scene.TaintedObject("BSCharacter.setSize", delegate()
173 { 175 {
174 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); 176 BulletSimAPI.SetObjectScaleMass(Scene.WorldID, LocalID, _scale, _mass, true);
175 }); 177 });
176 178
177 } 179 }
@@ -200,17 +202,17 @@ public class BSCharacter : PhysicsActor
200 202
201 public override Vector3 Position { 203 public override Vector3 Position {
202 get { 204 get {
203 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 205 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
204 return _position; 206 return _position;
205 } 207 }
206 set { 208 set {
207 _position = value; 209 _position = value;
208 PositionSanityCheck(); 210 PositionSanityCheck();
209 211
210 _scene.TaintedObject("BSCharacter.setPosition", delegate() 212 Scene.TaintedObject("BSCharacter.setPosition", delegate()
211 { 213 {
212 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 214 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 215 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
214 }); 216 });
215 } 217 }
216 } 218 }
@@ -223,16 +225,35 @@ public class BSCharacter : PhysicsActor
223 bool ret = false; 225 bool ret = false;
224 226
225 // If below the ground, move the avatar up 227 // If below the ground, move the avatar up
226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); 228 float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position);
227 if (_position.Z < terrainHeight) 229 if (Position.Z < terrainHeight)
228 { 230 {
229 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); 231 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
230 _position.Z = terrainHeight + 2.0f; 232 _position.Z = terrainHeight + 2.0f;
231 ret = true; 233 ret = true;
232 } 234 }
233 235
234 // TODO: check for out of bounds 236 // TODO: check for out of bounds
237 return ret;
238 }
235 239
240 // A version of the sanity check that also makes sure a new position value is
241 // pushed back to the physics engine. This routine would be used by anyone
242 // who is not already pushing the value.
243 private bool PositionSanityCheck2()
244 {
245 bool ret = false;
246 if (PositionSanityCheck())
247 {
248 // The new position value must be pushed into the physics engine but we can't
249 // just assign to "Position" because of potential call loops.
250 Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
251 {
252 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
253 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
254 });
255 ret = true;
256 }
236 return ret; 257 return ret;
237 } 258 }
238 259
@@ -241,6 +262,10 @@ public class BSCharacter : PhysicsActor
241 return _mass; 262 return _mass;
242 } 263 }
243 } 264 }
265
266 // used when we only want this prim's mass and not the linkset thing
267 public override float MassRaw { get {return _mass; } }
268
244 public override Vector3 Force { 269 public override Vector3 Force {
245 get { return _force; } 270 get { return _force; }
246 set { 271 set {
@@ -273,10 +298,10 @@ public class BSCharacter : PhysicsActor
273 set { 298 set {
274 _velocity = value; 299 _velocity = value;
275 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 300 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
276 _scene.TaintedObject("BSCharacter.setVelocity", delegate() 301 Scene.TaintedObject("BSCharacter.setVelocity", delegate()
277 { 302 {
278 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 303 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
279 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); 304 BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity);
280 }); 305 });
281 } 306 }
282 } 307 }
@@ -299,10 +324,10 @@ public class BSCharacter : PhysicsActor
299 set { 324 set {
300 _orientation = value; 325 _orientation = value;
301 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 326 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
302 _scene.TaintedObject("BSCharacter.setOrientation", delegate() 327 Scene.TaintedObject("BSCharacter.setOrientation", delegate()
303 { 328 {
304 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 329 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
305 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 330 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
306 }); 331 });
307 } 332 }
308 } 333 }
@@ -319,14 +344,13 @@ public class BSCharacter : PhysicsActor
319 public override bool Flying { 344 public override bool Flying {
320 get { return _flying; } 345 get { return _flying; }
321 set { 346 set {
322 if (_flying != value) 347 _flying = value;
323 { 348 // simulate flying by changing the effect of gravity
324 _flying = value; 349 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
325 // simulate flying by changing the effect of gravity
326 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
327 }
328 } 350 }
329 } 351 }
352 // Flying is implimented by changing the avatar's buoyancy.
353 // Would this be done better with a vehicle type?
330 private float ComputeBuoyancyFromFlying(bool ifFlying) { 354 private float ComputeBuoyancyFromFlying(bool ifFlying) {
331 return ifFlying ? 1f : 0f; 355 return ifFlying ? 1f : 0f;
332 } 356 }
@@ -340,11 +364,11 @@ public class BSCharacter : PhysicsActor
340 set { _throttleUpdates = value; } 364 set { _throttleUpdates = value; }
341 } 365 }
342 public override bool IsColliding { 366 public override bool IsColliding {
343 get { return (_collidingStep == _scene.SimulationStep); } 367 get { return (_collidingStep == Scene.SimulationStep); }
344 set { _isColliding = value; } 368 set { _isColliding = value; }
345 } 369 }
346 public override bool CollidingGround { 370 public override bool CollidingGround {
347 get { return (_collidingGroundStep == _scene.SimulationStep); } 371 get { return (_collidingGroundStep == Scene.SimulationStep); }
348 set { _collidingGround = value; } 372 set { _collidingGround = value; }
349 } 373 }
350 public override bool CollidingObj { 374 public override bool CollidingObj {
@@ -366,10 +390,10 @@ public class BSCharacter : PhysicsActor
366 public override float Buoyancy { 390 public override float Buoyancy {
367 get { return _buoyancy; } 391 get { return _buoyancy; }
368 set { _buoyancy = value; 392 set { _buoyancy = value;
369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() 393 Scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
370 { 394 {
371 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 395 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); 396 BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
373 }); 397 });
374 } 398 }
375 } 399 }
@@ -413,10 +437,10 @@ public class BSCharacter : PhysicsActor
413 _force.Y += force.Y; 437 _force.Y += force.Y;
414 _force.Z += force.Z; 438 _force.Z += force.Z;
415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 439 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
416 _scene.TaintedObject("BSCharacter.AddForce", delegate() 440 Scene.TaintedObject("BSCharacter.AddForce", delegate()
417 { 441 {
418 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); 442 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force); 443 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
420 }); 444 });
421 } 445 }
422 else 446 else
@@ -441,18 +465,23 @@ public class BSCharacter : PhysicsActor
441 465
442 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() 466 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
443 { 467 {
444 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 468 BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
445 }); 469 });
446 } 470 }
447 } 471 }
472
473 public override void ZeroMotion()
474 {
475 return;
476 }
477
448 // Stop collision events 478 // Stop collision events
449 public override void UnSubscribeEvents() { 479 public override void UnSubscribeEvents() {
450 _subscribedEventsMs = 0; 480 _subscribedEventsMs = 0;
451 // Avatars get all their collision events 481 Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
452 // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() 482 {
453 // { 483 BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
454 // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 484 });
455 // });
456 } 485 }
457 // Return 'true' if someone has subscribed to events 486 // Return 'true' if someone has subscribed to events
458 public override bool SubscribedEvents() { 487 public override bool SubscribedEvents() {
@@ -478,7 +507,7 @@ public class BSCharacter : PhysicsActor
478 507
479 // The physics engine says that properties have updated. Update same and inform 508 // The physics engine says that properties have updated. Update same and inform
480 // the world that things have changed. 509 // the world that things have changed.
481 public void UpdateProperties(EntityProperties entprop) 510 public override void UpdateProperties(EntityProperties entprop)
482 { 511 {
483 _position = entprop.Position; 512 _position = entprop.Position;
484 _orientation = entprop.Rotation; 513 _orientation = entprop.Rotation;
@@ -488,43 +517,46 @@ public class BSCharacter : PhysicsActor
488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 517 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
489 // base.RequestPhysicsterseUpdate(); 518 // base.RequestPhysicsterseUpdate();
490 519
491 /* 520 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
492 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 521 PositionSanityCheck2();
493 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 522
494 entprop.Acceleration, entprop.RotationalVelocity); 523 float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
495 */ 524 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
525 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
496 } 526 }
497 527
498 // Called by the scene when a collision with this object is reported 528 // Called by the scene when a collision with this object is reported
499 // The collision, if it should be reported to the character, is placed in a collection 529 // The collision, if it should be reported to the character, is placed in a collection
500 // that will later be sent to the simulator when SendCollisions() is called. 530 // that will later be sent to the simulator when SendCollisions() is called.
501 CollisionEventUpdate collisionCollection = null; 531 CollisionEventUpdate collisionCollection = null;
502 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) 532 public override bool Collide(uint collidingWith, BSPhysObject collidee, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
503 { 533 {
504 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 534 bool ret = false;
505 535
506 // The following makes IsColliding() and IsCollidingGround() work 536 // The following makes IsColliding() and IsCollidingGround() work
507 _collidingStep = _scene.SimulationStep; 537 _collidingStep = Scene.SimulationStep;
508 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) 538 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
509 { 539 {
510 _collidingGroundStep = _scene.SimulationStep; 540 _collidingGroundStep = Scene.SimulationStep;
511 } 541 }
512 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); 542 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
513 543
514 // throttle collisions to the rate specified in the subscription 544 // throttle collisions to the rate specified in the subscription
515 if (_subscribedEventsMs != 0) { 545 if (SubscribedEvents()) {
516 int nowTime = _scene.SimulationNowTime; 546 int nowTime = Scene.SimulationNowTime;
517 if (nowTime >= _nextCollisionOkTime) { 547 if (nowTime >= _nextCollisionOkTime) {
518 _nextCollisionOkTime = nowTime + _subscribedEventsMs; 548 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
519 549
520 if (collisionCollection == null) 550 if (collisionCollection == null)
521 collisionCollection = new CollisionEventUpdate(); 551 collisionCollection = new CollisionEventUpdate();
522 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 552 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
553 ret = true;
523 } 554 }
524 } 555 }
556 return ret;
525 } 557 }
526 558
527 public void SendCollisions() 559 public override void SendCollisions()
528 { 560 {
529 /* 561 /*
530 if (collisionCollection != null && collisionCollection.Count > 0) 562 if (collisionCollection != null && collisionCollection.Count > 0)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 25084d8..1376a29 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -48,11 +48,10 @@ public abstract class BSConstraint : IDisposable
48 { 48 {
49 if (m_enabled) 49 if (m_enabled)
50 { 50 {
51 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); 51 m_enabled = false;
52 bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); 52 bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
53 m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); 53 m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
54 m_constraint.Ptr = System.IntPtr.Zero; 54 m_constraint.Ptr = System.IntPtr.Zero;
55 m_enabled = false;
56 } 55 }
57 } 56 }
58 57
@@ -75,6 +74,17 @@ public abstract class BSConstraint : IDisposable
75 return ret; 74 return ret;
76 } 75 }
77 76
77 public virtual bool SetSolverIterations(float cnt)
78 {
79 bool ret = false;
80 if (m_enabled)
81 {
82 BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.Ptr, cnt);
83 ret = true;
84 }
85 return ret;
86 }
87
78 public virtual bool CalculateTransforms() 88 public virtual bool CalculateTransforms()
79 { 89 {
80 bool ret = false; 90 bool ret = false;
@@ -97,8 +107,9 @@ public abstract class BSConstraint : IDisposable
97 ret = CalculateTransforms(); 107 ret = CalculateTransforms();
98 if (ret) 108 if (ret)
99 { 109 {
100 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", 110 // Setting an object's mass to zero (making it static like when it's selected)
101 // BSScene.DetailLogZero, Body1.ID, Body2.ID); 111 // automatically disables the constraints.
112 // If the link is enabled, be sure to set the constraint itself to enabled.
102 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); 113 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
103 } 114 }
104 else 115 else
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 5a9f135..61006f0 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
57 private int frcount = 0; // Used to limit dynamics debug output to 57 private int frcount = 0; // Used to limit dynamics debug output to
58 // every 100th frame 58 // every 100th frame
59 59
60 private BSScene m_physicsScene;
60 private BSPrim m_prim; // the prim this dynamic controller belongs to 61 private BSPrim m_prim; // the prim this dynamic controller belongs to
61 62
62 // Vehicle properties 63 // Vehicle properties
@@ -74,13 +75,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
74 // HOVER_UP_ONLY 75 // HOVER_UP_ONLY
75 // LIMIT_MOTOR_UP 76 // LIMIT_MOTOR_UP
76 // LIMIT_ROLL_ONLY 77 // LIMIT_ROLL_ONLY
77 private VehicleFlag m_Hoverflags = (VehicleFlag)0;
78 private Vector3 m_BlockingEndPoint = Vector3.Zero; 78 private Vector3 m_BlockingEndPoint = Vector3.Zero;
79 private Quaternion m_RollreferenceFrame = Quaternion.Identity; 79 private Quaternion m_RollreferenceFrame = Quaternion.Identity;
80 // Linear properties 80 // Linear properties
81 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time 81 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
82 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL 82 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
83 private Vector3 m_dir = Vector3.Zero; // velocity applied to body 83 private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body
84 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 84 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
85 private float m_linearMotorDecayTimescale = 0; 85 private float m_linearMotorDecayTimescale = 0;
86 private float m_linearMotorTimescale = 0; 86 private float m_linearMotorTimescale = 0;
@@ -124,15 +124,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
124 private float m_verticalAttractionEfficiency = 1.0f; // damped 124 private float m_verticalAttractionEfficiency = 1.0f; // damped
125 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 125 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
126 126
127 public BSDynamics(BSPrim myPrim) 127 public BSDynamics(BSScene myScene, BSPrim myPrim)
128 { 128 {
129 m_physicsScene = myScene;
129 m_prim = myPrim; 130 m_prim = myPrim;
130 m_type = Vehicle.TYPE_NONE; 131 m_type = Vehicle.TYPE_NONE;
131 } 132 }
132 133
133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) 134 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
134 { 135 {
135 DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 136 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
136 switch (pParam) 137 switch (pParam)
137 { 138 {
138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 139 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
@@ -229,9 +230,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
229 } 230 }
230 }//end ProcessFloatVehicleParam 231 }//end ProcessFloatVehicleParam
231 232
232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) 233 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
233 { 234 {
234 DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 235 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
235 switch (pParam) 236 switch (pParam)
236 { 237 {
237 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 238 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
@@ -266,7 +267,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
266 267
267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 268 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
268 { 269 {
269 DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 270 VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
270 switch (pParam) 271 switch (pParam)
271 { 272 {
272 case Vehicle.REFERENCE_FRAME: 273 case Vehicle.REFERENCE_FRAME:
@@ -280,164 +281,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin
280 281
281 internal void ProcessVehicleFlags(int pParam, bool remove) 282 internal void ProcessVehicleFlags(int pParam, bool remove)
282 { 283 {
283 DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); 284 VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
285 VehicleFlag parm = (VehicleFlag)pParam;
284 if (remove) 286 if (remove)
285 { 287 {
286 if (pParam == -1) 288 if (pParam == -1)
287 { 289 {
288 m_flags = (VehicleFlag)0; 290 m_flags = (VehicleFlag)0;
289 m_Hoverflags = (VehicleFlag)0;
290 return;
291 } 291 }
292 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) 292 else
293 {
294 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0)
295 m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT);
296 }
297 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
298 {
299 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0)
300 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY);
301 }
302 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
303 {
304 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0)
305 m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY);
306 }
307 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
308 {
309 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0)
310 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY);
311 }
312 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
313 {
314 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0)
315 m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP);
316 }
317 if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY)
318 {
319 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0)
320 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
321 }
322 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
323 {
324 if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0)
325 m_flags &= ~(VehicleFlag.MOUSELOOK_BANK);
326 }
327 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
328 {
329 if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0)
330 m_flags &= ~(VehicleFlag.MOUSELOOK_STEER);
331 }
332 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
333 {
334 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0)
335 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP);
336 }
337 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
338 {
339 if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0)
340 m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED);
341 }
342 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
343 {
344 if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0)
345 m_flags &= ~(VehicleFlag.NO_X);
346 }
347 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
348 {
349 if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0)
350 m_flags &= ~(VehicleFlag.NO_Y);
351 }
352 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
353 {
354 if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0)
355 m_flags &= ~(VehicleFlag.NO_Z);
356 }
357 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
358 {
359 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0)
360 m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT);
361 }
362 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
363 {
364 if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0)
365 m_flags &= ~(VehicleFlag.NO_DEFLECTION);
366 }
367 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
368 { 293 {
369 if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) 294 m_flags &= ~parm;
370 m_flags &= ~(VehicleFlag.LOCK_ROTATION);
371 } 295 }
372 } 296 }
373 else 297 else {
374 { 298 m_flags |= parm;
375 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
376 {
377 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags);
378 }
379 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
380 {
381 m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags);
382 }
383 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
384 {
385 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags);
386 }
387 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
388 {
389 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags);
390 }
391 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
392 {
393 m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags);
394 }
395 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
396 {
397 m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags);
398 }
399 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
400 {
401 m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags);
402 }
403 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
404 {
405 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags);
406 }
407 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
408 {
409 m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags);
410 }
411 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
412 {
413 m_flags |= (VehicleFlag.NO_X);
414 }
415 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
416 {
417 m_flags |= (VehicleFlag.NO_Y);
418 }
419 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
420 {
421 m_flags |= (VehicleFlag.NO_Z);
422 }
423 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
424 {
425 m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT);
426 }
427 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
428 {
429 m_flags |= (VehicleFlag.NO_DEFLECTION);
430 }
431 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
432 {
433 m_flags |= (VehicleFlag.LOCK_ROTATION);
434 }
435 } 299 }
436 }//end ProcessVehicleFlags 300 }//end ProcessVehicleFlags
437 301
438 internal void ProcessTypeChange(Vehicle pType) 302 internal void ProcessTypeChange(Vehicle pType)
439 { 303 {
440 DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); 304 VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
441 // Set Defaults For Type 305 // Set Defaults For Type
442 m_type = pType; 306 m_type = pType;
443 switch (pType) 307 switch (pType)
@@ -478,10 +342,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
478 // m_bankingMix = 1; 342 // m_bankingMix = 1;
479 // m_bankingTimescale = 10; 343 // m_bankingTimescale = 10;
480 // m_referenceFrame = Quaternion.Identity; 344 // m_referenceFrame = Quaternion.Identity;
481 m_Hoverflags &= 345 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
346 m_flags &=
482 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 347 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
483 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 348 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
484 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
485 break; 349 break;
486 case Vehicle.TYPE_CAR: 350 case Vehicle.TYPE_CAR:
487 m_linearFrictionTimescale = new Vector3(100, 2, 1000); 351 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
@@ -506,10 +370,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
506 // m_bankingMix = 1; 370 // m_bankingMix = 1;
507 // m_bankingTimescale = 1; 371 // m_bankingTimescale = 1;
508 // m_referenceFrame = Quaternion.Identity; 372 // m_referenceFrame = Quaternion.Identity;
509 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
510 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | 373 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
511 VehicleFlag.LIMIT_MOTOR_UP); 374 VehicleFlag.LIMIT_MOTOR_UP);
512 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); 375 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
376 m_flags |= (VehicleFlag.HOVER_UP_ONLY);
513 break; 377 break;
514 case Vehicle.TYPE_BOAT: 378 case Vehicle.TYPE_BOAT:
515 m_linearFrictionTimescale = new Vector3(10, 3, 2); 379 m_linearFrictionTimescale = new Vector3(10, 3, 2);
@@ -534,12 +398,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
534 // m_bankingMix = 0.8f; 398 // m_bankingMix = 0.8f;
535 // m_bankingTimescale = 1; 399 // m_bankingTimescale = 1;
536 // m_referenceFrame = Quaternion.Identity; 400 // m_referenceFrame = Quaternion.Identity;
537 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | 401 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
538 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 402 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
539 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); 403 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
540 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | 404 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
541 VehicleFlag.LIMIT_MOTOR_UP); 405 VehicleFlag.LIMIT_MOTOR_UP);
542 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); 406 m_flags |= (VehicleFlag.HOVER_WATER_ONLY);
543 break; 407 break;
544 case Vehicle.TYPE_AIRPLANE: 408 case Vehicle.TYPE_AIRPLANE:
545 m_linearFrictionTimescale = new Vector3(200, 10, 5); 409 m_linearFrictionTimescale = new Vector3(200, 10, 5);
@@ -564,7 +428,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
564 // m_bankingMix = 0.7f; 428 // m_bankingMix = 0.7f;
565 // m_bankingTimescale = 2; 429 // m_bankingTimescale = 2;
566 // m_referenceFrame = Quaternion.Identity; 430 // m_referenceFrame = Quaternion.Identity;
567 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 431 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
568 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 432 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
569 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); 433 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
570 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 434 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
@@ -592,15 +456,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
592 // m_bankingMix = 0.7f; 456 // m_bankingMix = 0.7f;
593 // m_bankingTimescale = 5; 457 // m_bankingTimescale = 5;
594 // m_referenceFrame = Quaternion.Identity; 458 // m_referenceFrame = Quaternion.Identity;
595 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 459 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
596 VehicleFlag.HOVER_UP_ONLY); 460 VehicleFlag.HOVER_UP_ONLY);
597 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); 461 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
598 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 462 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
599 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); 463 m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
600 break; 464 break;
601 } 465 }
602 }//end SetDefaultsForType 466 }//end SetDefaultsForType
603 467
468 // One step of the vehicle properties for the next 'pTimestep' seconds.
604 internal void Step(float pTimestep) 469 internal void Step(float pTimestep)
605 { 470 {
606 if (m_type == Vehicle.TYPE_NONE) return; 471 if (m_type == Vehicle.TYPE_NONE) return;
@@ -613,29 +478,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin
613 MoveAngular(pTimestep); 478 MoveAngular(pTimestep);
614 LimitRotation(pTimestep); 479 LimitRotation(pTimestep);
615 480
616 DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 481 // remember the position so next step we can limit absolute movement effects
482 m_lastPositionVector = m_prim.Position;
483
484 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); 485 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
618 }// end Step 486 }// end Step
619 487
620 private void MoveLinear(float pTimestep) 488 private void MoveLinear(float pTimestep)
621 { 489 {
622 // requested m_linearMotorDirection is significant 490 // m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates
623 // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) 491 // m_lastLinearVelocityVector is the speed we are moving in that direction
624 if (m_linearMotorDirection.LengthSquared() > 0.0001f) 492 if (m_linearMotorDirection.LengthSquared() > 0.001f)
625 { 493 {
626 Vector3 origDir = m_linearMotorDirection; 494 Vector3 origDir = m_linearMotorDirection;
627 Vector3 origVel = m_lastLinearVelocityVector; 495 Vector3 origVel = m_lastLinearVelocityVector;
628 496
629 // add drive to body 497 // add drive to body
630 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); 498 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale / pTimestep);
631 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); 499 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep);
632 // lastLinearVelocityVector is the current body velocity vector? 500 // lastLinearVelocityVector is the current body velocity vector
633 // RA: Not sure what the *10 is for. A correction for pTimestep? 501 // RA: Not sure what the *10 is for. A correction for pTimestep?
634 // m_lastLinearVelocityVector += (addAmount*10); 502 // m_lastLinearVelocityVector += (addAmount*10);
635 m_lastLinearVelocityVector += addAmount; 503 m_lastLinearVelocityVector += addAmount;
636 504
637 // This will work temporarily, but we really need to compare speed on an axis
638 // KF: Limit body velocity to applied velocity?
639 // Limit the velocity vector to less than the last set linear motor direction 505 // Limit the velocity vector to less than the last set linear motor direction
640 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) 506 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
641 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; 507 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
@@ -644,120 +510,83 @@ namespace OpenSim.Region.Physics.BulletSPlugin
644 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) 510 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
645 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; 511 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
646 512
513 /*
647 // decay applied velocity 514 // decay applied velocity
648 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); 515 Vector3 decayfraction = Vector3.One/(m_linearMotorDecayTimescale / pTimestep);
516 // (RA: do not know where the 0.5f comes from)
649 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; 517 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
650
651 /*
652 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
653 m_lastLinearVelocityVector += addAmount;
654
655 float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
656 m_linearMotorDirection *= decayfraction;
657
658 */ 518 */
519 float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep));
520 m_linearMotorDirection *= keepfraction;
659 521
660 DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", 522 VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}",
661 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); 523 m_prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
662 } 524 }
663 else 525 else
664 { 526 {
665 // if what remains of applied is small, zero it. 527 // if what remains of direction is very small, zero it.
666 // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
667 // m_lastLinearVelocityVector = Vector3.Zero;
668 m_linearMotorDirection = Vector3.Zero; 528 m_linearMotorDirection = Vector3.Zero;
669 m_lastLinearVelocityVector = Vector3.Zero; 529 m_lastLinearVelocityVector = Vector3.Zero;
530 VDetailLog("{0},MoveLinear,zeroed", m_prim.LocalID);
670 } 531 }
671 532
672 // convert requested object velocity to world-referenced vector 533 // convert requested object velocity to object relative vector
673 Quaternion rotq = m_prim.Orientation; 534 Quaternion rotq = m_prim.Orientation;
674 m_dir = m_lastLinearVelocityVector * rotq; 535 m_newVelocity = m_lastLinearVelocityVector * rotq;
675 536
676 // Add the various forces into m_dir which will be our new direction vector (velocity) 537 // Add the various forces into m_dir which will be our new direction vector (velocity)
677 538
678 // add Gravity and Buoyancy 539 // add Gravity and Buoyancy
679 // KF: So far I have found no good method to combine a script-requested
680 // .Z velocity and gravity. Therefore only 0g will used script-requested
681 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
682 Vector3 grav = Vector3.Zero;
683 // There is some gravity, make a gravity force vector that is applied after object velocity. 540 // There is some gravity, make a gravity force vector that is applied after object velocity.
684 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 541 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
685 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); 542 Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy));
543
544 /*
545 * RA: Not sure why one would do this
686 // Preserve the current Z velocity 546 // Preserve the current Z velocity
687 Vector3 vel_now = m_prim.Velocity; 547 Vector3 vel_now = m_prim.Velocity;
688 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 548 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
549 */
689 550
690 Vector3 pos = m_prim.Position; 551 Vector3 pos = m_prim.Position;
691 Vector3 posChange = pos;
692// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); 552// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
693 double Zchange = Math.Abs(posChange.Z);
694 if (m_BlockingEndPoint != Vector3.Zero)
695 {
696 bool changed = false;
697 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
698 {
699 pos.X -= posChange.X + 1;
700 changed = true;
701 }
702 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
703 {
704 pos.Y -= posChange.Y + 1;
705 changed = true;
706 }
707 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
708 {
709 pos.Z -= posChange.Z + 1;
710 changed = true;
711 }
712 if (pos.X <= 0)
713 {
714 pos.X += posChange.X + 1;
715 changed = true;
716 }
717 if (pos.Y <= 0)
718 {
719 pos.Y += posChange.Y + 1;
720 changed = true;
721 }
722 if (changed)
723 {
724 m_prim.Position = pos;
725 DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
726 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
727 }
728 }
729 553
730 // If below the terrain, move us above the ground a little. 554 // If below the terrain, move us above the ground a little.
731 if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) 555 float terrainHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
556 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
557 // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
558 // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation;
559 // if (rotatedSize.Z < terrainHeight)
560 if (pos.Z < terrainHeight)
732 { 561 {
733 pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; 562 pos.Z = terrainHeight + 2;
734 m_prim.Position = pos; 563 m_prim.Position = pos;
735 DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); 564 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", m_prim.LocalID, terrainHeight, pos);
736 } 565 }
737 566
738 // Check if hovering 567 // Check if hovering
739 if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) 568 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
740 { 569 {
741 // We should hover, get the target height 570 // We should hover, get the target height
742 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) 571 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
743 { 572 {
744 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; 573 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight;
745 } 574 }
746 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 575 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
747 { 576 {
748 m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 577 m_VhoverTargetHeight = terrainHeight + m_VhoverHeight;
749 } 578 }
750 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 579 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
751 { 580 {
752 m_VhoverTargetHeight = m_VhoverHeight; 581 m_VhoverTargetHeight = m_VhoverHeight;
753 } 582 }
754 583
755 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) 584 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
756 { 585 {
757 // If body is aready heigher, use its height as target height 586 // If body is aready heigher, use its height as target height
758 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; 587 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
759 } 588 }
760 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 589 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
761 { 590 {
762 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) 591 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
763 { 592 {
@@ -770,82 +599,92 @@ namespace OpenSim.Region.Physics.BulletSPlugin
770 // Replace Vertical speed with correction figure if significant 599 // Replace Vertical speed with correction figure if significant
771 if (Math.Abs(herr0) > 0.01f) 600 if (Math.Abs(herr0) > 0.01f)
772 { 601 {
773 m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); 602 m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
774 //KF: m_VhoverEfficiency is not yet implemented 603 //KF: m_VhoverEfficiency is not yet implemented
775 } 604 }
776 else 605 else
777 { 606 {
778 m_dir.Z = 0f; 607 m_newVelocity.Z = 0f;
779 } 608 }
780 } 609 }
781 610
782 DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); 611 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight);
612 }
783 613
784// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped 614 Vector3 posChange = pos - m_lastPositionVector;
785// m_VhoverTimescale = 0f; // time to acheive height 615 if (m_BlockingEndPoint != Vector3.Zero)
786// pTimestep is time since last frame,in secs 616 {
617 bool changed = false;
618 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
619 {
620 pos.X -= posChange.X + 1;
621 changed = true;
622 }
623 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
624 {
625 pos.Y -= posChange.Y + 1;
626 changed = true;
627 }
628 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
629 {
630 pos.Z -= posChange.Z + 1;
631 changed = true;
632 }
633 if (pos.X <= 0)
634 {
635 pos.X += posChange.X + 1;
636 changed = true;
637 }
638 if (pos.Y <= 0)
639 {
640 pos.Y += posChange.Y + 1;
641 changed = true;
642 }
643 if (changed)
644 {
645 m_prim.Position = pos;
646 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
647 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
648 }
787 } 649 }
788 650
651 float Zchange = Math.Abs(posChange.Z);
789 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 652 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
790 { 653 {
791 //Start Experimental Values
792 if (Zchange > .3) 654 if (Zchange > .3)
793 {
794 grav.Z = (float)(grav.Z * 3); 655 grav.Z = (float)(grav.Z * 3);
795 }
796 if (Zchange > .15) 656 if (Zchange > .15)
797 {
798 grav.Z = (float)(grav.Z * 2); 657 grav.Z = (float)(grav.Z * 2);
799 }
800 if (Zchange > .75) 658 if (Zchange > .75)
801 {
802 grav.Z = (float)(grav.Z * 1.5); 659 grav.Z = (float)(grav.Z * 1.5);
803 }
804 if (Zchange > .05) 660 if (Zchange > .05)
805 {
806 grav.Z = (float)(grav.Z * 1.25); 661 grav.Z = (float)(grav.Z * 1.25);
807 }
808 if (Zchange > .025) 662 if (Zchange > .025)
809 {
810 grav.Z = (float)(grav.Z * 1.125); 663 grav.Z = (float)(grav.Z * 1.125);
811 } 664 float postemp = (pos.Z - terrainHeight);
812 float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
813 float postemp = (pos.Z - terraintemp);
814 if (postemp > 2.5f) 665 if (postemp > 2.5f)
815 {
816 grav.Z = (float)(grav.Z * 1.037125); 666 grav.Z = (float)(grav.Z * 1.037125);
817 } 667 VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
818 DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
819 //End Experimental Values
820 } 668 }
821 if ((m_flags & (VehicleFlag.NO_X)) != 0) 669 if ((m_flags & (VehicleFlag.NO_X)) != 0)
822 { 670 m_newVelocity.X = 0;
823 m_dir.X = 0;
824 }
825 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 671 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
826 { 672 m_newVelocity.Y = 0;
827 m_dir.Y = 0;
828 }
829 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 673 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
830 { 674 m_newVelocity.Z = 0;
831 m_dir.Z = 0;
832 }
833
834 m_lastPositionVector = m_prim.Position;
835 675
836 // Apply velocity 676 // Apply velocity
837 m_prim.Velocity = m_dir; 677 m_prim.Velocity = m_newVelocity;
838 // apply gravity force 678 // apply gravity force
839 // Why is this set here? The physics engine already does gravity. 679 // Why is this set here? The physics engine already does gravity.
840 // m_prim.AddForce(grav, false); 680 // m_prim.AddForce(grav, false);
841 // m_prim.Force = grav;
842 681
843 // Apply friction 682 // Apply friction
844 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 683 Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
845 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 684 m_lastLinearVelocityVector *= keepFraction;
846 685
847 DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", 686 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}",
848 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); 687 m_prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction);
849 688
850 } // end MoveLinear() 689 } // end MoveLinear()
851 690
@@ -870,30 +709,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin
870 // There are m_angularMotorApply steps. 709 // There are m_angularMotorApply steps.
871 Vector3 origAngularVelocity = m_angularMotorVelocity; 710 Vector3 origAngularVelocity = m_angularMotorVelocity;
872 // ramp up to new value 711 // ramp up to new value
873 // current velocity += error / (time to get there / step interval) 712 // current velocity += error / ( time to get there / step interval)
874 // requested speed - last motor speed 713 // requested speed - last motor speed
875 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); 714 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
876 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); 715 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
877 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); 716 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
878 717
879 DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", 718 VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}",
880 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); 719 m_prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
881 720
882 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected 721 // This is done so that if script request rate is less than phys frame rate the expected
883 // velocity may still be acheived. 722 // velocity may still be acheived.
723 m_angularMotorApply--;
884 } 724 }
885 else 725 else
886 { 726 {
887 // No motor recently applied, keep the body velocity 727 // No motor recently applied, keep the body velocity
888 // and decay the velocity 728 // and decay the velocity
889 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); 729 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
730 if (m_angularMotorVelocity.LengthSquared() < 0.00001)
731 m_angularMotorVelocity = Vector3.Zero;
890 } // end motor section 732 } // end motor section
891 733
892 // Vertical attractor section 734 // Vertical attractor section
893 Vector3 vertattr = Vector3.Zero; 735 Vector3 vertattr = Vector3.Zero;
894 if (m_verticalAttractionTimescale < 300) 736 if (m_verticalAttractionTimescale < 300)
895 { 737 {
896 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); 738 float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep);
897 // get present body rotation 739 // get present body rotation
898 Quaternion rotq = m_prim.Orientation; 740 Quaternion rotq = m_prim.Orientation;
899 // make a vector pointing up 741 // make a vector pointing up
@@ -924,7 +766,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
924 vertattr.X += bounce * angularVelocity.X; 766 vertattr.X += bounce * angularVelocity.X;
925 vertattr.Y += bounce * angularVelocity.Y; 767 vertattr.Y += bounce * angularVelocity.Y;
926 768
927 DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", 769 VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
928 m_prim.LocalID, verterr, bounce, vertattr); 770 m_prim.LocalID, verterr, bounce, vertattr);
929 771
930 } // else vertical attractor is off 772 } // else vertical attractor is off
@@ -942,13 +784,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
942 { 784 {
943 m_lastAngularVelocity.X = 0; 785 m_lastAngularVelocity.X = 0;
944 m_lastAngularVelocity.Y = 0; 786 m_lastAngularVelocity.Y = 0;
945 DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); 787 VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
946 } 788 }
947 789
948 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 790 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
949 { 791 {
950 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 792 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
951 DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); 793 VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
952 } 794 }
953 795
954 // apply friction 796 // apply friction
@@ -958,7 +800,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
958 // Apply to the body 800 // Apply to the body
959 m_prim.RotationalVelocity = m_lastAngularVelocity; 801 m_prim.RotationalVelocity = m_lastAngularVelocity;
960 802
961 DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); 803 VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
962 } //end MoveAngular 804 } //end MoveAngular
963 805
964 internal void LimitRotation(float timestep) 806 internal void LimitRotation(float timestep)
@@ -996,20 +838,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
996 m_rot.Y = 0; 838 m_rot.Y = 0;
997 changed = true; 839 changed = true;
998 } 840 }
999 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
1000 {
1001 m_rot.X = 0;
1002 m_rot.Y = 0;
1003 changed = true;
1004 }
1005 if (changed) 841 if (changed)
842 {
1006 m_prim.Orientation = m_rot; 843 m_prim.Orientation = m_rot;
844 VDetailLog("{0},LimitRotation,done,orig={1},new={2}", m_prim.LocalID, rotq, m_rot);
845 }
1007 846
1008 DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
1009 } 847 }
1010 848
1011 // Invoke the detailed logger and output something if it's enabled. 849 // Invoke the detailed logger and output something if it's enabled.
1012 private void DetailLog(string msg, params Object[] args) 850 private void VDetailLog(string msg, params Object[] args)
1013 { 851 {
1014 if (m_prim.Scene.VehicleLoggingEnabled) 852 if (m_prim.Scene.VehicleLoggingEnabled)
1015 m_prim.Scene.PhysicsLogging.Write(msg, args); 853 m_prim.Scene.PhysicsLogging.Write(msg, args);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 087b9bb..7e784eb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -36,14 +36,17 @@ public class BSLinkset
36{ 36{
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPrim m_linksetRoot; 39 private BSPhysObject m_linksetRoot;
40 public BSPrim LinksetRoot { get { return m_linksetRoot; } } 40 public BSPhysObject LinksetRoot { get { return m_linksetRoot; } }
41 41
42 private BSScene m_physicsScene; 42 private BSScene m_physicsScene;
43 public BSScene PhysicsScene { get { return m_physicsScene; } } 43 public BSScene PhysicsScene { get { return m_physicsScene; } }
44 44
45 static int m_nextLinksetID = 1;
46 public int LinksetID { get; private set; }
47
45 // The children under the root in this linkset 48 // The children under the root in this linkset
46 private List<BSPrim> m_children; 49 private List<BSPhysObject> m_children;
47 50
48 // We lock the diddling of linkset classes to prevent any badness. 51 // We lock the diddling of linkset classes to prevent any badness.
49 // This locks the modification of the instances of this class. Changes 52 // This locks the modification of the instances of this class. Changes
@@ -71,19 +74,23 @@ public class BSLinkset
71 get { return ComputeLinksetGeometricCenter(); } 74 get { return ComputeLinksetGeometricCenter(); }
72 } 75 }
73 76
74 public BSLinkset(BSScene scene, BSPrim parent) 77 public BSLinkset(BSScene scene, BSPhysObject parent)
75 { 78 {
76 // A simple linkset of one (no children) 79 // A simple linkset of one (no children)
80 LinksetID = m_nextLinksetID++;
81 // We create LOTS of linksets.
82 if (m_nextLinksetID < 0)
83 m_nextLinksetID = 1;
77 m_physicsScene = scene; 84 m_physicsScene = scene;
78 m_linksetRoot = parent; 85 m_linksetRoot = parent;
79 m_children = new List<BSPrim>(); 86 m_children = new List<BSPhysObject>();
80 m_mass = parent.MassRaw; 87 m_mass = parent.MassRaw;
81 } 88 }
82 89
83 // Link to a linkset where the child knows the parent. 90 // Link to a linkset where the child knows the parent.
84 // Parent changing should not happen so do some sanity checking. 91 // Parent changing should not happen so do some sanity checking.
85 // We return the parent's linkset so the child can track its membership. 92 // We return the parent's linkset so the child can track its membership.
86 public BSLinkset AddMeToLinkset(BSPrim child) 93 public BSLinkset AddMeToLinkset(BSPhysObject child)
87 { 94 {
88 lock (m_linksetActivityLock) 95 lock (m_linksetActivityLock)
89 { 96 {
@@ -95,7 +102,7 @@ public class BSLinkset
95 // Remove a child from a linkset. 102 // Remove a child from a linkset.
96 // Returns a new linkset for the child which is a linkset of one (just the 103 // Returns a new linkset for the child which is a linkset of one (just the
97 // orphened child). 104 // orphened child).
98 public BSLinkset RemoveMeFromLinkset(BSPrim child) 105 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
99 { 106 {
100 lock (m_linksetActivityLock) 107 lock (m_linksetActivityLock)
101 { 108 {
@@ -122,7 +129,7 @@ public class BSLinkset
122 } 129 }
123 130
124 // Return 'true' if the passed object is the root object of this linkset 131 // Return 'true' if the passed object is the root object of this linkset
125 public bool IsRoot(BSPrim requestor) 132 public bool IsRoot(BSPhysObject requestor)
126 { 133 {
127 return (requestor.LocalID == m_linksetRoot.LocalID); 134 return (requestor.LocalID == m_linksetRoot.LocalID);
128 } 135 }
@@ -133,12 +140,12 @@ public class BSLinkset
133 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 140 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
134 141
135 // Return 'true' if this child is in this linkset 142 // Return 'true' if this child is in this linkset
136 public bool HasChild(BSPrim child) 143 public bool HasChild(BSPhysObject child)
137 { 144 {
138 bool ret = false; 145 bool ret = false;
139 lock (m_linksetActivityLock) 146 lock (m_linksetActivityLock)
140 { 147 {
141 foreach (BSPrim bp in m_children) 148 foreach (BSPhysObject bp in m_children)
142 { 149 {
143 if (child.LocalID == bp.LocalID) 150 if (child.LocalID == bp.LocalID)
144 { 151 {
@@ -153,7 +160,7 @@ public class BSLinkset
153 private float ComputeLinksetMass() 160 private float ComputeLinksetMass()
154 { 161 {
155 float mass = m_linksetRoot.MassRaw; 162 float mass = m_linksetRoot.MassRaw;
156 foreach (BSPrim bp in m_children) 163 foreach (BSPhysObject bp in m_children)
157 { 164 {
158 mass += bp.MassRaw; 165 mass += bp.MassRaw;
159 } 166 }
@@ -167,7 +174,7 @@ public class BSLinkset
167 174
168 lock (m_linksetActivityLock) 175 lock (m_linksetActivityLock)
169 { 176 {
170 foreach (BSPrim bp in m_children) 177 foreach (BSPhysObject bp in m_children)
171 { 178 {
172 com += bp.Position * bp.MassRaw; 179 com += bp.Position * bp.MassRaw;
173 totalMass += bp.MassRaw; 180 totalMass += bp.MassRaw;
@@ -185,7 +192,7 @@ public class BSLinkset
185 192
186 lock (m_linksetActivityLock) 193 lock (m_linksetActivityLock)
187 { 194 {
188 foreach (BSPrim bp in m_children) 195 foreach (BSPhysObject bp in m_children)
189 { 196 {
190 com += bp.Position * bp.MassRaw; 197 com += bp.Position * bp.MassRaw;
191 } 198 }
@@ -195,11 +202,33 @@ public class BSLinkset
195 return com; 202 return com;
196 } 203 }
197 204
205 // The object is going dynamic (physical). Do any setup necessary
206 // for a dynamic linkset.
207 // Only the state of the passed object can be modified. The rest of the linkset
208 // has not yet been fully constructed.
209 // Return 'true' if any properties updated on the passed object.
210 // Called at taint-time!
211 public bool MakeDynamic(BSPhysObject child)
212 {
213 bool ret = false;
214 return ret;
215 }
216
217 // The object is going static (non-physical). Do any setup necessary
218 // for a static linkset.
219 // Return 'true' if any properties updated on the passed object.
220 // Called at taint-time!
221 public bool MakeStatic(BSPhysObject child)
222 {
223 // What is done for each object in BSPrim is what we want.
224 return false;
225 }
226
198 // When physical properties are changed the linkset needs to recalculate 227 // When physical properties are changed the linkset needs to recalculate
199 // its internal properties. 228 // its internal properties.
200 public void Refresh(BSPrim requestor) 229 public void Refresh(BSPhysObject requestor)
201 { 230 {
202 // If there are no children, there aren't any constraints to recompute 231 // If there are no children, there can't be any constraints to recompute
203 if (!HasAnyChildren) 232 if (!HasAnyChildren)
204 return; 233 return;
205 234
@@ -218,15 +247,16 @@ public class BSLinkset
218 // from a linkset to make sure the constraints know about the new mass and 247 // from a linkset to make sure the constraints know about the new mass and
219 // geometry. 248 // geometry.
220 // Must only be called at taint time!! 249 // Must only be called at taint time!!
221 private bool RecomputeLinksetConstraintVariables() 250 private void RecomputeLinksetConstraintVariables()
222 { 251 {
223 float linksetMass = LinksetMass; 252 float linksetMass = LinksetMass;
224 lock (m_linksetActivityLock) 253 lock (m_linksetActivityLock)
225 { 254 {
226 foreach (BSPrim child in m_children) 255 bool somethingMissing = false;
256 foreach (BSPhysObject child in m_children)
227 { 257 {
228 BSConstraint constrain; 258 BSConstraint constrain;
229 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) 259 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
230 { 260 {
231 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", 261 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
232 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); 262 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
@@ -234,32 +264,51 @@ public class BSLinkset
234 } 264 }
235 else 265 else
236 { 266 {
237 // Non-fatal error that can happen when children are being added to the linkset but 267 // Non-fatal error that happens when children are being added to the linkset but
238 // their constraints have not been created yet. 268 // their constraints have not been created yet.
239 // Caused by the fact that m_children is built at run time but building constraints 269 // Caused by the fact that m_children is built at run time but building constraints
240 // happens at taint time. 270 // happens at taint time.
241 // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", 271 somethingMissing = true;
242 // m_linksetRoot.Body.ID, child.Body.ID); 272 break;
243 } 273 }
244 } 274 }
275
276 // If the whole linkset is not here, doesn't make sense to recompute linkset wide values
277 if (!somethingMissing)
278 {
279 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
280 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
281 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
282 foreach (BSPhysObject child in m_children)
283 {
284 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
285 }
286 /*
287 // The root prim takes on the weight of the whole linkset
288 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass);
289 BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia);
290 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
291 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
292 BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr);
293 */
294 }
245 } 295 }
246 return false; 296 return;
247 } 297 }
248 298
249 // I am the root of a linkset and a new child is being added 299 // I am the root of a linkset and a new child is being added
250 // Called while LinkActivity is locked. 300 // Called while LinkActivity is locked.
251 private void AddChildToLinkset(BSPrim child) 301 private void AddChildToLinkset(BSPhysObject child)
252 { 302 {
253 if (!HasChild(child)) 303 if (!HasChild(child))
254 { 304 {
255 m_children.Add(child); 305 m_children.Add(child);
256 306
257 BSPrim rootx = LinksetRoot; // capture the root as of now 307 BSPhysObject rootx = LinksetRoot; // capture the root as of now
258 BSPrim childx = child; 308 BSPhysObject childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate() 309 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
260 { 310 {
261 // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 311 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child 312 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
264 }); 313 });
265 } 314 }
@@ -271,7 +320,7 @@ public class BSLinkset
271 // it's still connected to the linkset. 320 // it's still connected to the linkset.
272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information 321 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
273 // has to be updated also (like pointer to prim's parent). 322 // has to be updated also (like pointer to prim's parent).
274 private void RemoveChildFromOtherLinkset(BSPrim pchild) 323 private void RemoveChildFromOtherLinkset(BSPhysObject pchild)
275 { 324 {
276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild); 325 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
277 RemoveChildFromLinkset(pchild); 326 RemoveChildFromLinkset(pchild);
@@ -279,21 +328,20 @@ public class BSLinkset
279 328
280 // I am the root of a linkset and one of my children is being removed. 329 // I am the root of a linkset and one of my children is being removed.
281 // Safe to call even if the child is not really in my linkset. 330 // Safe to call even if the child is not really in my linkset.
282 private void RemoveChildFromLinkset(BSPrim child) 331 private void RemoveChildFromLinkset(BSPhysObject child)
283 { 332 {
284 if (m_children.Remove(child)) 333 if (m_children.Remove(child))
285 { 334 {
286 BSPrim rootx = LinksetRoot; // capture the root as of now 335 BSPhysObject rootx = LinksetRoot; // capture the root as of now
287 BSPrim childx = child; 336 BSPhysObject childx = child;
288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 337 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
289 { 338 {
290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 339 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
292 340
293 PhysicallyUnlinkAChildFromRoot(rootx, childx); 341 PhysicallyUnlinkAChildFromRoot(rootx, childx);
342 RecomputeLinksetConstraintVariables();
294 }); 343 });
295 344
296 RecomputeLinksetConstraintVariables();
297 } 345 }
298 else 346 else
299 { 347 {
@@ -305,7 +353,7 @@ public class BSLinkset
305 353
306 // Create a constraint between me (root of linkset) and the passed prim (the child). 354 // Create a constraint between me (root of linkset) and the passed prim (the child).
307 // Called at taint time! 355 // Called at taint time!
308 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim) 356 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
309 { 357 {
310 // Zero motion for children so they don't interpolate 358 // Zero motion for children so they don't interpolate
311 childPrim.ZeroMotion(); 359 childPrim.ZeroMotion();
@@ -319,19 +367,18 @@ public class BSLinkset
319 367
320 // create a constraint that allows no freedom of movement between the two objects 368 // create a constraint that allows no freedom of movement between the two objects
321 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 369 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
322 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
323 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", 370 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
324 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); 371 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
325 BS6DofConstraint constrain = new BS6DofConstraint( 372 BS6DofConstraint constrain = new BS6DofConstraint(
326 m_physicsScene.World, rootPrim.Body, childPrim.Body, 373 m_physicsScene.World, rootPrim.BSBody, childPrim.BSBody,
327 midPoint, 374 midPoint,
328 true, 375 true,
329 true 376 true
330 ); 377 );
331 /* NOTE: attempt to build constraint with full frame computation, etc. 378 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
332 * Using the midpoint is easier since it lets the Bullet code use the transforms 379 * Using the midpoint is easier since it lets the Bullet code use the transforms
333 * of the objects. 380 * of the objects.
334 * Code left here as an example. 381 * Code left as a warning to future programmers.
335 // ================================================================================== 382 // ==================================================================================
336 // relative position normalized to the root prim 383 // relative position normalized to the root prim
337 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); 384 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
@@ -343,7 +390,6 @@ public class BSLinkset
343 390
344 // create a constraint that allows no freedom of movement between the two objects 391 // create a constraint that allows no freedom of movement between the two objects
345 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 392 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
346 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
347 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 393 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
348 BS6DofConstraint constrain = new BS6DofConstraint( 394 BS6DofConstraint constrain = new BS6DofConstraint(
349 PhysicsScene.World, rootPrim.Body, childPrim.Body, 395 PhysicsScene.World, rootPrim.Body, childPrim.Body,
@@ -374,40 +420,34 @@ public class BSLinkset
374 PhysicsScene.Params.linkConstraintTransMotorMaxVel, 420 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
375 PhysicsScene.Params.linkConstraintTransMotorMaxForce); 421 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
376 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); 422 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
423 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
424 {
425 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
426 }
377 427
378 RecomputeLinksetConstraintVariables(); 428 RecomputeLinksetConstraintVariables();
379 } 429 }
380 430
381 // Remove linkage between myself and a particular child 431 // Remove linkage between myself and a particular child
382 // Called at taint time! 432 // Called at taint time!
383 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) 433 private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
384 { 434 {
385 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
386 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
387 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 435 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
388 436
389 // Find the constraint for this link and get rid of it from the overall collection and from my list 437 // Find the constraint for this link and get rid of it from the overall collection and from my list
390 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); 438 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody);
391 439
392 // Make the child refresh its location 440 // Make the child refresh its location
393 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); 441 BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr);
394 } 442 }
395 443
396 // Remove linkage between myself and any possible children I might have 444 // Remove linkage between myself and any possible children I might have
397 // Called at taint time! 445 // Called at taint time!
398 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) 446 private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
399 { 447 {
400 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 448 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
402 449
403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); 450 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody);
404 }
405
406 // Invoke the detailed logger and output something if it's enabled.
407 private void DebugLog(string msg, params Object[] args)
408 {
409 if (m_physicsScene.ShouldDebugLog)
410 m_physicsScene.Logger.DebugFormat(msg, args);
411 } 451 }
412 452
413 // Invoke the detailed logger and output something if it's enabled. 453 // Invoke the detailed logger and output something if it's enabled.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
new file mode 100755
index 0000000..3fe71e1
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -0,0 +1,64 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37// Class to wrap all objects.
38// The rest of BulletSim doesn't need to keep checking for avatars or prims
39// unless the difference is significant.
40public abstract class BSPhysObject : PhysicsActor
41{
42 public abstract BSLinkset Linkset { get; set; }
43
44 public abstract bool Collide(uint collidingWith, BSPhysObject collidee,
45 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
46 public abstract void SendCollisions();
47
48 // Return the object mass without calculating it or side effects
49 public abstract float MassRaw { get; }
50
51 // Reference to the physical body (btCollisionObject) of this object
52 public abstract BulletBody BSBody { get; set; }
53 // Reference to the physical shape (btCollisionShape) of this object
54 public abstract BulletShape BSShape { get; set; }
55
56 public abstract void ZeroMotion();
57
58 public virtual void StepVehicle(float timeStep) { }
59
60 public abstract void UpdateProperties(EntityProperties entprop);
61
62 public abstract void Destroy();
63}
64}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 9c20004..26a581f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -37,13 +37,11 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
37namespace OpenSim.Region.Physics.BulletSPlugin 37namespace OpenSim.Region.Physics.BulletSPlugin
38{ 38{
39 [Serializable] 39 [Serializable]
40public sealed class BSPrim : PhysicsActor 40public sealed class BSPrim : BSPhysObject
41{ 41{
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
44 44
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); }
46
47 private IMesh _mesh; 45 private IMesh _mesh;
48 private PrimitiveBaseShape _pbs; 46 private PrimitiveBaseShape _pbs;
49 private ShapeData.PhysicsShapeType _shapeType; 47 private ShapeData.PhysicsShapeType _shapeType;
@@ -90,23 +88,16 @@ public sealed class BSPrim : PhysicsActor
90 private float _buoyancy; 88 private float _buoyancy;
91 89
92 // Membership in a linkset is controlled by this class. 90 // Membership in a linkset is controlled by this class.
93 private BSLinkset _linkset; 91 public override BSLinkset Linkset { get; set; }
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
99 92
100 private int _subscribedEventsMs = 0; 93 private int _subscribedEventsMs = 0;
101 private int _nextCollisionOkTime = 0; 94 private int _nextCollisionOkTime = 0;
102 long _collidingStep; 95 long _collidingStep;
103 long _collidingGroundStep; 96 long _collidingGroundStep;
97 CollisionFlags m_currentCollisionFlags = 0;
104 98
105 private BulletBody m_body; 99 public override BulletBody BSBody { get; set; }
106 public BulletBody Body { 100 public override BulletShape BSShape { get; set; }
107 get { return m_body; }
108 set { m_body = value; }
109 }
110 101
111 private BSDynamics _vehicle; 102 private BSDynamics _vehicle;
112 103
@@ -124,6 +115,7 @@ public sealed class BSPrim : PhysicsActor
124 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 115 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
125 _localID = localID; 116 _localID = localID;
126 _avName = primName; 117 _avName = primName;
118 _physicsActorType = (int)ActorTypes.Prim;
127 _scene = parent_scene; 119 _scene = parent_scene;
128 _position = pos; 120 _position = pos;
129 _size = size; 121 _size = size;
@@ -141,35 +133,37 @@ public sealed class BSPrim : PhysicsActor
141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 133 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 134 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
143 _restitution = _scene.Params.defaultRestitution; 135 _restitution = _scene.Params.defaultRestitution;
144 _linkset = new BSLinkset(_scene, this); // a linkset of one 136 Linkset = new BSLinkset(Scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness 137 _vehicle = new BSDynamics(Scene, this); // add vehicleness
146 _mass = CalculateMass(); 138 _mass = CalculateMass();
147 // do the actual object creation at taint time
148 DetailLog("{0},BSPrim.constructor,call", LocalID); 139 DetailLog("{0},BSPrim.constructor,call", LocalID);
140 // do the actual object creation at taint time
149 _scene.TaintedObject("BSPrim.create", delegate() 141 _scene.TaintedObject("BSPrim.create", delegate()
150 { 142 {
151 RecreateGeomAndObject(); 143 CreateGeomAndObject(true);
152 144
153 // Get the pointer to the physical body for this object. 145 // Get the pointer to the physical body for this object.
154 // At the moment, we're still letting BulletSim manage the creation and destruction 146 // At the moment, we're still letting BulletSim manage the creation and destruction
155 // of the object. Someday we'll move that into the C# code. 147 // of the object. Someday we'll move that into the C# code.
156 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 148 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
149 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
150 m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr);
157 }); 151 });
158 } 152 }
159 153
160 // called when this prim is being destroyed and we should free all the resources 154 // called when this prim is being destroyed and we should free all the resources
161 public void Destroy() 155 public override void Destroy()
162 { 156 {
163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 157 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
164 158
165 // Undo any links between me and any other object 159 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.LinksetRoot; 160 BSPhysObject parentBefore = Linkset.LinksetRoot;
167 int childrenBefore = _linkset.NumberOfChildren; 161 int childrenBefore = Linkset.NumberOfChildren;
168 162
169 _linkset = _linkset.RemoveMeFromLinkset(this); 163 Linkset = Linkset.RemoveMeFromLinkset(this);
170 164
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", 165 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 166 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
173 167
174 // Undo any vehicle properties 168 // Undo any vehicle properties
175 this.VehicleType = (int)Vehicle.TYPE_NONE; 169 this.VehicleType = (int)Vehicle.TYPE_NONE;
@@ -192,9 +186,10 @@ public sealed class BSPrim : PhysicsActor
192 _scene.TaintedObject("BSPrim.setSize", delegate() 186 _scene.TaintedObject("BSPrim.setSize", delegate()
193 { 187 {
194 _mass = CalculateMass(); // changing size changes the mass 188 _mass = CalculateMass(); // changing size changes the mass
195 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); 189 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
196 // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); 190 // scale and margins are set.
197 RecreateGeomAndObject(); 191 CreateGeomAndObject(true);
192 DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical);
198 }); 193 });
199 } 194 }
200 } 195 }
@@ -204,7 +199,7 @@ public sealed class BSPrim : PhysicsActor
204 _scene.TaintedObject("BSPrim.setShape", delegate() 199 _scene.TaintedObject("BSPrim.setShape", delegate()
205 { 200 {
206 _mass = CalculateMass(); // changing the shape changes the mass 201 _mass = CalculateMass(); // changing the shape changes the mass
207 RecreateGeomAndObject(); 202 CreateGeomAndObject(false);
208 }); 203 });
209 } 204 }
210 } 205 }
@@ -232,14 +227,13 @@ public sealed class BSPrim : PhysicsActor
232 BSPrim parent = obj as BSPrim; 227 BSPrim parent = obj as BSPrim;
233 if (parent != null) 228 if (parent != null)
234 { 229 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); 230 BSPhysObject parentBefore = Linkset.LinksetRoot;
236 BSPrim parentBefore = _linkset.LinksetRoot; 231 int childrenBefore = Linkset.NumberOfChildren;
237 int childrenBefore = _linkset.NumberOfChildren;
238 232
239 _linkset = parent.Linkset.AddMeToLinkset(this); 233 Linkset = parent.Linkset.AddMeToLinkset(this);
240 234
241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 235 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 236 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
243 } 237 }
244 return; 238 return;
245 } 239 }
@@ -248,16 +242,14 @@ public sealed class BSPrim : PhysicsActor
248 public override void delink() { 242 public override void delink() {
249 // TODO: decide if this parent checking needs to happen at taint time 243 // TODO: decide if this parent checking needs to happen at taint time
250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 244 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
252 _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
253 245
254 BSPrim parentBefore = _linkset.LinksetRoot; 246 BSPhysObject parentBefore = Linkset.LinksetRoot;
255 int childrenBefore = _linkset.NumberOfChildren; 247 int childrenBefore = Linkset.NumberOfChildren;
256 248
257 _linkset = _linkset.RemoveMeFromLinkset(this); 249 Linkset = Linkset.RemoveMeFromLinkset(this);
258 250
259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 251 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 252 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
261 return; 253 return;
262 } 254 }
263 255
@@ -265,30 +257,30 @@ public sealed class BSPrim : PhysicsActor
265 // Do it to the properties so the values get set in the physics engine. 257 // Do it to the properties so the values get set in the physics engine.
266 // Push the setting of the values to the viewer. 258 // Push the setting of the values to the viewer.
267 // Called at taint time! 259 // Called at taint time!
268 public void ZeroMotion() 260 public override void ZeroMotion()
269 { 261 {
270 _velocity = OMV.Vector3.Zero; 262 _velocity = OMV.Vector3.Zero;
271 _acceleration = OMV.Vector3.Zero; 263 _acceleration = OMV.Vector3.Zero;
272 _rotationalVelocity = OMV.Vector3.Zero; 264 _rotationalVelocity = OMV.Vector3.Zero;
273 265
274 // Zero some other properties directly into the physics engine 266 // Zero some other properties directly into the physics engine
275 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); 267 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
276 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); 268 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
277 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); 269 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
278 BulletSimAPI.ClearForces2(Body.Ptr); 270 BulletSimAPI.ClearForces2(BSBody.Ptr);
279 } 271 }
280 272
281 public override void LockAngularMotion(OMV.Vector3 axis) 273 public override void LockAngularMotion(OMV.Vector3 axis)
282 { 274 {
283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 275 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
284 return; 276 return;
285 } 277 }
286 278
287 public override OMV.Vector3 Position { 279 public override OMV.Vector3 Position {
288 get { 280 get {
289 if (!_linkset.IsRoot(this)) 281 if (!Linkset.IsRoot(this))
290 // child prims move around based on their parent. Need to get the latest location 282 // child prims move around based on their parent. Need to get the latest location
291 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 283 _position = BulletSimAPI.GetPosition2(BSBody.Ptr);
292 284
293 // don't do the GetObjectPosition for root elements because this function is called a zillion times 285 // don't do the GetObjectPosition for root elements because this function is called a zillion times
294 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 286 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
@@ -299,8 +291,8 @@ public sealed class BSPrim : PhysicsActor
299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 291 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
300 _scene.TaintedObject("BSPrim.setPosition", delegate() 292 _scene.TaintedObject("BSPrim.setPosition", delegate()
301 { 293 {
302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 294 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 295 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
304 }); 296 });
305 } 297 }
306 } 298 }
@@ -311,23 +303,24 @@ public sealed class BSPrim : PhysicsActor
311 { 303 {
312 get 304 get
313 { 305 {
314 return _linkset.LinksetMass; 306 // return Linkset.LinksetMass;
307 return _mass;
315 } 308 }
316 } 309 }
317 310
318 // used when we only want this prim's mass and not the linkset thing 311 // used when we only want this prim's mass and not the linkset thing
319 public float MassRaw { get { return _mass; } } 312 public override float MassRaw { get { return _mass; } }
320 313
321 // Is this used? 314 // Is this used?
322 public override OMV.Vector3 CenterOfMass 315 public override OMV.Vector3 CenterOfMass
323 { 316 {
324 get { return _linkset.CenterOfMass; } 317 get { return Linkset.CenterOfMass; }
325 } 318 }
326 319
327 // Is this used? 320 // Is this used?
328 public override OMV.Vector3 GeometricCenter 321 public override OMV.Vector3 GeometricCenter
329 { 322 {
330 get { return _linkset.GeometricCenter; } 323 get { return Linkset.GeometricCenter; }
331 } 324 }
332 325
333 public override OMV.Vector3 Force { 326 public override OMV.Vector3 Force {
@@ -336,9 +329,8 @@ public sealed class BSPrim : PhysicsActor
336 _force = value; 329 _force = value;
337 _scene.TaintedObject("BSPrim.setForce", delegate() 330 _scene.TaintedObject("BSPrim.setForce", delegate()
338 { 331 {
339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 332 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 333 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
342 }); 334 });
343 } 335 }
344 } 336 }
@@ -364,14 +356,14 @@ public sealed class BSPrim : PhysicsActor
364 { 356 {
365 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 357 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
366 { 358 {
367 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 359 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
368 }); 360 });
369 } 361 }
370 public override void VehicleVectorParam(int param, OMV.Vector3 value) 362 public override void VehicleVectorParam(int param, OMV.Vector3 value)
371 { 363 {
372 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 364 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
373 { 365 {
374 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
375 }); 367 });
376 } 368 }
377 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 369 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
@@ -391,7 +383,7 @@ public sealed class BSPrim : PhysicsActor
391 383
392 // Called each simulation step to advance vehicle characteristics. 384 // Called each simulation step to advance vehicle characteristics.
393 // Called from Scene when doing simulation step so we're in taint processing time. 385 // Called from Scene when doing simulation step so we're in taint processing time.
394 public void StepVehicle(float timeStep) 386 public override void StepVehicle(float timeStep)
395 { 387 {
396 if (IsPhysical) 388 if (IsPhysical)
397 _vehicle.Step(timeStep); 389 _vehicle.Step(timeStep);
@@ -414,15 +406,15 @@ public sealed class BSPrim : PhysicsActor
414 _velocity = value; 406 _velocity = value;
415 _scene.TaintedObject("BSPrim.setVelocity", delegate() 407 _scene.TaintedObject("BSPrim.setVelocity", delegate()
416 { 408 {
417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 409 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 410 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity);
419 }); 411 });
420 } 412 }
421 } 413 }
422 public override OMV.Vector3 Torque { 414 public override OMV.Vector3 Torque {
423 get { return _torque; } 415 get { return _torque; }
424 set { _torque = value; 416 set { _torque = value;
425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 417 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
426 } 418 }
427 } 419 }
428 public override float CollisionScore { 420 public override float CollisionScore {
@@ -436,10 +428,10 @@ public sealed class BSPrim : PhysicsActor
436 } 428 }
437 public override OMV.Quaternion Orientation { 429 public override OMV.Quaternion Orientation {
438 get { 430 get {
439 if (!_linkset.IsRoot(this)) 431 if (!Linkset.IsRoot(this))
440 { 432 {
441 // Children move around because tied to parent. Get a fresh value. 433 // Children move around because tied to parent. Get a fresh value.
442 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); 434 _orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr);
443 } 435 }
444 return _orientation; 436 return _orientation;
445 } 437 }
@@ -449,15 +441,14 @@ public sealed class BSPrim : PhysicsActor
449 _scene.TaintedObject("BSPrim.setOrientation", delegate() 441 _scene.TaintedObject("BSPrim.setOrientation", delegate()
450 { 442 {
451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 443 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 444 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 445 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
454 }); 446 });
455 } 447 }
456 } 448 }
457 public override int PhysicsActorType { 449 public override int PhysicsActorType {
458 get { return _physicsActorType; } 450 get { return _physicsActorType; }
459 set { _physicsActorType = value; 451 set { _physicsActorType = value; }
460 }
461 } 452 }
462 public override bool IsPhysical { 453 public override bool IsPhysical {
463 get { return _isPhysical; } 454 get { return _isPhysical; }
@@ -484,30 +475,139 @@ public sealed class BSPrim : PhysicsActor
484 475
485 // Make gravity work if the object is physical and not selected 476 // Make gravity work if the object is physical and not selected
486 // No locking here because only called when it is safe 477 // No locking here because only called when it is safe
478 // There are four flags we're interested in:
479 // IsStatic: Object does not move, otherwise the object has mass and moves
480 // isSolid: other objects bounce off of this object
481 // isVolumeDetect: other objects pass through but can generate collisions
482 // collisionEvents: whether this object returns collision events
487 private void SetObjectDynamic() 483 private void SetObjectDynamic()
488 { 484 {
489 // RA: remove this for the moment. 485 // If it's becoming dynamic, it will need hullness
490 // The problem is that dynamic objects are hulls so if we are becoming physical 486 VerifyCorrectPhysicalShape();
491 // the shape has to be checked and possibly built. 487 UpdatePhysicalParameters();
492 // Maybe a VerifyCorrectPhysicalShape() routine? 488 }
493 // RecreateGeomAndObject();
494 489
490 private void UpdatePhysicalParameters()
491 {
492 /*
495 // Bullet wants static objects to have a mass of zero 493 // Bullet wants static objects to have a mass of zero
496 float mass = IsStatic ? 0f : _mass; 494 float mass = IsStatic ? 0f : _mass;
497 495
498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
497 */
498 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr);
499
500 // Set up the object physicalness (does gravity and collisions move this object)
501 MakeDynamic(IsStatic);
502
503 // Make solid or not (do things bounce off or pass through this object)
504 MakeSolid(IsSolid);
505
506 // Arrange for collisions events if the simulator wants them
507 EnableCollisions(SubscribedEvents());
508
509 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr);
499 510
500 // recompute any linkset parameters 511 // Recompute any linkset parameters.
501 _linkset.Refresh(this); 512 // When going from non-physical to physical, this re-enables the constraints that
513 // had been automatically disabled when the mass was set to zero.
514 Linkset.Refresh(this);
502 515
503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); 516 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}",
504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); 517 LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags);
518 }
519
520 // "Making dynamic" means changing to and from static.
521 // When static, gravity does not effect the object and it is fixed in space.
522 // When dynamic, the object can fall and be pushed by others.
523 // This is independent of its 'solidness' which controls what passes through
524 // this object and what interacts with it.
525 private void MakeDynamic(bool makeStatic)
526 {
527 if (makeStatic)
528 {
529 // Become a Bullet 'static' object type
530 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
531 // Stop all movement
532 BulletSimAPI.ClearAllForces2(BSBody.Ptr);
533 // Center of mass is at the center of the object
534 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.Ptr, _position, _orientation);
535 // Mass is zero which disables a bunch of physics stuff in Bullet
536 BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero);
537 // There is no inertia in a static object
538 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
539 // There can be special things needed for implementing linksets
540 Linkset.MakeStatic(this);
541 // The activation state is 'sleeping' so Bullet will not try to act on it
542 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING);
543 }
544 else
545 {
546 // Not a Bullet static object
547 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
548
549 // Set various physical properties so internal things will get computed correctly as they are set
550 BulletSimAPI.SetFriction2(BSBody.Ptr, Scene.Params.defaultFriction);
551 BulletSimAPI.SetRestitution2(BSBody.Ptr, Scene.Params.defaultRestitution);
552 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
553 BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
554 BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
555 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
556
557 // A dynamic object has mass
558 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr);
559 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass);
560 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia);
561 // Inertia is based on our new mass
562 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
563
564 // Various values for simulation limits
565 BulletSimAPI.SetDamping2(BSBody.Ptr, Scene.Params.linearDamping, Scene.Params.angularDamping);
566 BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, Scene.Params.deactivationTime);
567 BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, Scene.Params.linearSleepingThreshold, Scene.Params.angularSleepingThreshold);
568 BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, Scene.Params.contactProcessingThreshold);
569
570 // There can be special things needed for implementing linksets
571 Linkset.MakeDynamic(this);
572
573 // Force activation of the object so Bullet will act on it.
574 BulletSimAPI.Activate2(BSBody.Ptr, true);
575 }
576 }
577
578 // "Making solid" means that other object will not pass through this object.
579 private void MakeSolid(bool makeSolid)
580 {
581 if (makeSolid)
582 {
583 // Easy in Bullet -- just remove the object flag that controls collision response
584 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
585 }
586 else
587 {
588 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
589 }
590 }
591
592 // Turn on or off the flag controlling whether collision events are returned to the simulator.
593 private void EnableCollisions(bool wantsCollisionEvents)
594 {
595 if (wantsCollisionEvents)
596 {
597 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
598 }
599 else
600 {
601 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
602 }
505 } 603 }
506 604
507 // prims don't fly 605 // prims don't fly
508 public override bool Flying { 606 public override bool Flying {
509 get { return _flying; } 607 get { return _flying; }
510 set { _flying = value; } 608 set {
609 _flying = value;
610 }
511 } 611 }
512 public override bool SetAlwaysRun { 612 public override bool SetAlwaysRun {
513 get { return _setAlwaysRun; } 613 get { return _setAlwaysRun; }
@@ -558,8 +658,8 @@ public sealed class BSPrim : PhysicsActor
558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 658 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 659 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
560 { 660 {
561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 661 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 662 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity);
563 }); 663 });
564 } 664 }
565 } 665 }
@@ -575,8 +675,11 @@ public sealed class BSPrim : PhysicsActor
575 _buoyancy = value; 675 _buoyancy = value;
576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 676 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
577 { 677 {
578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 678 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 679 // Buoyancy is faked by changing the gravity applied to the object
680 float grav = Scene.Params.gravity * (1f - _buoyancy);
681 BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav));
682 // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
580 }); 683 });
581 } 684 }
582 } 685 }
@@ -624,7 +727,7 @@ public sealed class BSPrim : PhysicsActor
624 } 727 }
625 else 728 else
626 { 729 {
627 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 730 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
628 return; 731 return;
629 } 732 }
630 _scene.TaintedObject("BSPrim.AddForce", delegate() 733 _scene.TaintedObject("BSPrim.AddForce", delegate()
@@ -638,17 +741,18 @@ public sealed class BSPrim : PhysicsActor
638 } 741 }
639 m_accumulatedForces.Clear(); 742 m_accumulatedForces.Clear();
640 } 743 }
641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 744 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); 745 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
746 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum);
643 }); 747 });
644 } 748 }
645 749
646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 750 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 751 DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
648 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 752 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
649 } 753 }
650 public override void SetMomentum(OMV.Vector3 momentum) { 754 public override void SetMomentum(OMV.Vector3 momentum) {
651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 755 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
652 } 756 }
653 public override void SubscribeEvents(int ms) { 757 public override void SubscribeEvents(int ms) {
654 _subscribedEventsMs = ms; 758 _subscribedEventsMs = ms;
@@ -659,7 +763,7 @@ public sealed class BSPrim : PhysicsActor
659 763
660 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() 764 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
661 { 765 {
662 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 766 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
663 }); 767 });
664 } 768 }
665 } 769 }
@@ -667,7 +771,7 @@ public sealed class BSPrim : PhysicsActor
667 _subscribedEventsMs = 0; 771 _subscribedEventsMs = 0;
668 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() 772 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
669 { 773 {
670 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 774 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
671 }); 775 });
672 } 776 }
673 public override bool SubscribedEvents() { 777 public override bool SubscribedEvents() {
@@ -974,39 +1078,47 @@ public sealed class BSPrim : PhysicsActor
974 }// end CalculateMass 1078 }// end CalculateMass
975 #endregion Mass Calculation 1079 #endregion Mass Calculation
976 1080
977 // Create the geometry information in Bullet for later use 1081 // Create the geometry information in Bullet for later use.
978 // The objects needs a hull if it's physical otherwise a mesh is enough 1082 // The objects needs a hull if it's physical otherwise a mesh is enough.
979 // No locking here because this is done when we know physics is not simulating 1083 // No locking here because this is done when we know physics is not simulating.
980 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used 1084 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
981 // Returns 'true' if the geometry was rebuilt 1085 // Returns 'true' if the geometry was rebuilt.
1086 // Called at taint-time!
982 private bool CreateGeom(bool forceRebuild) 1087 private bool CreateGeom(bool forceRebuild)
983 { 1088 {
984 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
985 bool ret = false; 1089 bool ret = false;
986 if (!_scene.NeedsMeshing(_pbs)) 1090 bool haveShape = false;
1091
1092 // If the prim attributes are simple, this could be a simple Bullet native shape
1093 if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim)
1094 || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0
1095 && _pbs.ProfileHollow == 0
1096 && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0
1097 && _pbs.PathBegin == 0 && _pbs.PathEnd == 0
1098 && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0
1099 && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100
1100 && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) )
987 { 1101 {
988 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 1102 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
989 { 1103 {
990 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 1104 haveShape = true;
991 // { 1105 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
992 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 1106 {
993 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 1107 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
994 { 1108 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
995 // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); 1109 // Bullet native objects are scaled by the Bullet engine so pass the size in
996 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 1110 _scale = _size;
997 // Bullet native objects are scaled by the Bullet engine so pass the size in 1111 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
998 _scale = _size; 1112 ret = true;
999 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1113 }
1000 ret = true;
1001 }
1002 // }
1003 } 1114 }
1004 else 1115 else
1005 { 1116 {
1006 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1117 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1118 haveShape = true;
1007 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1119 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1008 { 1120 {
1009 // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); 1121 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
1010 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1122 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
1011 _scale = _size; 1123 _scale = _size;
1012 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1124 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@@ -1014,16 +1126,16 @@ public sealed class BSPrim : PhysicsActor
1014 } 1126 }
1015 } 1127 }
1016 } 1128 }
1017 else 1129 // If a simple shape isn't happening, create a mesh and possibly a hull
1130 if (!haveShape)
1018 { 1131 {
1019 if (IsPhysical) 1132 if (IsPhysical)
1020 { 1133 {
1021 if (forceRebuild || _hullKey == 0) 1134 if (forceRebuild || _hullKey == 0)
1022 { 1135 {
1023 // physical objects require a hull for interaction. 1136 // physical objects require a hull for interaction.
1024 // This will create the mesh if it doesn't already exist 1137 // This also creates the mesh if it doesn't already exist
1025 CreateGeomHull(); 1138 ret = CreateGeomHull();
1026 ret = true;
1027 } 1139 }
1028 } 1140 }
1029 else 1141 else
@@ -1031,8 +1143,7 @@ public sealed class BSPrim : PhysicsActor
1031 if (forceRebuild || _meshKey == 0) 1143 if (forceRebuild || _meshKey == 0)
1032 { 1144 {
1033 // Static (non-physical) objects only need a mesh for bumping into 1145 // Static (non-physical) objects only need a mesh for bumping into
1034 CreateGeomMesh(); 1146 ret = CreateGeomMesh();
1035 ret = true;
1036 } 1147 }
1037 } 1148 }
1038 } 1149 }
@@ -1040,21 +1151,30 @@ public sealed class BSPrim : PhysicsActor
1040 } 1151 }
1041 1152
1042 // No locking here because this is done when we know physics is not simulating 1153 // No locking here because this is done when we know physics is not simulating
1043 private void CreateGeomMesh() 1154 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1155 // Called at taint-time!
1156 private bool CreateGeomMesh()
1044 { 1157 {
1045 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1158 // level of detail based on size and type of the object
1159 float lod = _scene.MeshLOD;
1160 if (_pbs.SculptEntry)
1161 lod = _scene.SculptLOD;
1162 float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z));
1163 if (maxAxis > _scene.MeshMegaPrimThreshold)
1164 lod = _scene.MeshMegaPrimLOD;
1165
1046 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); 1166 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
1047 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); 1167 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
1048 1168
1049 // if this new shape is the same as last time, don't recreate the mesh 1169 // if this new shape is the same as last time, don't recreate the mesh
1050 if (_meshKey == newMeshKey) return; 1170 if (_meshKey == newMeshKey) return false;
1051 1171
1052 // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); 1172 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1053 // Since we're recreating new, get rid of any previously generated shape 1173 // Since we're recreating new, get rid of any previously generated shape
1054 if (_meshKey != 0) 1174 if (_meshKey != 0)
1055 { 1175 {
1056 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1176 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1057 // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1177 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1058 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1178 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1059 _mesh = null; 1179 _mesh = null;
1060 _meshKey = 0; 1180 _meshKey = 0;
@@ -1084,27 +1204,27 @@ public sealed class BSPrim : PhysicsActor
1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1204 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1085 // meshes are already scaled by the meshmerizer 1205 // meshes are already scaled by the meshmerizer
1086 _scale = new OMV.Vector3(1f, 1f, 1f); 1206 _scale = new OMV.Vector3(1f, 1f, 1f);
1087 // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); 1207 return true;
1088 return;
1089 } 1208 }
1090 1209
1091 // No locking here because this is done when we know physics is not simulating 1210 // No locking here because this is done when we know physics is not simulating
1092 private void CreateGeomHull() 1211 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1212 private bool CreateGeomHull()
1093 { 1213 {
1094 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1214 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1095 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); 1215 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
1096 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); 1216 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
1097 1217
1098 // if the hull hasn't changed, don't rebuild it 1218 // if the hull hasn't changed, don't rebuild it
1099 if (newHullKey == _hullKey) return; 1219 if (newHullKey == _hullKey) return false;
1100 1220
1101 // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); 1221 DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1102 1222
1103 // Since we're recreating new, get rid of any previously generated shape 1223 // Since we're recreating new, get rid of any previously generated shape
1104 if (_hullKey != 0) 1224 if (_hullKey != 0)
1105 { 1225 {
1106 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1226 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1107 // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); 1227 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1108 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1228 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1109 _hullKey = 0; 1229 _hullKey = 0;
1110 } 1230 }
@@ -1198,8 +1318,8 @@ public sealed class BSPrim : PhysicsActor
1198 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1318 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1199 // meshes are already scaled by the meshmerizer 1319 // meshes are already scaled by the meshmerizer
1200 _scale = new OMV.Vector3(1f, 1f, 1f); 1320 _scale = new OMV.Vector3(1f, 1f, 1f);
1201 // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); 1321 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1202 return; 1322 return true;
1203 } 1323 }
1204 1324
1205 // Callback from convex hull creater with a newly created hull. 1325 // Callback from convex hull creater with a newly created hull.
@@ -1210,6 +1330,19 @@ public sealed class BSPrim : PhysicsActor
1210 return; 1330 return;
1211 } 1331 }
1212 1332
1333 private void VerifyCorrectPhysicalShape()
1334 {
1335 if (!IsStatic)
1336 {
1337 // if not static, it will need a hull to efficiently collide with things
1338 if (_hullKey == 0)
1339 {
1340 CreateGeomAndObject(false);
1341 }
1342
1343 }
1344 }
1345
1213 // Create an object in Bullet if it has not already been created 1346 // Create an object in Bullet if it has not already been created
1214 // No locking here because this is done when the physics engine is not simulating 1347 // No locking here because this is done when the physics engine is not simulating
1215 // Returns 'true' if an object was actually created. 1348 // Returns 'true' if an object was actually created.
@@ -1223,8 +1356,9 @@ public sealed class BSPrim : PhysicsActor
1223 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); 1356 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1224 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1357 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1225 1358
1226 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1359 // the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
1227 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 1360 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1361 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
1228 1362
1229 return ret; 1363 return ret;
1230 } 1364 }
@@ -1248,15 +1382,20 @@ public sealed class BSPrim : PhysicsActor
1248 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1382 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1249 } 1383 }
1250 1384
1251
1252 // Rebuild the geometry and object. 1385 // Rebuild the geometry and object.
1253 // This is called when the shape changes so we need to recreate the mesh/hull. 1386 // This is called when the shape changes so we need to recreate the mesh/hull.
1254 // No locking here because this is done when the physics engine is not simulating 1387 // No locking here because this is done when the physics engine is not simulating
1255 private void RecreateGeomAndObject() 1388 private void CreateGeomAndObject(bool forceRebuild)
1256 { 1389 {
1257 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); 1390 // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild);
1258 if (CreateGeom(true)) 1391 // Create the geometry that will make up the object
1392 if (CreateGeom(forceRebuild))
1393 {
1394 // Create the object and place it into the world
1259 CreateObject(); 1395 CreateObject();
1396 // Make sure the properties are set on the new object
1397 UpdatePhysicalParameters();
1398 }
1260 return; 1399 return;
1261 } 1400 }
1262 1401
@@ -1277,7 +1416,7 @@ public sealed class BSPrim : PhysicsActor
1277 const float ACCELERATION_TOLERANCE = 0.01f; 1416 const float ACCELERATION_TOLERANCE = 0.01f;
1278 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1417 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1279 1418
1280 public void UpdateProperties(EntityProperties entprop) 1419 public override void UpdateProperties(EntityProperties entprop)
1281 { 1420 {
1282 /* 1421 /*
1283 UpdatedProperties changed = 0; 1422 UpdatedProperties changed = 0;
@@ -1325,7 +1464,7 @@ public sealed class BSPrim : PhysicsActor
1325 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1464 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1326 1465
1327 // Updates only for individual prims and for the root object of a linkset. 1466 // Updates only for individual prims and for the root object of a linkset.
1328 if (_linkset.IsRoot(this)) 1467 if (Linkset.IsRoot(this))
1329 { 1468 {
1330 // Assign to the local variables so the normal set action does not happen 1469 // Assign to the local variables so the normal set action does not happen
1331 _position = entprop.Position; 1470 _position = entprop.Position;
@@ -1334,17 +1473,17 @@ public sealed class BSPrim : PhysicsActor
1334 _acceleration = entprop.Acceleration; 1473 _acceleration = entprop.Acceleration;
1335 _rotationalVelocity = entprop.RotationalVelocity; 1474 _rotationalVelocity = entprop.RotationalVelocity;
1336 1475
1337 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1476 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1477 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1339 // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1478
1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1479 // BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr);
1341 1480
1342 base.RequestPhysicsterseUpdate(); 1481 base.RequestPhysicsterseUpdate();
1343 } 1482 }
1344 /* 1483 /*
1345 else 1484 else
1346 { 1485 {
1347 // For debugging, we also report the movement of children 1486 // For debugging, we can also report the movement of children
1348 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1487 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1349 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1488 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1350 entprop.Acceleration, entprop.RotationalVelocity); 1489 entprop.Acceleration, entprop.RotationalVelocity);
@@ -1353,36 +1492,45 @@ public sealed class BSPrim : PhysicsActor
1353 } 1492 }
1354 1493
1355 // I've collided with something 1494 // I've collided with something
1495 // Called at taint time from within the Step() function
1356 CollisionEventUpdate collisionCollection; 1496 CollisionEventUpdate collisionCollection;
1357 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 1497 public override bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1358 { 1498 {
1359 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 1499 bool ret = false;
1360 1500
1361 // The following lines make IsColliding() and IsCollidingGround() work 1501 // The following lines make IsColliding() and IsCollidingGround() work
1362 _collidingStep = _scene.SimulationStep; 1502 _collidingStep = Scene.SimulationStep;
1363 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) 1503 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
1364 { 1504 {
1365 _collidingGroundStep = _scene.SimulationStep; 1505 _collidingGroundStep = Scene.SimulationStep;
1366 } 1506 }
1367 1507
1368 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); 1508 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1369 1509
1370 // if someone is subscribed to collision events.... 1510 // prims in the same linkset cannot collide with each other
1371 if (_subscribedEventsMs != 0) { 1511 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
1512 {
1513 return ret;
1514 }
1515
1516 // if someone has subscribed for collision events....
1517 if (SubscribedEvents()) {
1372 // throttle the collisions to the number of milliseconds specified in the subscription 1518 // throttle the collisions to the number of milliseconds specified in the subscription
1373 int nowTime = _scene.SimulationNowTime; 1519 int nowTime = Scene.SimulationNowTime;
1374 if (nowTime >= _nextCollisionOkTime) { 1520 if (nowTime >= _nextCollisionOkTime) {
1375 _nextCollisionOkTime = nowTime + _subscribedEventsMs; 1521 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1376 1522
1377 if (collisionCollection == null) 1523 if (collisionCollection == null)
1378 collisionCollection = new CollisionEventUpdate(); 1524 collisionCollection = new CollisionEventUpdate();
1379 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 1525 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1526 ret = true;
1380 } 1527 }
1381 } 1528 }
1529 return ret;
1382 } 1530 }
1383 1531
1384 // The scene is telling us it's time to pass our collected collisions into the simulator 1532 // The scene is telling us it's time to pass our collected collisions into the simulator
1385 public void SendCollisions() 1533 public override void SendCollisions()
1386 { 1534 {
1387 if (collisionCollection != null && collisionCollection.Count > 0) 1535 if (collisionCollection != null && collisionCollection.Count > 0)
1388 { 1536 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index a31c578..52997dd 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,8 +39,6 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Debug linkset
43// Test with multiple regions in one simulator
44// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) 42// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
45// Test sculpties 43// Test sculpties
46// Compute physics FPS reasonably 44// Compute physics FPS reasonably
@@ -54,13 +52,10 @@ using OpenMetaverse;
54// Use collision masks for collision with terrain and phantom objects 52// Use collision masks for collision with terrain and phantom objects
55// Check out llVolumeDetect. Must do something for that. 53// Check out llVolumeDetect. Must do something for that.
56// Should prim.link() and prim.delink() membership checking happen at taint time? 54// Should prim.link() and prim.delink() membership checking happen at taint time?
57// changing the position and orientation of a linked prim must rebuild the constraint with the root.
58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 55// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
61// Implement LockAngularMotion 57// Implement LockAngularMotion
62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
63// Does NeedsMeshing() really need to exclude all the different shapes?
64// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 59// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
65// Add PID movement operations. What does ScenePresence.MoveToTarget do? 60// Add PID movement operations. What does ScenePresence.MoveToTarget do?
66// Check terrain size. 128 or 127? 61// Check terrain size. 128 or 127?
@@ -73,62 +68,56 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 68 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 69 private static readonly string LogHeader = "[BULLETS SCENE]";
75 70
76 public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } 71 // The name of the region we're working for.
72 public string RegionName { get; private set; }
77 73
78 public string BulletSimVersion = "?"; 74 public string BulletSimVersion = "?";
79 75
80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 76 public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>();
81 private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>(); 77
82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); 78 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
83 private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>(); 79 // Following is a kludge and can be removed when avatar animation updating is
84 private List<BSPrim> m_vehicles = new List<BSPrim>(); 80 // moved to a better place.
85 private float[] m_heightMap; 81 private HashSet<BSPhysObject> m_avatarsWithCollisions = new HashSet<BSPhysObject>();
86 private float m_waterLevel; 82
87 private uint m_worldID; 83 // List of all the objects that have vehicle properties and should be called
88 public uint WorldID { get { return m_worldID; } } 84 // to update each physics step.
85 private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
89 86
90 // let my minuions use my logger 87 // let my minuions use my logger
91 public ILog Logger { get { return m_log; } } 88 public ILog Logger { get { return m_log; } }
92 89
93 private bool m_initialized = false; 90 // If non-zero, the number of simulation steps between calls to the physics
94 91 // engine to output detailed physics stats. Debug logging level must be on also.
95 private int m_detailedStatsStep = 0; 92 private int m_detailedStatsStep = 0;
96 93
97 public IMesher mesher; 94 public IMesher mesher;
98 private float m_meshLOD; 95 // Level of Detail values kept as float because that's what the Meshmerizer wants
99 public float MeshLOD 96 public float MeshLOD { get; private set; }
100 { 97 public float MeshMegaPrimLOD { get; private set; }
101 get { return m_meshLOD; } 98 public float MeshMegaPrimThreshold { get; private set; }
102 } 99 public float SculptLOD { get; private set; }
103 private float m_sculptLOD;
104 public float SculptLOD
105 {
106 get { return m_sculptLOD; }
107 }
108 100
109 private BulletSim m_worldSim; 101 public uint WorldID { get; private set; }
110 public BulletSim World 102 public BulletSim World { get; private set; }
111 {
112 get { return m_worldSim; }
113 }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
119 103
104 // All the constraints that have been allocated in this instance.
105 public BSConstraintCollection Constraints { get; private set; }
106
107 // Simulation parameters
120 private int m_maxSubSteps; 108 private int m_maxSubSteps;
121 private float m_fixedTimeStep; 109 private float m_fixedTimeStep;
122 private long m_simulationStep = 0; 110 private long m_simulationStep = 0;
123 public long SimulationStep { get { return m_simulationStep; } } 111 public long SimulationStep { get { return m_simulationStep; } }
124 112
125 public float LastSimulatedTimestep { get; private set; }
126
127 // A value of the time now so all the collision and update routines do not have to get their own 113 // A value of the time now so all the collision and update routines do not have to get their own
128 // Set to 'now' just before all the prims and actors are called for collisions and updates 114 // Set to 'now' just before all the prims and actors are called for collisions and updates
129 private int m_simulationNowTime; 115 public int SimulationNowTime { get; private set; }
130 public int SimulationNowTime { get { return m_simulationNowTime; } } 116
117 // True if initialized and ready to do simulation steps
118 private bool m_initialized = false;
131 119
120 // Pinned memory used to pass step information between managed and unmanaged
132 private int m_maxCollisionsPerFrame; 121 private int m_maxCollisionsPerFrame;
133 private CollisionDesc[] m_collisionArray; 122 private CollisionDesc[] m_collisionArray;
134 private GCHandle m_collisionArrayPinnedHandle; 123 private GCHandle m_collisionArrayPinnedHandle;
@@ -137,14 +126,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
137 private EntityProperties[] m_updateArray; 126 private EntityProperties[] m_updateArray;
138 private GCHandle m_updateArrayPinnedHandle; 127 private GCHandle m_updateArrayPinnedHandle;
139 128
140 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 129 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
141 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes 130 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
142 131
143 public float PID_D { get; private set; } // derivative 132 public float PID_D { get; private set; } // derivative
144 public float PID_P { get; private set; } // proportional 133 public float PID_P { get; private set; } // proportional
145 134
146 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 135 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
147 public const uint GROUNDPLANE_ID = 1; 136 public const uint GROUNDPLANE_ID = 1;
137 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
138
139 private float m_waterLevel;
140 public BSTerrainManager TerrainManager { get; private set; }
148 141
149 public ConfigurationParameters Params 142 public ConfigurationParameters Params
150 { 143 {
@@ -154,13 +147,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
154 { 147 {
155 get { return new Vector3(0f, 0f, Params.gravity); } 148 get { return new Vector3(0f, 0f, Params.gravity); }
156 } 149 }
157 150 // Just the Z value of the gravity
158 private float m_maximumObjectMass; 151 public float DefaultGravityZ
159 public float MaximumObjectMass
160 { 152 {
161 get { return m_maximumObjectMass; } 153 get { return Params.gravity; }
162 } 154 }
163 155
156 public float MaximumObjectMass { get; private set; }
157
158 // When functions in the unmanaged code must be called, it is only
159 // done at a known time just before the simulation step. The taint
160 // system saves all these function calls and executes them in
161 // order before the simulation.
164 public delegate void TaintCallback(); 162 public delegate void TaintCallback();
165 private struct TaintCallbackEntry 163 private struct TaintCallbackEntry
166 { 164 {
@@ -172,15 +170,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
172 callback = c; 170 callback = c;
173 } 171 }
174 } 172 }
173 private Object _taintLock = new Object(); // lock for using the next object
175 private List<TaintCallbackEntry> _taintedObjects; 174 private List<TaintCallbackEntry> _taintedObjects;
176 private Object _taintLock = new Object();
177 175
178 // A pointer to an instance if this structure is passed to the C++ code 176 // A pointer to an instance if this structure is passed to the C++ code
177 // Used to pass basic configuration values to the unmanaged code.
179 ConfigurationParameters[] m_params; 178 ConfigurationParameters[] m_params;
180 GCHandle m_paramsHandle; 179 GCHandle m_paramsHandle;
181 180
182 public bool ShouldDebugLog { get; private set; } 181 // Handle to the callback used by the unmanaged code to call into the managed code.
183 182 // Used for debug logging.
183 // Need to store the handle in a persistant variable so it won't be freed.
184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
185 185
186 // Sometimes you just have to log everything. 186 // Sometimes you just have to log everything.
@@ -189,13 +189,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters
189 private string m_physicsLoggingDir; 189 private string m_physicsLoggingDir;
190 private string m_physicsLoggingPrefix; 190 private string m_physicsLoggingPrefix;
191 private int m_physicsLoggingFileMinutes; 191 private int m_physicsLoggingFileMinutes;
192 // 'true' of the vehicle code is to log lots of details
193 public bool VehicleLoggingEnabled { get; private set; }
192 194
193 private bool m_vehicleLoggingEnabled; 195 #region Construction and Initialization
194 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
195
196 public BSScene(string identifier) 196 public BSScene(string identifier)
197 { 197 {
198 m_initialized = false; 198 m_initialized = false;
199 // we are passed the name of the region we're working for.
200 RegionName = identifier;
199 } 201 }
200 202
201 public override void Initialise(IMesher meshmerizer, IConfigSource config) 203 public override void Initialise(IMesher meshmerizer, IConfigSource config)
@@ -213,6 +215,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
213 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; 215 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
214 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); 216 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
215 217
218 mesher = meshmerizer;
219 _taintedObjects = new List<TaintCallbackEntry>();
220
216 // Enable very detailed logging. 221 // Enable very detailed logging.
217 // By creating an empty logger when not logging, the log message invocation code 222 // By creating an empty logger when not logging, the log message invocation code
218 // can be left in and every call doesn't have to check for null. 223 // can be left in and every call doesn't have to check for null.
@@ -225,38 +230,43 @@ public class BSScene : PhysicsScene, IPhysicsParameters
225 PhysicsLogging = new Logging.LogWriter(); 230 PhysicsLogging = new Logging.LogWriter();
226 } 231 }
227 232
228 // Get the version of the DLL 233 // If Debug logging level, enable logging from the unmanaged code
229 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 234 m_DebugLogCallbackHandle = null;
230 // BulletSimVersion = BulletSimAPI.GetVersion();
231 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
232
233 // if Debug, enable logging from the unmanaged code
234 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 235 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
235 { 236 {
236 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 237 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
237 if (PhysicsLogging.Enabled) 238 if (PhysicsLogging.Enabled)
239 // The handle is saved in a variable to make sure it doesn't get freed after this call
238 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); 240 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
239 else 241 else
240 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 242 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
241 // the handle is saved in a variable to make sure it doesn't get freed after this call
242 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
243 } 243 }
244 244
245 _taintedObjects = new List<TaintCallbackEntry>(); 245 // Get the version of the DLL
246 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
247 // BulletSimVersion = BulletSimAPI.GetVersion();
248 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
246 249
247 mesher = meshmerizer; 250 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
248 // The bounding box for the simulated world 251 // a child in a mega-region.
252 // Turns out that Bullet really doesn't care about the extents of the simulated
253 // area. It tracks active objects no matter where they are.
249 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); 254 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
250 255
251 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 256 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
252 m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), 257 WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
253 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 258 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
254 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 259 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
260 m_DebugLogCallbackHandle);
255 261
256 // Initialization to support the transition to a new API which puts most of the logic 262 // Initialization to support the transition to a new API which puts most of the logic
257 // into the C# code so it is easier to modify and add to. 263 // into the C# code so it is easier to modify and add to.
258 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID)); 264 World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID));
259 m_constraintCollection = new BSConstraintCollection(World); 265
266 Constraints = new BSConstraintCollection(World);
267
268 TerrainManager = new BSTerrainManager(this);
269 TerrainManager.CreateInitialGroundPlaneAndTerrain();
260 270
261 m_initialized = true; 271 m_initialized = true;
262 } 272 }
@@ -281,10 +291,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
281 // Very detailed logging for physics debugging 291 // Very detailed logging for physics debugging
282 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 292 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
283 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); 293 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
284 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); 294 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
285 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); 295 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
286 // Very detailed logging for vehicle debugging 296 // Very detailed logging for vehicle debugging
287 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 297 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
298
299 // Do any replacements in the parameters
300 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
288 } 301 }
289 } 302 }
290 } 303 }
@@ -316,6 +329,38 @@ public class BSScene : PhysicsScene, IPhysicsParameters
316 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); 329 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
317 } 330 }
318 331
332 public override void Dispose()
333 {
334 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
335
336 // make sure no stepping happens while we're deleting stuff
337 m_initialized = false;
338
339 TerrainManager.ReleaseGroundPlaneAndTerrain();
340
341 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
342 {
343 kvp.Value.Destroy();
344 }
345 PhysObjects.Clear();
346
347 // Now that the prims are all cleaned up, there should be no constraints left
348 if (Constraints != null)
349 {
350 Constraints.Dispose();
351 Constraints = null;
352 }
353
354 // Anything left in the unmanaged code should be cleaned out
355 BulletSimAPI.Shutdown(WorldID);
356
357 // Not logging any more
358 PhysicsLogging.Close();
359 }
360 #endregion // Construction and Initialization
361
362 #region Prim and Avatar addition and removal
363
319 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 364 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
320 { 365 {
321 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader); 366 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
@@ -329,7 +374,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
329 if (!m_initialized) return null; 374 if (!m_initialized) return null;
330 375
331 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 376 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
332 lock (m_avatars) m_avatars.Add(localID, actor); 377 lock (PhysObjects) PhysObjects.Add(localID, actor);
378
379 // TODO: Remove kludge someday.
380 // We must generate a collision for avatars whether they collide or not.
381 // This is required by OpenSim to update avatar animations, etc.
382 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor);
383
333 return actor; 384 return actor;
334 } 385 }
335 386
@@ -344,7 +395,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
344 { 395 {
345 try 396 try
346 { 397 {
347 lock (m_avatars) m_avatars.Remove(actor.LocalID); 398 lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
399 // Remove kludge someday
400 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor);
348 } 401 }
349 catch (Exception e) 402 catch (Exception e)
350 { 403 {
@@ -362,11 +415,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
362 BSPrim bsprim = prim as BSPrim; 415 BSPrim bsprim = prim as BSPrim;
363 if (bsprim != null) 416 if (bsprim != null)
364 { 417 {
365 // DetailLog("{0},RemovePrim,call", bsprim.LocalID); 418 DetailLog("{0},RemovePrim,call", bsprim.LocalID);
366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 419 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
367 try 420 try
368 { 421 {
369 lock (m_prims) m_prims.Remove(bsprim.LocalID); 422 lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
370 } 423 }
371 catch (Exception e) 424 catch (Exception e)
372 { 425 {
@@ -388,10 +441,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
388 441
389 if (!m_initialized) return null; 442 if (!m_initialized) return null;
390 443
391 // DetailLog("{0},AddPrimShape,call", localID); 444 DetailLog("{0},AddPrimShape,call", localID);
392 445
393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 446 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
394 lock (m_prims) m_prims.Add(localID, prim); 447 lock (PhysObjects) PhysObjects.Add(localID, prim);
395 return prim; 448 return prim;
396 } 449 }
397 450
@@ -400,6 +453,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
400 // information call is not needed. 453 // information call is not needed.
401 public override void AddPhysicsActorTaint(PhysicsActor prim) { } 454 public override void AddPhysicsActorTaint(PhysicsActor prim) { }
402 455
456 #endregion // Prim and Avatar addition and removal
457
458 #region Simulation
403 // Simulate one timestep 459 // Simulate one timestep
404 public override float Simulate(float timeStep) 460 public override float Simulate(float timeStep)
405 { 461 {
@@ -408,18 +464,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
408 int collidersCount = 0; 464 int collidersCount = 0;
409 IntPtr collidersPtr; 465 IntPtr collidersPtr;
410 466
411 LastSimulatedTimestep = timeStep;
412
413 // prevent simulation until we've been initialized 467 // prevent simulation until we've been initialized
414 if (!m_initialized) return 10.0f; 468 if (!m_initialized) return 5.0f;
415
416 int simulateStartTime = Util.EnvironmentTickCount();
417 469
418 // update the prim states while we know the physics engine is not busy 470 // update the prim states while we know the physics engine is not busy
471 int numTaints = _taintedObjects.Count;
419 ProcessTaints(); 472 ProcessTaints();
420 473
421 // Some of the prims operate with special vehicle properties 474 // Some of the prims operate with special vehicle properties
422 ProcessVehicles(timeStep); 475 ProcessVehicles(timeStep);
476 numTaints += _taintedObjects.Count;
423 ProcessTaints(); // the vehicles might have added taints 477 ProcessTaints(); // the vehicles might have added taints
424 478
425 // step the physical world one interval 479 // step the physical world one interval
@@ -427,15 +481,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
427 int numSubSteps = 0; 481 int numSubSteps = 0;
428 try 482 try
429 { 483 {
430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 484 numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 485 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
432 // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 486 DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}",
487 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
433 } 488 }
434 catch (Exception e) 489 catch (Exception e)
435 { 490 {
436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); 491 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
437 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 492 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
438 // updatedEntityCount = 0; 493 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
494 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
495 updatedEntityCount = 0;
439 collidersCount = 0; 496 collidersCount = 0;
440 } 497 }
441 498
@@ -443,7 +500,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
443 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 500 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
444 501
445 // Get a value for 'now' so all the collision and update routines don't have to get their own 502 // Get a value for 'now' so all the collision and update routines don't have to get their own
446 m_simulationNowTime = Util.EnvironmentTickCount(); 503 SimulationNowTime = Util.EnvironmentTickCount();
504
505 // This is a kludge to get avatar movement updates.
506 // ODE sends collisions for avatars even if there are have been no collisions. This updates
507 // avatar animations and stuff.
508 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
509 m_objectsWithCollisions = new HashSet<BSPhysObject>(m_avatarsWithCollisions);
447 510
448 // If there were collisions, process them by sending the event to the prim. 511 // If there were collisions, process them by sending the event to the prim.
449 // Collisions must be processed before updates. 512 // Collisions must be processed before updates.
@@ -462,19 +525,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
462 525
463 // The above SendCollision's batch up the collisions on the objects. 526 // The above SendCollision's batch up the collisions on the objects.
464 // Now push the collisions into the simulator. 527 // Now push the collisions into the simulator.
465 foreach (BSPrim bsp in m_primsWithCollisions) 528 foreach (BSPhysObject bsp in m_objectsWithCollisions)
466 bsp.SendCollisions(); 529 bsp.SendCollisions();
467 m_primsWithCollisions.Clear(); 530 m_objectsWithCollisions.Clear();
468
469 // This is a kludge to get avatar movement updated.
470 // Don't send collisions only if there were collisions -- send everytime.
471 // ODE sends collisions even if there are none and this is used to update
472 // avatar animations and stuff.
473 // foreach (BSCharacter bsc in m_avatarsWithCollisions)
474 // bsc.SendCollisions();
475 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
476 kvp.Value.SendCollisions();
477 m_avatarsWithCollisions.Clear();
478 531
479 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 532 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
480 if (updatedEntityCount > 0) 533 if (updatedEntityCount > 0)
@@ -482,17 +535,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
482 for (int ii = 0; ii < updatedEntityCount; ii++) 535 for (int ii = 0; ii < updatedEntityCount; ii++)
483 { 536 {
484 EntityProperties entprop = m_updateArray[ii]; 537 EntityProperties entprop = m_updateArray[ii];
485 BSPrim prim; 538 BSPhysObject pobj;
486 if (m_prims.TryGetValue(entprop.ID, out prim)) 539 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
487 {
488 prim.UpdateProperties(entprop);
489 continue;
490 }
491 BSCharacter actor;
492 if (m_avatars.TryGetValue(entprop.ID, out actor))
493 { 540 {
494 actor.UpdateProperties(entprop); 541 pobj.UpdateProperties(entprop);
495 continue;
496 } 542 }
497 } 543 }
498 } 544 }
@@ -506,79 +552,59 @@ public class BSScene : PhysicsScene, IPhysicsParameters
506 } 552 }
507 } 553 }
508 554
509 // this is a waste since the outside routine also calcuates the physics simulation 555 // The physics engine returns the number of milliseconds it simulated this call.
510 // period. TODO: There should be a way of computing physics frames from simulator computation. 556 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
511 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); 557 // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS.
512 // return (timeStep * (float)simulateTotalTime); 558 return numSubSteps * m_fixedTimeStep;
513
514 // TODO: FIX THIS: fps calculation possibly wrong.
515 // This calculation says 1/timeStep is the ideal frame rate. Any time added to
516 // that by the physics simulation gives a slower frame rate.
517 long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
518 if (totalSimulationTime >= timeStep)
519 return 0;
520 return 1f / (timeStep + totalSimulationTime);
521 } 559 }
522 560
523 // Something has collided 561 // Something has collided
524 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) 562 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
525 { 563 {
526 if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) 564 if (localID <= TerrainManager.HighestTerrainID)
527 { 565 {
528 return; // don't send collisions to the terrain 566 return; // don't send collisions to the terrain
529 } 567 }
530 568
531 ActorTypes type = ActorTypes.Prim; 569 BSPhysObject collider;
532 if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) 570 if (!PhysObjects.TryGetValue(localID, out collider))
533 type = ActorTypes.Ground; 571 {
534 else if (m_avatars.ContainsKey(collidingWith)) 572 // If the object that is colliding cannot be found, just ignore the collision.
535 type = ActorTypes.Agent;
536
537 BSPrim prim;
538 if (m_prims.TryGetValue(localID, out prim)) {
539 prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
540 m_primsWithCollisions.Add(prim);
541 return; 573 return;
542 } 574 }
543 BSCharacter actor; 575
544 if (m_avatars.TryGetValue(localID, out actor)) { 576 // The terrain is not in the physical object list so 'collidee'
545 actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); 577 // can be null when Collide() is called.
546 m_avatarsWithCollisions.Add(actor); 578 BSPhysObject collidee = null;
547 return; 579 PhysObjects.TryGetValue(collidingWith, out collidee);
580
581 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
582
583 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
584 {
585 // If a collision was posted, remember to send it to the simulator
586 m_objectsWithCollisions.Add(collider);
548 } 587 }
588
549 return; 589 return;
550 } 590 }
551 591
552 public override void GetResults() { } 592 #endregion // Simulation
553 593
554 public override void SetTerrain(float[] heightMap) { 594 public override void GetResults() { }
555 m_heightMap = heightMap;
556 this.TaintedObject("BSScene.SetTerrain", delegate()
557 {
558 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
559 });
560 }
561 595
562 // Someday we will have complex terrain with caves and tunnels 596 #region Terrain
563 // For the moment, it's flat and convex
564 public float GetTerrainHeightAtXYZ(Vector3 loc)
565 {
566 return GetTerrainHeightAtXY(loc.X, loc.Y);
567 }
568 597
569 public float GetTerrainHeightAtXY(float tX, float tY) 598 public override void SetTerrain(float[] heightMap) {
570 { 599 TerrainManager.SetTerrain(heightMap);
571 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
572 return 30;
573 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
574 } 600 }
575 601
576 public override void SetWaterLevel(float baseheight) 602 public override void SetWaterLevel(float baseheight)
577 { 603 {
578 m_waterLevel = baseheight; 604 m_waterLevel = baseheight;
579 // TODO: pass to physics engine so things will float?
580 } 605 }
581 public float GetWaterLevel() 606 // Someday....
607 public float GetWaterLevelAtXYZ(Vector3 loc)
582 { 608 {
583 return m_waterLevel; 609 return m_waterLevel;
584 } 610 }
@@ -588,39 +614,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters
588 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); 614 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
589 } 615 }
590 616
591 public override void Dispose() 617 // Although no one seems to check this, I do support combining.
618 public override bool SupportsCombining()
592 { 619 {
593 // m_log.DebugFormat("{0}: Dispose()", LogHeader); 620 return TerrainManager.SupportsCombining();
594 621 }
595 // make sure no stepping happens while we're deleting stuff 622 // This call says I am a child to region zero in a mega-region. 'pScene' is that
596 m_initialized = false; 623 // of region zero, 'offset' is my offset from regions zero's origin, and
597 624 // 'extents' is the largest XY that is handled in my region.
598 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 625 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
599 { 626 {
600 kvp.Value.Destroy(); 627 TerrainManager.Combine(pScene, offset, extents);
601 } 628 }
602 m_avatars.Clear();
603
604 foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
605 {
606 kvp.Value.Destroy();
607 }
608 m_prims.Clear();
609
610 // Now that the prims are all cleaned up, there should be no constraints left
611 if (m_constraintCollection != null)
612 {
613 m_constraintCollection.Dispose();
614 m_constraintCollection = null;
615 }
616
617 // Anything left in the unmanaged code should be cleaned out
618 BulletSimAPI.Shutdown(WorldID);
619 629
620 // Not logging any more 630 // Unhook all the combining that I know about.
621 PhysicsLogging.Close(); 631 public override void UnCombine(PhysicsScene pScene)
632 {
633 TerrainManager.UnCombine(pScene);
622 } 634 }
623 635
636 #endregion // Terrain
637
624 public override Dictionary<uint, float> GetTopColliders() 638 public override Dictionary<uint, float> GetTopColliders()
625 { 639 {
626 return new Dictionary<uint, float>(); 640 return new Dictionary<uint, float>();
@@ -628,121 +642,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
628 642
629 public override bool IsThreaded { get { return false; } } 643 public override bool IsThreaded { get { return false; } }
630 644
631 /// <summary>
632 /// Routine to figure out if we need to mesh this prim with our mesher
633 /// </summary>
634 /// <param name="pbs"></param>
635 /// <returns>true if the prim needs meshing</returns>
636 public bool NeedsMeshing(PrimitiveBaseShape pbs)
637 {
638 // most of this is redundant now as the mesher will return null if it cant mesh a prim
639 // but we still need to check for sculptie meshing being enabled so this is the most
640 // convenient place to do it for now...
641
642 // int iPropertiesNotSupportedDefault = 0;
643
644 if (pbs.SculptEntry && !_meshSculptedPrim)
645 {
646 // Render sculpties as boxes
647 return false;
648 }
649
650 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet
651 // can use an internal representation for the prim
652 if (!_forceSimplePrimMeshing)
653 {
654 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
655 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
656 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
657 {
658
659 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
660 && pbs.ProfileHollow == 0
661 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
662 && pbs.PathBegin == 0 && pbs.PathEnd == 0
663 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
664 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
665 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
666 {
667 return false;
668 }
669 }
670 }
671
672 /* TODO: verify that the mesher will now do all these shapes
673 if (pbs.ProfileHollow != 0)
674 iPropertiesNotSupportedDefault++;
675
676 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
677 iPropertiesNotSupportedDefault++;
678
679 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
680 iPropertiesNotSupportedDefault++;
681
682 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
683 iPropertiesNotSupportedDefault++;
684
685 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
686 iPropertiesNotSupportedDefault++;
687
688 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
689 iPropertiesNotSupportedDefault++;
690
691 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
692 iPropertiesNotSupportedDefault++;
693
694 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
695 iPropertiesNotSupportedDefault++;
696
697 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
698 iPropertiesNotSupportedDefault++;
699
700 // test for torus
701 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
702 {
703 if (pbs.PathCurve == (byte)Extrusion.Curve1)
704 {
705 iPropertiesNotSupportedDefault++;
706 }
707 }
708 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
709 {
710 if (pbs.PathCurve == (byte)Extrusion.Straight)
711 {
712 iPropertiesNotSupportedDefault++;
713 }
714 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
715 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
716 {
717 iPropertiesNotSupportedDefault++;
718 }
719 }
720 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
721 {
722 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
723 {
724 iPropertiesNotSupportedDefault++;
725 }
726 }
727 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
728 {
729 if (pbs.PathCurve == (byte)Extrusion.Straight)
730 {
731 iPropertiesNotSupportedDefault++;
732 }
733 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
734 {
735 iPropertiesNotSupportedDefault++;
736 }
737 }
738 if (iPropertiesNotSupportedDefault == 0)
739 {
740 return false;
741 }
742 */
743 return true;
744 }
745
746 // Calls to the PhysicsActors can't directly call into the physics engine 645 // Calls to the PhysicsActors can't directly call into the physics engine
747 // because it might be busy. We delay changes to a known time. 646 // because it might be busy. We delay changes to a known time.
748 // We rely on C#'s closure to save and restore the context for the delegate. 647 // We rely on C#'s closure to save and restore the context for the delegate.
@@ -751,7 +650,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
751 if (!m_initialized) return; 650 if (!m_initialized) return;
752 651
753 lock (_taintLock) 652 lock (_taintLock)
653 {
754 _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); 654 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
655 }
656
755 return; 657 return;
756 } 658 }
757 659
@@ -830,14 +732,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
830 // no locking because only called when physics engine is not busy 732 // no locking because only called when physics engine is not busy
831 private void ProcessVehicles(float timeStep) 733 private void ProcessVehicles(float timeStep)
832 { 734 {
833 foreach (BSPrim prim in m_vehicles) 735 foreach (BSPhysObject pobj in m_vehicles)
834 { 736 {
835 prim.StepVehicle(timeStep); 737 pobj.StepVehicle(timeStep);
836 } 738 }
837 } 739 }
838 #endregion Vehicles 740 #endregion Vehicles
839 741
840 #region Parameters 742 #region INI and command line parameter processing
841 743
842 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 744 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
843 delegate float ParamGet(BSScene scene); 745 delegate float ParamGet(BSScene scene);
@@ -888,25 +790,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
888 { 790 {
889 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", 791 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
890 ConfigurationParameters.numericTrue, 792 ConfigurationParameters.numericTrue,
891 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, 793 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
892 (s) => { return s.NumericBool(s._meshSculptedPrim); }, 794 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
893 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), 795 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
894 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", 796 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
895 ConfigurationParameters.numericFalse, 797 ConfigurationParameters.numericFalse,
896 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, 798 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
897 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, 799 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
898 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), 800 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
899 801
900 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 802 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
901 8f, 803 8f,
902 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, 804 (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
903 (s) => { return (float)s.m_meshLOD; }, 805 (s) => { return s.MeshLOD; },
904 (s,p,l,v) => { s.m_meshLOD = (int)v; } ), 806 (s,p,l,v) => { s.MeshLOD = v; } ),
905 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 807 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
808 16f,
809 (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
810 (s) => { return s.MeshMegaPrimLOD; },
811 (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
812 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
813 10f,
814 (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
815 (s) => { return s.MeshMegaPrimThreshold; },
816 (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
817 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
906 32f, 818 32f,
907 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, 819 (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
908 (s) => { return (float)s.m_sculptLOD; }, 820 (s) => { return s.SculptLOD; },
909 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), 821 (s,p,l,v) => { s.SculptLOD = v; } ),
910 822
911 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 823 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
912 10f, 824 10f,
@@ -930,9 +842,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
930 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), 842 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
931 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 843 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
932 10000.01f, 844 10000.01f,
933 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, 845 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
934 (s) => { return (float)s.m_maximumObjectMass; }, 846 (s) => { return (float)s.MaximumObjectMass; },
935 (s,p,l,v) => { s.m_maximumObjectMass = v; } ), 847 (s,p,l,v) => { s.MaximumObjectMass = v; } ),
936 848
937 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 849 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
938 2200f, 850 2200f,
@@ -976,42 +888,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
976 0f, 888 0f,
977 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, 889 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
978 (s) => { return s.m_params[0].linearDamping; }, 890 (s) => { return s.m_params[0].linearDamping; },
979 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), 891 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ),
980 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 892 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
981 0f, 893 0f,
982 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, 894 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
983 (s) => { return s.m_params[0].angularDamping; }, 895 (s) => { return s.m_params[0].angularDamping; },
984 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), 896 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ),
985 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 897 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
986 0.2f, 898 0.2f,
987 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, 899 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
988 (s) => { return s.m_params[0].deactivationTime; }, 900 (s) => { return s.m_params[0].deactivationTime; },
989 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), 901 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ),
990 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 902 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
991 0.8f, 903 0.8f,
992 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, 904 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
993 (s) => { return s.m_params[0].linearSleepingThreshold; }, 905 (s) => { return s.m_params[0].linearSleepingThreshold; },
994 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), 906 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
995 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 907 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
996 1.0f, 908 1.0f,
997 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, 909 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].angularSleepingThreshold; }, 910 (s) => { return s.m_params[0].angularSleepingThreshold; },
999 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), 911 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
1000 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 912 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1001 0f, // set to zero to disable 913 0f, // set to zero to disable
1002 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, 914 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1003 (s) => { return s.m_params[0].ccdMotionThreshold; }, 915 (s) => { return s.m_params[0].ccdMotionThreshold; },
1004 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), 916 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
1005 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 917 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1006 0f, 918 0f,
1007 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, 919 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1008 (s) => { return s.m_params[0].ccdSweptSphereRadius; }, 920 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1009 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), 921 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
1010 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 922 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1011 0.1f, 923 0.1f,
1012 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, 924 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1013 (s) => { return s.m_params[0].contactProcessingThreshold; }, 925 (s) => { return s.m_params[0].contactProcessingThreshold; },
1014 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), 926 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
1015 927
1016 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 928 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1017 0.5f, 929 0.5f,
@@ -1029,35 +941,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1029 (s) => { return s.m_params[0].terrainRestitution; }, 941 (s) => { return s.m_params[0].terrainRestitution; },
1030 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), 942 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
1031 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 943 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1032 0.5f, 944 0.2f,
1033 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 945 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1034 (s) => { return s.m_params[0].avatarFriction; }, 946 (s) => { return s.m_params[0].avatarFriction; },
1035 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), 947 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1036 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 948 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1037 60f, 949 60f,
1038 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, 950 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1039 (s) => { return s.m_params[0].avatarDensity; }, 951 (s) => { return s.m_params[0].avatarDensity; },
1040 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), 952 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
1041 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 953 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1042 0f, 954 0f,
1043 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, 955 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1044 (s) => { return s.m_params[0].avatarRestitution; }, 956 (s) => { return s.m_params[0].avatarRestitution; },
1045 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), 957 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1046 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 958 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
1047 0.37f, 959 0.37f,
1048 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, 960 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].avatarCapsuleRadius; }, 961 (s) => { return s.m_params[0].avatarCapsuleRadius; },
1050 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), 962 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
1051 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 963 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1052 1.5f, 964 1.5f,
1053 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, 965 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1054 (s) => { return s.m_params[0].avatarCapsuleHeight; }, 966 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1055 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), 967 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1056 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 968 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1057 0.1f, 969 0.1f,
1058 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, 970 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1059 (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, 971 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1060 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 972 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1061 973
1062 974
1063 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 975 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
@@ -1121,8 +1033,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1121 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, 1033 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1122 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, 1034 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1123 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), 1035 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1124 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", 1036 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1125 0.0f, 1037 0.1f,
1126 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, 1038 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1127 (s) => { return s.m_params[0].linkConstraintCFM; }, 1039 (s) => { return s.m_params[0].linkConstraintCFM; },
1128 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), 1040 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
@@ -1131,18 +1043,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1131 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, 1043 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1132 (s) => { return s.m_params[0].linkConstraintERP; }, 1044 (s) => { return s.m_params[0].linkConstraintERP; },
1133 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), 1045 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1046 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1047 40,
1048 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1050 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1134 1051
1135 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 1052 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1136 0f, 1053 0f,
1137 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, 1054 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
1138 (s) => { return (float)s.m_detailedStatsStep; }, 1055 (s) => { return (float)s.m_detailedStatsStep; },
1139 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1056 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1140 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1141 ConfigurationParameters.numericFalse,
1142 (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1143 (s) => { return s.NumericBool(s.ShouldDebugLog); },
1144 (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
1145
1146 }; 1057 };
1147 1058
1148 // Convert a boolean to our numeric true and false values 1059 // Convert a boolean to our numeric true and false values
@@ -1200,6 +1111,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1200 1111
1201 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; 1112 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1202 1113
1114 // This creates an array in the correct format for returning the list of
1115 // parameters. This is used by the 'list' option of the 'physics' command.
1203 private void BuildParameterTable() 1116 private void BuildParameterTable()
1204 { 1117 {
1205 if (SettableParameters.Length < ParameterDefinitions.Length) 1118 if (SettableParameters.Length < ParameterDefinitions.Length)
@@ -1250,18 +1163,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1250 } 1163 }
1251 1164
1252 // check to see if we are updating a parameter for a particular or all of the prims 1165 // check to see if we are updating a parameter for a particular or all of the prims
1253 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) 1166 protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val)
1254 {
1255 List<uint> operateOn;
1256 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
1257 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1258 }
1259
1260 // check to see if we are updating a parameter for a particular or all of the avatars
1261 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
1262 { 1167 {
1263 List<uint> operateOn; 1168 List<uint> operateOn;
1264 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); 1169 lock (PhysObjects) operateOn = new List<uint>(PhysObjects.Keys);
1265 UpdateParameterSet(operateOn, ref loc, parm, localID, val); 1170 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1266 } 1171 }
1267 1172
@@ -1284,7 +1189,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1284 TaintedObject("BSScene.UpdateParameterSet", delegate() { 1189 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1285 foreach (uint lID in objectIDs) 1190 foreach (uint lID in objectIDs)
1286 { 1191 {
1287 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); 1192 BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
1288 } 1193 }
1289 }); 1194 });
1290 break; 1195 break;
@@ -1302,7 +1207,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1302 string xparm = parm.ToLower(); 1207 string xparm = parm.ToLower();
1303 float xval = val; 1208 float xval = val;
1304 TaintedObject("BSScene.TaintedUpdateParameter", delegate() { 1209 TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
1305 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1210 BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval);
1306 }); 1211 });
1307 } 1212 }
1308 1213
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
new file mode 100755
index 0000000..d48462e
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -0,0 +1,480 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public class BSTerrainManager
44{
45 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
46
47 // These height values are fractional so the odd values will be
48 // noticable when debugging.
49 public const float HEIGHT_INITIALIZATION = 24.987f;
50 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
51 public const float HEIGHT_GETHEIGHT_RET = 24.765f;
52
53 // If the min and max height are equal, we reduce the min by this
54 // amount to make sure that a bounding box is built for the terrain.
55 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
56
57 public const float TERRAIN_COLLISION_MARGIN = 0.0f;
58
59 // Until the whole simulator is changed to pass us the region size, we rely on constants.
60 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f);
61
62 // The scene that I am part of
63 private BSScene m_physicsScene;
64
65 // The ground plane created to keep thing from falling to infinity.
66 private BulletBody m_groundPlane;
67
68 // If doing mega-regions, if we're region zero we will be managing multiple
69 // region terrains since region zero does the physics for the whole mega-region.
70 private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
71
72 // True of the terrain has been modified.
73 // Used to force recalculation of terrain height after terrain has been modified
74 private bool m_terrainModified;
75
76 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
77 // This is incremented before assigning to new region so it is the last ID allocated.
78 private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
79 public uint HighestTerrainID { get {return m_terrainCount; } }
80
81 // If doing mega-regions, this holds our offset from region zero of
82 // the mega-regions. "parentScene" points to the PhysicsScene of region zero.
83 private Vector3 m_worldOffset;
84 // If the parent region (region 0), this is the extent of the combined regions
85 // relative to the origin of region zero
86 private Vector3 m_worldMax;
87 private PhysicsScene m_parentScene;
88
89 public BSTerrainManager(BSScene physicsScene)
90 {
91 m_physicsScene = physicsScene;
92 m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
93 m_terrainModified = false;
94
95 // Assume one region of default size
96 m_worldOffset = Vector3.Zero;
97 m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f);
98 m_parentScene = null;
99 }
100
101 // Create the initial instance of terrain and the underlying ground plane.
102 // The objects are allocated in the unmanaged space and the pointers are tracked
103 // by the managed code.
104 // The terrains and the groundPlane are not added to the list of PhysObjects.
105 // This is called from the initialization routine so we presume it is
106 // safe to call Bullet in real time. We hope no one is moving prims around yet.
107 public void CreateInitialGroundPlaneAndTerrain()
108 {
109 // The ground plane is here to catch things that are trying to drop to negative infinity
110 BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN));
111 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
112 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity));
113 BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
114
115 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
116 Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
117 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
118 float[] initialMap = new float[totalHeights];
119 for (int ii = 0; ii < totalHeights; ii++)
120 {
121 initialMap[ii] = HEIGHT_INITIALIZATION;
122 }
123 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
124 }
125
126 // Release all the terrain structures we might have allocated
127 public void ReleaseGroundPlaneAndTerrain()
128 {
129 if (m_groundPlane.Ptr != IntPtr.Zero)
130 {
131 if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
132 {
133 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
134 }
135 m_groundPlane.Ptr = IntPtr.Zero;
136 }
137
138 ReleaseTerrain();
139 }
140
141 // Release all the terrain we have allocated
142 public void ReleaseTerrain()
143 {
144 foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
145 {
146 if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
147 {
148 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
149 BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
150 }
151 }
152 m_heightMaps.Clear();
153 }
154
155 // The simulator wants to set a new heightmap for the terrain.
156 public void SetTerrain(float[] heightMap) {
157 float[] localHeightMap = heightMap;
158 m_physicsScene.TaintedObject("TerrainManager.SetTerrain", delegate()
159 {
160 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
161 {
162 // If a child of a mega-region, we shouldn't have any terrain allocated for us
163 ReleaseGroundPlaneAndTerrain();
164 // If doing the mega-prim stuff and we are the child of the zero region,
165 // the terrain is added to our parent
166 if (m_parentScene is BSScene)
167 {
168 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
169 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
170 ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
171 localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
172 }
173 }
174 else
175 {
176 // If not doing the mega-prim thing, just change the terrain
177 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
178
179 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
180 }
181 });
182 }
183
184 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
185 // based on the passed information. The 'id' should be either the terrain id or
186 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
187 // The latter feature is for creating child terrains for mega-regions.
188 // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
189 // then a new body and shape is created and the mapInfo is filled.
190 // This call is used for doing the initial terrain creation.
191 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
192 // terrain shape is created and added to the body.
193 // This call is most often used to update the heightMap and parameters of the terrain.
194 // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
195 // calling this routine from initialization or taint-time routines) or whether to delay
196 // all the unmanaged activities to taint-time.
197 private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow)
198 {
199 DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}",
200 BSScene.DetailLogZero, minCoords, maxCoords, doNow);
201
202 float minZ = float.MaxValue;
203 float maxZ = float.MinValue;
204 Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
205
206 int heightMapSize = heightMap.Length;
207 for (int ii = 0; ii < heightMapSize; ii++)
208 {
209 float height = heightMap[ii];
210 if (height < minZ) minZ = height;
211 if (height > maxZ) maxZ = height;
212 }
213
214 // The shape of the terrain is from its base to its extents.
215 minCoords.Z = minZ;
216 maxCoords.Z = maxZ;
217
218 BulletHeightMapInfo mapInfo;
219 if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
220 {
221 // If this is terrain we know about, it's easy to update
222
223 mapInfo.heightMap = heightMap;
224 mapInfo.minCoords = minCoords;
225 mapInfo.maxCoords = maxCoords;
226 mapInfo.minZ = minZ;
227 mapInfo.maxZ = maxZ;
228 mapInfo.sizeX = maxCoords.X - minCoords.X;
229 mapInfo.sizeY = maxCoords.Y - minCoords.Y;
230 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
231 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
232
233 BSScene.TaintCallback rebuildOperation = delegate()
234 {
235 if (m_parentScene != null)
236 {
237 // It's possible that Combine() was called after this code was queued.
238 // If we are a child of combined regions, we don't create any terrain for us.
239 DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
240
241 // Get rid of any terrain that may have been allocated for us.
242 ReleaseGroundPlaneAndTerrain();
243
244 // I hate doing this, but just bail
245 return;
246 }
247
248 if (mapInfo.terrainBody.Ptr != IntPtr.Zero)
249 {
250 // Updating an existing terrain.
251 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
252 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
253
254 // Remove from the dynamics world because we're going to mangle this object
255 BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
256
257 // Get rid of the old terrain
258 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
259 BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
260 mapInfo.Ptr = IntPtr.Zero;
261
262 /*
263 // NOTE: This routine is half here because I can't get the terrain shape replacement
264 // to work. In the short term, the above three lines completely delete the old
265 // terrain and the code below recreates one from scratch.
266 // Hopefully the Bullet community will help me out on this one.
267
268 // First, release the old collision shape (there is only one terrain)
269 BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
270
271 // Fill the existing height map info with the new location and size information
272 BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
273 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
274
275 // Create a terrain shape based on the new info
276 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
277
278 // Stuff the shape into the existing terrain body
279 BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
280 */
281 }
282 // else
283 {
284 // Creating a new terrain.
285 DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
286 BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
287
288 mapInfo.ID = id;
289 mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID,
290 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
291
292 // The terrain object initial position is at the center of the object
293 Vector3 centerPos;
294 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
295 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
296 centerPos.Z = minZ + ((maxZ - minZ) / 2f);
297
298 // Create the terrain shape from the mapInfo
299 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
300
301 mapInfo.terrainBody = new BulletBody(mapInfo.ID,
302 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr,
303 centerPos, Quaternion.Identity));
304 }
305
306 // Make sure the entry is in the heightmap table
307 m_heightMaps[terrainRegionBase] = mapInfo;
308
309 // Set current terrain attributes
310 BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
311 BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
312 BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
313 BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
314
315 BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero);
316 BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr);
317
318 // Return the new terrain to the world of physical objects
319 BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
320
321 // redo its bounding box now that it is in the world
322 BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
323
324 // Make sure the new shape is processed.
325 BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
326
327 m_terrainModified = true;
328 };
329
330 // There is the option to do the changes now (we're already in 'taint time'), or
331 // to do the Bullet operations later.
332 if (doNow)
333 rebuildOperation();
334 else
335 m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
336 }
337 else
338 {
339 // We don't know about this terrain so either we are creating a new terrain or
340 // our mega-prim child is giving us a new terrain to add to the phys world
341
342 // if this is a child terrain, calculate a unique terrain id
343 uint newTerrainID = id;
344 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
345 newTerrainID = ++m_terrainCount;
346
347 float[] heightMapX = heightMap;
348 Vector3 minCoordsX = minCoords;
349 Vector3 maxCoordsX = maxCoords;
350
351 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
352 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
353
354 // Code that must happen at taint-time
355 BSScene.TaintCallback createOperation = delegate()
356 {
357 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
358 // Create a new mapInfo that will be filled with the new info
359 mapInfo = new BulletHeightMapInfo(id, heightMapX,
360 BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID,
361 minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
362 // Put the unfilled heightmap info into the collection of same
363 m_heightMaps.Add(terrainRegionBase, mapInfo);
364 // Build the terrain
365 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
366
367 m_terrainModified = true;
368 };
369
370 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
371 if (doNow)
372 createOperation();
373 else
374 m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
375 }
376 }
377
378 // Someday we will have complex terrain with caves and tunnels
379 public float GetTerrainHeightAtXYZ(Vector3 loc)
380 {
381 // For the moment, it's flat and convex
382 return GetTerrainHeightAtXY(loc.X, loc.Y);
383 }
384
385 // Given an X and Y, find the height of the terrain.
386 // Since we could be handling multiple terrains for a mega-region,
387 // the base of the region is calcuated assuming all regions are
388 // the same size and that is the default.
389 // Once the heightMapInfo is found, we have all the information to
390 // compute the offset into the array.
391 private float lastHeightTX = 999999f;
392 private float lastHeightTY = 999999f;
393 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
394 private float GetTerrainHeightAtXY(float tX, float tY)
395 {
396 // You'd be surprized at the number of times this routine is called
397 // with the same parameters as last time.
398 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
399 return lastHeight;
400
401 lastHeightTX = tX;
402 lastHeightTY = tY;
403 float ret = HEIGHT_GETHEIGHT_RET;
404
405 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
406 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
407 Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
408
409 BulletHeightMapInfo mapInfo;
410 if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
411 {
412 float regionX = tX - offsetX;
413 float regionY = tY - offsetY;
414 int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
415 try
416 {
417 ret = mapInfo.heightMap[mapIndex];
418 }
419 catch
420 {
421 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
422 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}",
423 LogHeader, terrainBaseXY, regionX, regionY);
424 ret = HEIGHT_GETHEIGHT_RET;
425 }
426 // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
427 // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
428 }
429 else
430 {
431 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
432 LogHeader, m_physicsScene.RegionName, tX, tY);
433 }
434 m_terrainModified = false;
435 lastHeight = ret;
436 return ret;
437 }
438
439 // Although no one seems to check this, I do support combining.
440 public bool SupportsCombining()
441 {
442 return true;
443 }
444
445 // This routine is called two ways:
446 // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
447 // extent of the combined regions. This is to inform the parent of the size
448 // of the combined regions.
449 // and one with 'offset' as the offset of the child region to the base region,
450 // 'pScene' pointing to the parent and 'extents' of zero. This informs the
451 // child of its relative base and new parent.
452 public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
453 {
454 m_worldOffset = offset;
455 m_worldMax = extents;
456 m_parentScene = pScene;
457 if (pScene != null)
458 {
459 // We are a child.
460 // We want m_worldMax to be the highest coordinate of our piece of terrain.
461 m_worldMax = offset + DefaultRegionSize;
462 }
463 DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
464 BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
465 }
466
467 // Unhook all the combining that I know about.
468 public void UnCombine(PhysicsScene pScene)
469 {
470 // Just like ODE, for the moment a NOP
471 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
472 }
473
474
475 private void DetailLog(string msg, params Object[] args)
476 {
477 m_physicsScene.PhysicsLogging.Write(msg, args);
478 }
479}
480}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 504bd3c..9221cdb 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -33,15 +33,25 @@ using OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin { 33namespace OpenSim.Region.Physics.BulletSPlugin {
34 34
35// Classes to allow some type checking for the API 35// Classes to allow some type checking for the API
36// These hold pointers to allocated objects in the unmanaged space.
37
38// The physics engine controller class created at initialization
36public struct BulletSim 39public struct BulletSim
37{ 40{
38 public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } 41 public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; }
39 public uint ID; 42 public uint worldID;
40 // The scene is only in here so very low level routines have a handle to print debug/error messages 43 // The scene is only in here so very low level routines have a handle to print debug/error messages
41 public BSScene scene; 44 public BSScene scene;
42 public IntPtr Ptr; 45 public IntPtr Ptr;
43} 46}
44 47
48public struct BulletShape
49{
50 public BulletShape(IntPtr xx) { Ptr = xx; }
51 public IntPtr Ptr;
52}
53
54// An allocated Bullet btRigidBody
45public struct BulletBody 55public struct BulletBody
46{ 56{
47 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } 57 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
@@ -49,12 +59,41 @@ public struct BulletBody
49 public uint ID; 59 public uint ID;
50} 60}
51 61
62// An allocated Bullet btConstraint
52public struct BulletConstraint 63public struct BulletConstraint
53{ 64{
54 public BulletConstraint(IntPtr xx) { Ptr = xx; } 65 public BulletConstraint(IntPtr xx) { Ptr = xx; }
55 public IntPtr Ptr; 66 public IntPtr Ptr;
56} 67}
57 68
69// An allocated HeightMapThing which hold various heightmap info
70// Made a class rather than a struct so there would be only one
71// instance of this and C# will pass around pointers rather
72// than making copies.
73public class BulletHeightMapInfo
74{
75 public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
76 ID = id;
77 Ptr = xx;
78 heightMap = hm;
79 terrainRegionBase = new Vector2(0f, 0f);
80 minCoords = new Vector3(100f, 100f, 25f);
81 maxCoords = new Vector3(101f, 101f, 26f);
82 minZ = maxZ = 0f;
83 sizeX = sizeY = 256f;
84 }
85 public uint ID;
86 public IntPtr Ptr;
87 public float[] heightMap;
88 public Vector2 terrainRegionBase;
89 public Vector3 minCoords;
90 public Vector3 maxCoords;
91 public float sizeX, sizeY;
92 public float minZ, maxZ;
93 public BulletShape terrainShape;
94 public BulletBody terrainBody;
95}
96
58// =============================================================================== 97// ===============================================================================
59[StructLayout(LayoutKind.Sequential)] 98[StructLayout(LayoutKind.Sequential)]
60public struct ConvexHull 99public struct ConvexHull
@@ -174,12 +213,26 @@ public struct ConfigurationParameters
174 public float linkConstraintTransMotorMaxForce; 213 public float linkConstraintTransMotorMaxForce;
175 public float linkConstraintERP; 214 public float linkConstraintERP;
176 public float linkConstraintCFM; 215 public float linkConstraintCFM;
216 public float linkConstraintSolverIterations;
177 217
178 public const float numericTrue = 1f; 218 public const float numericTrue = 1f;
179 public const float numericFalse = 0f; 219 public const float numericFalse = 0f;
180} 220}
181 221
182// Values used by Bullet and BulletSim to control collisions 222
223// The states a bullet collision object can have
224public enum ActivationState : uint
225{
226 ACTIVE_TAG = 1,
227 ISLAND_SLEEPING,
228 WANTS_DEACTIVATION,
229 DISABLE_DEACTIVATION,
230 DISABLE_SIMULATION
231}
232
233// Values used by Bullet and BulletSim to control object properties.
234// Bullet's "CollisionFlags" has more to do with operations on the
235// object (if collisions happen, if gravity effects it, ...).
183public enum CollisionFlags : uint 236public enum CollisionFlags : uint
184{ 237{
185 CF_STATIC_OBJECT = 1 << 0, 238 CF_STATIC_OBJECT = 1 << 0,
@@ -194,8 +247,75 @@ public enum CollisionFlags : uint
194 BS_VOLUME_DETECT_OBJECT = 1 << 11, 247 BS_VOLUME_DETECT_OBJECT = 1 << 11,
195 BS_PHANTOM_OBJECT = 1 << 12, 248 BS_PHANTOM_OBJECT = 1 << 12,
196 BS_PHYSICAL_OBJECT = 1 << 13, 249 BS_PHYSICAL_OBJECT = 1 << 13,
250 BS_TERRAIN_OBJECT = 1 << 14,
251 BS_NONE = 0,
252 BS_ALL = 0xFFFFFFFF
253};
254
255// Values for collisions groups and masks
256public enum CollisionFilterGroups : uint
257{
258 NoneFilter = 0,
259 DefaultFilter = 1 << 0,
260 StaticFilter = 1 << 1,
261 KinematicFilter = 1 << 2,
262 DebrisFilter = 1 << 3,
263 SensorTrigger = 1 << 4,
264 CharacterFilter = 1 << 5,
265 AllFilter = 0xFFFFFFFF,
266 // Filter groups defined by BulletSim
267 GroundPlaneFilter = 1 << 10,
268 TerrainFilter = 1 << 11,
269 RaycastFilter = 1 << 12,
270 SolidFilter = 1 << 13,
197}; 271};
198 272
273 // For each type, we first clear and then set the collision flags
274public enum ClearCollisionFlag : uint
275{
276 Terrain = CollisionFlags.BS_ALL,
277 Phantom = CollisionFlags.BS_ALL,
278 VolumeDetect = CollisionFlags.BS_ALL,
279 PhysicalObject = CollisionFlags.BS_ALL,
280 StaticObject = CollisionFlags.BS_ALL
281}
282
283public enum SetCollisionFlag : uint
284{
285 Terrain = CollisionFlags.CF_STATIC_OBJECT
286 | CollisionFlags.BS_TERRAIN_OBJECT,
287 Phantom = CollisionFlags.CF_STATIC_OBJECT
288 | CollisionFlags.BS_PHANTOM_OBJECT
289 | CollisionFlags.CF_NO_CONTACT_RESPONSE,
290 VolumeDetect = CollisionFlags.CF_STATIC_OBJECT
291 | CollisionFlags.BS_VOLUME_DETECT_OBJECT
292 | CollisionFlags.CF_NO_CONTACT_RESPONSE,
293 PhysicalObject = CollisionFlags.BS_PHYSICAL_OBJECT,
294 StaticObject = CollisionFlags.CF_STATIC_OBJECT,
295}
296
297// Collision filters used for different types of objects
298public enum SetCollisionFilter : uint
299{
300 Terrain = CollisionFilterGroups.AllFilter,
301 Phantom = CollisionFilterGroups.GroundPlaneFilter
302 | CollisionFilterGroups.TerrainFilter,
303 VolumeDetect = CollisionFilterGroups.AllFilter,
304 PhysicalObject = CollisionFilterGroups.AllFilter,
305 StaticObject = CollisionFilterGroups.AllFilter,
306}
307
308// Collision masks used for different types of objects
309public enum SetCollisionMask : uint
310{
311 Terrain = CollisionFilterGroups.AllFilter,
312 Phantom = CollisionFilterGroups.GroundPlaneFilter
313 | CollisionFilterGroups.TerrainFilter,
314 VolumeDetect = CollisionFilterGroups.AllFilter,
315 PhysicalObject = CollisionFilterGroups.AllFilter,
316 StaticObject = CollisionFilterGroups.AllFilter
317}
318
199// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 319// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
200// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. 320// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
201public enum ConstraintParams : int 321public enum ConstraintParams : int
@@ -221,6 +341,10 @@ public enum ConstraintParamAxis : int
221// =============================================================================== 341// ===============================================================================
222static class BulletSimAPI { 342static class BulletSimAPI {
223 343
344// Link back to the managed code for outputting log messages
345[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
346public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
347
224[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 348[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
225[return: MarshalAs(UnmanagedType.LPStr)] 349[return: MarshalAs(UnmanagedType.LPStr)]
226public static extern string GetVersion(); 350public static extern string GetVersion();
@@ -228,7 +352,11 @@ public static extern string GetVersion();
228[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 352[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
229public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, 353public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
230 int maxCollisions, IntPtr collisionArray, 354 int maxCollisions, IntPtr collisionArray,
231 int maxUpdates, IntPtr updateArray); 355 int maxUpdates, IntPtr updateArray,
356 DebugLogCallback logRoutine);
357
358[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
359public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
232 360
233[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 361[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
234public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); 362public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
@@ -268,23 +396,6 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
268[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
269public static extern bool CreateObject(uint worldID, ShapeData shapeData); 397public static extern bool CreateObject(uint worldID, ShapeData shapeData);
270 398
271/* Remove old functionality
272[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
273public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
274
275[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
276public static extern void AddConstraint(uint worldID, uint id1, uint id2,
277 Vector3 frame1, Quaternion frame1rot,
278 Vector3 frame2, Quaternion frame2rot,
279 Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
280
281[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
282public static extern bool RemoveConstraintByID(uint worldID, uint id1);
283
284[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
285public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
286 */
287
288[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
289public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 400public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
290 401
@@ -300,6 +411,7 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc
300[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 411[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
301public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); 412public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity);
302 413
414// Set the current force acting on the object
303[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 415[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
304public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); 416public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force);
305 417
@@ -342,8 +454,6 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
342public static extern void DumpBulletStatistics(); 454public static extern void DumpBulletStatistics();
343 455
344// Log a debug message 456// Log a debug message
345[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
346public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
347[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
348public static extern void SetDebugLogCallback(DebugLogCallback callback); 458public static extern void SetDebugLogCallback(DebugLogCallback callback);
349 459
@@ -358,6 +468,7 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback);
358// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt 468// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
359// and the old code is removed. 469// and the old code is removed.
360 470
471// Functions use while converting from API1 to API2. Can be removed when totally converted.
361[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 472[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
362public static extern IntPtr GetSimHandle2(uint worldID); 473public static extern IntPtr GetSimHandle2(uint worldID);
363 474
@@ -368,6 +479,7 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
368public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); 479public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
369 480
370// =============================================================================== 481// ===============================================================================
482// Initialization and simulation
371[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 483[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
372public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, 484public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
373 int maxCollisions, IntPtr collisionArray, 485 int maxCollisions, IntPtr collisionArray,
@@ -377,7 +489,7 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
377public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); 489public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
378 490
379[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 491[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
380public static extern void SetHeightmap2(IntPtr world, float[] heightmap); 492public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
381 493
382[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 494[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
383public static extern void Shutdown2(IntPtr sim); 495public static extern void Shutdown2(IntPtr sim);
@@ -392,23 +504,78 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 504[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool PushUpdate2(IntPtr obj); 505public static extern bool PushUpdate2(IntPtr obj);
394 506
395/* 507// =====================================================================================
508// Mesh, hull, shape and body creation helper routines
509[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
510public static extern IntPtr CreateMeshShape2(IntPtr world,
511 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
512 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
513
514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
515public static extern IntPtr CreateHullShape2(IntPtr world,
516 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
517
518[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
519public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape);
520
521[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
522public static extern IntPtr BuildNativeShape2(IntPtr world,
523 float shapeType, float collisionMargin, Vector3 scale);
524
525[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
526public static extern bool IsNativeShape2(IntPtr shape);
527
528[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
529public static extern IntPtr CreateCompoundShape2(IntPtr sim);
530
531[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
532public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
533
534[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
535public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
536
537[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
538public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo);
539
540[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
541public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
542
396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 543[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
397public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices ); 544public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
398 545
399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 546[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
400public static extern bool BuildHull2(IntPtr world, IntPtr mesh); 547public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
401 548
402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 549[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
403public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh); 550public static extern IntPtr AllocateBodyInfo2(IntPtr obj);
404 551
405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 552[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
406public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh); 553public static extern void ReleaseBodyInfo2(IntPtr obj);
407 554
408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 555[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
409public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData); 556public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
410*/
411 557
558// =====================================================================================
559// Terrain creation and helper routines
560[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
561public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
562 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
563
564[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
565public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
566 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
567
568[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
569public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
570
571[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
572public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
573
574[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
575public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
576
577// =====================================================================================
578// Constraint creation and helper routines
412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 579[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
413public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, 580public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
414 Vector3 frame1loc, Quaternion frame1rot, 581 Vector3 frame1loc, Quaternion frame1rot,
@@ -460,11 +627,108 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams
460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 627[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
461public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); 628public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
462 629
630// =====================================================================================
631// btCollisionWorld entries
632[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
633public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj);
634
635[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
636public static extern void UpdateAabbs2(IntPtr world);
637
638[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
639public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
640
641[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
642public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
643
644// =====================================================================================
645// btDynamicsWorld entries
646[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
647public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
648
649[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
650public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
651
652[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
653public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
654
655[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
656public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
657// =====================================================================================
658// btCollisionObject entries
659[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
660public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
661
662[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
663public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
664
665[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
666public static extern bool HasAnisotripicFriction2(IntPtr constrain);
667
668[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
669public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
670
463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 671[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj); 672public static extern float GetContactProcessingThreshold2(IntPtr obj);
465 673
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 674[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
467public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 675public static extern bool IsStaticObject2(IntPtr obj);
676
677[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
678public static extern bool IsKinematicObject2(IntPtr obj);
679
680[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
681public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
682
683[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
684public static extern bool HasContactResponse2(IntPtr obj);
685
686[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
687public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
688
689[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
690public static extern IntPtr GetCollisionShape2(IntPtr obj);
691
692[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
693public static extern int GetActivationState2(IntPtr obj);
694
695[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
696public static extern void SetActivationState2(IntPtr obj, int state);
697
698[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
699public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
700
701[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
702public static extern float GetDeactivationTime2(IntPtr obj);
703
704[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
705public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
706
707[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
708public static extern void Activate2(IntPtr obj, bool forceActivation);
709
710[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
711public static extern bool IsActive2(IntPtr obj);
712
713[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
714public static extern void SetRestitution2(IntPtr obj, float val);
715
716[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
717public static extern float GetRestitution2(IntPtr obj);
718
719[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
720public static extern void SetFriction2(IntPtr obj, float val);
721
722[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
723public static extern float GetFriction2(IntPtr obj);
724
725 /* Haven't defined the type 'Transform'
726[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
727public static extern Transform GetWorldTransform2(IntPtr obj);
728
729[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
730public static extern void setWorldTransform2(IntPtr obj, Transform trans);
731 */
468 732
469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 733[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
470public static extern Vector3 GetPosition2(IntPtr obj); 734public static extern Vector3 GetPosition2(IntPtr obj);
@@ -473,85 +737,293 @@ public static extern Vector3 GetPosition2(IntPtr obj);
473public static extern Quaternion GetOrientation2(IntPtr obj); 737public static extern Quaternion GetOrientation2(IntPtr obj);
474 738
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 739[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
476public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); 740public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
477 741
478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 742[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
479public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); 743public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
480 744
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 745[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); 746public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
483 747
748 /*
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 749[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); 750public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
486 751
487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 752[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern bool AddObjectForce2(IntPtr obj, Vector3 force); 753public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
754 */
489 755
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 756[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
491public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); 757public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
492 758
493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 759[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
494public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); 760public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
495 761
496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 762[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
497public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); 763public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
498 764
499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 765[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
500public static extern bool SetDeactivationTime2(IntPtr obj, float val); 766public static extern float GetHitFraction2(IntPtr obj);
501 767
502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 768[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
503public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); 769public static extern void SetHitFraction2(IntPtr obj, float val);
504 770
505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 771[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
506public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); 772public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
507 773
508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 774[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
509public static extern bool SetFriction2(IntPtr obj, float val); 775public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
510 776
511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 777[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
512public static extern bool SetRestitution2(IntPtr obj, float val); 778public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
513 779
514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 780[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
515public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); 781public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
516 782
517[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 783[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
518public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); 784public static extern float GetCcdMotionThreshold2(IntPtr obj);
519 785
520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 786[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
521public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); 787public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
788
789[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
790public static extern float GetCcdSweepSphereRadius2(IntPtr obj);
791
792[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
793public static extern void SetCcdSweepSphereRadius2(IntPtr obj, float val);
794
795[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
796public static extern IntPtr GetUserPointer2(IntPtr obj);
797
798[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
799public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
800
801// =====================================================================================
802// btRigidBody entries
803[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
804public static extern void ApplyGravity2(IntPtr obj);
805
806[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
807public static extern void SetGravity2(IntPtr obj, Vector3 val);
808
809[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
810public static extern Vector3 GetGravity2(IntPtr obj);
811
812[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
813public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
814
815[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
816public static extern float GetLinearDamping2(IntPtr obj);
817
818[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
819public static extern float GetAngularDamping2(IntPtr obj);
820
821[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
822public static extern float GetLinearSleepingThreshold2(IntPtr obj);
823
824[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
825public static extern float GetAngularSleepingThreshold2(IntPtr obj);
826
827[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
828public static extern void ApplyDamping2(IntPtr obj, float timeStep);
829
830[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
831public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
832
833[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
834public static extern Vector3 GetLinearFactor2(IntPtr obj);
835
836[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
837public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
838
839 /*
840[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
841public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
842 */
843
844[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
845public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
846
847// Add a force to the object as if its mass is one.
848[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
849public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
850
851// Set the force being applied to the object as if its mass is one.
852[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
853public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
854
855[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
856public static extern Vector3 GetTotalForce2(IntPtr obj);
857
858[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
859public static extern Vector3 GetTotalTorque2(IntPtr obj);
860
861[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
862public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
863
864[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
865public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
866
867[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
868public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
869
870[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
871public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
872
873// Apply force at the given point. Will add torque to the object.
874[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
875public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos);
876
877// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
878[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
879public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp);
880
881// Apply impulse to the object's torque. Force is scaled by object's mass.
882[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
883public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp);
884
885// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
886[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
887public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos);
888
889[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
890public static extern void ClearForces2(IntPtr obj);
891
892[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
893public static extern void ClearAllForces2(IntPtr obj);
894
895[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
896public static extern void UpdateInertiaTensor2(IntPtr obj);
897
898[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
899public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj);
900
901 /*
902[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
903public static extern Transform GetCenterOfMassTransform2(IntPtr obj);
904 */
905
906[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
907public static extern Vector3 GetLinearVelocity2(IntPtr obj);
908
909[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
910public static extern Vector3 GetAngularVelocity2(IntPtr obj);
911
912[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
913public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val);
914
915[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
916public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
917
918[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
919public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos);
920
921[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
922public static extern void Translate2(IntPtr obj, Vector3 trans);
923
924[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
925public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
926
927[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
928public static extern bool WantsSleeping2(IntPtr obj);
929
930[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
931public static extern void SetAngularFactor2(IntPtr obj, float factor);
932
933[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
934public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
935
936[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
937public static extern Vector3 GetAngularFactor2(IntPtr obj);
938
939[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
940public static extern bool IsInWorld2(IntPtr obj);
941
942[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
943public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
944
945[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
946public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
947
948[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
949public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
950
951[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
952public static extern int GetNumConstraintRefs2(IntPtr obj);
953
954[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
955public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj);
956
957[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
958public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj);
959
960[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
961public static extern Vector3 GetPushVelocity2(IntPtr obj);
962
963[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
964public static extern Vector3 GetTurnVelocity2(IntPtr obj);
965
966// =====================================================================================
967// btCollisionShape entries
968
969[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
970public static extern float GetAngularMotionDisc2(IntPtr shape);
971
972[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
973public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
974
975[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
976public static extern bool IsPolyhedral2(IntPtr shape);
977
978[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
979public static extern bool IsConvex2d2(IntPtr shape);
980
981[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
982public static extern bool IsConvex2(IntPtr shape);
983
984[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
985public static extern bool IsNonMoving2(IntPtr shape);
986
987[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
988public static extern bool IsConcave2(IntPtr shape);
989
990[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
991public static extern bool IsCompound2(IntPtr shape);
522 992
523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 993[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
524public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags); 994public static extern bool IsSoftBody2(IntPtr shape);
525 995
526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 996[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
527public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); 997public static extern bool IsInfinite2(IntPtr shape);
528 998
529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 999[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
530public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); 1000public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
531 1001
532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1002[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
533public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); 1003public static extern Vector3 GetLocalScaling2(IntPtr shape);
534 1004
535[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1005[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
536public static extern bool UpdateInertiaTensor2(IntPtr obj); 1006public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass);
537 1007
538[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1008[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
539public static extern bool SetGravity2(IntPtr obj, Vector3 val); 1009public static extern int GetShapeType2(IntPtr shape);
540 1010
541[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1011[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
542public static extern IntPtr ClearForces2(IntPtr obj); 1012public static extern void SetMargin2(IntPtr shape, float val);
543 1013
544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1014[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
545public static extern IntPtr ClearAllForces2(IntPtr obj); 1015public static extern float GetMargin2(IntPtr shape);
546 1016
547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1017[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
548public static extern bool SetMargin2(IntPtr obj, float val); 1018public static extern void SetCollisionFilterMask(IntPtr shape, uint filter, uint mask);
549 1019
1020// =====================================================================================
1021// Debugging
550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1022[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
551public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); 1023public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
552 1024
553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1025[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
554public static extern bool DestroyObject2(IntPtr world, uint id); 1026public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
555 1027
556[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1028[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
557public static extern void DumpPhysicsStatistics2(IntPtr sim); 1029public static extern void DumpPhysicsStatistics2(IntPtr sim);