aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs17
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs16
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs218
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs32
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs196
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs67
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs60
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs29
9 files changed, 351 insertions, 286 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index fa22c78..a9b1365 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,10 +529,12 @@ 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, ActorTypes type, 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 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
538 535
536 bool ret = false;
537
539 // The following makes IsColliding() and IsCollidingGround() work 538 // The following makes IsColliding() and IsCollidingGround() work
540 _collidingStep = Scene.SimulationStep; 539 _collidingStep = Scene.SimulationStep;
541 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) 540 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
@@ -553,8 +552,10 @@ public class BSCharacter : BSPhysObject
553 if (collisionCollection == null) 552 if (collisionCollection == null)
554 collisionCollection = new CollisionEventUpdate(); 553 collisionCollection = new CollisionEventUpdate();
555 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 554 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
555 ret = true;
556 } 556 }
557 } 557 }
558 return ret;
558 } 559 }
559 560
560 public override void SendCollisions() 561 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..098fea7 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;
@@ -475,32 +475,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin
475 frcount = 0; 475 frcount = 0;
476 476
477 MoveLinear(pTimestep); 477 MoveLinear(pTimestep);
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,34 +510,29 @@ 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
@@ -544,60 +540,31 @@ namespace OpenSim.Region.Physics.BulletSPlugin
544 // KF: So far I have found no good method to combine a script-requested 540 // 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 541 // .Z velocity and gravity. Therefore only 0g will used script-requested
546 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. 542 // .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. 543 // There is some gravity, make a gravity force vector that is applied after object velocity.
549 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 544 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
550 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); 545 Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy));
546
547 /*
548 * RA: Not sure why one would do this
551 // Preserve the current Z velocity 549 // Preserve the current Z velocity
552 Vector3 vel_now = m_prim.Velocity; 550 Vector3 vel_now = m_prim.Velocity;
553 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 551 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
552 */
554 553
555 Vector3 pos = m_prim.Position; 554 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); 555// 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 556
595 // If below the terrain, move us above the ground a little. 557 // If below the terrain, move us above the ground a little.
596 if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos)) 558 float terrainHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
559 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
560 // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
561 // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation;
562 // if (rotatedSize.Z < terrainHeight)
563 if (pos.Z < terrainHeight)
597 { 564 {
598 pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2; 565 pos.Z = terrainHeight + 2;
599 m_prim.Position = pos; 566 m_prim.Position = pos;
600 VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); 567 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", m_prim.LocalID, terrainHeight, pos);
601 } 568 }
602 569
603 // Check if hovering 570 // Check if hovering
@@ -606,11 +573,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
606 // We should hover, get the target height 573 // We should hover, get the target height
607 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) 574 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
608 { 575 {
609 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; 576 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight;
610 } 577 }
611 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 578 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
612 { 579 {
613 m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 580 m_VhoverTargetHeight = terrainHeight + m_VhoverHeight;
614 } 581 }
615 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 582 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
616 { 583 {
@@ -635,82 +602,92 @@ namespace OpenSim.Region.Physics.BulletSPlugin
635 // Replace Vertical speed with correction figure if significant 602 // Replace Vertical speed with correction figure if significant
636 if (Math.Abs(herr0) > 0.01f) 603 if (Math.Abs(herr0) > 0.01f)
637 { 604 {
638 m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); 605 m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
639 //KF: m_VhoverEfficiency is not yet implemented 606 //KF: m_VhoverEfficiency is not yet implemented
640 } 607 }
641 else 608 else
642 { 609 {
643 m_dir.Z = 0f; 610 m_newVelocity.Z = 0f;
644 } 611 }
645 } 612 }
646 613
647 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); 614 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight);
615 }
648 616
649// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped 617 Vector3 posChange = pos - m_lastPositionVector;
650// m_VhoverTimescale = 0f; // time to acheive height 618 if (m_BlockingEndPoint != Vector3.Zero)
651// pTimestep is time since last frame,in secs 619 {
620 bool changed = false;
621 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
622 {
623 pos.X -= posChange.X + 1;
624 changed = true;
625 }
626 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
627 {
628 pos.Y -= posChange.Y + 1;
629 changed = true;
630 }
631 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
632 {
633 pos.Z -= posChange.Z + 1;
634 changed = true;
635 }
636 if (pos.X <= 0)
637 {
638 pos.X += posChange.X + 1;
639 changed = true;
640 }
641 if (pos.Y <= 0)
642 {
643 pos.Y += posChange.Y + 1;
644 changed = true;
645 }
646 if (changed)
647 {
648 m_prim.Position = pos;
649 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
650 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
651 }
652 } 652 }
653 653
654 float Zchange = Math.Abs(posChange.Z);
654 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 655 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
655 { 656 {
656 //Start Experimental Values
657 if (Zchange > .3) 657 if (Zchange > .3)
658 {
659 grav.Z = (float)(grav.Z * 3); 658 grav.Z = (float)(grav.Z * 3);
660 }
661 if (Zchange > .15) 659 if (Zchange > .15)
662 {
663 grav.Z = (float)(grav.Z * 2); 660 grav.Z = (float)(grav.Z * 2);
664 }
665 if (Zchange > .75) 661 if (Zchange > .75)
666 {
667 grav.Z = (float)(grav.Z * 1.5); 662 grav.Z = (float)(grav.Z * 1.5);
668 }
669 if (Zchange > .05) 663 if (Zchange > .05)
670 {
671 grav.Z = (float)(grav.Z * 1.25); 664 grav.Z = (float)(grav.Z * 1.25);
672 }
673 if (Zchange > .025) 665 if (Zchange > .025)
674 {
675 grav.Z = (float)(grav.Z * 1.125); 666 grav.Z = (float)(grav.Z * 1.125);
676 } 667 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) 668 if (postemp > 2.5f)
680 {
681 grav.Z = (float)(grav.Z * 1.037125); 669 grav.Z = (float)(grav.Z * 1.037125);
682 }
683 VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); 670 VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
684 //End Experimental Values
685 } 671 }
686 if ((m_flags & (VehicleFlag.NO_X)) != 0) 672 if ((m_flags & (VehicleFlag.NO_X)) != 0)
687 { 673 m_newVelocity.X = 0;
688 m_dir.X = 0;
689 }
690 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 674 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
691 { 675 m_newVelocity.Y = 0;
692 m_dir.Y = 0;
693 }
694 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 676 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
695 { 677 m_newVelocity.Z = 0;
696 m_dir.Z = 0;
697 }
698
699 m_lastPositionVector = m_prim.Position;
700 678
701 // Apply velocity 679 // Apply velocity
702 m_prim.Velocity = m_dir; 680 m_prim.Velocity = m_newVelocity;
703 // apply gravity force 681 // apply gravity force
704 // Why is this set here? The physics engine already does gravity. 682 // Why is this set here? The physics engine already does gravity.
705 // m_prim.AddForce(grav, false); 683 // m_prim.AddForce(grav, false);
706 // m_prim.Force = grav;
707 684
708 // Apply friction 685 // Apply friction
709 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 686 Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
710 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 687 m_lastLinearVelocityVector *= keepFraction;
711 688
712 VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", 689 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}",
713 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); 690 m_prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction);
714 691
715 } // end MoveLinear() 692 } // end MoveLinear()
716 693
@@ -735,17 +712,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
735 // There are m_angularMotorApply steps. 712 // There are m_angularMotorApply steps.
736 Vector3 origAngularVelocity = m_angularMotorVelocity; 713 Vector3 origAngularVelocity = m_angularMotorVelocity;
737 // ramp up to new value 714 // ramp up to new value
738 // current velocity += error / (time to get there / step interval) 715 // current velocity += error / ( time to get there / step interval)
739 // requested speed - last motor speed 716 // requested speed - last motor speed
740 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); 717 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); 718 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); 719 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
743 720
744 VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", 721 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); 722 m_prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
746 723
747 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected 724 // This is done so that if script request rate is less than phys frame rate the expected
748 // velocity may still be acheived. 725 // velocity may still be acheived.
726 m_angularMotorApply--;
749 } 727 }
750 else 728 else
751 { 729 {
@@ -760,7 +738,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
760 Vector3 vertattr = Vector3.Zero; 738 Vector3 vertattr = Vector3.Zero;
761 if (m_verticalAttractionTimescale < 300) 739 if (m_verticalAttractionTimescale < 300)
762 { 740 {
763 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); 741 float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep);
764 // get present body rotation 742 // get present body rotation
765 Quaternion rotq = m_prim.Orientation; 743 Quaternion rotq = m_prim.Orientation;
766 // make a vector pointing up 744 // make a vector pointing up
@@ -863,16 +841,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
863 m_rot.Y = 0; 841 m_rot.Y = 0;
864 changed = true; 842 changed = true;
865 } 843 }
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) 844 if (changed)
845 {
873 m_prim.Orientation = m_rot; 846 m_prim.Orientation = m_rot;
847 VDetailLog("{0},LimitRotation,done,orig={1},new={2}", m_prim.LocalID, rotq, m_rot);
848 }
874 849
875 VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
876 } 850 }
877 851
878 // Invoke the detailed logger and output something if it's enabled. 852 // 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..dc1de6c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -206,7 +206,7 @@ public class BSLinkset
206 // its internal properties. 206 // its internal properties.
207 public void Refresh(BSPhysObject requestor) 207 public void Refresh(BSPhysObject requestor)
208 { 208 {
209 // If there are no children, there aren't any constraints to recompute 209 // If there are no children, there can't be any constraints to recompute
210 if (!HasAnyChildren) 210 if (!HasAnyChildren)
211 return; 211 return;
212 212
@@ -225,11 +225,12 @@ public class BSLinkset
225 // from a linkset to make sure the constraints know about the new mass and 225 // from a linkset to make sure the constraints know about the new mass and
226 // geometry. 226 // geometry.
227 // Must only be called at taint time!! 227 // Must only be called at taint time!!
228 private bool RecomputeLinksetConstraintVariables() 228 private void RecomputeLinksetConstraintVariables()
229 { 229 {
230 float linksetMass = LinksetMass; 230 float linksetMass = LinksetMass;
231 lock (m_linksetActivityLock) 231 lock (m_linksetActivityLock)
232 { 232 {
233 bool somethingMissing = false;
233 foreach (BSPhysObject child in m_children) 234 foreach (BSPhysObject child in m_children)
234 { 235 {
235 BSConstraint constrain; 236 BSConstraint constrain;
@@ -241,16 +242,29 @@ public class BSLinkset
241 } 242 }
242 else 243 else
243 { 244 {
244 // Non-fatal error that can happen when children are being added to the linkset but 245 // Non-fatal error that happens when children are being added to the linkset but
245 // their constraints have not been created yet. 246 // their constraints have not been created yet.
246 // Caused by the fact that m_children is built at run time but building constraints 247 // Caused by the fact that m_children is built at run time but building constraints
247 // happens at taint time. 248 // happens at taint time.
248 // m_physicsScene.Logger.ErrorFormat("{0} RecomputeLinksetConstraintVariables: constraint not found for root={1}, child={2}", 249 somethingMissing = true;
249 // LogHeader, m_linksetRoot.Body.ID, child.Body.ID); 250 break;
250 } 251 }
251 } 252 }
253
254 // If the whole linkset is not here, doesn't make sense to recompute the root prim now.
255 if (!somethingMissing)
256 {
257 // The root prim takes on the weight of the whole linkset
258 /*
259 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass);
260 BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia);
261 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
262 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
263 BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr);
264 */
265 }
252 } 266 }
253 return false; 267 return;
254 } 268 }
255 269
256 // I am the root of a linkset and a new child is being added 270 // I am the root of a linkset and a new child is being added
@@ -296,9 +310,9 @@ public class BSLinkset
296 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 310 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
297 311
298 PhysicallyUnlinkAChildFromRoot(rootx, childx); 312 PhysicallyUnlinkAChildFromRoot(rootx, childx);
313 RecomputeLinksetConstraintVariables();
299 }); 314 });
300 315
301 RecomputeLinksetConstraintVariables();
302 } 316 }
303 else 317 else
304 { 318 {
@@ -377,6 +391,10 @@ public class BSLinkset
377 PhysicsScene.Params.linkConstraintTransMotorMaxVel, 391 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
378 PhysicsScene.Params.linkConstraintTransMotorMaxForce); 392 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
379 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); 393 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
394 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
395 {
396 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
397 }
380 398
381 RecomputeLinksetConstraintVariables(); 399 RecomputeLinksetConstraintVariables();
382 } 400 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index e411fcb..969c53e 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, ActorTypes type,
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..481a8db 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 }
@@ -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,12 +522,12 @@ 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);
526 // Mass is zero which disables a bunch of physics stuff in Bullet 533 // Mass is zero which disables a bunch of physics stuff in Bullet
@@ -533,12 +540,11 @@ public sealed class BSPrim : BSPhysObject
533 else 540 else
534 { 541 {
535 // Not a Bullet static object 542 // Not a Bullet static object
536 BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); 543 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
537 // A dynamic object has mass 544 // 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); 545 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr);
541 BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero); 546 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass);
547 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia);
542 // Inertia is based on our new mass 548 // Inertia is based on our new mass
543 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); 549 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
544 // Force activation of the object so Bullet will act on it. 550 // Force activation of the object so Bullet will act on it.
@@ -546,8 +552,31 @@ public sealed class BSPrim : BSPhysObject
546 } 552 }
547 } 553 }
548 554
549 private void MakeSolid() 555 // "Making solid" means that other object will not pass through this object.
556 private void MakeSolid(bool makeSolid)
550 { 557 {
558 if (makeSolid)
559 {
560 // Easy in Bullet -- just remove the object flag that controls collision response
561 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
562 }
563 else
564 {
565 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
566 }
567 }
568
569 // Turn on or off the flag controlling whether collision events are returned to the simulator.
570 private void EnableCollisions(bool wantsCollisionEvents)
571 {
572 if (wantsCollisionEvents)
573 {
574 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
575 }
576 else
577 {
578 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
579 }
551 } 580 }
552 581
553 // prims don't fly 582 // prims don't fly
@@ -607,7 +636,7 @@ public sealed class BSPrim : BSPhysObject
607 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 636 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
608 { 637 {
609 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 638 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
610 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 639 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity);
611 }); 640 });
612 } 641 }
613 } 642 }
@@ -624,7 +653,10 @@ public sealed class BSPrim : BSPhysObject
624 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 653 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
625 { 654 {
626 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 655 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
627 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 656 // Buoyancy is faked by changing the gravity applied to the object
657 float grav = Scene.Params.gravity * (1f - _buoyancy);
658 BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav));
659 // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
628 }); 660 });
629 } 661 }
630 } 662 }
@@ -686,8 +718,8 @@ public sealed class BSPrim : BSPhysObject
686 } 718 }
687 m_accumulatedForces.Clear(); 719 m_accumulatedForces.Clear();
688 } 720 }
689 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 721 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
690 // For unknown reason, "ApplyCentralForce" is really additive. 722 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
691 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); 723 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum);
692 }); 724 });
693 } 725 }
@@ -1030,29 +1062,36 @@ public sealed class BSPrim : BSPhysObject
1030 // Returns 'true' if the geometry was rebuilt 1062 // Returns 'true' if the geometry was rebuilt
1031 private bool CreateGeom(bool forceRebuild) 1063 private bool CreateGeom(bool forceRebuild)
1032 { 1064 {
1033 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
1034 bool ret = false; 1065 bool ret = false;
1035 if (!_scene.NeedsMeshing(_pbs)) 1066 bool haveShape = false;
1067
1068 // If the prim attributes are simple, this could be a simple Bullet native shape
1069 if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim)
1070 || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0
1071 && _pbs.ProfileHollow == 0
1072 && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0
1073 && _pbs.PathBegin == 0 && _pbs.PathEnd == 0
1074 && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0
1075 && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100
1076 && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) )
1036 { 1077 {
1037 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 1078 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1038 { 1079 {
1039 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 1080 haveShape = true;
1040 // { 1081 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
1041 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 1082 {
1042 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 1083 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
1043 { 1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
1044 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); 1085 // Bullet native objects are scaled by the Bullet engine so pass the size in
1045 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 1086 _scale = _size;
1046 // Bullet native objects are scaled by the Bullet engine so pass the size in 1087 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1047 _scale = _size; 1088 ret = true;
1048 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1089 }
1049 ret = true;
1050 }
1051 // }
1052 } 1090 }
1053 else 1091 else
1054 { 1092 {
1055 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1093 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1094 haveShape = true;
1056 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1095 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1057 { 1096 {
1058 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); 1097 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
@@ -1063,16 +1102,16 @@ public sealed class BSPrim : BSPhysObject
1063 } 1102 }
1064 } 1103 }
1065 } 1104 }
1066 else 1105 // If a simple shape isn't happening, create a mesh and possibly a hull
1106 if (!haveShape)
1067 { 1107 {
1068 if (IsPhysical) 1108 if (IsPhysical)
1069 { 1109 {
1070 if (forceRebuild || _hullKey == 0) 1110 if (forceRebuild || _hullKey == 0)
1071 { 1111 {
1072 // physical objects require a hull for interaction. 1112 // physical objects require a hull for interaction.
1073 // This will create the mesh if it doesn't already exist 1113 // This also creates the mesh if it doesn't already exist
1074 CreateGeomHull(); 1114 ret = CreateGeomHull();
1075 ret = true;
1076 } 1115 }
1077 } 1116 }
1078 else 1117 else
@@ -1080,8 +1119,7 @@ public sealed class BSPrim : BSPhysObject
1080 if (forceRebuild || _meshKey == 0) 1119 if (forceRebuild || _meshKey == 0)
1081 { 1120 {
1082 // Static (non-physical) objects only need a mesh for bumping into 1121 // Static (non-physical) objects only need a mesh for bumping into
1083 CreateGeomMesh(); 1122 ret = CreateGeomMesh();
1084 ret = true;
1085 } 1123 }
1086 } 1124 }
1087 } 1125 }
@@ -1089,7 +1127,8 @@ public sealed class BSPrim : BSPhysObject
1089 } 1127 }
1090 1128
1091 // No locking here because this is done when we know physics is not simulating 1129 // No locking here because this is done when we know physics is not simulating
1092 private void CreateGeomMesh() 1130 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1131 private bool CreateGeomMesh()
1093 { 1132 {
1094 // level of detail based on size and type of the object 1133 // level of detail based on size and type of the object
1095 float lod = _scene.MeshLOD; 1134 float lod = _scene.MeshLOD;
@@ -1103,7 +1142,7 @@ public sealed class BSPrim : BSPhysObject
1103 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); 1142 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
1104 1143
1105 // if this new shape is the same as last time, don't recreate the mesh 1144 // if this new shape is the same as last time, don't recreate the mesh
1106 if (_meshKey == newMeshKey) return; 1145 if (_meshKey == newMeshKey) return false;
1107 1146
1108 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); 1147 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1109 // Since we're recreating new, get rid of any previously generated shape 1148 // Since we're recreating new, get rid of any previously generated shape
@@ -1140,19 +1179,19 @@ public sealed class BSPrim : BSPhysObject
1140 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1179 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1141 // meshes are already scaled by the meshmerizer 1180 // meshes are already scaled by the meshmerizer
1142 _scale = new OMV.Vector3(1f, 1f, 1f); 1181 _scale = new OMV.Vector3(1f, 1f, 1f);
1143 DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); 1182 return true;
1144 return;
1145 } 1183 }
1146 1184
1147 // No locking here because this is done when we know physics is not simulating 1185 // No locking here because this is done when we know physics is not simulating
1148 private void CreateGeomHull() 1186 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1187 private bool CreateGeomHull()
1149 { 1188 {
1150 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1189 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1151 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); 1190 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
1152 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); 1191 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
1153 1192
1154 // if the hull hasn't changed, don't rebuild it 1193 // if the hull hasn't changed, don't rebuild it
1155 if (newHullKey == _hullKey) return; 1194 if (newHullKey == _hullKey) return false;
1156 1195
1157 DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); 1196 DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1158 1197
@@ -1255,7 +1294,7 @@ public sealed class BSPrim : BSPhysObject
1255 // meshes are already scaled by the meshmerizer 1294 // meshes are already scaled by the meshmerizer
1256 _scale = new OMV.Vector3(1f, 1f, 1f); 1295 _scale = new OMV.Vector3(1f, 1f, 1f);
1257 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); 1296 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1258 return; 1297 return true;
1259 } 1298 }
1260 1299
1261 // Callback from convex hull creater with a newly created hull. 1300 // Callback from convex hull creater with a newly created hull.
@@ -1268,20 +1307,12 @@ public sealed class BSPrim : BSPhysObject
1268 1307
1269 private void VerifyCorrectPhysicalShape() 1308 private void VerifyCorrectPhysicalShape()
1270 { 1309 {
1271 if (IsStatic) 1310 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 { 1311 {
1281 // if not static, it will need a hull to efficiently collide with things 1312 // if not static, it will need a hull to efficiently collide with things
1282 if (_hullKey == 0) 1313 if (_hullKey == 0)
1283 { 1314 {
1284 RecreateGeomAndObject(); 1315 CreateGeomAndObject(false);
1285 } 1316 }
1286 1317
1287 } 1318 }
@@ -1300,8 +1331,9 @@ public sealed class BSPrim : BSPhysObject
1300 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); 1331 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1301 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1332 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1302 1333
1303 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1334 // 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)); 1335 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1336 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
1305 1337
1306 return ret; 1338 return ret;
1307 } 1339 }
@@ -1325,15 +1357,20 @@ public sealed class BSPrim : BSPhysObject
1325 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1357 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1326 } 1358 }
1327 1359
1328
1329 // Rebuild the geometry and object. 1360 // Rebuild the geometry and object.
1330 // This is called when the shape changes so we need to recreate the mesh/hull. 1361 // 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 1362 // No locking here because this is done when the physics engine is not simulating
1332 private void RecreateGeomAndObject() 1363 private void CreateGeomAndObject(bool forceRebuild)
1333 { 1364 {
1334 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); 1365 // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild);
1335 if (CreateGeom(true)) 1366 // Create the geometry that will make up the object
1367 if (CreateGeom(forceRebuild))
1368 {
1369 // Create the object and place it into the world
1336 CreateObject(); 1370 CreateObject();
1371 // Make sure the properties are set on the new object
1372 UpdatePhysicalParameters();
1373 }
1337 return; 1374 return;
1338 } 1375 }
1339 1376
@@ -1430,9 +1467,10 @@ public sealed class BSPrim : BSPhysObject
1430 // I've collided with something 1467 // I've collided with something
1431 // Called at taint time from within the Step() function 1468 // Called at taint time from within the Step() function
1432 CollisionEventUpdate collisionCollection; 1469 CollisionEventUpdate collisionCollection;
1433 public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 1470 public override bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1434 { 1471 {
1435 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 1472 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
1473 bool ret = false;
1436 1474
1437 // The following lines make IsColliding() and IsCollidingGround() work 1475 // The following lines make IsColliding() and IsCollidingGround() work
1438 _collidingStep = _scene.SimulationStep; 1476 _collidingStep = _scene.SimulationStep;
@@ -1446,7 +1484,7 @@ public sealed class BSPrim : BSPhysObject
1446 // prims in the same linkset cannot collide with each other 1484 // prims in the same linkset cannot collide with each other
1447 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) 1485 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
1448 { 1486 {
1449 return; 1487 return ret;
1450 } 1488 }
1451 1489
1452 // if someone has subscribed for collision events.... 1490 // if someone has subscribed for collision events....
@@ -1459,8 +1497,10 @@ public sealed class BSPrim : BSPhysObject
1459 if (collisionCollection == null) 1497 if (collisionCollection == null)
1460 collisionCollection = new CollisionEventUpdate(); 1498 collisionCollection = new CollisionEventUpdate();
1461 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 1499 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1500 ret = true;
1462 } 1501 }
1463 } 1502 }
1503 return ret;
1464 } 1504 }
1465 1505
1466 // The scene is telling us it's time to pass our collected collisions into the simulator 1506 // 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..eea899f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -79,7 +79,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
79 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>(); 79 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
80 // Following is a kludge and can be removed when avatar animation updating is 80 // Following is a kludge and can be removed when avatar animation updating is
81 // moved to a better place. 81 // moved to a better place.
82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); 82 private HashSet<BSPhysObject> m_avatarsWithCollisions = new HashSet<BSPhysObject>();
83 83
84 // List of all the objects that have vehicle properties and should be called 84 // List of all the objects that have vehicle properties and should be called
85 // to update each physics step. 85 // to update each physics step.
@@ -132,8 +132,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
132 private EntityProperties[] m_updateArray; 132 private EntityProperties[] m_updateArray;
133 private GCHandle m_updateArrayPinnedHandle; 133 private GCHandle m_updateArrayPinnedHandle;
134 134
135 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 135 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 136 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
137 137
138 public float PID_D { get; private set; } // derivative 138 public float PID_D { get; private set; } // derivative
139 public float PID_P { get; private set; } // proportional 139 public float PID_P { get; private set; } // proportional
@@ -153,6 +153,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
153 { 153 {
154 get { return new Vector3(0f, 0f, Params.gravity); } 154 get { return new Vector3(0f, 0f, Params.gravity); }
155 } 155 }
156 // Just the Z value of the gravity
157 public float DefaultGravityZ
158 {
159 get { return Params.gravity; }
160 }
156 161
157 public float MaximumObjectMass { get; private set; } 162 public float MaximumObjectMass { get; private set; }
158 163
@@ -171,8 +176,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
171 callback = c; 176 callback = c;
172 } 177 }
173 } 178 }
179 private Object _taintLock = new Object(); // lock for using the next object
174 private List<TaintCallbackEntry> _taintedObjects; 180 private List<TaintCallbackEntry> _taintedObjects;
175 private Object _taintLock = new Object();
176 181
177 // A pointer to an instance if this structure is passed to the C++ code 182 // 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. 183 // Used to pass basic configuration values to the unmanaged code.
@@ -478,6 +483,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
478 483
479 // Some of the prims operate with special vehicle properties 484 // Some of the prims operate with special vehicle properties
480 ProcessVehicles(timeStep); 485 ProcessVehicles(timeStep);
486 numTaints += _taintedObjects.Count;
481 ProcessTaints(); // the vehicles might have added taints 487 ProcessTaints(); // the vehicles might have added taints
482 488
483 // step the physical world one interval 489 // step the physical world one interval
@@ -506,6 +512,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 512 // Get a value for 'now' so all the collision and update routines don't have to get their own
507 SimulationNowTime = Util.EnvironmentTickCount(); 513 SimulationNowTime = Util.EnvironmentTickCount();
508 514
515 // This is a kludge to get avatar movement updates.
516 // ODE sends collisions for avatars even if there are have been no collisions. This updates
517 // avatar animations and stuff.
518 // If you fix avatar animation updates, remove this overhead and let collisions happen.
519 m_objectsWithCollisions = new HashSet<BSPhysObject>(m_avatarsWithCollisions);
520
509 // If there were collisions, process them by sending the event to the prim. 521 // If there were collisions, process them by sending the event to the prim.
510 // Collisions must be processed before updates. 522 // Collisions must be processed before updates.
511 if (collidersCount > 0) 523 if (collidersCount > 0)
@@ -527,13 +539,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
527 bsp.SendCollisions(); 539 bsp.SendCollisions();
528 m_objectsWithCollisions.Clear(); 540 m_objectsWithCollisions.Clear();
529 541
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 542 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
538 if (updatedEntityCount > 0) 543 if (updatedEntityCount > 0)
539 { 544 {
@@ -544,7 +549,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
544 if (PhysObjects.TryGetValue(entprop.ID, out pobj)) 549 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
545 { 550 {
546 pobj.UpdateProperties(entprop); 551 pobj.UpdateProperties(entprop);
547 continue;
548 } 552 }
549 } 553 }
550 } 554 }
@@ -600,8 +604,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
600 604
601 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); 605 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
602 606
603 collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration); 607 if (collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration))
604 m_objectsWithCollisions.Add(collider); 608 {
609 // If a collision was posted, remember to send it to the simulator
610 m_objectsWithCollisions.Add(collider);
611 }
605 612
606 return; 613 return;
607 } 614 }
@@ -619,9 +626,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
619 public override void SetWaterLevel(float baseheight) 626 public override void SetWaterLevel(float baseheight)
620 { 627 {
621 m_waterLevel = baseheight; 628 m_waterLevel = baseheight;
622 // TODO: pass to physics engine so things will float?
623 } 629 }
624 public float GetWaterLevel() 630 // Someday....
631 public float GetWaterLevelAtXYZ(Vector3 loc)
625 { 632 {
626 return m_waterLevel; 633 return m_waterLevel;
627 } 634 }
@@ -672,7 +679,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
672 679
673 // int iPropertiesNotSupportedDefault = 0; 680 // int iPropertiesNotSupportedDefault = 0;
674 681
675 if (pbs.SculptEntry && !_meshSculptedPrim) 682 if (pbs.SculptEntry && !ShouldMeshSculptedPrim)
676 { 683 {
677 // Render sculpties as boxes 684 // Render sculpties as boxes
678 return false; 685 return false;
@@ -680,7 +687,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
680 687
681 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet 688 // 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 689 // can use an internal representation for the prim
683 if (!_forceSimplePrimMeshing) 690 if (!ShouldForceSimplePrimMeshing)
684 { 691 {
685 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 692 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
686 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 693 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
@@ -782,7 +789,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
782 if (!m_initialized) return; 789 if (!m_initialized) return;
783 790
784 lock (_taintLock) 791 lock (_taintLock)
792 {
785 _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); 793 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
794 }
795
786 return; 796 return;
787 } 797 }
788 798
@@ -919,14 +929,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
919 { 929 {
920 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", 930 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
921 ConfigurationParameters.numericTrue, 931 ConfigurationParameters.numericTrue,
922 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, 932 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
923 (s) => { return s.NumericBool(s._meshSculptedPrim); }, 933 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
924 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), 934 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
925 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", 935 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
926 ConfigurationParameters.numericFalse, 936 ConfigurationParameters.numericFalse,
927 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, 937 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
928 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, 938 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
929 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), 939 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
930 940
931 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 941 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
932 8f, 942 8f,
@@ -1162,8 +1172,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1162 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, 1172 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1163 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, 1173 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1164 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), 1174 (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", 1175 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1166 0.0f, 1176 0.1f,
1167 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, 1177 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1168 (s) => { return s.m_params[0].linkConstraintCFM; }, 1178 (s) => { return s.m_params[0].linkConstraintCFM; },
1169 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), 1179 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
@@ -1172,6 +1182,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1172 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, 1182 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1173 (s) => { return s.m_params[0].linkConstraintERP; }, 1183 (s) => { return s.m_params[0].linkConstraintERP; },
1174 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), 1184 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1185 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1186 40,
1187 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1188 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1189 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1175 1190
1176 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 1191 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1177 0f, 1192 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..043423e 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
@@ -545,6 +529,15 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
545public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); 529public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
546 530
547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 531[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
532public static extern IntPtr CreateCompoundShape2(IntPtr sim);
533
534[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
535public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
536
537[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
538public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
539
540[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
548public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); 541public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo);
549 542
550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 543[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -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);