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.cs15
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs13
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs16
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs185
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs7
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs62
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs90
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs81
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs23
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs31
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs4
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs15
12 files changed, 335 insertions, 207 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 2a52e01..2e6b2da 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -263,7 +263,7 @@ public class BSCharacter : BSPhysObject
263 // A version of the sanity check that also makes sure a new position value is 263 // A version of the sanity check that also makes sure a new position value is
264 // pushed back to the physics engine. This routine would be used by anyone 264 // pushed back to the physics engine. This routine would be used by anyone
265 // who is not already pushing the value. 265 // who is not already pushing the value.
266 private bool PositionSanityCheck2(bool atTaintTime) 266 private bool PositionSanityCheck2(bool inTaintTime)
267 { 267 {
268 bool ret = false; 268 bool ret = false;
269 if (PositionSanityCheck()) 269 if (PositionSanityCheck())
@@ -275,7 +275,7 @@ public class BSCharacter : BSPhysObject
275 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 275 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
276 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); 276 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
277 }; 277 };
278 if (atTaintTime) 278 if (inTaintTime)
279 sanityOperation(); 279 sanityOperation();
280 else 280 else
281 PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); 281 PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation);
@@ -332,6 +332,13 @@ public class BSCharacter : BSPhysObject
332 }); 332 });
333 } 333 }
334 } 334 }
335 public override OMV.Vector3 ForceVelocity {
336 get { return _velocity; }
337 set {
338 _velocity = value;
339 BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity);
340 }
341 }
335 public override OMV.Vector3 Torque { 342 public override OMV.Vector3 Torque {
336 get { return _torque; } 343 get { return _torque; }
337 set { _torque = value; 344 set { _torque = value;
@@ -432,6 +439,10 @@ public class BSCharacter : BSPhysObject
432 get { return _rotationalVelocity; } 439 get { return _rotationalVelocity; }
433 set { _rotationalVelocity = value; } 440 set { _rotationalVelocity = value; }
434 } 441 }
442 public override OMV.Vector3 ForceRotationalVelocity {
443 get { return _rotationalVelocity; }
444 set { _rotationalVelocity = value; }
445 }
435 public override bool Kinematic { 446 public override bool Kinematic {
436 get { return _kinematic; } 447 get { return _kinematic; }
437 set { _kinematic = value; } 448 set { _kinematic = value; }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 63a4127..a20be3a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -49,9 +49,16 @@ public abstract class BSConstraint : IDisposable
49 if (m_enabled) 49 if (m_enabled)
50 { 50 {
51 m_enabled = false; 51 m_enabled = false;
52 bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); 52 if (m_constraint.ptr != IntPtr.Zero)
53 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); 53 {
54 m_constraint.ptr = System.IntPtr.Zero; 54 bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
55 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
56 BSScene.DetailLogZero,
57 m_body1.ID, m_body1.ptr.ToString("X"),
58 m_body2.ID, m_body2.ptr.ToString("X"),
59 success);
60 m_constraint.ptr = System.IntPtr.Zero;
61 }
55 } 62 }
56 } 63 }
57 64
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 4ba2f62..56342b8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -462,7 +462,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
462 return; 462 return;
463 463
464 // Set the prim's inertia to zero. The vehicle code handles that and this 464 // Set the prim's inertia to zero. The vehicle code handles that and this
465 // removes the torque action introduced by Bullet. 465 // removes the motion and torque actions introduced by Bullet.
466 Vector3 inertia = Vector3.Zero; 466 Vector3 inertia = Vector3.Zero;
467 BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); 467 BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia);
468 BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); 468 BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr);
@@ -481,7 +481,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
481 m_lastPositionVector = Prim.ForcePosition; 481 m_lastPositionVector = Prim.ForcePosition;
482 482
483 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 483 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
484 Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); 484 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
485 }// end Step 485 }// end Step
486 486
487 // Apply the effect of the linear motor. 487 // Apply the effect of the linear motor.
@@ -540,7 +540,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
540 // add Gravity and Buoyancy 540 // add Gravity and Buoyancy
541 // There is some gravity, make a gravity force vector that is applied after object velocity. 541 // There is some gravity, make a gravity force vector that is applied after object velocity.
542 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 542 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
543 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Mass * (1f - m_VehicleBuoyancy)); 543 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy));
544 544
545 /* 545 /*
546 * RA: Not sure why one would do this 546 * RA: Not sure why one would do this
@@ -678,10 +678,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
678 m_newVelocity.Z = 0; 678 m_newVelocity.Z = 0;
679 679
680 // Apply velocity 680 // Apply velocity
681 Prim.Velocity = m_newVelocity; 681 Prim.ForceVelocity = m_newVelocity;
682 // apply gravity force 682 // apply gravity force
683 // Why is this set here? The physics engine already does gravity. 683 // Why is this set here? The physics engine already does gravity.
684 // m_prim.AddForce(grav, false); 684 Prim.AddForce(grav, false, true);
685 685
686 // Apply friction 686 // Apply friction
687 Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); 687 Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
@@ -704,7 +704,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
704 // m_lastAngularVelocity // what was last applied to body 704 // m_lastAngularVelocity // what was last applied to body
705 705
706 // Get what the body is doing, this includes 'external' influences 706 // Get what the body is doing, this includes 'external' influences
707 Vector3 angularVelocity = Prim.RotationalVelocity; 707 Vector3 angularVelocity = Prim.ForceRotationalVelocity;
708 708
709 if (m_angularMotorApply > 0) 709 if (m_angularMotorApply > 0)
710 { 710 {
@@ -810,7 +810,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
810 m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; 810 m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
811 811
812 // Apply to the body 812 // Apply to the body
813 Prim.RotationalVelocity = m_lastAngularVelocity; 813 Prim.ForceRotationalVelocity = m_lastAngularVelocity;
814 814
815 VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); 815 VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity);
816 } //end MoveAngular 816 } //end MoveAngular
@@ -862,7 +862,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
862 private void VDetailLog(string msg, params Object[] args) 862 private void VDetailLog(string msg, params Object[] args)
863 { 863 {
864 if (Prim.PhysicsScene.VehicleLoggingEnabled) 864 if (Prim.PhysicsScene.VehicleLoggingEnabled)
865 Prim.PhysicsScene.PhysicsLogging.Write(msg, args); 865 Prim.PhysicsScene.DetailLog(msg, args);
866 } 866 }
867 } 867 }
868} 868}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 3e82642..43b1262 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -52,8 +52,8 @@ public class BSLinkset
52 // the physical 'taint' children separately. 52 // the physical 'taint' children separately.
53 // After taint processing and before the simulation step, these 53 // After taint processing and before the simulation step, these
54 // two lists must be the same. 54 // two lists must be the same.
55 private List<BSPhysObject> m_children; 55 private HashSet<BSPhysObject> m_children;
56 private List<BSPhysObject> m_taintChildren; 56 private HashSet<BSPhysObject> m_taintChildren;
57 57
58 // We lock the diddling of linkset classes to prevent any badness. 58 // We lock the diddling of linkset classes to prevent any badness.
59 // This locks the modification of the instances of this class. Changes 59 // This locks the modification of the instances of this class. Changes
@@ -90,8 +90,8 @@ public class BSLinkset
90 m_nextLinksetID = 1; 90 m_nextLinksetID = 1;
91 PhysicsScene = scene; 91 PhysicsScene = scene;
92 LinksetRoot = parent; 92 LinksetRoot = parent;
93 m_children = new List<BSPhysObject>(); 93 m_children = new HashSet<BSPhysObject>();
94 m_taintChildren = new List<BSPhysObject>(); 94 m_taintChildren = new HashSet<BSPhysObject>();
95 m_mass = parent.MassRaw; 95 m_mass = parent.MassRaw;
96 } 96 }
97 97
@@ -160,6 +160,28 @@ public class BSLinkset
160 return ret; 160 return ret;
161 } 161 }
162 162
163 // When physical properties are changed the linkset needs to recalculate
164 // its internal properties.
165 // May be called at runtime or taint-time (just pass the appropriate flag).
166 public void Refresh(BSPhysObject requestor, bool inTaintTime)
167 {
168 // If there are no children, not physical or not root, I am not the one that recomputes the constraints
169 // (For the moment, static linksets do create constraints so remove the test for physical.)
170 if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor))
171 return;
172
173 BSScene.TaintCallback refreshOperation = delegate()
174 {
175 RecomputeLinksetConstraintVariables();
176 DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}",
177 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
178 };
179 if (inTaintTime)
180 refreshOperation();
181 else
182 PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation);
183 }
184
163 // The object is going dynamic (physical). Do any setup necessary 185 // The object is going dynamic (physical). Do any setup necessary
164 // for a dynamic linkset. 186 // for a dynamic linkset.
165 // Only the state of the passed object can be modified. The rest of the linkset 187 // Only the state of the passed object can be modified. The rest of the linkset
@@ -182,22 +204,19 @@ public class BSLinkset
182 return false; 204 return false;
183 } 205 }
184 206
185 // When physical properties are changed the linkset needs to recalculate 207 // If the software is handling the movement of all the objects in a linkset
186 // its internal properties. 208 // (like if one doesn't use constraints for static linksets), this is called
187 // Called at runtime. 209 // when an update for the root of the linkset is received.
188 public void Refresh(BSPhysObject requestor) 210 // Called at taint-time!!
211 public void UpdateProperties(BSPhysObject physObject)
189 { 212 {
190 // If there are no children, there can't be any constraints to recompute 213 // The root local properties have been updated. Apply to the children if appropriate.
191 if (!HasAnyChildren) 214 if (IsRoot(physObject) && HasAnyChildren)
192 return;
193
194 // Only the root does the recomputation
195 if (IsRoot(requestor))
196 { 215 {
197 PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() 216 if (!physObject.IsPhysical)
198 { 217 {
199 RecomputeLinksetConstraintVariables(); 218 // TODO: implement software linkset update for static object linksets
200 }); 219 }
201 } 220 }
202 } 221 }
203 222
@@ -215,13 +234,10 @@ public class BSLinkset
215 if (IsRoot(child)) 234 if (IsRoot(child))
216 { 235 {
217 // If the one with the dependency is root, must undo all children 236 // If the one with the dependency is root, must undo all children
218 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", 237 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
219 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); 238 child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
220 foreach (BSPhysObject bpo in m_taintChildren) 239
221 { 240 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
222 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
223 ret = true;
224 }
225 } 241 }
226 else 242 else
227 { 243 {
@@ -229,20 +245,16 @@ public class BSLinkset
229 child.LocalID, 245 child.LocalID,
230 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), 246 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
231 child.LocalID, child.BSBody.ptr.ToString("X")); 247 child.LocalID, child.BSBody.ptr.ToString("X"));
232 // Remove the dependency on the body of this one 248 // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child);
233 if (m_taintChildren.Contains(child)) 249 // Despite the function name, this removes any link to the specified object.
234 { 250 ret = PhysicallyUnlinkAllChildrenFromRoot(child);
235 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
236 ret = true;
237 }
238 } 251 }
239 } 252 }
240 return ret; 253 return ret;
241 } 254 }
242 255
243 // Routine used when rebuilding the body of the root of the linkset 256 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
244 // This is called after RemoveAllLinksToRoot() to restore all the constraints. 257 // this routine will restore the removed constraints.
245 // This is called when the root body has been changed.
246 // Called at taint-time!! 258 // Called at taint-time!!
247 public void RestoreBodyDependencies(BSPrim child) 259 public void RestoreBodyDependencies(BSPrim child)
248 { 260 {
@@ -254,7 +266,7 @@ public class BSLinkset
254 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); 266 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
255 foreach (BSPhysObject bpo in m_taintChildren) 267 foreach (BSPhysObject bpo in m_taintChildren)
256 { 268 {
257 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); 269 PhysicallyLinkAChildToRoot(LinksetRoot, bpo);
258 } 270 }
259 } 271 }
260 else 272 else
@@ -263,7 +275,7 @@ public class BSLinkset
263 LinksetRoot.LocalID, 275 LinksetRoot.LocalID,
264 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), 276 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
265 child.LocalID, child.BSBody.ptr.ToString("X")); 277 child.LocalID, child.BSBody.ptr.ToString("X"));
266 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); 278 PhysicallyLinkAChildToRoot(LinksetRoot, child);
267 } 279 }
268 } 280 }
269 } 281 }
@@ -330,22 +342,22 @@ public class BSLinkset
330 { 342 {
331 m_children.Add(child); 343 m_children.Add(child);
332 344
333 BSPhysObject rootx = LinksetRoot; // capture the root and body as of now 345 BSPhysObject rootx = LinksetRoot; // capture the root as of now
334 BSPhysObject childx = child; 346 BSPhysObject childx = child;
335 347
336 DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", 348 DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
337 rootx.LocalID,
338 rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
339 childx.LocalID, childx.BSBody.ptr.ToString("X"));
340 349
341 PhysicsScene.TaintedObject("AddChildToLinkset", delegate() 350 PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
342 { 351 {
343 DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); 352 DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}",
344 // build the physical binding between me and the child 353 rootx.LocalID,
345 m_taintChildren.Add(childx); 354 rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
346 355 childx.LocalID, childx.BSBody.ptr.ToString("X"));
347 // Since this is taint-time, the body and shape could have changed for the child 356 // Since this is taint-time, the body and shape could have changed for the child
348 PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody); 357 rootx.ForcePosition = rootx.Position; // DEBUG
358 childx.ForcePosition = childx.Position; // DEBUG
359 PhysicallyLinkAChildToRoot(rootx, childx);
360 m_taintChildren.Add(child);
349 }); 361 });
350 } 362 }
351 return; 363 return;
@@ -378,10 +390,8 @@ public class BSLinkset
378 390
379 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 391 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
380 { 392 {
381 if (m_taintChildren.Contains(childx)) 393 m_taintChildren.Remove(child);
382 m_taintChildren.Remove(childx); 394 PhysicallyUnlinkAChildFromRoot(rootx, childx);
383
384 PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody);
385 RecomputeLinksetConstraintVariables(); 395 RecomputeLinksetConstraintVariables();
386 }); 396 });
387 397
@@ -396,8 +406,7 @@ public class BSLinkset
396 406
397 // Create a constraint between me (root of linkset) and the passed prim (the child). 407 // Create a constraint between me (root of linkset) and the passed prim (the child).
398 // Called at taint time! 408 // Called at taint time!
399 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody, 409 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
400 BSPhysObject childPrim, BulletBody childBody)
401 { 410 {
402 // Zero motion for children so they don't interpolate 411 // Zero motion for children so they don't interpolate
403 childPrim.ZeroMotion(); 412 childPrim.ZeroMotion();
@@ -409,33 +418,17 @@ public class BSLinkset
409 // real world coordinate of midpoint between the two objects 418 // real world coordinate of midpoint between the two objects
410 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); 419 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
411 420
412 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", 421 DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
413 rootPrim.LocalID, 422 rootPrim.LocalID,
414 rootPrim.LocalID, rootBody.ptr.ToString("X"), 423 rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
415 childPrim.LocalID, childBody.ptr.ToString("X"), 424 childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"),
416 rootPrim.Position, childPrim.Position, midPoint); 425 rootPrim.Position, childPrim.Position, midPoint);
417 426
418 // create a constraint that allows no freedom of movement between the two objects 427 // create a constraint that allows no freedom of movement between the two objects
419 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 428 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
420 429
421 // There is great subtlty in these paramters. Notice the check for a ptr of zero.
422 // We pass the BulletBody structure into the taint in order to capture the pointer
423 // of the body at the time of constraint creation. This doesn't work for the very first
424 // construction because there is no body yet. The body
425 // is constructed later at taint time. Thus we use the body address at time of the
426 // taint creation but, if it is zero, use what's in the prim at the moment.
427 // There is a possible race condition since shape can change without a taint call
428 // (like changing to a mesh that is already constructed). The fix for that would be
429 // to only change BSShape at taint time thus syncronizing these operations at
430 // the cost of efficiency and lag.
431 BS6DofConstraint constrain = new BS6DofConstraint( 430 BS6DofConstraint constrain = new BS6DofConstraint(
432 PhysicsScene.World, 431 PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true );
433 rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody,
434 childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody,
435 midPoint,
436 true,
437 true
438 );
439 432
440 /* NOTE: below is an attempt to build constraint with full frame computation, etc. 433 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
441 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms 434 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
@@ -452,7 +445,7 @@ public class BSLinkset
452 445
453 // create a constraint that allows no freedom of movement between the two objects 446 // create a constraint that allows no freedom of movement between the two objects
454 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 447 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
455 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 448 DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
456 BS6DofConstraint constrain = new BS6DofConstraint( 449 BS6DofConstraint constrain = new BS6DofConstraint(
457 PhysicsScene.World, rootPrim.Body, childPrim.Body, 450 PhysicsScene.World, rootPrim.Body, childPrim.Body,
458 OMV.Vector3.Zero, 451 OMV.Vector3.Zero,
@@ -486,39 +479,44 @@ public class BSLinkset
486 { 479 {
487 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); 480 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
488 } 481 }
489
490 RecomputeLinksetConstraintVariables();
491 } 482 }
492 483
493 // Remove linkage between myself and a particular child 484 // Remove linkage between myself and a particular child
494 // The root and child bodies are passed in because we need to remove the constraint between 485 // The root and child bodies are passed in because we need to remove the constraint between
495 // the bodies that were at unlink time. 486 // the bodies that were at unlink time.
496 // Called at taint time! 487 // Called at taint time!
497 private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, 488 private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
498 BSPhysObject childPrim, BulletBody childBody)
499 { 489 {
500 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", 490 bool ret = false;
491 DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
501 rootPrim.LocalID, 492 rootPrim.LocalID,
502 rootPrim.LocalID, rootBody.ptr.ToString("X"), 493 rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
503 childPrim.LocalID, childBody.ptr.ToString("X")); 494 childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"));
504 495
505 // Find the constraint for this link and get rid of it from the overall collection and from my list 496 // Find the constraint for this link and get rid of it from the overall collection and from my list
506 PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody); 497 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody))
498 {
499 // Make the child refresh its location
500 BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
501 ret = true;
502 }
507 503
508 // Make the child refresh its location 504 return ret;
509 BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
510 } 505 }
511 506
512 /*
513 // Remove linkage between myself and any possible children I might have. 507 // Remove linkage between myself and any possible children I might have.
514 // Called at taint time! 508 // Called at taint time!
515 private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) 509 private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
516 { 510 {
517 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 511 DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
512 bool ret = false;
518 513
519 PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); 514 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody))
515 {
516 ret = true;
517 }
518 return ret;
520 } 519 }
521 */
522 520
523 // Call each of the constraints that make up this linkset and recompute the 521 // Call each of the constraints that make up this linkset and recompute the
524 // various transforms and variables. Used when objects are added or removed 522 // various transforms and variables. Used when objects are added or removed
@@ -550,11 +548,17 @@ public class BSLinkset
550 { 548 {
551 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass 549 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
552 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); 550 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
553 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); 551 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr,
552 centerOfMass, OMV.Quaternion.Identity);
553 DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}",
554 LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"));
554 foreach (BSPhysObject child in m_taintChildren) 555 foreach (BSPhysObject child in m_taintChildren)
555 { 556 {
556 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); 557 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr,
558 centerOfMass, OMV.Quaternion.Identity);
557 } 559 }
560
561 // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG
558 } 562 }
559 return; 563 return;
560 } 564 }
@@ -563,7 +567,8 @@ public class BSLinkset
563 // Invoke the detailed logger and output something if it's enabled. 567 // Invoke the detailed logger and output something if it's enabled.
564 private void DetailLog(string msg, params Object[] args) 568 private void DetailLog(string msg, params Object[] args)
565 { 569 {
566 PhysicsScene.PhysicsLogging.Write(msg, args); 570 if (PhysicsScene.PhysicsLogging.Enabled)
571 PhysicsScene.DetailLog(msg, args);
567 } 572 }
568 573
569} 574}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 1ac8c59..cae599c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -85,6 +85,10 @@ public abstract class BSPhysObject : PhysicsActor
85 85
86 public abstract OMV.Quaternion ForceOrientation { get; set; } 86 public abstract OMV.Quaternion ForceOrientation { get; set; }
87 87
88 public abstract OMV.Vector3 ForceVelocity { get; set; }
89
90 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
91
88 #region Collisions 92 #region Collisions
89 93
90 // Requested number of milliseconds between collision events. Zero means disabled. 94 // Requested number of milliseconds between collision events. Zero means disabled.
@@ -207,7 +211,8 @@ public abstract class BSPhysObject : PhysicsActor
207 // High performance detailed logging routine used by the physical objects. 211 // High performance detailed logging routine used by the physical objects.
208 protected void DetailLog(string msg, params Object[] args) 212 protected void DetailLog(string msg, params Object[] args)
209 { 213 {
210 PhysicsScene.PhysicsLogging.Write(msg, args); 214 if (PhysicsScene.PhysicsLogging.Enabled)
215 PhysicsScene.DetailLog(msg, args);
211 } 216 }
212} 217}
213} 218}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index f7b68ba..6a4365c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -196,7 +196,7 @@ public sealed class BSPrim : BSPhysObject
196 _isSelected = value; 196 _isSelected = value;
197 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 197 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
198 { 198 {
199 // DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 199 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
200 SetObjectDynamic(false); 200 SetObjectDynamic(false);
201 }); 201 });
202 } 202 }
@@ -265,6 +265,11 @@ public sealed class BSPrim : BSPhysObject
265 return _position; 265 return _position;
266 } 266 }
267 set { 267 set {
268 // If you must push the position into the physics engine, use ForcePosition.
269 if (_position == value)
270 {
271 return;
272 }
268 _position = value; 273 _position = value;
269 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 274 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
270 PositionSanityCheck(); 275 PositionSanityCheck();
@@ -322,7 +327,7 @@ public sealed class BSPrim : BSPhysObject
322 // A version of the sanity check that also makes sure a new position value is 327 // A version of the sanity check that also makes sure a new position value is
323 // pushed back to the physics engine. This routine would be used by anyone 328 // pushed back to the physics engine. This routine would be used by anyone
324 // who is not already pushing the value. 329 // who is not already pushing the value.
325 private bool PositionSanityCheck2(bool atTaintTime) 330 private bool PositionSanityCheck2(bool inTaintTime)
326 { 331 {
327 bool ret = false; 332 bool ret = false;
328 if (PositionSanityCheck()) 333 if (PositionSanityCheck())
@@ -334,7 +339,7 @@ public sealed class BSPrim : BSPhysObject
334 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 339 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
335 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); 340 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
336 }; 341 };
337 if (atTaintTime) 342 if (inTaintTime)
338 sanityOperation(); 343 sanityOperation();
339 else 344 else
340 PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); 345 PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation);
@@ -453,7 +458,6 @@ public sealed class BSPrim : BSPhysObject
453 } 458 }
454 return; 459 return;
455 } 460 }
456
457 public override OMV.Vector3 Velocity { 461 public override OMV.Vector3 Velocity {
458 get { return _velocity; } 462 get { return _velocity; }
459 set { 463 set {
@@ -465,6 +469,13 @@ public sealed class BSPrim : BSPhysObject
465 }); 469 });
466 } 470 }
467 } 471 }
472 public override OMV.Vector3 ForceVelocity {
473 get { return _velocity; }
474 set {
475 _velocity = value;
476 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
477 }
478 }
468 public override OMV.Vector3 Torque { 479 public override OMV.Vector3 Torque {
469 get { return _torque; } 480 get { return _torque; }
470 set { _torque = value; 481 set { _torque = value;
@@ -490,6 +501,8 @@ public sealed class BSPrim : BSPhysObject
490 return _orientation; 501 return _orientation;
491 } 502 }
492 set { 503 set {
504 if (_orientation == value)
505 return;
493 _orientation = value; 506 _orientation = value;
494 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 507 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
495 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 508 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
@@ -570,7 +583,7 @@ public sealed class BSPrim : BSPhysObject
570 // Set up the object physicalness (does gravity and collisions move this object) 583 // Set up the object physicalness (does gravity and collisions move this object)
571 MakeDynamic(IsStatic); 584 MakeDynamic(IsStatic);
572 585
573 // Update vehicle specific parameters 586 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
574 _vehicle.Refresh(); 587 _vehicle.Refresh();
575 588
576 // Arrange for collision events if the simulator wants them 589 // Arrange for collision events if the simulator wants them
@@ -593,7 +606,7 @@ public sealed class BSPrim : BSPhysObject
593 // Recompute any linkset parameters. 606 // Recompute any linkset parameters.
594 // When going from non-physical to physical, this re-enables the constraints that 607 // When going from non-physical to physical, this re-enables the constraints that
595 // had been automatically disabled when the mass was set to zero. 608 // had been automatically disabled when the mass was set to zero.
596 Linkset.Refresh(this); 609 Linkset.Refresh(this, true);
597 610
598 DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", 611 DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
599 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); 612 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape);
@@ -620,8 +633,10 @@ public sealed class BSPrim : BSPhysObject
620 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); 633 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
621 // There can be special things needed for implementing linksets 634 // There can be special things needed for implementing linksets
622 Linkset.MakeStatic(this); 635 Linkset.MakeStatic(this);
623 // The activation state is 'disabled' so Bullet will not try to act on it 636 // The activation state is 'disabled' so Bullet will not try to act on it.
624 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); 637 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION);
638 // Start it out sleeping and physical actions could wake it up.
639 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
625 640
626 BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; 641 BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
627 BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; 642 BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
@@ -638,6 +653,9 @@ public sealed class BSPrim : BSPhysObject
638 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 653 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
639 BulletSimAPI.ClearAllForces2(BSBody.ptr); 654 BulletSimAPI.ClearAllForces2(BSBody.ptr);
640 655
656 // For good measure, make sure the transform is set through to the motion state
657 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
658
641 // A dynamic object has mass 659 // A dynamic object has mass
642 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); 660 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr);
643 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); 661 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
@@ -655,8 +673,8 @@ public sealed class BSPrim : BSPhysObject
655 673
656 // Force activation of the object so Bullet will act on it. 674 // Force activation of the object so Bullet will act on it.
657 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 675 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
658 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); 676 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
659 BulletSimAPI.Activate2(BSBody.ptr, true); 677 // BulletSimAPI.Activate2(BSBody.ptr, true);
660 678
661 BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; 679 BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
662 BSBody.collisionMask = CollisionFilterGroups.ObjectMask; 680 BSBody.collisionMask = CollisionFilterGroups.ObjectMask;
@@ -774,6 +792,15 @@ public sealed class BSPrim : BSPhysObject
774 }); 792 });
775 } 793 }
776 } 794 }
795 public override OMV.Vector3 ForceRotationalVelocity {
796 get {
797 return _rotationalVelocity;
798 }
799 set {
800 _rotationalVelocity = value;
801 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity);
802 }
803 }
777 public override bool Kinematic { 804 public override bool Kinematic {
778 get { return _kinematic; } 805 get { return _kinematic; }
779 set { _kinematic = value; 806 set { _kinematic = value;
@@ -828,6 +855,9 @@ public sealed class BSPrim : BSPhysObject
828 855
829 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); 856 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
830 public override void AddForce(OMV.Vector3 force, bool pushforce) { 857 public override void AddForce(OMV.Vector3 force, bool pushforce) {
858 AddForce(force, pushforce, false);
859 }
860 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
831 // for an object, doesn't matter if force is a pushforce or not 861 // for an object, doesn't matter if force is a pushforce or not
832 if (force.IsFinite()) 862 if (force.IsFinite())
833 { 863 {
@@ -840,11 +870,12 @@ public sealed class BSPrim : BSPhysObject
840 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 870 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
841 return; 871 return;
842 } 872 }
843 PhysicsScene.TaintedObject("BSPrim.AddForce", delegate() 873 BSScene.TaintCallback addForceOperation = delegate()
844 { 874 {
845 OMV.Vector3 fSum = OMV.Vector3.Zero; 875 OMV.Vector3 fSum = OMV.Vector3.Zero;
846 lock (m_accumulatedForces) 876 lock (m_accumulatedForces)
847 { 877 {
878 // Sum the accumulated additional forces for one big force to apply once.
848 foreach (OMV.Vector3 v in m_accumulatedForces) 879 foreach (OMV.Vector3 v in m_accumulatedForces)
849 { 880 {
850 fSum += v; 881 fSum += v;
@@ -854,7 +885,11 @@ public sealed class BSPrim : BSPhysObject
854 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); 885 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
855 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. 886 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
856 BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); 887 BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum);
857 }); 888 };
889 if (inTaintTime)
890 addForceOperation();
891 else
892 PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation);
858 } 893 }
859 894
860 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 895 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
@@ -1204,6 +1239,7 @@ public sealed class BSPrim : BSPhysObject
1204 { 1239 {
1205 // Called if the current prim body is about to be destroyed. 1240 // Called if the current prim body is about to be destroyed.
1206 // Remove all the physical dependencies on the old body. 1241 // Remove all the physical dependencies on the old body.
1242 // (Maybe someday make the changing of BSShape an event handled by BSLinkset.)
1207 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); 1243 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
1208 }); 1244 });
1209 1245
@@ -1294,6 +1330,8 @@ public sealed class BSPrim : BSPhysObject
1294 1330
1295 PositionSanityCheck2(true); 1331 PositionSanityCheck2(true);
1296 1332
1333 Linkset.UpdateProperties(this);
1334
1297 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1335 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1298 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1336 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1299 1337
@@ -1304,7 +1342,7 @@ public sealed class BSPrim : BSPhysObject
1304 /* 1342 /*
1305 else 1343 else
1306 { 1344 {
1307 // For debugging, we can also report the movement of children 1345 // For debugging, report the movement of children
1308 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1346 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1309 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1347 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1310 entprop.Acceleration, entprop.RotationalVelocity); 1348 entprop.Acceleration, entprop.RotationalVelocity);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index aaed7de..2c3c481 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,7 +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// Move all logic out of the C++ code and into the C# code for easier future modifications.
43// Test sculpties (verified that they don't work) 42// Test sculpties (verified that they don't work)
44// Compute physics FPS reasonably 43// Compute physics FPS reasonably
45// Based on material, set density and friction 44// Based on material, set density and friction
@@ -90,10 +89,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
90 // let my minuions use my logger 89 // let my minuions use my logger
91 public ILog Logger { get { return m_log; } } 90 public ILog Logger { get { return m_log; } }
92 91
93 // If non-zero, the number of simulation steps between calls to the physics
94 // engine to output detailed physics stats. Debug logging level must be on also.
95 private int m_detailedStatsStep = 0;
96
97 public IMesher mesher; 92 public IMesher mesher;
98 // Level of Detail values kept as float because that's what the Meshmerizer wants 93 // Level of Detail values kept as float because that's what the Meshmerizer wants
99 public float MeshLOD { get; private set; } 94 public float MeshLOD { get; private set; }
@@ -112,6 +107,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
112 private float m_fixedTimeStep; 107 private float m_fixedTimeStep;
113 private long m_simulationStep = 0; 108 private long m_simulationStep = 0;
114 public long SimulationStep { get { return m_simulationStep; } } 109 public long SimulationStep { get { return m_simulationStep; } }
110 private int m_taintsToProcessPerStep;
115 111
116 // A value of the time now so all the collision and update routines do not have to get their own 112 // A value of the time now so all the collision and update routines do not have to get their own
117 // Set to 'now' just before all the prims and actors are called for collisions and updates 113 // Set to 'now' just before all the prims and actors are called for collisions and updates
@@ -131,6 +127,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
131 127
132 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed 128 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
133 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes 129 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
130 public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
134 131
135 public float PID_D { get; private set; } // derivative 132 public float PID_D { get; private set; } // derivative
136 public float PID_P { get; private set; } // proportional 133 public float PID_P { get; private set; } // proportional
@@ -254,7 +251,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
254 251
255 // The bounding box for the simulated world. The origin is 0,0,0 unless we're 252 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
256 // a child in a mega-region. 253 // a child in a mega-region.
257 // Turns out that Bullet really doesn't care about the extents of the simulated 254 // Bullet actually doesn't care about the extents of the simulated
258 // area. It tracks active objects no matter where they are. 255 // area. It tracks active objects no matter where they are.
259 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 256 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
260 257
@@ -331,7 +328,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
331 // Called directly from unmanaged code so don't do much 328 // Called directly from unmanaged code so don't do much
332 private void BulletLoggerPhysLog(string msg) 329 private void BulletLoggerPhysLog(string msg)
333 { 330 {
334 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); 331 DetailLog("[BULLETS UNMANAGED]:" + msg);
335 } 332 }
336 333
337 public override void Dispose() 334 public override void Dispose()
@@ -494,8 +491,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
494 m_simulationStep++; 491 m_simulationStep++;
495 int numSubSteps = 0; 492 int numSubSteps = 0;
496 493
497 // Sometimes needed for debugging to find out what happened before the step 494 // DEBUG
498 // PhysicsLogging.Flush(); 495 // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep);
499 496
500 try 497 try
501 { 498 {
@@ -505,8 +502,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
505 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 502 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
506 503
507 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); 504 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
508 DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}", 505 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
509 DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); 506 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
510 } 507 }
511 catch (Exception e) 508 catch (Exception e)
512 { 509 {
@@ -582,19 +579,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
582 } 579 }
583 } 580 }
584 581
585 // If enabled, call into the physics engine to dump statistics
586 if (m_detailedStatsStep > 0)
587 {
588 if ((m_simulationStep % m_detailedStatsStep) == 0)
589 {
590 BulletSimAPI.DumpBulletStatistics();
591 }
592 }
593
594 // The physics engine returns the number of milliseconds it simulated this call. 582 // The physics engine returns the number of milliseconds it simulated this call.
595 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 583 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
596 // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. 584 // We multiply by 45 to give a recognizable running rate (45 or less).
597 return numSubSteps * m_fixedTimeStep * 1000; 585 return numSubSteps * m_fixedTimeStep * 1000 * 45;
586 // return timeStep * 1000 * 45;
598 } 587 }
599 588
600 // Something has collided 589 // Something has collided
@@ -617,7 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
617 BSPhysObject collidee = null; 606 BSPhysObject collidee = null;
618 PhysObjects.TryGetValue(collidingWith, out collidee); 607 PhysObjects.TryGetValue(collidingWith, out collidee);
619 608
620 DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); 609 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
621 610
622 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) 611 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
623 { 612 {
@@ -704,6 +693,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
704 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process 693 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
705 { 694 {
706 // swizzle a new list into the list location so we can process what's there 695 // swizzle a new list into the list location so we can process what's there
696 int taintCount = m_taintsToProcessPerStep;
697 TaintCallbackEntry oneCallback = new TaintCallbackEntry();
698 while (_taintedObjects.Count > 0 && taintCount-- > 0)
699 {
700 bool gotOne = false;
701 lock (_taintLock)
702 {
703 if (_taintedObjects.Count > 0)
704 {
705 oneCallback = _taintedObjects[0];
706 _taintedObjects.RemoveAt(0);
707 gotOne = true;
708 }
709 }
710 if (gotOne)
711 {
712 try
713 {
714 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
715 oneCallback.callback();
716 }
717 catch (Exception e)
718 {
719 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
720 }
721 }
722 }
723 /*
724 // swizzle a new list into the list location so we can process what's there
707 List<TaintCallbackEntry> oldList; 725 List<TaintCallbackEntry> oldList;
708 lock (_taintLock) 726 lock (_taintLock)
709 { 727 {
@@ -715,6 +733,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
715 { 733 {
716 try 734 try
717 { 735 {
736 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
718 tcbe.callback(); 737 tcbe.callback();
719 } 738 }
720 catch (Exception e) 739 catch (Exception e)
@@ -723,6 +742,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
723 } 742 }
724 } 743 }
725 oldList.Clear(); 744 oldList.Clear();
745 */
726 } 746 }
727 } 747 }
728 748
@@ -834,6 +854,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
834 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, 854 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
835 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, 855 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
836 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), 856 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
857 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
858 ConfigurationParameters.numericTrue,
859 (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
860 (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
861 (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
837 862
838 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 863 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
839 8f, 864 8f,
@@ -876,6 +901,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
876 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, 901 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
877 (s) => { return (float)s.m_maxUpdatesPerFrame; }, 902 (s) => { return (float)s.m_maxUpdatesPerFrame; },
878 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), 903 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
904 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
905 100f,
906 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
907 (s) => { return (float)s.m_taintsToProcessPerStep; },
908 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
879 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 909 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
880 10000.01f, 910 10000.01f,
881 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, 911 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
@@ -1070,12 +1100,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1070 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, 1100 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1071 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), 1101 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1072 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", 1102 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1073 0.1f, 1103 0.001f,
1074 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, 1104 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1075 (s) => { return s.m_params[0].linkConstraintCFM; }, 1105 (s) => { return s.m_params[0].linkConstraintCFM; },
1076 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), 1106 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
1077 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", 1107 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1078 0.2f, 1108 0.8f,
1079 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, 1109 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1080 (s) => { return s.m_params[0].linkConstraintERP; }, 1110 (s) => { return s.m_params[0].linkConstraintERP; },
1081 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), 1111 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
@@ -1085,11 +1115,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1085 (s) => { return s.m_params[0].linkConstraintSolverIterations; }, 1115 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1086 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), 1116 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1087 1117
1088 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 1118 new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
1089 0f, 1119 0f,
1090 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, 1120 (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
1091 (s) => { return (float)s.m_detailedStatsStep; }, 1121 (s) => { return (float)s.m_params[0].physicsLoggingFrames; },
1092 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1122 (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ),
1093 }; 1123 };
1094 1124
1095 // Convert a boolean to our numeric true and false values 1125 // Convert a boolean to our numeric true and false values
@@ -1270,6 +1300,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1270 public void DetailLog(string msg, params Object[] args) 1300 public void DetailLog(string msg, params Object[] args)
1271 { 1301 {
1272 PhysicsLogging.Write(msg, args); 1302 PhysicsLogging.Write(msg, args);
1303 // Add the Flush() if debugging crashes to get all the messages written out.
1304 // PhysicsLogging.Flush();
1273 } 1305 }
1274 // used to fill in the LocalID when there isn't one 1306 // used to fill in the LocalID when there isn't one
1275 public const string DetailLogZero = "0000000000"; 1307 public const string DetailLogZero = "0000000000";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 399a133..d189f1d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -67,8 +67,8 @@ public class BSShapeCollection : IDisposable
67 public DateTime lastReferenced; 67 public DateTime lastReferenced;
68 } 68 }
69 69
70 private Dictionary<ulong, MeshDesc> Meshes = new Dictionary<ulong, MeshDesc>(); 70 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
71 private Dictionary<ulong, HullDesc> Hulls = new Dictionary<ulong, HullDesc>(); 71 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
72 private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>(); 72 private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>();
73 73
74 public BSShapeCollection(BSScene physScene) 74 public BSShapeCollection(BSScene physScene)
@@ -121,7 +121,7 @@ public class BSShapeCollection : IDisposable
121 // Track another user of a body 121 // Track another user of a body
122 // We presume the caller has allocated the body. 122 // We presume the caller has allocated the body.
123 // Bodies only have one user so the reference count is either 1 or 0. 123 // Bodies only have one user so the reference count is either 1 or 0.
124 public void ReferenceBody(BulletBody body, bool atTaintTime) 124 public void ReferenceBody(BulletBody body, bool inTaintTime)
125 { 125 {
126 lock (m_collectionActivityLock) 126 lock (m_collectionActivityLock)
127 { 127 {
@@ -136,7 +136,21 @@ public class BSShapeCollection : IDisposable
136 // New entry 136 // New entry
137 bodyDesc.ptr = body.ptr; 137 bodyDesc.ptr = body.ptr;
138 bodyDesc.referenceCount = 1; 138 bodyDesc.referenceCount = 1;
139 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", body.ID, body, bodyDesc.referenceCount); 139 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}",
140 body.ID, body, bodyDesc.referenceCount);
141 BSScene.TaintCallback createOperation = delegate()
142 {
143 if (!BulletSimAPI.IsInWorld2(body.ptr))
144 {
145 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
146 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}",
147 body.ID, body);
148 }
149 };
150 if (inTaintTime)
151 createOperation();
152 else
153 PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation);
140 } 154 }
141 bodyDesc.lastReferenced = System.DateTime.Now; 155 bodyDesc.lastReferenced = System.DateTime.Now;
142 Bodies[body.ID] = bodyDesc; 156 Bodies[body.ID] = bodyDesc;
@@ -160,21 +174,22 @@ public class BSShapeCollection : IDisposable
160 Bodies[body.ID] = bodyDesc; 174 Bodies[body.ID] = bodyDesc;
161 DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); 175 DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount);
162 176
163 // If body is no longer being used, free it -- bodies are never shared. 177 // If body is no longer being used, free it -- bodies can never be shared.
164 if (bodyDesc.referenceCount == 0) 178 if (bodyDesc.referenceCount == 0)
165 { 179 {
166 Bodies.Remove(body.ID); 180 Bodies.Remove(body.ID);
167 BSScene.TaintCallback removeOperation = delegate() 181 BSScene.TaintCallback removeOperation = delegate()
168 { 182 {
169 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", 183 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}",
170 body.ID, body.ptr.ToString("X")); 184 body.ID, body.ptr.ToString("X"), inTaintTime);
171 // If the caller needs to know the old body is going away, pass the event up. 185 // If the caller needs to know the old body is going away, pass the event up.
172 if (bodyCallback != null) bodyCallback(body); 186 if (bodyCallback != null) bodyCallback(body);
173 187
174 // Zero any reference to the shape so it is not freed when the body is deleted.
175 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
176 // It may have already been removed from the world in which case the next is a NOOP. 188 // It may have already been removed from the world in which case the next is a NOOP.
177 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); 189 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
190
191 // Zero any reference to the shape so it is not freed when the body is deleted.
192 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
178 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); 193 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
179 }; 194 };
180 // If already in taint-time, do the operations now. Otherwise queue for later. 195 // If already in taint-time, do the operations now. Otherwise queue for later.
@@ -208,7 +223,7 @@ public class BSShapeCollection : IDisposable
208 { 223 {
209 // There is an existing instance of this mesh. 224 // There is an existing instance of this mesh.
210 meshDesc.referenceCount++; 225 meshDesc.referenceCount++;
211 DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}", 226 DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
212 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 227 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
213 } 228 }
214 else 229 else
@@ -217,7 +232,7 @@ public class BSShapeCollection : IDisposable
217 meshDesc.ptr = shape.ptr; 232 meshDesc.ptr = shape.ptr;
218 // We keep a reference to the underlying IMesh data so a hull can be built 233 // We keep a reference to the underlying IMesh data so a hull can be built
219 meshDesc.referenceCount = 1; 234 meshDesc.referenceCount = 1;
220 DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}", 235 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
221 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 236 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
222 ret = true; 237 ret = true;
223 } 238 }
@@ -230,7 +245,7 @@ public class BSShapeCollection : IDisposable
230 { 245 {
231 // There is an existing instance of this hull. 246 // There is an existing instance of this hull.
232 hullDesc.referenceCount++; 247 hullDesc.referenceCount++;
233 DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}", 248 DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
234 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 249 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
235 } 250 }
236 else 251 else
@@ -238,7 +253,7 @@ public class BSShapeCollection : IDisposable
238 // This is a new reference to a hull 253 // This is a new reference to a hull
239 hullDesc.ptr = shape.ptr; 254 hullDesc.ptr = shape.ptr;
240 hullDesc.referenceCount = 1; 255 hullDesc.referenceCount = 1;
241 DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}", 256 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
242 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 257 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
243 ret = true; 258 ret = true;
244 259
@@ -257,7 +272,7 @@ public class BSShapeCollection : IDisposable
257 272
258 // Release the usage of a shape. 273 // Release the usage of a shape.
259 // The collisionObject is released since it is a copy of the real collision shape. 274 // The collisionObject is released since it is a copy of the real collision shape.
260 public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) 275 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
261 { 276 {
262 if (shape.ptr == IntPtr.Zero) 277 if (shape.ptr == IntPtr.Zero)
263 return; 278 return;
@@ -279,14 +294,14 @@ public class BSShapeCollection : IDisposable
279 if (shape.ptr != IntPtr.Zero & shape.isNativeShape) 294 if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
280 { 295 {
281 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", 296 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
282 BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); 297 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
283 if (shapeCallback != null) shapeCallback(shape); 298 if (shapeCallback != null) shapeCallback(shape);
284 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 299 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
285 } 300 }
286 break; 301 break;
287 } 302 }
288 }; 303 };
289 if (atTaintTime) 304 if (inTaintTime)
290 { 305 {
291 lock (m_collectionActivityLock) 306 lock (m_collectionActivityLock)
292 { 307 {
@@ -358,7 +373,8 @@ public class BSShapeCollection : IDisposable
358 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 373 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
359 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) 374 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
360 { 375 {
361 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 376 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
377 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
362 { 378 {
363 haveShape = true; 379 haveShape = true;
364 if (forceRebuild 380 if (forceRebuild
@@ -372,7 +388,7 @@ public class BSShapeCollection : IDisposable
372 prim.LocalID, forceRebuild, prim.BSShape); 388 prim.LocalID, forceRebuild, prim.BSShape);
373 } 389 }
374 } 390 }
375 else 391 if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
376 { 392 {
377 haveShape = true; 393 haveShape = true;
378 if (forceRebuild 394 if (forceRebuild
@@ -392,7 +408,7 @@ public class BSShapeCollection : IDisposable
392 // made. Native shapes are best used in either case. 408 // made. Native shapes are best used in either case.
393 if (!haveShape) 409 if (!haveShape)
394 { 410 {
395 if (prim.IsPhysical) 411 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects)
396 { 412 {
397 // Update prim.BSShape to reference a hull of this shape. 413 // Update prim.BSShape to reference a hull of this shape.
398 ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); 414 ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback);
@@ -426,7 +442,7 @@ public class BSShapeCollection : IDisposable
426 442
427 // Native shapes are always built independently. 443 // Native shapes are always built independently.
428 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); 444 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
429 newShape.shapeKey = (ulong)shapeKey; 445 newShape.shapeKey = (System.UInt64)shapeKey;
430 newShape.isNativeShape = true; 446 newShape.isNativeShape = true;
431 447
432 // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. 448 // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked.
@@ -446,7 +462,7 @@ public class BSShapeCollection : IDisposable
446 BulletShape newShape = new BulletShape(IntPtr.Zero); 462 BulletShape newShape = new BulletShape(IntPtr.Zero);
447 463
448 float lod; 464 float lod;
449 ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); 465 System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);
450 466
451 // if this new shape is the same as last time, don't recreate the mesh 467 // if this new shape is the same as last time, don't recreate the mesh
452 if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) 468 if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
@@ -469,7 +485,7 @@ public class BSShapeCollection : IDisposable
469 return true; // 'true' means a new shape has been added to this prim 485 return true; // 'true' means a new shape has been added to this prim
470 } 486 }
471 487
472 private BulletShape CreatePhysicalMesh(string objName, ulong newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 488 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
473 { 489 {
474 IMesh meshData = null; 490 IMesh meshData = null;
475 IntPtr meshPtr; 491 IntPtr meshPtr;
@@ -516,7 +532,7 @@ public class BSShapeCollection : IDisposable
516 BulletShape newShape; 532 BulletShape newShape;
517 533
518 float lod; 534 float lod;
519 ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); 535 System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod);
520 536
521 // if the hull hasn't changed, don't rebuild it 537 // if the hull hasn't changed, don't rebuild it
522 if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) 538 if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
@@ -525,7 +541,7 @@ public class BSShapeCollection : IDisposable
525 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", 541 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
526 prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); 542 prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
527 543
528 // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. 544 // Remove usage of the previous shape.
529 DereferenceShape(prim.BSShape, true, shapeCallback); 545 DereferenceShape(prim.BSShape, true, shapeCallback);
530 546
531 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); 547 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
@@ -539,7 +555,7 @@ public class BSShapeCollection : IDisposable
539 } 555 }
540 556
541 List<ConvexResult> m_hulls; 557 List<ConvexResult> m_hulls;
542 private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 558 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
543 { 559 {
544 560
545 IntPtr hullPtr; 561 IntPtr hullPtr;
@@ -652,22 +668,23 @@ public class BSShapeCollection : IDisposable
652 668
653 // Create a hash of all the shape parameters to be used as a key 669 // Create a hash of all the shape parameters to be used as a key
654 // for this particular shape. 670 // for this particular shape.
655 private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) 671 private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod)
656 { 672 {
657 // level of detail based on size and type of the object 673 // level of detail based on size and type of the object
658 float lod = PhysicsScene.MeshLOD; 674 float lod = PhysicsScene.MeshLOD;
659 if (pbs.SculptEntry) 675 if (pbs.SculptEntry)
660 lod = PhysicsScene.SculptLOD; 676 lod = PhysicsScene.SculptLOD;
661 677
678 // Mega prims usually get more detail because one can interact with shape approximations at this size.
662 float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); 679 float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
663 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) 680 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
664 lod = PhysicsScene.MeshMegaPrimLOD; 681 lod = PhysicsScene.MeshMegaPrimLOD;
665 682
666 retLod = lod; 683 retLod = lod;
667 return (ulong)pbs.GetMeshKey(shapeData.Size, lod); 684 return pbs.GetMeshKey(shapeData.Size, lod);
668 } 685 }
669 // For those who don't want the LOD 686 // For those who don't want the LOD
670 private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) 687 private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs)
671 { 688 {
672 float lod; 689 float lod;
673 return ComputeShapeKey(shapeData, pbs, out lod); 690 return ComputeShapeKey(shapeData, pbs, out lod);
@@ -701,6 +718,7 @@ public class BSShapeCollection : IDisposable
701 718
702 if (mustRebuild || forceRebuild) 719 if (mustRebuild || forceRebuild)
703 { 720 {
721 // Free any old body
704 DereferenceBody(prim.BSBody, true, bodyCallback); 722 DereferenceBody(prim.BSBody, true, bodyCallback);
705 723
706 BulletBody aBody; 724 BulletBody aBody;
@@ -709,13 +727,13 @@ public class BSShapeCollection : IDisposable
709 { 727 {
710 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, 728 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
711 shapeData.ID, shapeData.Position, shapeData.Rotation); 729 shapeData.ID, shapeData.Position, shapeData.Rotation);
712 // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 730 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
713 } 731 }
714 else 732 else
715 { 733 {
716 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, 734 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
717 shapeData.ID, shapeData.Position, shapeData.Rotation); 735 shapeData.ID, shapeData.Position, shapeData.Rotation);
718 // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 736 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
719 } 737 }
720 aBody = new BulletBody(shapeData.ID, bodyPtr); 738 aBody = new BulletBody(shapeData.ID, bodyPtr);
721 739
@@ -731,7 +749,8 @@ public class BSShapeCollection : IDisposable
731 749
732 private void DetailLog(string msg, params Object[] args) 750 private void DetailLog(string msg, params Object[] args)
733 { 751 {
734 PhysicsScene.PhysicsLogging.Write(msg, args); 752 if (PhysicsScene.PhysicsLogging.Enabled)
753 PhysicsScene.DetailLog(msg, args);
735 } 754 }
736} 755}
737} 756}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 70aa429..caf411e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -114,6 +114,8 @@ public class BSTerrainManager
114 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, 114 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
115 Vector3.Zero, Quaternion.Identity)); 115 Vector3.Zero, Quaternion.Identity));
116 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); 116 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
117 // Ground plane does not move
118 BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
117 // Everything collides with the ground plane. 119 // Everything collides with the ground plane.
118 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, 120 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
119 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); 121 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
@@ -201,10 +203,10 @@ public class BSTerrainManager
201 // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when 203 // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
202 // calling this routine from initialization or taint-time routines) or whether to delay 204 // calling this routine from initialization or taint-time routines) or whether to delay
203 // all the unmanaged activities to taint-time. 205 // all the unmanaged activities to taint-time.
204 private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool atTaintTime) 206 private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
205 { 207 {
206 DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},atTaintTime={3}", 208 DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
207 BSScene.DetailLogZero, minCoords, maxCoords, atTaintTime); 209 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
208 210
209 float minZ = float.MaxValue; 211 float minZ = float.MaxValue;
210 float maxZ = float.MinValue; 212 float maxZ = float.MinValue;
@@ -296,16 +298,16 @@ public class BSTerrainManager
296 mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, 298 mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID,
297 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); 299 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
298 300
301 // Create the terrain shape from the mapInfo
302 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
303 ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
304
299 // The terrain object initial position is at the center of the object 305 // The terrain object initial position is at the center of the object
300 Vector3 centerPos; 306 Vector3 centerPos;
301 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); 307 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
302 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); 308 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
303 centerPos.Z = minZ + ((maxZ - minZ) / 2f); 309 centerPos.Z = minZ + ((maxZ - minZ) / 2f);
304 310
305 // Create the terrain shape from the mapInfo
306 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
307 ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
308
309 mapInfo.terrainBody = new BulletBody(mapInfo.ID, 311 mapInfo.terrainBody = new BulletBody(mapInfo.ID,
310 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, 312 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr,
311 id, centerPos, Quaternion.Identity)); 313 id, centerPos, Quaternion.Identity));
@@ -320,9 +322,6 @@ public class BSTerrainManager
320 BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); 322 BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
321 BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 323 BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
322 324
323 BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, 0f, Vector3.Zero);
324 BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr);
325
326 // Return the new terrain to the world of physical objects 325 // Return the new terrain to the world of physical objects
327 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); 326 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
328 327
@@ -342,7 +341,7 @@ public class BSTerrainManager
342 341
343 // There is the option to do the changes now (we're already in 'taint time'), or 342 // There is the option to do the changes now (we're already in 'taint time'), or
344 // to do the Bullet operations later. 343 // to do the Bullet operations later.
345 if (atTaintTime) 344 if (inTaintTime)
346 rebuildOperation(); 345 rebuildOperation();
347 else 346 else
348 PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); 347 PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
@@ -381,7 +380,7 @@ public class BSTerrainManager
381 }; 380 };
382 381
383 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. 382 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
384 if (atTaintTime) 383 if (inTaintTime)
385 createOperation(); 384 createOperation();
386 else 385 else
387 PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); 386 PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index a43880d..276111c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -101,9 +101,8 @@ public struct BulletShape
101 } 101 }
102 public IntPtr ptr; 102 public IntPtr ptr;
103 public ShapeData.PhysicsShapeType type; 103 public ShapeData.PhysicsShapeType type;
104 public ulong shapeKey; 104 public System.UInt64 shapeKey;
105 public bool isNativeShape; 105 public bool isNativeShape;
106 // Hulls have an underlying mesh. A pointer to it is hidden here.
107 public override string ToString() 106 public override string ToString()
108 { 107 {
109 StringBuilder buff = new StringBuilder(); 108 StringBuilder buff = new StringBuilder();
@@ -192,8 +191,9 @@ public struct ShapeData
192 SHAPE_SPHERE = 5, 191 SHAPE_SPHERE = 5,
193 SHAPE_MESH = 6, 192 SHAPE_MESH = 6,
194 SHAPE_HULL = 7, 193 SHAPE_HULL = 7,
195 SHAPE_GROUNDPLANE = 8, 194 // following defined by BulletSim
196 SHAPE_TERRAIN = 9, 195 SHAPE_GROUNDPLANE = 20,
196 SHAPE_TERRAIN = 21,
197 }; 197 };
198 public uint ID; 198 public uint ID;
199 public PhysicsShapeType Type; 199 public PhysicsShapeType Type;
@@ -305,6 +305,8 @@ public struct ConfigurationParameters
305 public float linkConstraintCFM; 305 public float linkConstraintCFM;
306 public float linkConstraintSolverIterations; 306 public float linkConstraintSolverIterations;
307 307
308 public float physicsLoggingFrames;
309
308 public const float numericTrue = 1f; 310 public const float numericTrue = 1f;
309 public const float numericFalse = 0f; 311 public const float numericFalse = 0f;
310} 312}
@@ -1037,18 +1039,6 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
1037public static extern int GetNumConstraintRefs2(IntPtr obj); 1039public static extern int GetNumConstraintRefs2(IntPtr obj);
1038 1040
1039[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1041[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1040public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj);
1041
1042[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1043public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj);
1044
1045[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1046public static extern Vector3 GetPushVelocity2(IntPtr obj);
1047
1048[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1049public static extern Vector3 GetTurnVelocity2(IntPtr obj);
1050
1051[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1052public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); 1042public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
1053 1043
1054// ===================================================================================== 1044// =====================================================================================
@@ -1108,6 +1098,15 @@ public static extern float GetMargin2(IntPtr shape);
1108public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); 1098public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
1109 1099
1110[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1100[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1101public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
1102
1103[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1104public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
1105
1106[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1107public static extern void DumpAllInfo2(IntPtr sim);
1108
1109[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1111public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); 1110public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
1112 1111
1113[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1112[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index f3b0630..c736557 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin
100 private bool m_hackSentFly = false; 100 private bool m_hackSentFly = false;
101 private int m_requestedUpdateFrequency = 0; 101 private int m_requestedUpdateFrequency = 0;
102 private Vector3 m_taintPosition; 102 private Vector3 m_taintPosition;
103 103 internal bool m_avatarplanted = false;
104 /// <summary> 104 /// <summary>
105 /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force 105 /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force
106 /// while calculatios are going on 106 /// while calculatios are going on
@@ -413,7 +413,7 @@ namespace OpenSim.Region.Physics.OdePlugin
413 set 413 set
414 { 414 {
415 m_iscollidingObj = value; 415 m_iscollidingObj = value;
416 if (value) 416 if (value && !m_avatarplanted)
417 m_pidControllerActive = false; 417 m_pidControllerActive = false;
418 else 418 else
419 m_pidControllerActive = true; 419 m_pidControllerActive = true;
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 7a50c4c..cbe21e2 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -501,6 +501,8 @@ namespace OpenSim.Region.Physics.OdePlugin
501 public int physics_logging_interval = 0; 501 public int physics_logging_interval = 0;
502 public bool physics_logging_append_existing_logfile = false; 502 public bool physics_logging_append_existing_logfile = false;
503 503
504 private bool avplanted = false;
505 private bool av_av_collisions_off = false;
504 506
505 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); 507 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
506 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); 508 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
@@ -644,6 +646,9 @@ namespace OpenSim.Region.Physics.OdePlugin
644 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); 646 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
645 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); 647 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
646 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); 648 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
649 avplanted = physicsconfig.GetBoolean("av_planted", false);
650 av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false);
651
647 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); 652 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
648 653
649 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); 654 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
@@ -663,6 +668,8 @@ namespace OpenSim.Region.Physics.OdePlugin
663 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); 668 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
664 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); 669 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
665 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); 670 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
671
672
666 673
667 if (Environment.OSVersion.Platform == PlatformID.Unix) 674 if (Environment.OSVersion.Platform == PlatformID.Unix)
668 { 675 {
@@ -1309,6 +1316,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1309 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) 1316 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
1310 skipThisContact = true; // No collision on volume detect prims 1317 skipThisContact = true; // No collision on volume detect prims
1311 1318
1319 if (av_av_collisions_off)
1320 if ((p1 is OdeCharacter) && (p2 is OdeCharacter))
1321 skipThisContact = true;
1322
1312 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) 1323 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1313 skipThisContact = true; // No collision on volume detect prims 1324 skipThisContact = true; // No collision on volume detect prims
1314 1325
@@ -1972,7 +1983,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1972 1983
1973 newAv.Flying = isFlying; 1984 newAv.Flying = isFlying;
1974 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; 1985 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1975 1986 newAv.m_avatarplanted = avplanted;
1987
1976 return newAv; 1988 return newAv;
1977 } 1989 }
1978 1990
@@ -1987,6 +1999,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1987 1999
1988 internal void AddCharacter(OdeCharacter chr) 2000 internal void AddCharacter(OdeCharacter chr)
1989 { 2001 {
2002 chr.m_avatarplanted = avplanted;
1990 if (!_characters.Contains(chr)) 2003 if (!_characters.Contains(chr))
1991 { 2004 {
1992 _characters.Add(chr); 2005 _characters.Add(chr);