aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorMelanie2012-09-16 04:11:20 +0100
committerMelanie2012-09-16 04:11:20 +0100
commitdb774d4292588db1e2ac4a9fafe977ddbec353ee (patch)
tree5fc381d7cb96cc0d2b47e4807821f488c339ec13 /OpenSim/Region/Physics
parentMerge branch 'avination' into careminster (diff)
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC_OLD-db774d4292588db1e2ac4a9fafe977ddbec353ee.zip
opensim-SC_OLD-db774d4292588db1e2ac4a9fafe977ddbec353ee.tar.gz
opensim-SC_OLD-db774d4292588db1e2ac4a9fafe977ddbec353ee.tar.bz2
opensim-SC_OLD-db774d4292588db1e2ac4a9fafe977ddbec353ee.tar.xz
Merge branch 'master' into careminster
Conflicts: OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs OpenSim/Region/Framework/Scenes/EventManager.cs
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs21
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs16
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs225
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs61
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs250
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs230
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs60
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs45
9 files changed, 446 insertions, 464 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index fa22c78..526dbad 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -131,8 +131,6 @@ public class BSCharacter : BSPhysObject
131 BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); 131 BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
132 132
133 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); 133 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
134 // avatars get all collisions no matter what (makes walking on ground and such work)
135 BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
136 }); 134 });
137 135
138 return; 136 return;
@@ -480,11 +478,10 @@ public class BSCharacter : BSPhysObject
480 // Stop collision events 478 // Stop collision events
481 public override void UnSubscribeEvents() { 479 public override void UnSubscribeEvents() {
482 _subscribedEventsMs = 0; 480 _subscribedEventsMs = 0;
483 // Avatars get all their collision events 481 Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
484 // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() 482 {
485 // { 483 BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
486 // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 484 });
487 // });
488 } 485 }
489 // Return 'true' if someone has subscribed to events 486 // Return 'true' if someone has subscribed to events
490 public override bool SubscribedEvents() { 487 public override bool SubscribedEvents() {
@@ -532,20 +529,20 @@ public class BSCharacter : BSPhysObject
532 // The collision, if it should be reported to the character, is placed in a collection 529 // The collision, if it should be reported to the character, is placed in a collection
533 // that will later be sent to the simulator when SendCollisions() is called. 530 // that will later be sent to the simulator when SendCollisions() is called.
534 CollisionEventUpdate collisionCollection = null; 531 CollisionEventUpdate collisionCollection = null;
535 public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) 532 public override bool Collide(uint collidingWith, BSPhysObject collidee, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
536 { 533 {
537 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 534 bool ret = false;
538 535
539 // The following makes IsColliding() and IsCollidingGround() work 536 // The following makes IsColliding() and IsCollidingGround() work
540 _collidingStep = Scene.SimulationStep; 537 _collidingStep = Scene.SimulationStep;
541 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) 538 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
542 { 539 {
543 _collidingGroundStep = Scene.SimulationStep; 540 _collidingGroundStep = Scene.SimulationStep;
544 } 541 }
545 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); 542 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
546 543
547 // throttle collisions to the rate specified in the subscription 544 // throttle collisions to the rate specified in the subscription
548 if (_subscribedEventsMs != 0) { 545 if (SubscribedEvents()) {
549 int nowTime = Scene.SimulationNowTime; 546 int nowTime = Scene.SimulationNowTime;
550 if (nowTime >= _nextCollisionOkTime) { 547 if (nowTime >= _nextCollisionOkTime) {
551 _nextCollisionOkTime = nowTime + _subscribedEventsMs; 548 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
@@ -553,8 +550,10 @@ public class BSCharacter : BSPhysObject
553 if (collisionCollection == null) 550 if (collisionCollection == null)
554 collisionCollection = new CollisionEventUpdate(); 551 collisionCollection = new CollisionEventUpdate();
555 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 552 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
553 ret = true;
556 } 554 }
557 } 555 }
556 return ret;
558 } 557 }
559 558
560 public override void SendCollisions() 559 public override void SendCollisions()
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 2e15ced..1376a29 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -74,6 +74,17 @@ public abstract class BSConstraint : IDisposable
74 return ret; 74 return ret;
75 } 75 }
76 76
77 public virtual bool SetSolverIterations(float cnt)
78 {
79 bool ret = false;
80 if (m_enabled)
81 {
82 BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.Ptr, cnt);
83 ret = true;
84 }
85 return ret;
86 }
87
77 public virtual bool CalculateTransforms() 88 public virtual bool CalculateTransforms()
78 { 89 {
79 bool ret = false; 90 bool ret = false;
@@ -96,12 +107,9 @@ public abstract class BSConstraint : IDisposable
96 ret = CalculateTransforms(); 107 ret = CalculateTransforms();
97 if (ret) 108 if (ret)
98 { 109 {
99 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}",
100 // BSScene.DetailLogZero, Body1.ID, Body2.ID);
101
102 // Setting an object's mass to zero (making it static like when it's selected) 110 // Setting an object's mass to zero (making it static like when it's selected)
103 // automatically disables the constraints. 111 // automatically disables the constraints.
104 // If enabled, be sure to set the constraint itself to enabled. 112 // If the link is enabled, be sure to set the constraint itself to enabled.
105 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); 113 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
106 } 114 }
107 else 115 else
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 8169e99..61006f0 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
80 // Linear properties 80 // Linear properties
81 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time 81 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
82 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL 82 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
83 private Vector3 m_dir = Vector3.Zero; // velocity applied to body 83 private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body
84 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 84 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
85 private float m_linearMotorDecayTimescale = 0; 85 private float m_linearMotorDecayTimescale = 0;
86 private float m_linearMotorTimescale = 0; 86 private float m_linearMotorTimescale = 0;
@@ -131,7 +131,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
131 m_type = Vehicle.TYPE_NONE; 131 m_type = Vehicle.TYPE_NONE;
132 } 132 }
133 133
134 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) 134 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
135 { 135 {
136 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 136 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
137 switch (pParam) 137 switch (pParam)
@@ -230,7 +230,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
230 } 230 }
231 }//end ProcessFloatVehicleParam 231 }//end ProcessFloatVehicleParam
232 232
233 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) 233 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
234 { 234 {
235 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 235 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
236 switch (pParam) 236 switch (pParam)
@@ -299,7 +299,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
299 } 299 }
300 }//end ProcessVehicleFlags 300 }//end ProcessVehicleFlags
301 301
302 internal void ProcessTypeChange(Vehicle pType, float stepSize) 302 internal void ProcessTypeChange(Vehicle pType)
303 { 303 {
304 VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); 304 VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
305 // Set Defaults For Type 305 // Set Defaults For Type
@@ -478,29 +478,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin
478 MoveAngular(pTimestep); 478 MoveAngular(pTimestep);
479 LimitRotation(pTimestep); 479 LimitRotation(pTimestep);
480 480
481 // remember the position so next step we can limit absolute movement effects
482 m_lastPositionVector = m_prim.Position;
483
481 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 484 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
482 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); 485 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
483 }// end Step 486 }// end Step
484 487
485 private void MoveLinear(float pTimestep) 488 private void MoveLinear(float pTimestep)
486 { 489 {
487 // requested m_linearMotorDirection is significant 490 // m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates
488 // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) 491 // m_lastLinearVelocityVector is the speed we are moving in that direction
489 if (m_linearMotorDirection.LengthSquared() > 0.0001f) 492 if (m_linearMotorDirection.LengthSquared() > 0.001f)
490 { 493 {
491 Vector3 origDir = m_linearMotorDirection; 494 Vector3 origDir = m_linearMotorDirection;
492 Vector3 origVel = m_lastLinearVelocityVector; 495 Vector3 origVel = m_lastLinearVelocityVector;
493 496
494 // add drive to body 497 // add drive to body
495 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); 498 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale / pTimestep);
496 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); 499 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep);
497 // lastLinearVelocityVector is the current body velocity vector? 500 // lastLinearVelocityVector is the current body velocity vector
498 // RA: Not sure what the *10 is for. A correction for pTimestep? 501 // RA: Not sure what the *10 is for. A correction for pTimestep?
499 // m_lastLinearVelocityVector += (addAmount*10); 502 // m_lastLinearVelocityVector += (addAmount*10);
500 m_lastLinearVelocityVector += addAmount; 503 m_lastLinearVelocityVector += addAmount;
501 504
502 // This will work temporarily, but we really need to compare speed on an axis
503 // KF: Limit body velocity to applied velocity?
504 // Limit the velocity vector to less than the last set linear motor direction 505 // Limit the velocity vector to less than the last set linear motor direction
505 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) 506 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
506 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; 507 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
@@ -509,95 +510,58 @@ namespace OpenSim.Region.Physics.BulletSPlugin
509 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) 510 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
510 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; 511 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
511 512
513 /*
512 // decay applied velocity 514 // decay applied velocity
513 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); 515 Vector3 decayfraction = Vector3.One/(m_linearMotorDecayTimescale / pTimestep);
516 // (RA: do not know where the 0.5f comes from)
514 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; 517 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
515
516 /*
517 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
518 m_lastLinearVelocityVector += addAmount;
519
520 float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
521 m_linearMotorDirection *= decayfraction;
522
523 */ 518 */
519 float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep));
520 m_linearMotorDirection *= keepfraction;
524 521
525 VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", 522 VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}",
526 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); 523 m_prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
527 } 524 }
528 else 525 else
529 { 526 {
530 // if what remains of applied is small, zero it. 527 // if what remains of direction is very small, zero it.
531 // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
532 // m_lastLinearVelocityVector = Vector3.Zero;
533 m_linearMotorDirection = Vector3.Zero; 528 m_linearMotorDirection = Vector3.Zero;
534 m_lastLinearVelocityVector = Vector3.Zero; 529 m_lastLinearVelocityVector = Vector3.Zero;
530 VDetailLog("{0},MoveLinear,zeroed", m_prim.LocalID);
535 } 531 }
536 532
537 // convert requested object velocity to object relative vector 533 // convert requested object velocity to object relative vector
538 Quaternion rotq = m_prim.Orientation; 534 Quaternion rotq = m_prim.Orientation;
539 m_dir = m_lastLinearVelocityVector * rotq; 535 m_newVelocity = m_lastLinearVelocityVector * rotq;
540 536
541 // Add the various forces into m_dir which will be our new direction vector (velocity) 537 // Add the various forces into m_dir which will be our new direction vector (velocity)
542 538
543 // add Gravity and Buoyancy 539 // add Gravity and Buoyancy
544 // KF: So far I have found no good method to combine a script-requested
545 // .Z velocity and gravity. Therefore only 0g will used script-requested
546 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
547 Vector3 grav = Vector3.Zero;
548 // There is some gravity, make a gravity force vector that is applied after object velocity. 540 // There is some gravity, make a gravity force vector that is applied after object velocity.
549 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 541 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
550 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); 542 Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy));
543
544 /*
545 * RA: Not sure why one would do this
551 // Preserve the current Z velocity 546 // Preserve the current Z velocity
552 Vector3 vel_now = m_prim.Velocity; 547 Vector3 vel_now = m_prim.Velocity;
553 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 548 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
549 */
554 550
555 Vector3 pos = m_prim.Position; 551 Vector3 pos = m_prim.Position;
556 Vector3 posChange = pos;
557// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); 552// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
558 double Zchange = Math.Abs(posChange.Z);
559 if (m_BlockingEndPoint != Vector3.Zero)
560 {
561 bool changed = false;
562 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
563 {
564 pos.X -= posChange.X + 1;
565 changed = true;
566 }
567 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
568 {
569 pos.Y -= posChange.Y + 1;
570 changed = true;
571 }
572 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
573 {
574 pos.Z -= posChange.Z + 1;
575 changed = true;
576 }
577 if (pos.X <= 0)
578 {
579 pos.X += posChange.X + 1;
580 changed = true;
581 }
582 if (pos.Y <= 0)
583 {
584 pos.Y += posChange.Y + 1;
585 changed = true;
586 }
587 if (changed)
588 {
589 m_prim.Position = pos;
590 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
591 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
592 }
593 }
594 553
595 // If below the terrain, move us above the ground a little. 554 // If below the terrain, move us above the ground a little.
596 if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos)) 555 float terrainHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
556 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
557 // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
558 // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation;
559 // if (rotatedSize.Z < terrainHeight)
560 if (pos.Z < terrainHeight)
597 { 561 {
598 pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2; 562 pos.Z = terrainHeight + 2;
599 m_prim.Position = pos; 563 m_prim.Position = pos;
600 VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); 564 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", m_prim.LocalID, terrainHeight, pos);
601 } 565 }
602 566
603 // Check if hovering 567 // Check if hovering
@@ -606,11 +570,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
606 // We should hover, get the target height 570 // We should hover, get the target height
607 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) 571 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
608 { 572 {
609 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; 573 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight;
610 } 574 }
611 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 575 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
612 { 576 {
613 m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 577 m_VhoverTargetHeight = terrainHeight + m_VhoverHeight;
614 } 578 }
615 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 579 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
616 { 580 {
@@ -635,82 +599,92 @@ namespace OpenSim.Region.Physics.BulletSPlugin
635 // Replace Vertical speed with correction figure if significant 599 // Replace Vertical speed with correction figure if significant
636 if (Math.Abs(herr0) > 0.01f) 600 if (Math.Abs(herr0) > 0.01f)
637 { 601 {
638 m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); 602 m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
639 //KF: m_VhoverEfficiency is not yet implemented 603 //KF: m_VhoverEfficiency is not yet implemented
640 } 604 }
641 else 605 else
642 { 606 {
643 m_dir.Z = 0f; 607 m_newVelocity.Z = 0f;
644 } 608 }
645 } 609 }
646 610
647 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); 611 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight);
612 }
648 613
649// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped 614 Vector3 posChange = pos - m_lastPositionVector;
650// m_VhoverTimescale = 0f; // time to acheive height 615 if (m_BlockingEndPoint != Vector3.Zero)
651// pTimestep is time since last frame,in secs 616 {
617 bool changed = false;
618 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
619 {
620 pos.X -= posChange.X + 1;
621 changed = true;
622 }
623 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
624 {
625 pos.Y -= posChange.Y + 1;
626 changed = true;
627 }
628 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
629 {
630 pos.Z -= posChange.Z + 1;
631 changed = true;
632 }
633 if (pos.X <= 0)
634 {
635 pos.X += posChange.X + 1;
636 changed = true;
637 }
638 if (pos.Y <= 0)
639 {
640 pos.Y += posChange.Y + 1;
641 changed = true;
642 }
643 if (changed)
644 {
645 m_prim.Position = pos;
646 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
647 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
648 }
652 } 649 }
653 650
651 float Zchange = Math.Abs(posChange.Z);
654 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 652 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
655 { 653 {
656 //Start Experimental Values
657 if (Zchange > .3) 654 if (Zchange > .3)
658 {
659 grav.Z = (float)(grav.Z * 3); 655 grav.Z = (float)(grav.Z * 3);
660 }
661 if (Zchange > .15) 656 if (Zchange > .15)
662 {
663 grav.Z = (float)(grav.Z * 2); 657 grav.Z = (float)(grav.Z * 2);
664 }
665 if (Zchange > .75) 658 if (Zchange > .75)
666 {
667 grav.Z = (float)(grav.Z * 1.5); 659 grav.Z = (float)(grav.Z * 1.5);
668 }
669 if (Zchange > .05) 660 if (Zchange > .05)
670 {
671 grav.Z = (float)(grav.Z * 1.25); 661 grav.Z = (float)(grav.Z * 1.25);
672 }
673 if (Zchange > .025) 662 if (Zchange > .025)
674 {
675 grav.Z = (float)(grav.Z * 1.125); 663 grav.Z = (float)(grav.Z * 1.125);
676 } 664 float postemp = (pos.Z - terrainHeight);
677 float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
678 float postemp = (pos.Z - terraintemp);
679 if (postemp > 2.5f) 665 if (postemp > 2.5f)
680 {
681 grav.Z = (float)(grav.Z * 1.037125); 666 grav.Z = (float)(grav.Z * 1.037125);
682 }
683 VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); 667 VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
684 //End Experimental Values
685 } 668 }
686 if ((m_flags & (VehicleFlag.NO_X)) != 0) 669 if ((m_flags & (VehicleFlag.NO_X)) != 0)
687 { 670 m_newVelocity.X = 0;
688 m_dir.X = 0;
689 }
690 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 671 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
691 { 672 m_newVelocity.Y = 0;
692 m_dir.Y = 0;
693 }
694 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 673 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
695 { 674 m_newVelocity.Z = 0;
696 m_dir.Z = 0;
697 }
698
699 m_lastPositionVector = m_prim.Position;
700 675
701 // Apply velocity 676 // Apply velocity
702 m_prim.Velocity = m_dir; 677 m_prim.Velocity = m_newVelocity;
703 // apply gravity force 678 // apply gravity force
704 // Why is this set here? The physics engine already does gravity. 679 // Why is this set here? The physics engine already does gravity.
705 // m_prim.AddForce(grav, false); 680 // m_prim.AddForce(grav, false);
706 // m_prim.Force = grav;
707 681
708 // Apply friction 682 // Apply friction
709 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 683 Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
710 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 684 m_lastLinearVelocityVector *= keepFraction;
711 685
712 VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", 686 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}",
713 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); 687 m_prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction);
714 688
715 } // end MoveLinear() 689 } // end MoveLinear()
716 690
@@ -735,17 +709,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
735 // There are m_angularMotorApply steps. 709 // There are m_angularMotorApply steps.
736 Vector3 origAngularVelocity = m_angularMotorVelocity; 710 Vector3 origAngularVelocity = m_angularMotorVelocity;
737 // ramp up to new value 711 // ramp up to new value
738 // current velocity += error / (time to get there / step interval) 712 // current velocity += error / ( time to get there / step interval)
739 // requested speed - last motor speed 713 // requested speed - last motor speed
740 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); 714 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
741 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); 715 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
742 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); 716 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
743 717
744 VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", 718 VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}",
745 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); 719 m_prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
746 720
747 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected 721 // This is done so that if script request rate is less than phys frame rate the expected
748 // velocity may still be acheived. 722 // velocity may still be acheived.
723 m_angularMotorApply--;
749 } 724 }
750 else 725 else
751 { 726 {
@@ -760,7 +735,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
760 Vector3 vertattr = Vector3.Zero; 735 Vector3 vertattr = Vector3.Zero;
761 if (m_verticalAttractionTimescale < 300) 736 if (m_verticalAttractionTimescale < 300)
762 { 737 {
763 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); 738 float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep);
764 // get present body rotation 739 // get present body rotation
765 Quaternion rotq = m_prim.Orientation; 740 Quaternion rotq = m_prim.Orientation;
766 // make a vector pointing up 741 // make a vector pointing up
@@ -863,16 +838,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
863 m_rot.Y = 0; 838 m_rot.Y = 0;
864 changed = true; 839 changed = true;
865 } 840 }
866 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
867 {
868 m_rot.X = 0;
869 m_rot.Y = 0;
870 changed = true;
871 }
872 if (changed) 841 if (changed)
842 {
873 m_prim.Orientation = m_rot; 843 m_prim.Orientation = m_rot;
844 VDetailLog("{0},LimitRotation,done,orig={1},new={2}", m_prim.LocalID, rotq, m_rot);
845 }
874 846
875 VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
876 } 847 }
877 848
878 // Invoke the detailed logger and output something if it's enabled. 849 // Invoke the detailed logger and output something if it's enabled.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 5f6601d..7e784eb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -202,11 +202,33 @@ public class BSLinkset
202 return com; 202 return com;
203 } 203 }
204 204
205 // The object is going dynamic (physical). Do any setup necessary
206 // for a dynamic linkset.
207 // Only the state of the passed object can be modified. The rest of the linkset
208 // has not yet been fully constructed.
209 // Return 'true' if any properties updated on the passed object.
210 // Called at taint-time!
211 public bool MakeDynamic(BSPhysObject child)
212 {
213 bool ret = false;
214 return ret;
215 }
216
217 // The object is going static (non-physical). Do any setup necessary
218 // for a static linkset.
219 // Return 'true' if any properties updated on the passed object.
220 // Called at taint-time!
221 public bool MakeStatic(BSPhysObject child)
222 {
223 // What is done for each object in BSPrim is what we want.
224 return false;
225 }
226
205 // When physical properties are changed the linkset needs to recalculate 227 // When physical properties are changed the linkset needs to recalculate
206 // its internal properties. 228 // its internal properties.
207 public void Refresh(BSPhysObject requestor) 229 public void Refresh(BSPhysObject requestor)
208 { 230 {
209 // If there are no children, there aren't any constraints to recompute 231 // If there are no children, there can't be any constraints to recompute
210 if (!HasAnyChildren) 232 if (!HasAnyChildren)
211 return; 233 return;
212 234
@@ -225,11 +247,12 @@ public class BSLinkset
225 // from a linkset to make sure the constraints know about the new mass and 247 // from a linkset to make sure the constraints know about the new mass and
226 // geometry. 248 // geometry.
227 // Must only be called at taint time!! 249 // Must only be called at taint time!!
228 private bool RecomputeLinksetConstraintVariables() 250 private void RecomputeLinksetConstraintVariables()
229 { 251 {
230 float linksetMass = LinksetMass; 252 float linksetMass = LinksetMass;
231 lock (m_linksetActivityLock) 253 lock (m_linksetActivityLock)
232 { 254 {
255 bool somethingMissing = false;
233 foreach (BSPhysObject child in m_children) 256 foreach (BSPhysObject child in m_children)
234 { 257 {
235 BSConstraint constrain; 258 BSConstraint constrain;
@@ -241,16 +264,36 @@ public class BSLinkset
241 } 264 }
242 else 265 else
243 { 266 {
244 // Non-fatal error that can happen when children are being added to the linkset but 267 // Non-fatal error that happens when children are being added to the linkset but
245 // their constraints have not been created yet. 268 // their constraints have not been created yet.
246 // Caused by the fact that m_children is built at run time but building constraints 269 // Caused by the fact that m_children is built at run time but building constraints
247 // happens at taint time. 270 // happens at taint time.
248 // m_physicsScene.Logger.ErrorFormat("{0} RecomputeLinksetConstraintVariables: constraint not found for root={1}, child={2}", 271 somethingMissing = true;
249 // LogHeader, m_linksetRoot.Body.ID, child.Body.ID); 272 break;
250 } 273 }
251 } 274 }
275
276 // If the whole linkset is not here, doesn't make sense to recompute linkset wide values
277 if (!somethingMissing)
278 {
279 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
280 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
281 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
282 foreach (BSPhysObject child in m_children)
283 {
284 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
285 }
286 /*
287 // The root prim takes on the weight of the whole linkset
288 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass);
289 BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia);
290 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
291 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
292 BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr);
293 */
294 }
252 } 295 }
253 return false; 296 return;
254 } 297 }
255 298
256 // I am the root of a linkset and a new child is being added 299 // I am the root of a linkset and a new child is being added
@@ -296,9 +339,9 @@ public class BSLinkset
296 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 339 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
297 340
298 PhysicallyUnlinkAChildFromRoot(rootx, childx); 341 PhysicallyUnlinkAChildFromRoot(rootx, childx);
342 RecomputeLinksetConstraintVariables();
299 }); 343 });
300 344
301 RecomputeLinksetConstraintVariables();
302 } 345 }
303 else 346 else
304 { 347 {
@@ -377,6 +420,10 @@ public class BSLinkset
377 PhysicsScene.Params.linkConstraintTransMotorMaxVel, 420 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
378 PhysicsScene.Params.linkConstraintTransMotorMaxForce); 421 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
379 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); 422 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
423 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
424 {
425 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
426 }
380 427
381 RecomputeLinksetConstraintVariables(); 428 RecomputeLinksetConstraintVariables();
382 } 429 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index e411fcb..3fe71e1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -41,7 +41,7 @@ public abstract class BSPhysObject : PhysicsActor
41{ 41{
42 public abstract BSLinkset Linkset { get; set; } 42 public abstract BSLinkset Linkset { get; set; }
43 43
44 public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, 44 public abstract bool Collide(uint collidingWith, BSPhysObject collidee,
45 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); 45 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
46 public abstract void SendCollisions(); 46 public abstract void SendCollisions();
47 47
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 6d0af63..26a581f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -136,11 +136,11 @@ public sealed class BSPrim : BSPhysObject
136 Linkset = new BSLinkset(Scene, this); // a linkset of one 136 Linkset = new BSLinkset(Scene, this); // a linkset of one
137 _vehicle = new BSDynamics(Scene, this); // add vehicleness 137 _vehicle = new BSDynamics(Scene, this); // add vehicleness
138 _mass = CalculateMass(); 138 _mass = CalculateMass();
139 // do the actual object creation at taint time
140 DetailLog("{0},BSPrim.constructor,call", LocalID); 139 DetailLog("{0},BSPrim.constructor,call", LocalID);
140 // do the actual object creation at taint time
141 _scene.TaintedObject("BSPrim.create", delegate() 141 _scene.TaintedObject("BSPrim.create", delegate()
142 { 142 {
143 RecreateGeomAndObject(); 143 CreateGeomAndObject(true);
144 144
145 // Get the pointer to the physical body for this object. 145 // Get the pointer to the physical body for this object.
146 // At the moment, we're still letting BulletSim manage the creation and destruction 146 // At the moment, we're still letting BulletSim manage the creation and destruction
@@ -186,9 +186,10 @@ public sealed class BSPrim : BSPhysObject
186 _scene.TaintedObject("BSPrim.setSize", delegate() 186 _scene.TaintedObject("BSPrim.setSize", delegate()
187 { 187 {
188 _mass = CalculateMass(); // changing size changes the mass 188 _mass = CalculateMass(); // changing size changes the mass
189 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); 189 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
190 DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); 190 // scale and margins are set.
191 RecreateGeomAndObject(); 191 CreateGeomAndObject(true);
192 DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical);
192 }); 193 });
193 } 194 }
194 } 195 }
@@ -198,7 +199,7 @@ public sealed class BSPrim : BSPhysObject
198 _scene.TaintedObject("BSPrim.setShape", delegate() 199 _scene.TaintedObject("BSPrim.setShape", delegate()
199 { 200 {
200 _mass = CalculateMass(); // changing the shape changes the mass 201 _mass = CalculateMass(); // changing the shape changes the mass
201 RecreateGeomAndObject(); 202 CreateGeomAndObject(false);
202 }); 203 });
203 } 204 }
204 } 205 }
@@ -279,7 +280,7 @@ public sealed class BSPrim : BSPhysObject
279 get { 280 get {
280 if (!Linkset.IsRoot(this)) 281 if (!Linkset.IsRoot(this))
281 // child prims move around based on their parent. Need to get the latest location 282 // child prims move around based on their parent. Need to get the latest location
282 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 283 _position = BulletSimAPI.GetPosition2(BSBody.Ptr);
283 284
284 // don't do the GetObjectPosition for root elements because this function is called a zillion times 285 // don't do the GetObjectPosition for root elements because this function is called a zillion times
285 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 286 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
@@ -291,7 +292,7 @@ public sealed class BSPrim : BSPhysObject
291 _scene.TaintedObject("BSPrim.setPosition", delegate() 292 _scene.TaintedObject("BSPrim.setPosition", delegate()
292 { 293 {
293 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 294 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
294 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 295 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
295 }); 296 });
296 } 297 }
297 } 298 }
@@ -302,7 +303,8 @@ public sealed class BSPrim : BSPhysObject
302 { 303 {
303 get 304 get
304 { 305 {
305 return Linkset.LinksetMass; 306 // return Linkset.LinksetMass;
307 return _mass;
306 } 308 }
307 } 309 }
308 310
@@ -328,7 +330,6 @@ public sealed class BSPrim : BSPhysObject
328 _scene.TaintedObject("BSPrim.setForce", delegate() 330 _scene.TaintedObject("BSPrim.setForce", delegate()
329 { 331 {
330 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 332 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
331 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
332 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); 333 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
333 }); 334 });
334 } 335 }
@@ -345,7 +346,7 @@ public sealed class BSPrim : BSPhysObject
345 { 346 {
346 // Done at taint time so we're sure the physics engine is not using the variables 347 // Done at taint time so we're sure the physics engine is not using the variables
347 // Vehicle code changes the parameters for this vehicle type. 348 // Vehicle code changes the parameters for this vehicle type.
348 _vehicle.ProcessTypeChange(type, Scene.LastSimulatedTimestep); 349 _vehicle.ProcessTypeChange(type);
349 // Tell the scene about the vehicle so it will get processing each frame. 350 // Tell the scene about the vehicle so it will get processing each frame.
350 _scene.VehicleInSceneTypeChanged(this, type); 351 _scene.VehicleInSceneTypeChanged(this, type);
351 }); 352 });
@@ -355,14 +356,14 @@ public sealed class BSPrim : BSPhysObject
355 { 356 {
356 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 357 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
357 { 358 {
358 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 359 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
359 }); 360 });
360 } 361 }
361 public override void VehicleVectorParam(int param, OMV.Vector3 value) 362 public override void VehicleVectorParam(int param, OMV.Vector3 value)
362 { 363 {
363 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 364 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
364 { 365 {
365 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
366 }); 367 });
367 } 368 }
368 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 369 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
@@ -406,7 +407,7 @@ public sealed class BSPrim : BSPhysObject
406 _scene.TaintedObject("BSPrim.setVelocity", delegate() 407 _scene.TaintedObject("BSPrim.setVelocity", delegate()
407 { 408 {
408 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 409 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
409 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 410 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity);
410 }); 411 });
411 } 412 }
412 } 413 }
@@ -430,7 +431,7 @@ public sealed class BSPrim : BSPhysObject
430 if (!Linkset.IsRoot(this)) 431 if (!Linkset.IsRoot(this))
431 { 432 {
432 // Children move around because tied to parent. Get a fresh value. 433 // Children move around because tied to parent. Get a fresh value.
433 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); 434 _orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr);
434 } 435 }
435 return _orientation; 436 return _orientation;
436 } 437 }
@@ -441,7 +442,7 @@ public sealed class BSPrim : BSPhysObject
441 { 442 {
442 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 443 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
443 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 444 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
444 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 445 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
445 }); 446 });
446 } 447 }
447 } 448 }
@@ -483,31 +484,37 @@ public sealed class BSPrim : BSPhysObject
483 { 484 {
484 // If it's becoming dynamic, it will need hullness 485 // If it's becoming dynamic, it will need hullness
485 VerifyCorrectPhysicalShape(); 486 VerifyCorrectPhysicalShape();
487 UpdatePhysicalParameters();
488 }
486 489
490 private void UpdatePhysicalParameters()
491 {
492 /*
487 // Bullet wants static objects to have a mass of zero 493 // Bullet wants static objects to have a mass of zero
488 float mass = IsStatic ? 0f : _mass; 494 float mass = IsStatic ? 0f : _mass;
489 495
490 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
491 /* 497 */
492 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr); 498 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr);
493 499
494 // Set up the object physicalness (static or dynamic) 500 // Set up the object physicalness (does gravity and collisions move this object)
495 MakeDynamic(); 501 MakeDynamic(IsStatic);
496 502
497 // Make solid or not and arrange for collisions, etc 503 // Make solid or not (do things bounce off or pass through this object)
498 MakeSolid(); 504 MakeSolid(IsSolid);
499 505
500 m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); 506 // Arrange for collisions events if the simulator wants them
507 EnableCollisions(SubscribedEvents());
501 508
502 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); 509 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr);
503 */
504 510
505 // Recompute any linkset parameters. 511 // Recompute any linkset parameters.
506 // When going from non-physical to physical, this re-enables the constraints that 512 // When going from non-physical to physical, this re-enables the constraints that
507 // had been automatically disabled when the mass was set to zero. 513 // had been automatically disabled when the mass was set to zero.
508 Linkset.Refresh(this); 514 Linkset.Refresh(this);
509 515
510 DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, m_currentCollisionFlags); 516 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}",
517 LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags);
511 } 518 }
512 519
513 // "Making dynamic" means changing to and from static. 520 // "Making dynamic" means changing to and from static.
@@ -515,39 +522,84 @@ public sealed class BSPrim : BSPhysObject
515 // When dynamic, the object can fall and be pushed by others. 522 // When dynamic, the object can fall and be pushed by others.
516 // This is independent of its 'solidness' which controls what passes through 523 // This is independent of its 'solidness' which controls what passes through
517 // this object and what interacts with it. 524 // this object and what interacts with it.
518 private void MakeDynamic() 525 private void MakeDynamic(bool makeStatic)
519 { 526 {
520 if (IsStatic) 527 if (makeStatic)
521 { 528 {
522 // Become a Bullet 'static' object type 529 // Become a Bullet 'static' object type
523 BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); 530 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
524 // Stop all movement 531 // Stop all movement
525 BulletSimAPI.ClearAllForces2(BSBody.Ptr); 532 BulletSimAPI.ClearAllForces2(BSBody.Ptr);
533 // Center of mass is at the center of the object
534 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.Ptr, _position, _orientation);
526 // Mass is zero which disables a bunch of physics stuff in Bullet 535 // Mass is zero which disables a bunch of physics stuff in Bullet
527 BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero); 536 BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero);
528 // There is no inertia in a static object 537 // There is no inertia in a static object
529 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); 538 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
539 // There can be special things needed for implementing linksets
540 Linkset.MakeStatic(this);
530 // The activation state is 'sleeping' so Bullet will not try to act on it 541 // The activation state is 'sleeping' so Bullet will not try to act on it
531 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); 542 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING);
532 } 543 }
533 else 544 else
534 { 545 {
535 // Not a Bullet static object 546 // Not a Bullet static object
536 BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); 547 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
548
549 // Set various physical properties so internal things will get computed correctly as they are set
550 BulletSimAPI.SetFriction2(BSBody.Ptr, Scene.Params.defaultFriction);
551 BulletSimAPI.SetRestitution2(BSBody.Ptr, Scene.Params.defaultRestitution);
552 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
553 BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
554 BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
555 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
556
537 // A dynamic object has mass 557 // A dynamic object has mass
538 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, OMV.Vector3.Zero);
539 // The shape is interesting and has mass and a center of gravity
540 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); 558 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr);
541 BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero); 559 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass);
560 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia);
542 // Inertia is based on our new mass 561 // Inertia is based on our new mass
543 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); 562 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
563
564 // Various values for simulation limits
565 BulletSimAPI.SetDamping2(BSBody.Ptr, Scene.Params.linearDamping, Scene.Params.angularDamping);
566 BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, Scene.Params.deactivationTime);
567 BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, Scene.Params.linearSleepingThreshold, Scene.Params.angularSleepingThreshold);
568 BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, Scene.Params.contactProcessingThreshold);
569
570 // There can be special things needed for implementing linksets
571 Linkset.MakeDynamic(this);
572
544 // Force activation of the object so Bullet will act on it. 573 // Force activation of the object so Bullet will act on it.
545 BulletSimAPI.Activate2(BSBody.Ptr, true); 574 BulletSimAPI.Activate2(BSBody.Ptr, true);
546 } 575 }
547 } 576 }
548 577
549 private void MakeSolid() 578 // "Making solid" means that other object will not pass through this object.
579 private void MakeSolid(bool makeSolid)
550 { 580 {
581 if (makeSolid)
582 {
583 // Easy in Bullet -- just remove the object flag that controls collision response
584 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
585 }
586 else
587 {
588 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
589 }
590 }
591
592 // Turn on or off the flag controlling whether collision events are returned to the simulator.
593 private void EnableCollisions(bool wantsCollisionEvents)
594 {
595 if (wantsCollisionEvents)
596 {
597 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
598 }
599 else
600 {
601 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
602 }
551 } 603 }
552 604
553 // prims don't fly 605 // prims don't fly
@@ -607,7 +659,7 @@ public sealed class BSPrim : BSPhysObject
607 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 659 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
608 { 660 {
609 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 661 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
610 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 662 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity);
611 }); 663 });
612 } 664 }
613 } 665 }
@@ -624,7 +676,10 @@ public sealed class BSPrim : BSPhysObject
624 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 676 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
625 { 677 {
626 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 678 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
627 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 679 // Buoyancy is faked by changing the gravity applied to the object
680 float grav = Scene.Params.gravity * (1f - _buoyancy);
681 BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav));
682 // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
628 }); 683 });
629 } 684 }
630 } 685 }
@@ -686,8 +741,8 @@ public sealed class BSPrim : BSPhysObject
686 } 741 }
687 m_accumulatedForces.Clear(); 742 m_accumulatedForces.Clear();
688 } 743 }
689 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 744 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
690 // For unknown reason, "ApplyCentralForce" is really additive. 745 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
691 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); 746 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum);
692 }); 747 });
693 } 748 }
@@ -1023,36 +1078,44 @@ public sealed class BSPrim : BSPhysObject
1023 }// end CalculateMass 1078 }// end CalculateMass
1024 #endregion Mass Calculation 1079 #endregion Mass Calculation
1025 1080
1026 // Create the geometry information in Bullet for later use 1081 // Create the geometry information in Bullet for later use.
1027 // The objects needs a hull if it's physical otherwise a mesh is enough 1082 // The objects needs a hull if it's physical otherwise a mesh is enough.
1028 // No locking here because this is done when we know physics is not simulating 1083 // No locking here because this is done when we know physics is not simulating.
1029 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used 1084 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
1030 // Returns 'true' if the geometry was rebuilt 1085 // Returns 'true' if the geometry was rebuilt.
1086 // Called at taint-time!
1031 private bool CreateGeom(bool forceRebuild) 1087 private bool CreateGeom(bool forceRebuild)
1032 { 1088 {
1033 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
1034 bool ret = false; 1089 bool ret = false;
1035 if (!_scene.NeedsMeshing(_pbs)) 1090 bool haveShape = false;
1091
1092 // If the prim attributes are simple, this could be a simple Bullet native shape
1093 if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim)
1094 || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0
1095 && _pbs.ProfileHollow == 0
1096 && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0
1097 && _pbs.PathBegin == 0 && _pbs.PathEnd == 0
1098 && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0
1099 && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100
1100 && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) )
1036 { 1101 {
1037 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 1102 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1038 { 1103 {
1039 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 1104 haveShape = true;
1040 // { 1105 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
1041 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 1106 {
1042 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 1107 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
1043 { 1108 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
1044 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); 1109 // Bullet native objects are scaled by the Bullet engine so pass the size in
1045 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 1110 _scale = _size;
1046 // Bullet native objects are scaled by the Bullet engine so pass the size in 1111 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1047 _scale = _size; 1112 ret = true;
1048 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1113 }
1049 ret = true;
1050 }
1051 // }
1052 } 1114 }
1053 else 1115 else
1054 { 1116 {
1055 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1117 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1118 haveShape = true;
1056 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1119 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1057 { 1120 {
1058 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); 1121 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
@@ -1063,16 +1126,16 @@ public sealed class BSPrim : BSPhysObject
1063 } 1126 }
1064 } 1127 }
1065 } 1128 }
1066 else 1129 // If a simple shape isn't happening, create a mesh and possibly a hull
1130 if (!haveShape)
1067 { 1131 {
1068 if (IsPhysical) 1132 if (IsPhysical)
1069 { 1133 {
1070 if (forceRebuild || _hullKey == 0) 1134 if (forceRebuild || _hullKey == 0)
1071 { 1135 {
1072 // physical objects require a hull for interaction. 1136 // physical objects require a hull for interaction.
1073 // This will create the mesh if it doesn't already exist 1137 // This also creates the mesh if it doesn't already exist
1074 CreateGeomHull(); 1138 ret = CreateGeomHull();
1075 ret = true;
1076 } 1139 }
1077 } 1140 }
1078 else 1141 else
@@ -1080,8 +1143,7 @@ public sealed class BSPrim : BSPhysObject
1080 if (forceRebuild || _meshKey == 0) 1143 if (forceRebuild || _meshKey == 0)
1081 { 1144 {
1082 // Static (non-physical) objects only need a mesh for bumping into 1145 // Static (non-physical) objects only need a mesh for bumping into
1083 CreateGeomMesh(); 1146 ret = CreateGeomMesh();
1084 ret = true;
1085 } 1147 }
1086 } 1148 }
1087 } 1149 }
@@ -1089,7 +1151,9 @@ public sealed class BSPrim : BSPhysObject
1089 } 1151 }
1090 1152
1091 // No locking here because this is done when we know physics is not simulating 1153 // No locking here because this is done when we know physics is not simulating
1092 private void CreateGeomMesh() 1154 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1155 // Called at taint-time!
1156 private bool CreateGeomMesh()
1093 { 1157 {
1094 // level of detail based on size and type of the object 1158 // level of detail based on size and type of the object
1095 float lod = _scene.MeshLOD; 1159 float lod = _scene.MeshLOD;
@@ -1103,7 +1167,7 @@ public sealed class BSPrim : BSPhysObject
1103 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); 1167 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
1104 1168
1105 // if this new shape is the same as last time, don't recreate the mesh 1169 // if this new shape is the same as last time, don't recreate the mesh
1106 if (_meshKey == newMeshKey) return; 1170 if (_meshKey == newMeshKey) return false;
1107 1171
1108 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); 1172 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1109 // Since we're recreating new, get rid of any previously generated shape 1173 // Since we're recreating new, get rid of any previously generated shape
@@ -1140,19 +1204,19 @@ public sealed class BSPrim : BSPhysObject
1140 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1204 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1141 // meshes are already scaled by the meshmerizer 1205 // meshes are already scaled by the meshmerizer
1142 _scale = new OMV.Vector3(1f, 1f, 1f); 1206 _scale = new OMV.Vector3(1f, 1f, 1f);
1143 DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); 1207 return true;
1144 return;
1145 } 1208 }
1146 1209
1147 // No locking here because this is done when we know physics is not simulating 1210 // No locking here because this is done when we know physics is not simulating
1148 private void CreateGeomHull() 1211 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1212 private bool CreateGeomHull()
1149 { 1213 {
1150 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1214 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1151 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); 1215 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
1152 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); 1216 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
1153 1217
1154 // if the hull hasn't changed, don't rebuild it 1218 // if the hull hasn't changed, don't rebuild it
1155 if (newHullKey == _hullKey) return; 1219 if (newHullKey == _hullKey) return false;
1156 1220
1157 DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); 1221 DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1158 1222
@@ -1255,7 +1319,7 @@ public sealed class BSPrim : BSPhysObject
1255 // meshes are already scaled by the meshmerizer 1319 // meshes are already scaled by the meshmerizer
1256 _scale = new OMV.Vector3(1f, 1f, 1f); 1320 _scale = new OMV.Vector3(1f, 1f, 1f);
1257 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); 1321 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1258 return; 1322 return true;
1259 } 1323 }
1260 1324
1261 // Callback from convex hull creater with a newly created hull. 1325 // Callback from convex hull creater with a newly created hull.
@@ -1268,20 +1332,12 @@ public sealed class BSPrim : BSPhysObject
1268 1332
1269 private void VerifyCorrectPhysicalShape() 1333 private void VerifyCorrectPhysicalShape()
1270 { 1334 {
1271 if (IsStatic) 1335 if (!IsStatic)
1272 {
1273 // if static, we don't need a hull so, if there is one, rebuild without it
1274 if (_hullKey != 0)
1275 {
1276 RecreateGeomAndObject();
1277 }
1278 }
1279 else
1280 { 1336 {
1281 // if not static, it will need a hull to efficiently collide with things 1337 // if not static, it will need a hull to efficiently collide with things
1282 if (_hullKey == 0) 1338 if (_hullKey == 0)
1283 { 1339 {
1284 RecreateGeomAndObject(); 1340 CreateGeomAndObject(false);
1285 } 1341 }
1286 1342
1287 } 1343 }
@@ -1300,8 +1356,9 @@ public sealed class BSPrim : BSPhysObject
1300 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); 1356 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1301 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1357 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1302 1358
1303 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1359 // the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
1304 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 1360 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1361 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
1305 1362
1306 return ret; 1363 return ret;
1307 } 1364 }
@@ -1325,15 +1382,20 @@ public sealed class BSPrim : BSPhysObject
1325 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1382 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1326 } 1383 }
1327 1384
1328
1329 // Rebuild the geometry and object. 1385 // Rebuild the geometry and object.
1330 // This is called when the shape changes so we need to recreate the mesh/hull. 1386 // This is called when the shape changes so we need to recreate the mesh/hull.
1331 // No locking here because this is done when the physics engine is not simulating 1387 // No locking here because this is done when the physics engine is not simulating
1332 private void RecreateGeomAndObject() 1388 private void CreateGeomAndObject(bool forceRebuild)
1333 { 1389 {
1334 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); 1390 // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild);
1335 if (CreateGeom(true)) 1391 // Create the geometry that will make up the object
1392 if (CreateGeom(forceRebuild))
1393 {
1394 // Create the object and place it into the world
1336 CreateObject(); 1395 CreateObject();
1396 // Make sure the properties are set on the new object
1397 UpdatePhysicalParameters();
1398 }
1337 return; 1399 return;
1338 } 1400 }
1339 1401
@@ -1414,12 +1476,14 @@ public sealed class BSPrim : BSPhysObject
1414 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1476 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1415 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1477 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1416 1478
1479 // BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr);
1480
1417 base.RequestPhysicsterseUpdate(); 1481 base.RequestPhysicsterseUpdate();
1418 } 1482 }
1419 /* 1483 /*
1420 else 1484 else
1421 { 1485 {
1422 // For debugging, we also report the movement of children 1486 // For debugging, we can also report the movement of children
1423 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1487 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1424 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1488 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1425 entprop.Acceleration, entprop.RotationalVelocity); 1489 entprop.Acceleration, entprop.RotationalVelocity);
@@ -1430,15 +1494,15 @@ public sealed class BSPrim : BSPhysObject
1430 // I've collided with something 1494 // I've collided with something
1431 // Called at taint time from within the Step() function 1495 // Called at taint time from within the Step() function
1432 CollisionEventUpdate collisionCollection; 1496 CollisionEventUpdate collisionCollection;
1433 public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 1497 public override bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1434 { 1498 {
1435 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 1499 bool ret = false;
1436 1500
1437 // The following lines make IsColliding() and IsCollidingGround() work 1501 // The following lines make IsColliding() and IsCollidingGround() work
1438 _collidingStep = _scene.SimulationStep; 1502 _collidingStep = Scene.SimulationStep;
1439 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) 1503 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
1440 { 1504 {
1441 _collidingGroundStep = _scene.SimulationStep; 1505 _collidingGroundStep = Scene.SimulationStep;
1442 } 1506 }
1443 1507
1444 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); 1508 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
@@ -1446,21 +1510,23 @@ public sealed class BSPrim : BSPhysObject
1446 // prims in the same linkset cannot collide with each other 1510 // prims in the same linkset cannot collide with each other
1447 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) 1511 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
1448 { 1512 {
1449 return; 1513 return ret;
1450 } 1514 }
1451 1515
1452 // if someone has subscribed for collision events.... 1516 // if someone has subscribed for collision events....
1453 if (SubscribedEvents()) { 1517 if (SubscribedEvents()) {
1454 // throttle the collisions to the number of milliseconds specified in the subscription 1518 // throttle the collisions to the number of milliseconds specified in the subscription
1455 int nowTime = _scene.SimulationNowTime; 1519 int nowTime = Scene.SimulationNowTime;
1456 if (nowTime >= _nextCollisionOkTime) { 1520 if (nowTime >= _nextCollisionOkTime) {
1457 _nextCollisionOkTime = nowTime + _subscribedEventsMs; 1521 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1458 1522
1459 if (collisionCollection == null) 1523 if (collisionCollection == null)
1460 collisionCollection = new CollisionEventUpdate(); 1524 collisionCollection = new CollisionEventUpdate();
1461 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 1525 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1526 ret = true;
1462 } 1527 }
1463 } 1528 }
1529 return ret;
1464 } 1530 }
1465 1531
1466 // The scene is telling us it's time to pass our collected collisions into the simulator 1532 // The scene is telling us it's time to pass our collected collisions into the simulator
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 4a468af..52997dd 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -56,7 +56,6 @@ using OpenMetaverse;
56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
57// Implement LockAngularMotion 57// Implement LockAngularMotion
58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
59// Does NeedsMeshing() really need to exclude all the different shapes?
60// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 59// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
61// Add PID movement operations. What does ScenePresence.MoveToTarget do? 60// Add PID movement operations. What does ScenePresence.MoveToTarget do?
62// Check terrain size. 128 or 127? 61// Check terrain size. 128 or 127?
@@ -79,7 +78,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
79 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>(); 78 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
80 // Following is a kludge and can be removed when avatar animation updating is 79 // Following is a kludge and can be removed when avatar animation updating is
81 // moved to a better place. 80 // moved to a better place.
82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); 81 private HashSet<BSPhysObject> m_avatarsWithCollisions = new HashSet<BSPhysObject>();
83 82
84 // List of all the objects that have vehicle properties and should be called 83 // List of all the objects that have vehicle properties and should be called
85 // to update each physics step. 84 // to update each physics step.
@@ -111,11 +110,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
111 private long m_simulationStep = 0; 110 private long m_simulationStep = 0;
112 public long SimulationStep { get { return m_simulationStep; } } 111 public long SimulationStep { get { return m_simulationStep; } }
113 112
114 // The length of the last timestep we were asked to simulate.
115 // This is used by the vehicle code. Since the vehicle code is called
116 // once per simulation step, its constants need to be scaled by this.
117 public float LastSimulatedTimestep { get; private set; }
118
119 // A value of the time now so all the collision and update routines do not have to get their own 113 // A value of the time now so all the collision and update routines do not have to get their own
120 // Set to 'now' just before all the prims and actors are called for collisions and updates 114 // Set to 'now' just before all the prims and actors are called for collisions and updates
121 public int SimulationNowTime { get; private set; } 115 public int SimulationNowTime { get; private set; }
@@ -132,8 +126,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
132 private EntityProperties[] m_updateArray; 126 private EntityProperties[] m_updateArray;
133 private GCHandle m_updateArrayPinnedHandle; 127 private GCHandle m_updateArrayPinnedHandle;
134 128
135 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 129 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
136 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes 130 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
137 131
138 public float PID_D { get; private set; } // derivative 132 public float PID_D { get; private set; } // derivative
139 public float PID_P { get; private set; } // proportional 133 public float PID_P { get; private set; } // proportional
@@ -153,6 +147,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
153 { 147 {
154 get { return new Vector3(0f, 0f, Params.gravity); } 148 get { return new Vector3(0f, 0f, Params.gravity); }
155 } 149 }
150 // Just the Z value of the gravity
151 public float DefaultGravityZ
152 {
153 get { return Params.gravity; }
154 }
156 155
157 public float MaximumObjectMass { get; private set; } 156 public float MaximumObjectMass { get; private set; }
158 157
@@ -171,8 +170,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
171 callback = c; 170 callback = c;
172 } 171 }
173 } 172 }
173 private Object _taintLock = new Object(); // lock for using the next object
174 private List<TaintCallbackEntry> _taintedObjects; 174 private List<TaintCallbackEntry> _taintedObjects;
175 private Object _taintLock = new Object();
176 175
177 // A pointer to an instance if this structure is passed to the C++ code 176 // A pointer to an instance if this structure is passed to the C++ code
178 // Used to pass basic configuration values to the unmanaged code. 177 // Used to pass basic configuration values to the unmanaged code.
@@ -465,12 +464,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
465 int collidersCount = 0; 464 int collidersCount = 0;
466 IntPtr collidersPtr; 465 IntPtr collidersPtr;
467 466
468 LastSimulatedTimestep = timeStep;
469
470 // prevent simulation until we've been initialized 467 // prevent simulation until we've been initialized
471 if (!m_initialized) return 10.0f; 468 if (!m_initialized) return 5.0f;
472
473 int simulateStartTime = Util.EnvironmentTickCount();
474 469
475 // update the prim states while we know the physics engine is not busy 470 // update the prim states while we know the physics engine is not busy
476 int numTaints = _taintedObjects.Count; 471 int numTaints = _taintedObjects.Count;
@@ -478,6 +473,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
478 473
479 // Some of the prims operate with special vehicle properties 474 // Some of the prims operate with special vehicle properties
480 ProcessVehicles(timeStep); 475 ProcessVehicles(timeStep);
476 numTaints += _taintedObjects.Count;
481 ProcessTaints(); // the vehicles might have added taints 477 ProcessTaints(); // the vehicles might have added taints
482 478
483 // step the physical world one interval 479 // step the physical world one interval
@@ -506,6 +502,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
506 // Get a value for 'now' so all the collision and update routines don't have to get their own 502 // Get a value for 'now' so all the collision and update routines don't have to get their own
507 SimulationNowTime = Util.EnvironmentTickCount(); 503 SimulationNowTime = Util.EnvironmentTickCount();
508 504
505 // This is a kludge to get avatar movement updates.
506 // ODE sends collisions for avatars even if there are have been no collisions. This updates
507 // avatar animations and stuff.
508 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
509 m_objectsWithCollisions = new HashSet<BSPhysObject>(m_avatarsWithCollisions);
510
509 // If there were collisions, process them by sending the event to the prim. 511 // If there were collisions, process them by sending the event to the prim.
510 // Collisions must be processed before updates. 512 // Collisions must be processed before updates.
511 if (collidersCount > 0) 513 if (collidersCount > 0)
@@ -527,13 +529,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
527 bsp.SendCollisions(); 529 bsp.SendCollisions();
528 m_objectsWithCollisions.Clear(); 530 m_objectsWithCollisions.Clear();
529 531
530 // This is a kludge to get avatar movement updated.
531 // ODE sends collisions even if there are none and this is used to update
532 // avatar animations and stuff.
533 foreach (BSPhysObject bpo in m_avatarsWithCollisions)
534 bpo.SendCollisions();
535 // m_avatarsWithCollisions.Clear();
536
537 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 532 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
538 if (updatedEntityCount > 0) 533 if (updatedEntityCount > 0)
539 { 534 {
@@ -544,7 +539,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
544 if (PhysObjects.TryGetValue(entprop.ID, out pobj)) 539 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
545 { 540 {
546 pobj.UpdateProperties(entprop); 541 pobj.UpdateProperties(entprop);
547 continue;
548 } 542 }
549 } 543 }
550 } 544 }
@@ -558,18 +552,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
558 } 552 }
559 } 553 }
560 554
561 // this is a waste since the outside routine also calcuates the physics simulation 555 // The physics engine returns the number of milliseconds it simulated this call.
562 // period. TODO: There should be a way of computing physics frames from simulator computation. 556 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
563 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); 557 // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS.
564 // return (timeStep * (float)simulateTotalTime); 558 return numSubSteps * m_fixedTimeStep;
565
566 // TODO: FIX THIS: fps calculation possibly wrong.
567 // This calculation says 1/timeStep is the ideal frame rate. Any time added to
568 // that by the physics simulation gives a slower frame rate.
569 long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
570 if (totalSimulationTime >= timeStep)
571 return 0;
572 return 1f / (timeStep + totalSimulationTime);
573 } 559 }
574 560
575 // Something has collided 561 // Something has collided
@@ -580,28 +566,25 @@ public class BSScene : PhysicsScene, IPhysicsParameters
580 return; // don't send collisions to the terrain 566 return; // don't send collisions to the terrain
581 } 567 }
582 568
583 BSPhysObject collider = PhysObjects[localID]; 569 BSPhysObject collider;
584 // TODO: as of this code, terrain was not in the physical object list. 570 if (!PhysObjects.TryGetValue(localID, out collider))
585 // When BSTerrain is created and it will be in the list, we can remove
586 // the possibility that it's not there and just fetch the collidee.
587 BSPhysObject collidee = null;
588
589 ActorTypes type = ActorTypes.Prim;
590 if (collidingWith <= TerrainManager.HighestTerrainID)
591 {
592 type = ActorTypes.Ground;
593 }
594 else
595 { 571 {
596 collidee = PhysObjects[collidingWith]; 572 // If the object that is colliding cannot be found, just ignore the collision.
597 if (collidee is BSCharacter) 573 return;
598 type = ActorTypes.Agent;
599 } 574 }
600 575
576 // The terrain is not in the physical object list so 'collidee'
577 // can be null when Collide() is called.
578 BSPhysObject collidee = null;
579 PhysObjects.TryGetValue(collidingWith, out collidee);
580
601 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); 581 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
602 582
603 collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration); 583 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
604 m_objectsWithCollisions.Add(collider); 584 {
585 // If a collision was posted, remember to send it to the simulator
586 m_objectsWithCollisions.Add(collider);
587 }
605 588
606 return; 589 return;
607 } 590 }
@@ -619,9 +602,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
619 public override void SetWaterLevel(float baseheight) 602 public override void SetWaterLevel(float baseheight)
620 { 603 {
621 m_waterLevel = baseheight; 604 m_waterLevel = baseheight;
622 // TODO: pass to physics engine so things will float?
623 } 605 }
624 public float GetWaterLevel() 606 // Someday....
607 public float GetWaterLevelAtXYZ(Vector3 loc)
625 { 608 {
626 return m_waterLevel; 609 return m_waterLevel;
627 } 610 }
@@ -659,121 +642,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
659 642
660 public override bool IsThreaded { get { return false; } } 643 public override bool IsThreaded { get { return false; } }
661 644
662 /// <summary>
663 /// Routine to figure out if we need to mesh this prim with our mesher
664 /// </summary>
665 /// <param name="pbs"></param>
666 /// <returns>true if the prim needs meshing</returns>
667 public bool NeedsMeshing(PrimitiveBaseShape pbs)
668 {
669 // most of this is redundant now as the mesher will return null if it cant mesh a prim
670 // but we still need to check for sculptie meshing being enabled so this is the most
671 // convenient place to do it for now...
672
673 // int iPropertiesNotSupportedDefault = 0;
674
675 if (pbs.SculptEntry && !_meshSculptedPrim)
676 {
677 // Render sculpties as boxes
678 return false;
679 }
680
681 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet
682 // can use an internal representation for the prim
683 if (!_forceSimplePrimMeshing)
684 {
685 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
686 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
687 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
688 {
689
690 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
691 && pbs.ProfileHollow == 0
692 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
693 && pbs.PathBegin == 0 && pbs.PathEnd == 0
694 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
695 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
696 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
697 {
698 return false;
699 }
700 }
701 }
702
703 /* TODO: verify that the mesher will now do all these shapes
704 if (pbs.ProfileHollow != 0)
705 iPropertiesNotSupportedDefault++;
706
707 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
708 iPropertiesNotSupportedDefault++;
709
710 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
711 iPropertiesNotSupportedDefault++;
712
713 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
714 iPropertiesNotSupportedDefault++;
715
716 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
717 iPropertiesNotSupportedDefault++;
718
719 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
720 iPropertiesNotSupportedDefault++;
721
722 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
723 iPropertiesNotSupportedDefault++;
724
725 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
726 iPropertiesNotSupportedDefault++;
727
728 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
729 iPropertiesNotSupportedDefault++;
730
731 // test for torus
732 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
733 {
734 if (pbs.PathCurve == (byte)Extrusion.Curve1)
735 {
736 iPropertiesNotSupportedDefault++;
737 }
738 }
739 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
740 {
741 if (pbs.PathCurve == (byte)Extrusion.Straight)
742 {
743 iPropertiesNotSupportedDefault++;
744 }
745 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
746 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
747 {
748 iPropertiesNotSupportedDefault++;
749 }
750 }
751 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
752 {
753 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
754 {
755 iPropertiesNotSupportedDefault++;
756 }
757 }
758 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
759 {
760 if (pbs.PathCurve == (byte)Extrusion.Straight)
761 {
762 iPropertiesNotSupportedDefault++;
763 }
764 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
765 {
766 iPropertiesNotSupportedDefault++;
767 }
768 }
769 if (iPropertiesNotSupportedDefault == 0)
770 {
771 return false;
772 }
773 */
774 return true;
775 }
776
777 // Calls to the PhysicsActors can't directly call into the physics engine 645 // Calls to the PhysicsActors can't directly call into the physics engine
778 // because it might be busy. We delay changes to a known time. 646 // because it might be busy. We delay changes to a known time.
779 // We rely on C#'s closure to save and restore the context for the delegate. 647 // We rely on C#'s closure to save and restore the context for the delegate.
@@ -782,7 +650,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
782 if (!m_initialized) return; 650 if (!m_initialized) return;
783 651
784 lock (_taintLock) 652 lock (_taintLock)
653 {
785 _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); 654 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
655 }
656
786 return; 657 return;
787 } 658 }
788 659
@@ -919,14 +790,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
919 { 790 {
920 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", 791 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
921 ConfigurationParameters.numericTrue, 792 ConfigurationParameters.numericTrue,
922 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, 793 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
923 (s) => { return s.NumericBool(s._meshSculptedPrim); }, 794 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
924 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), 795 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
925 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", 796 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
926 ConfigurationParameters.numericFalse, 797 ConfigurationParameters.numericFalse,
927 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, 798 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
928 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, 799 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
929 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), 800 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
930 801
931 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 802 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
932 8f, 803 8f,
@@ -1162,8 +1033,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1162 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, 1033 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1163 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, 1034 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1164 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), 1035 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1165 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", 1036 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1166 0.0f, 1037 0.1f,
1167 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, 1038 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1168 (s) => { return s.m_params[0].linkConstraintCFM; }, 1039 (s) => { return s.m_params[0].linkConstraintCFM; },
1169 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), 1040 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
@@ -1172,6 +1043,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1172 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, 1043 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1173 (s) => { return s.m_params[0].linkConstraintERP; }, 1044 (s) => { return s.m_params[0].linkConstraintERP; },
1174 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), 1045 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1046 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1047 40,
1048 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1050 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1175 1051
1176 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 1052 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1177 0f, 1053 0f,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 47d7199..d48462e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -154,27 +154,31 @@ public class BSTerrainManager
154 154
155 // The simulator wants to set a new heightmap for the terrain. 155 // The simulator wants to set a new heightmap for the terrain.
156 public void SetTerrain(float[] heightMap) { 156 public void SetTerrain(float[] heightMap) {
157 if (m_worldOffset != Vector3.Zero && m_parentScene != null) 157 float[] localHeightMap = heightMap;
158 m_physicsScene.TaintedObject("TerrainManager.SetTerrain", delegate()
158 { 159 {
159 // If a child of a mega-region, we shouldn't have any terrain allocated for us 160 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
160 ReleaseGroundPlaneAndTerrain();
161 // If doing the mega-prim stuff and we are the child of the zero region,
162 // the terrain is added to our parent
163 if (m_parentScene is BSScene)
164 { 161 {
165 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", 162 // If a child of a mega-region, we shouldn't have any terrain allocated for us
166 BSScene.DetailLogZero, m_worldOffset, m_worldMax); 163 ReleaseGroundPlaneAndTerrain();
167 ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, 164 // If doing the mega-prim stuff and we are the child of the zero region,
168 heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false); 165 // the terrain is added to our parent
166 if (m_parentScene is BSScene)
167 {
168 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
169 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
170 ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
171 localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
172 }
169 } 173 }
170 } 174 else
171 else 175 {
172 { 176 // If not doing the mega-prim thing, just change the terrain
173 // If not doing the mega-prim thing, just change the terrain 177 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
174 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
175 178
176 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false); 179 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
177 } 180 }
181 });
178 } 182 }
179 183
180 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain 184 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
@@ -319,6 +323,8 @@ public class BSTerrainManager
319 323
320 // Make sure the new shape is processed. 324 // Make sure the new shape is processed.
321 BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true); 325 BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
326
327 m_terrainModified = true;
322 }; 328 };
323 329
324 // There is the option to do the changes now (we're already in 'taint time'), or 330 // There is the option to do the changes now (we're already in 'taint time'), or
@@ -357,6 +363,8 @@ public class BSTerrainManager
357 m_heightMaps.Add(terrainRegionBase, mapInfo); 363 m_heightMaps.Add(terrainRegionBase, mapInfo);
358 // Build the terrain 364 // Build the terrain
359 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); 365 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
366
367 m_terrainModified = true;
360 }; 368 };
361 369
362 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. 370 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
@@ -383,7 +391,7 @@ public class BSTerrainManager
383 private float lastHeightTX = 999999f; 391 private float lastHeightTX = 999999f;
384 private float lastHeightTY = 999999f; 392 private float lastHeightTY = 999999f;
385 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; 393 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
386 public float GetTerrainHeightAtXY(float tX, float tY) 394 private float GetTerrainHeightAtXY(float tX, float tY)
387 { 395 {
388 // You'd be surprized at the number of times this routine is called 396 // You'd be surprized at the number of times this routine is called
389 // with the same parameters as last time. 397 // with the same parameters as last time.
@@ -403,11 +411,18 @@ public class BSTerrainManager
403 { 411 {
404 float regionX = tX - offsetX; 412 float regionX = tX - offsetX;
405 float regionY = tY - offsetY; 413 float regionY = tY - offsetY;
406 if (regionX >= mapInfo.sizeX || regionX < 0f) regionX = 0;
407 if (regionY >= mapInfo.sizeY || regionY < 0f) regionY = 0;
408 int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; 414 int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
409 ret = mapInfo.heightMap[mapIndex]; 415 try
410 m_terrainModified = false; 416 {
417 ret = mapInfo.heightMap[mapIndex];
418 }
419 catch
420 {
421 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
422 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}",
423 LogHeader, terrainBaseXY, regionX, regionY);
424 ret = HEIGHT_GETHEIGHT_RET;
425 }
411 // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", 426 // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
412 // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); 427 // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
413 } 428 }
@@ -416,6 +431,7 @@ public class BSTerrainManager
416 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", 431 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
417 LogHeader, m_physicsScene.RegionName, tX, tY); 432 LogHeader, m_physicsScene.RegionName, tX, tY);
418 } 433 }
434 m_terrainModified = false;
419 lastHeight = ret; 435 lastHeight = ret;
420 return ret; 436 return ret;
421 } 437 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index e579cf2..9221cdb 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -213,6 +213,7 @@ public struct ConfigurationParameters
213 public float linkConstraintTransMotorMaxForce; 213 public float linkConstraintTransMotorMaxForce;
214 public float linkConstraintERP; 214 public float linkConstraintERP;
215 public float linkConstraintCFM; 215 public float linkConstraintCFM;
216 public float linkConstraintSolverIterations;
216 217
217 public const float numericTrue = 1f; 218 public const float numericTrue = 1f;
218 public const float numericFalse = 0f; 219 public const float numericFalse = 0f;
@@ -395,23 +396,6 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
395[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
396public static extern bool CreateObject(uint worldID, ShapeData shapeData); 397public static extern bool CreateObject(uint worldID, ShapeData shapeData);
397 398
398/* Remove old functionality
399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
400public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
401
402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
403public static extern void AddConstraint(uint worldID, uint id1, uint id2,
404 Vector3 frame1, Quaternion frame1rot,
405 Vector3 frame2, Quaternion frame2rot,
406 Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
407
408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
409public static extern bool RemoveConstraintByID(uint worldID, uint id1);
410
411[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
412public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
413 */
414
415[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
416public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 400public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
417 401
@@ -539,15 +523,27 @@ public static extern IntPtr BuildNativeShape2(IntPtr world,
539 float shapeType, float collisionMargin, Vector3 scale); 523 float shapeType, float collisionMargin, Vector3 scale);
540 524
541[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 525[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
542public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); 526public static extern bool IsNativeShape2(IntPtr shape);
543 527
544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 528[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
545public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); 529public static extern IntPtr CreateCompoundShape2(IntPtr sim);
530
531[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
532public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
533
534[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
535public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
546 536
547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 537[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
548public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); 538public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo);
549 539
550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 540[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
541public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
542
543[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
544public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
545
546[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
551public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); 547public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
552 548
553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 549[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -562,9 +558,6 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
562// ===================================================================================== 558// =====================================================================================
563// Terrain creation and helper routines 559// Terrain creation and helper routines
564[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 560[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
565public static extern void DumpMapInfo(IntPtr sim, IntPtr manInfo);
566
567[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
568public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, 561public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
569 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); 562 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
570 563
@@ -1010,7 +1003,7 @@ public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
1010public static extern Vector3 GetLocalScaling2(IntPtr shape); 1003public static extern Vector3 GetLocalScaling2(IntPtr shape);
1011 1004
1012[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1005[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1013public static extern void CalculateLocalInertia2(IntPtr shape, float mass, Vector3 inertia); 1006public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass);
1014 1007
1015[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1008[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1016public static extern int GetShapeType2(IntPtr shape); 1009public static extern int GetShapeType2(IntPtr shape);
@@ -1027,6 +1020,12 @@ public static extern void SetCollisionFilterMask(IntPtr shape, uint filter, uint
1027// ===================================================================================== 1020// =====================================================================================
1028// Debugging 1021// Debugging
1029[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1022[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1023public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
1024
1025[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1026public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
1027
1028[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1030public static extern void DumpPhysicsStatistics2(IntPtr sim); 1029public static extern void DumpPhysicsStatistics2(IntPtr sim);
1031 1030
1032} 1031}