aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs287
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs376
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs7
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs61
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs1
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt87
6 files changed, 461 insertions, 358 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index be8a502..fa3110c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -24,21 +24,10 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * 26 *
27 27 * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
28/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to 28 * are Copyright (c) 2009 Linden Research, Inc and are used under their license
29 * call the BulletSim system. 29 * of Creative Commons Attribution-Share Alike 3.0
30 */ 30 * (http://creativecommons.org/licenses/by-sa/3.0/).
31/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
32 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
33 * ODEPrim.cs contains methods dealing with Prim editing, Prim
34 * characteristics and Kinetic motion.
35 * ODEDynamics.cs contains methods dealing with Prim Physical motion
36 * (dynamics) and the associated settings. Old Linear and angular
37 * motors for dynamic motion have been replace with MoveLinear()
38 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
39 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
40 * switch between 'VEHICLE' parameter use and general dynamics
41 * settings use.
42 */ 31 */
43 32
44using System; 33using System;
@@ -111,7 +100,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
111 private float m_bankingEfficiency = 0; 100 private float m_bankingEfficiency = 0;
112 private float m_bankingMix = 0; 101 private float m_bankingMix = 0;
113 private float m_bankingTimescale = 0; 102 private float m_bankingTimescale = 0;
114 private Vector3 m_lastBanking = Vector3.Zero;
115 103
116 //Hover and Buoyancy properties 104 //Hover and Buoyancy properties
117 private float m_VhoverHeight = 0f; 105 private float m_VhoverHeight = 0f;
@@ -125,8 +113,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
125 113
126 //Attractor properties 114 //Attractor properties
127 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); 115 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
128 private float m_verticalAttractionEfficiency = 1.0f; // damped 116 private float m_verticalAttractionEfficiency = 1.0f; // damped
129 private float m_verticalAttractionTimescale = 600f; // Timescale > 500 means no vert attractor. 117 private float m_verticalAttractionCutoff = 500f; // per the documentation
118 // Timescale > cutoff means no vert attractor.
119 private float m_verticalAttractionTimescale = 510f;
130 120
131 public BSDynamics(BSScene myScene, BSPrim myPrim) 121 public BSDynamics(BSScene myScene, BSPrim myPrim)
132 { 122 {
@@ -329,7 +319,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
329 m_bankingEfficiency = 0; 319 m_bankingEfficiency = 0;
330 m_bankingTimescale = 1000; 320 m_bankingTimescale = 1000;
331 m_bankingMix = 1; 321 m_bankingMix = 1;
332 m_lastBanking = Vector3.Zero;
333 322
334 m_referenceFrame = Quaternion.Identity; 323 m_referenceFrame = Quaternion.Identity;
335 m_flags = (VehicleFlag)0; 324 m_flags = (VehicleFlag)0;
@@ -364,7 +353,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
364 m_bankingEfficiency = 0; 353 m_bankingEfficiency = 0;
365 m_bankingTimescale = 10; 354 m_bankingTimescale = 10;
366 m_bankingMix = 1; 355 m_bankingMix = 1;
367 m_lastBanking = Vector3.Zero;
368 356
369 m_referenceFrame = Quaternion.Identity; 357 m_referenceFrame = Quaternion.Identity;
370 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 358 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -374,6 +362,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
374 m_flags |= (VehicleFlag.NO_DEFLECTION_UP 362 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
375 | VehicleFlag.LIMIT_ROLL_ONLY 363 | VehicleFlag.LIMIT_ROLL_ONLY
376 | VehicleFlag.LIMIT_MOTOR_UP); 364 | VehicleFlag.LIMIT_MOTOR_UP);
365
377 break; 366 break;
378 case Vehicle.TYPE_CAR: 367 case Vehicle.TYPE_CAR:
379 m_linearMotorDirection = Vector3.Zero; 368 m_linearMotorDirection = Vector3.Zero;
@@ -403,7 +392,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
403 m_bankingEfficiency = -0.2f; 392 m_bankingEfficiency = -0.2f;
404 m_bankingMix = 1; 393 m_bankingMix = 1;
405 m_bankingTimescale = 1; 394 m_bankingTimescale = 1;
406 m_lastBanking = Vector3.Zero;
407 395
408 m_referenceFrame = Quaternion.Identity; 396 m_referenceFrame = Quaternion.Identity;
409 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 397 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -442,7 +430,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
442 m_bankingEfficiency = -0.3f; 430 m_bankingEfficiency = -0.3f;
443 m_bankingMix = 0.8f; 431 m_bankingMix = 0.8f;
444 m_bankingTimescale = 1; 432 m_bankingTimescale = 1;
445 m_lastBanking = Vector3.Zero;
446 433
447 m_referenceFrame = Quaternion.Identity; 434 m_referenceFrame = Quaternion.Identity;
448 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY 435 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
@@ -481,7 +468,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
481 m_bankingEfficiency = 1; 468 m_bankingEfficiency = 1;
482 m_bankingMix = 0.7f; 469 m_bankingMix = 0.7f;
483 m_bankingTimescale = 2; 470 m_bankingTimescale = 2;
484 m_lastBanking = Vector3.Zero;
485 471
486 m_referenceFrame = Quaternion.Identity; 472 m_referenceFrame = Quaternion.Identity;
487 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 473 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -520,7 +506,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
520 m_bankingEfficiency = 0; 506 m_bankingEfficiency = 0;
521 m_bankingMix = 0.7f; 507 m_bankingMix = 0.7f;
522 m_bankingTimescale = 5; 508 m_bankingTimescale = 5;
523 m_lastBanking = Vector3.Zero;
524 509
525 m_referenceFrame = Quaternion.Identity; 510 m_referenceFrame = Quaternion.Identity;
526 511
@@ -554,8 +539,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
554 // Z goes away and we keep X and Y 539 // Z goes away and we keep X and Y
555 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); 540 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
556 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 541 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
557
558 // m_bankingMotor = new BSVMotor("BankingMotor", ...);
559 } 542 }
560 543
561 // Some of the properties of this prim may have changed. 544 // Some of the properties of this prim may have changed.
@@ -577,15 +560,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
577 float angularDamping = PhysicsScene.Params.vehicleAngularDamping; 560 float angularDamping = PhysicsScene.Params.vehicleAngularDamping;
578 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); 561 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping);
579 562
563 // Vehicles report collision events so we know when it's on the ground
564 BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
565
580 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet 566 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
581 // Vector3 localInertia = new Vector3(1f, 1f, 1f); 567 // Vector3 localInertia = new Vector3(1f, 1f, 1f);
582 Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass); 568 // Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
569 Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass);
583 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); 570 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
584 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); 571 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
585 572
586 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}", 573 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
587 Prim.LocalID, friction, localInertia, angularDamping); 574 Prim.LocalID, friction, localInertia, angularDamping);
588 } 575 }
576 else
577 {
578 BulletSimAPI.RemoveFromCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
579 }
589 } 580 }
590 581
591 public bool RemoveBodyDependencies(BSPhysObject prim) 582 public bool RemoveBodyDependencies(BSPhysObject prim)
@@ -618,13 +609,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
618 private float? m_knownWaterLevel; 609 private float? m_knownWaterLevel;
619 private Vector3? m_knownPosition; 610 private Vector3? m_knownPosition;
620 private Vector3? m_knownVelocity; 611 private Vector3? m_knownVelocity;
612 private Vector3 m_knownForce;
621 private Quaternion? m_knownOrientation; 613 private Quaternion? m_knownOrientation;
622 private Vector3? m_knownRotationalVelocity; 614 private Vector3? m_knownRotationalVelocity;
615 private Vector3 m_knownRotationalForce;
616 private float? m_knownForwardSpeed;
623 617
624 private const int m_knownChangedPosition = 1 << 0; 618 private const int m_knownChangedPosition = 1 << 0;
625 private const int m_knownChangedVelocity = 1 << 1; 619 private const int m_knownChangedVelocity = 1 << 1;
626 private const int m_knownChangedOrientation = 1 << 2; 620 private const int m_knownChangedForce = 1 << 2;
627 private const int m_knownChangedRotationalVelocity = 1 << 3; 621 private const int m_knownChangedOrientation = 1 << 3;
622 private const int m_knownChangedRotationalVelocity = 1 << 4;
623 private const int m_knownChangedRotationalForce = 1 << 5;
628 624
629 private void ForgetKnownVehicleProperties() 625 private void ForgetKnownVehicleProperties()
630 { 626 {
@@ -632,8 +628,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
632 m_knownWaterLevel = null; 628 m_knownWaterLevel = null;
633 m_knownPosition = null; 629 m_knownPosition = null;
634 m_knownVelocity = null; 630 m_knownVelocity = null;
631 m_knownForce = Vector3.Zero;
635 m_knownOrientation = null; 632 m_knownOrientation = null;
636 m_knownRotationalVelocity = null; 633 m_knownRotationalVelocity = null;
634 m_knownRotationalForce = Vector3.Zero;
635 m_knownForwardSpeed = null;
637 m_knownChanged = 0; 636 m_knownChanged = 0;
638 } 637 }
639 private void PushKnownChanged() 638 private void PushKnownChanged()
@@ -645,12 +644,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
645 if ((m_knownChanged & m_knownChangedOrientation) != 0) 644 if ((m_knownChanged & m_knownChangedOrientation) != 0)
646 Prim.ForceOrientation = VehicleOrientation; 645 Prim.ForceOrientation = VehicleOrientation;
647 if ((m_knownChanged & m_knownChangedVelocity) != 0) 646 if ((m_knownChanged & m_knownChangedVelocity) != 0)
647 {
648 Prim.ForceVelocity = VehicleVelocity; 648 Prim.ForceVelocity = VehicleVelocity;
649 BulletSimAPI.SetInterpolationLinearVelocity2(Prim.PhysBody.ptr, VehicleVelocity);
650 }
651 if ((m_knownChanged & m_knownChangedForce) != 0)
652 Prim.AddForce((Vector3)m_knownForce, false, true);
653
649 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) 654 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
650 { 655 {
651 Prim.ForceRotationalVelocity = VehicleRotationalVelocity; 656 Prim.ForceRotationalVelocity = VehicleRotationalVelocity;
657 // Fake out Bullet by making it think the velocity is the same as last time.
652 BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity); 658 BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity);
653 } 659 }
660 if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
661 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true);
662
654 // If we set one of the values (ie, the physics engine didn't do it) we must force 663 // If we set one of the values (ie, the physics engine didn't do it) we must force
655 // an UpdateProperties event to send the changes up to the simulator. 664 // an UpdateProperties event to send the changes up to the simulator.
656 BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); 665 BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr);
@@ -720,6 +729,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
720 } 729 }
721 } 730 }
722 731
732 private void VehicleAddForce(Vector3 aForce)
733 {
734 m_knownForce += aForce;
735 m_knownChanged |= m_knownChangedForce;
736 }
737
723 private Vector3 VehicleRotationalVelocity 738 private Vector3 VehicleRotationalVelocity
724 { 739 {
725 get 740 get
@@ -734,6 +749,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
734 m_knownChanged |= m_knownChangedRotationalVelocity; 749 m_knownChanged |= m_knownChangedRotationalVelocity;
735 } 750 }
736 } 751 }
752 private void VehicleAddAngularForce(Vector3 aForce)
753 {
754 m_knownRotationalForce += aForce;
755 m_knownChanged |= m_knownChangedRotationalForce;
756 }
757 private float VehicleForwardSpeed
758 {
759 get
760 {
761 if (m_knownForwardSpeed == null)
762 m_knownForwardSpeed = (VehicleVelocity * Quaternion.Inverse(VehicleOrientation)).X;
763 return (float)m_knownForwardSpeed;
764 }
765 }
766
737 #endregion // Known vehicle value functions 767 #endregion // Known vehicle value functions
738 768
739 // One step of the vehicle properties for the next 'pTimestep' seconds. 769 // One step of the vehicle properties for the next 'pTimestep' seconds.
@@ -769,10 +799,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
769 linearMotorContribution *= VehicleOrientation; 799 linearMotorContribution *= VehicleOrientation;
770 800
771 // ================================================================== 801 // ==================================================================
772 // Gravity and Buoyancy 802 // Buoyancy: force to overcome gravity.
773 // There is some gravity, make a gravity force vector that is applied after object velocity.
774 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 803 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
775 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); 804 // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity.
805 Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy;
776 806
777 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); 807 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
778 808
@@ -797,14 +827,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
797 newVelocity.Z = 0; 827 newVelocity.Z = 0;
798 828
799 // ================================================================== 829 // ==================================================================
800 // Clamp REALLY high or low velocities 830 // Clamp high or low velocities
801 float newVelocityLengthSq = newVelocity.LengthSquared(); 831 float newVelocityLengthSq = newVelocity.LengthSquared();
802 if (newVelocityLengthSq > 1e6f) 832 // if (newVelocityLengthSq > 1e6f)
833 if (newVelocityLengthSq > 1000f)
803 { 834 {
804 newVelocity /= newVelocity.Length(); 835 newVelocity /= newVelocity.Length();
805 newVelocity *= 1000f; 836 newVelocity *= 1000f;
806 } 837 }
807 else if (newVelocityLengthSq < 1e-6f) 838 // else if (newVelocityLengthSq < 1e-6f)
839 else if (newVelocityLengthSq < 0.001f)
808 newVelocity = Vector3.Zero; 840 newVelocity = Vector3.Zero;
809 841
810 // ================================================================== 842 // ==================================================================
@@ -813,15 +845,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
813 VehicleVelocity = newVelocity; 845 VehicleVelocity = newVelocity;
814 846
815 // Other linear forces are applied as forces. 847 // Other linear forces are applied as forces.
816 Vector3 totalDownForce = grav * m_vehicleMass * pTimestep; 848 Vector3 totalDownForce = buoyancyContribution * m_vehicleMass;
817 if (totalDownForce != Vector3.Zero) 849 if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
818 { 850 {
819 Prim.AddForce(totalDownForce, false); 851 VehicleAddForce(totalDownForce);
820 } 852 }
821 853
822 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},linContrib={3},terrContrib={4},hoverContrib={5},limitContrib={6}", 854 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}",
823 Prim.LocalID, newVelocity, totalDownForce, 855 Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding);
824 linearMotorContribution, terrainHeightContribution, hoverContribution, limitMotorUpContribution 856 VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}",
857 Prim.LocalID,
858 linearMotorContribution, terrainHeightContribution, hoverContribution,
859 limitMotorUpContribution, buoyancyContribution
825 ); 860 );
826 861
827 } // end MoveLinear() 862 } // end MoveLinear()
@@ -942,21 +977,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
942 } 977 }
943 978
944 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 979 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
945 // Prevent ground vehicles from motoring into the sky.This flag has a subtle effect when 980 // Prevent ground vehicles from motoring into the sky. This flag has a subtle effect when
946 // used with conjunction with banking: the strength of the banking will decay when the 981 // used with conjunction with banking: the strength of the banking will decay when the
947 // vehicle no longer experiences collisions. The decay timescale is the same as 982 // vehicle no longer experiences collisions. The decay timescale is the same as
948 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 983 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
949 // when they are in mid jump. 984 // when they are in mid jump.
950 // TODO: this code is wrong. Also, what should it do for boats? 985 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
986 // This is just using the ground and a general collision check. Should really be using
987 // a downward raycast to find what is below.
951 public Vector3 ComputeLinearMotorUp(float pTimestep) 988 public Vector3 ComputeLinearMotorUp(float pTimestep)
952 { 989 {
953 Vector3 ret = Vector3.Zero; 990 Vector3 ret = Vector3.Zero;
991
954 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 992 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
955 { 993 {
956 // If the vehicle is motoring into the sky, get it going back down. 994 // If the vehicle is motoring into the sky, get it going back down.
957 // float distanceAboveGround = pos.Z - Math.Max(GetTerrainHeight(pos), GetWaterLevel(pos));
958 float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition); 995 float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
959 if (distanceAboveGround > 1f) 996 // Not colliding if the vehicle is off the ground
997 if (!Prim.IsColliding)
960 { 998 {
961 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); 999 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
962 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1000 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
@@ -977,8 +1015,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
977 // ======================================================================= 1015 // =======================================================================
978 // Apply the effect of the angular motor. 1016 // Apply the effect of the angular motor.
979 // The 'contribution' is how much angular correction velocity each function wants. 1017 // The 'contribution' is how much angular correction velocity each function wants.
980 // All the contributions are added together and the orientation of the vehicle 1018 // All the contributions are added together and the resulting velocity is
981 // is changed by all the contributed corrections. 1019 // set directly on the vehicle.
982 private void MoveAngular(float pTimestep) 1020 private void MoveAngular(float pTimestep)
983 { 1021 {
984 // The user wants how many radians per second angular change? 1022 // The user wants how many radians per second angular change?
@@ -1001,7 +1039,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1001 1039
1002 Vector3 deflectionContribution = ComputeAngularDeflection(); 1040 Vector3 deflectionContribution = ComputeAngularDeflection();
1003 1041
1004 Vector3 bankingContribution = ComputeAngularBanking(angularMotorContribution.Z); 1042 Vector3 bankingContribution = ComputeAngularBanking();
1005 1043
1006 // ================================================================== 1044 // ==================================================================
1007 m_lastVertAttractor = verticalAttractionContribution; 1045 m_lastVertAttractor = verticalAttractionContribution;
@@ -1013,11 +1051,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1013 + bankingContribution; 1051 + bankingContribution;
1014 1052
1015 // ================================================================== 1053 // ==================================================================
1016 // The correction is applied to the current orientation. 1054 // Apply the correction velocity.
1055 // TODO: Should this be applied as an angular force (torque)?
1017 if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f)) 1056 if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f))
1018 { 1057 {
1019 Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep; 1058 Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep;
1020
1021 VehicleRotationalVelocity = scaledCorrection; 1059 VehicleRotationalVelocity = scaledCorrection;
1022 1060
1023 VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}", 1061 VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}",
@@ -1029,7 +1067,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1029 } 1067 }
1030 else 1068 else
1031 { 1069 {
1032 // The vehicle is not adding anything velocity wise. 1070 // The vehicle is not adding anything angular wise.
1033 VehicleRotationalVelocity = Vector3.Zero; 1071 VehicleRotationalVelocity = Vector3.Zero;
1034 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); 1072 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID);
1035 } 1073 }
@@ -1060,19 +1098,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1060 torqueFromOffset.Y = 0; 1098 torqueFromOffset.Y = 0;
1061 if (float.IsNaN(torqueFromOffset.Z)) 1099 if (float.IsNaN(torqueFromOffset.Z))
1062 torqueFromOffset.Z = 0; 1100 torqueFromOffset.Z = 0;
1063 torqueFromOffset *= m_vehicleMass; 1101
1064 Prim.ApplyTorqueImpulse(torqueFromOffset, true); 1102 VehicleAddAngularForce(torqueFromOffset * m_vehicleMass);
1065 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); 1103 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
1066 } 1104 }
1067 1105
1068 } 1106 }
1069 1107 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1108 // Some vehicles, like boats, should always keep their up-side up. This can be done by
1109 // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to
1110 // the world z-axis (a.k.a. "up"). To take advantage of this feature you would set the
1111 // VEHICLE_VERTICAL_ATTRACTION_TIMESCALE to control the period of the spring frequency,
1112 // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An
1113 // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an
1114 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
1070 public Vector3 ComputeAngularVerticalAttraction() 1115 public Vector3 ComputeAngularVerticalAttraction()
1071 { 1116 {
1072 Vector3 ret = Vector3.Zero; 1117 Vector3 ret = Vector3.Zero;
1073 1118
1074 // If vertical attaction timescale is reasonable and we applied an angular force last time... 1119 // If vertical attaction timescale is reasonable and we applied an angular force last time...
1075 if (m_verticalAttractionTimescale < 500) 1120 if (m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1076 { 1121 {
1077 // Take a vector pointing up and convert it from world to vehicle relative coords. 1122 // Take a vector pointing up and convert it from world to vehicle relative coords.
1078 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; 1123 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
@@ -1097,91 +1142,121 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1097 ret.Y = - verticalError.X; 1142 ret.Y = - verticalError.X;
1098 ret.Z = 0f; 1143 ret.Z = 0f;
1099 1144
1100 // scale by the time scale and timestep 1145 // Scale the correction force by how far we're off from vertical.
1146 // Z error of one says little error. As Z gets smaller, the vehicle is leaning farther over.
1147 float clampedSqrZError = ClampInRange(0.01f, verticalError.Z * verticalError.Z, 1f);
1148 float vertForce = 1f / clampedSqrZError;
1149
1150 ret *= vertForce;
1151
1152 // Correction happens over a number of seconds.
1101 Vector3 unscaledContrib = ret; 1153 Vector3 unscaledContrib = ret;
1102 ret /= m_verticalAttractionTimescale; 1154 ret /= m_verticalAttractionTimescale;
1103 // This returns the angular correction desired. Timestep is added later. 1155
1104 // ret *= pTimestep; 1156 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},vertForce={3},eff={4},vertAttr={5}",
1105 1157 Prim.LocalID, verticalError, unscaledContrib, vertForce, m_verticalAttractionEfficiency, ret);
1106 // apply efficiency
1107 Vector3 preEfficiencyContrib = ret;
1108 // TODO: implement efficiency.
1109 // Effenciency squared seems to give a more realistic effect
1110 float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
1111 // ret *= efficencySquared;
1112
1113 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}",
1114 Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
1115 m_verticalAttractionEfficiency, efficencySquared,
1116 ret);
1117 } 1158 }
1118 return ret; 1159 return ret;
1119 } 1160 }
1120 1161
1121 // Return the angular correction to correct the direction the vehicle is pointing to be 1162 // Return the angular correction to correct the direction the vehicle is pointing to be
1122 // the direction is should want to be pointing. 1163 // the direction is should want to be pointing.
1164 // The vehicle is moving in some direction and correct its orientation to it is pointing
1165 // in that direction.
1166 // TODO: implement reference frame.
1123 public Vector3 ComputeAngularDeflection() 1167 public Vector3 ComputeAngularDeflection()
1124 { 1168 {
1125 Vector3 ret = Vector3.Zero; 1169 Vector3 ret = Vector3.Zero;
1170 return ret; // DEBUG DEBUG DEBUG debug one force at a time
1126 1171
1127 if (m_angularDeflectionEfficiency != 0) 1172 if (m_angularDeflectionEfficiency != 0)
1128 { 1173 {
1129 // Where the vehicle should want to point relative to the vehicle 1174 // The direction the vehicle is moving
1130 Vector3 preferredDirection = Vector3.UnitX * m_referenceFrame; 1175 Vector3 movingDirection = VehicleVelocity;
1176 movingDirection.Normalize();
1131 1177
1132 // Where the vehicle is pointing relative to the vehicle. 1178 // The direction the vehicle is pointing
1133 Vector3 currentDirection = Vector3.UnitX * Quaternion.Add(VehicleOrientation, m_referenceFrame); 1179 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1180 pointingDirection.Normalize();
1134 1181
1135 // Difference between where vehicle is pointing and where it should wish to point 1182 // The difference between what is and what should be
1136 Vector3 directionCorrection = preferredDirection - currentDirection; 1183 Vector3 deflectionError = movingDirection - pointingDirection;
1137 1184
1138 // Scale the correction by recovery timescale and efficiency 1185 // Scale the correction by recovery timescale and efficiency
1139 ret = directionCorrection * m_angularDeflectionEfficiency / m_angularDeflectionTimescale; 1186 ret = (-deflectionError * VehicleForwardSpeed) * m_angularDeflectionEfficiency;
1187 ret /= m_angularDeflectionTimescale;
1140 1188
1141 VDetailLog("{0}, MoveAngular,Deflection,perfDir={1},currentDir={2},dirCorrection={3},ret={4}", 1189 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1142 Prim.LocalID, preferredDirection, currentDirection, directionCorrection, ret); 1190 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret);
1143 } 1191 }
1144 return ret; 1192 return ret;
1145 } 1193 }
1146 1194
1147 // Return an angular change to tip the vehicle (around X axis) when turning (turned around Z). 1195 // Return an angular change to rotate the vehicle around the Z axis when the vehicle
1148 // Remembers the last banking value calculated and returns the difference needed this tick. 1196 // is tipped around the X axis.
1149 // TurningFactor is rate going left or right (pos=left, neg=right, scale=0..1). 1197 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1150 public Vector3 ComputeAngularBanking(float turningFactor) 1198 // The vertical attractor feature must be enabled in order for the banking behavior to
1199 // function. The way banking works is this: a rotation around the vehicle's roll-axis will
1200 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1201 // of the yaw effect will be proportional to the
1202 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1203 // velocity along its preferred axis of motion.
1204 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1205 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1206 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1207 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1208 // Negating the banking coefficient will make it so that the vehicle leans to the
1209 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1210 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1211 // banking vehicles do what you want rather than what the laws of physics allow.
1212 // For example, consider a real motorcycle...it must be moving forward in order for
1213 // it to turn while banking, however video-game motorcycles are often configured
1214 // to turn in place when at a dead stop--because they are often easier to control
1215 // that way using the limited interface of the keyboard or game controller. The
1216 // VEHICLE_BANKING_MIX enables combinations of both realistic and non-realistic
1217 // banking by functioning as a slider between a banking that is correspondingly
1218 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1219 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1220 // to "dynamic" where the banking is also proportional to its velocity along its
1221 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1222 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1223 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1224 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1225 // make a sluggish vehicle by giving it a timescale of several seconds.
1226 public Vector3 ComputeAngularBanking()
1151 { 1227 {
1152 Vector3 ret = Vector3.Zero; 1228 Vector3 ret = Vector3.Zero;
1153 Vector3 computedBanking = Vector3.Zero;
1154 1229
1155 if (m_bankingEfficiency != 0) 1230 if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1156 { 1231 {
1157 Vector3 currentDirection = Vector3.UnitX * VehicleOrientation; 1232 // This works by rotating a unit vector to the orientation of the vehicle. The
1158 1233 // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt
1159 float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1); 1234 // up to one for full over).
1235 Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation;
1160 1236
1161 //Use the square of the efficiency, as it looks much more how SL banking works 1237 // Figure out the yaw value for this much roll.
1162 float effSquared = (m_bankingEfficiency * m_bankingEfficiency); 1238 float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency;
1163 if (m_bankingEfficiency < 0) 1239 // Keep the sign
1164 effSquared *= -1; //Keep the negative! 1240 if (rollComponents.Y < 0f)
1241 turnComponent = -turnComponent;
1165 1242
1166 float mix = Math.Abs(m_bankingMix); 1243 // TODO: there must be a better computation of the banking force.
1167 // TODO: Must include reference frame. 1244 float bankingTurnForce = turnComponent;
1168 float forwardSpeed = VehicleVelocity.X;
1169 1245
1170 if (!Prim.IsColliding && forwardSpeed > mix) 1246 // actual error = static turn error + dynamic turn error
1171 { 1247 float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed;
1172 computedBanking.X = ClampInRange(-3f, turningFactor * (effSquared * mult), 3f); 1248 // TODO: the banking effect should not go to infinity but what to limit it to?
1173 } 1249 mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f);
1174 1250
1175 // 'computedBanking' is now how much banking that should be happening. 1251 // Build the force vector to change rotation from what it is to what it should be
1176 ret = computedBanking - m_lastBanking; 1252 ret.Z = -mixedBankingError;
1177 1253
1178 // Scale the correction by timescale and efficiency 1254 // Don't do it all at once.
1179 ret /= m_bankingTimescale * m_bankingEfficiency; 1255 ret /= m_bankingTimescale;
1180 1256
1181 VDetailLog("{0}, MoveAngular,Banking,computedB={1},lastB={2},bEff={3},effSq={4},mult={5},mix={6},banking={7}", 1257 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}",
1182 Prim.LocalID, computedBanking, m_lastBanking, m_bankingEfficiency, effSquared, mult, mix, ret); 1258 Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret);
1183 } 1259 }
1184 m_lastBanking = computedBanking;
1185 return ret; 1260 return ret;
1186 } 1261 }
1187 1262
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
index 663b6f4..390c2f9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
@@ -1,191 +1,185 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD 9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30using System.Reflection; 30using System.Reflection;
31using Nini.Config; 31using Nini.Config;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 35
36public struct MaterialAttributes 36public struct MaterialAttributes
37{ 37{
38 // Material type values that correspond with definitions for LSL 38 // Material type values that correspond with definitions for LSL
39 public enum Material : int 39 public enum Material : int
40 { 40 {
41 Stone = 0, 41 Stone = 0,
42 Metal, 42 Metal,
43 Glass, 43 Glass,
44 Wood, 44 Wood,
45 Flesh, 45 Flesh,
46 Plastic, 46 Plastic,
47 Rubber, 47 Rubber,
48 Light, 48 Light,
49 // Hereafter are BulletSim additions 49 // Hereafter are BulletSim additions
50 Avatar, 50 Avatar,
51 NumberOfTypes // the count of types in the enum. 51 NumberOfTypes // the count of types in the enum.
52 } 52 }
53 // Names must be in the order of the above enum. 53 // Names must be in the order of the above enum.
54 public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", 54 public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
55 "Flesh", "Plastic", "Rubber", "Light", "Avatar" }; 55 "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
56 public static string[] MaterialAttribs = { "Density", "Friction", "Restitution", 56 public static string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
57 "ccdMotionThreshold", "ccdSweptSphereRadius" }; 57
58 58 public MaterialAttributes(string t, float d, float f, float r)
59 public MaterialAttributes(string t, float d, float f, float r, float ccdM, float ccdS) 59 {
60 { 60 type = t;
61 type = t; 61 density = d;
62 density = d; 62 friction = f;
63 friction = f; 63 restitution = r;
64 restitution = r; 64 }
65 ccdMotionThreshold = ccdM; 65 public string type;
66 ccdSweptSphereRadius = ccdS; 66 public float density;
67 } 67 public float friction;
68 public string type; 68 public float restitution;
69 public float density; 69}
70 public float friction; 70
71 public float restitution; 71public static class BSMaterials
72 public float ccdMotionThreshold; 72{
73 public float ccdSweptSphereRadius; 73 public static MaterialAttributes[] Attributes;
74} 74
75 75 static BSMaterials()
76public static class BSMaterials 76 {
77{ 77 // Attribute sets for both the non-physical and physical instances of materials.
78 public static MaterialAttributes[] Attributes; 78 Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
79 79 }
80 static BSMaterials() 80
81 { 81 // This is where all the default material attributes are defined.
82 // Attribute sets for both the non-physical and physical instances of materials. 82 public static void InitializeFromDefaults(ConfigurationParameters parms)
83 Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2]; 83 {
84 } 84 // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
85 85 // public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
86 // This is where all the default material attributes are defined. 86 // "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
87 public static void InitializeFromDefaults(ConfigurationParameters parms) 87 float dFriction = parms.defaultFriction;
88 { 88 float dRestitution = parms.defaultRestitution;
89 // public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", 89 float dDensity = parms.defaultDensity;
90 // "Flesh", "Plastic", "Rubber", "Light", "Avatar" }; 90 Attributes[(int)MaterialAttributes.Material.Stone] =
91 float dFriction = parms.defaultFriction; 91 new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
92 float dRestitution = parms.defaultRestitution; 92 Attributes[(int)MaterialAttributes.Material.Metal] =
93 float dDensity = parms.defaultDensity; 93 new MaterialAttributes("metal",dDensity, 0.3f, 0.4f);
94 float dCcdM = parms.ccdMotionThreshold; 94 Attributes[(int)MaterialAttributes.Material.Glass] =
95 float dCcdS = parms.ccdSweptSphereRadius; 95 new MaterialAttributes("glass",dDensity, 0.2f, 0.7f);
96 Attributes[(int)MaterialAttributes.Material.Stone] = 96 Attributes[(int)MaterialAttributes.Material.Wood] =
97 new MaterialAttributes("stone",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 97 new MaterialAttributes("wood",dDensity, 0.6f, 0.5f);
98 Attributes[(int)MaterialAttributes.Material.Metal] = 98 Attributes[(int)MaterialAttributes.Material.Flesh] =
99 new MaterialAttributes("metal",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 99 new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f);
100 Attributes[(int)MaterialAttributes.Material.Glass] = 100 Attributes[(int)MaterialAttributes.Material.Plastic] =
101 new MaterialAttributes("glass",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 101 new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f);
102 Attributes[(int)MaterialAttributes.Material.Wood] = 102 Attributes[(int)MaterialAttributes.Material.Rubber] =
103 new MaterialAttributes("wood",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 103 new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f);
104 Attributes[(int)MaterialAttributes.Material.Flesh] = 104 Attributes[(int)MaterialAttributes.Material.Light] =
105 new MaterialAttributes("flesh",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 105 new MaterialAttributes("light",dDensity, dFriction, dRestitution);
106 Attributes[(int)MaterialAttributes.Material.Plastic] = 106 Attributes[(int)MaterialAttributes.Material.Avatar] =
107 new MaterialAttributes("plastic",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 107 new MaterialAttributes("avatar",60f, 0.2f, 0f);
108 Attributes[(int)MaterialAttributes.Material.Rubber] = 108
109 new MaterialAttributes("rubber",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 109 Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
110 Attributes[(int)MaterialAttributes.Material.Light] = 110 new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
111 new MaterialAttributes("light",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 111 Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
112 Attributes[(int)MaterialAttributes.Material.Avatar] = 112 new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f);
113 new MaterialAttributes("avatar",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 113 Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
114 114 new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f);
115 Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = 115 Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
116 new MaterialAttributes("stonePhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 116 new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f);
117 Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = 117 Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
118 new MaterialAttributes("metalPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 118 new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f);
119 Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = 119 Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
120 new MaterialAttributes("glassPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 120 new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f);
121 Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = 121 Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
122 new MaterialAttributes("woodPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 122 new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f);
123 Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = 123 Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
124 new MaterialAttributes("fleshPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 124 new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
125 Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = 125 Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
126 new MaterialAttributes("plasticPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 126 new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f);
127 Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = 127 }
128 new MaterialAttributes("rubberPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 128
129 Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = 129 // Under the [BulletSim] section, one can change the individual material
130 new MaterialAttributes("lightPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 130 // attribute values. The format of the configuration parameter is:
131 Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = 131 // <materialName><Attribute>["Physical"] = floatValue
132 new MaterialAttributes("avatarPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 132 // For instance:
133 } 133 // [BulletSim]
134 134 // StoneFriction = 0.2
135 // Under the [BulletSim] section, one can change the individual material 135 // FleshRestitutionPhysical = 0.8
136 // attribute values. The format of the configuration parameter is: 136 // Materials can have different parameters for their static and
137 // <materialName><Attribute>["Physical"] = floatValue 137 // physical instantiations. When setting the non-physical value,
138 // For instance: 138 // both values are changed. Setting the physical value only changes
139 // [BulletSim] 139 // the physical value.
140 // StoneFriction = 0.2 140 public static void InitializefromParameters(IConfig pConfig)
141 // FleshRestitutionPhysical = 0.8 141 {
142 // Materials can have different parameters for their static and 142 int matType = 0;
143 // physical instantiations. When setting the non-physical value, 143 foreach (string matName in MaterialAttributes.MaterialNames)
144 // both values are changed. Setting the physical value only changes 144 {
145 // the physical value. 145 foreach (string attribName in MaterialAttributes.MaterialAttribs)
146 public static void InitializefromParameters(IConfig pConfig) 146 {
147 { 147 string paramName = matName + attribName;
148 int matType = 0; 148 if (pConfig.Contains(paramName))
149 foreach (string matName in MaterialAttributes.MaterialNames) 149 {
150 { 150 float paramValue = pConfig.GetFloat(paramName);
151 foreach (string attribName in MaterialAttributes.MaterialAttribs) 151 SetAttributeValue(matType, attribName, paramValue);
152 { 152 // set the physical value also
153 string paramName = matName + attribName; 153 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
154 if (pConfig.Contains(paramName)) 154 }
155 { 155 paramName += "Physical";
156 float paramValue = pConfig.GetFloat(paramName); 156 if (pConfig.Contains(paramName))
157 SetAttributeValue(matType, attribName, paramValue); 157 {
158 // set the physical value also 158 float paramValue = pConfig.GetFloat(paramName);
159 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); 159 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
160 } 160 }
161 paramName += "Physical"; 161 }
162 if (pConfig.Contains(paramName)) 162 matType++;
163 { 163 }
164 float paramValue = pConfig.GetFloat(paramName); 164 }
165 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); 165
166 } 166 private static void SetAttributeValue(int matType, string attribName, float val)
167 } 167 {
168 matType++; 168 MaterialAttributes thisAttrib = Attributes[matType];
169 } 169 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName);
170 } 170 if (fieldInfo != null)
171 171 {
172 private static void SetAttributeValue(int matType, string attribName, float val) 172 fieldInfo.SetValue(thisAttrib, val);
173 { 173 Attributes[matType] = thisAttrib;
174 MaterialAttributes thisAttrib = Attributes[matType]; 174 }
175 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName); 175 }
176 if (fieldInfo != null) 176
177 { 177 public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
178 fieldInfo.SetValue(thisAttrib, val); 178 {
179 Attributes[matType] = thisAttrib; 179 int ind = (int)type;
180 } 180 if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
181 } 181 return Attributes[ind];
182 182 }
183 public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical) 183
184 { 184}
185 int ind = (int)type; 185}
186 if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
187 return Attributes[ind];
188 }
189
190}
191}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index ea1f71a..62aaf80 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -1010,6 +1010,9 @@ public sealed class BSPrim : BSPhysObject
1010 }); 1010 });
1011 } 1011 }
1012 // A torque impulse. 1012 // A torque impulse.
1013 // ApplyTorqueImpulse adds torque directly to the angularVelocity.
1014 // AddAngularForce accumulates the force and applied it to the angular velocity all at once.
1015 // Computed as: angularVelocity += impulse * inertia;
1013 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1016 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1014 { 1017 {
1015 OMV.Vector3 applyImpulse = impulse; 1018 OMV.Vector3 applyImpulse = impulse;
@@ -1396,7 +1399,7 @@ public sealed class BSPrim : BSPhysObject
1396 _rotationalVelocity = entprop.RotationalVelocity; 1399 _rotationalVelocity = entprop.RotationalVelocity;
1397 1400
1398 // The sanity check can change the velocity and/or position. 1401 // The sanity check can change the velocity and/or position.
1399 if (PositionSanityCheck(true)) 1402 if (IsPhysical && PositionSanityCheck(true))
1400 { 1403 {
1401 entprop.Position = _position; 1404 entprop.Position = _position;
1402 entprop.Velocity = _velocity; 1405 entprop.Velocity = _velocity;
@@ -1410,8 +1413,6 @@ public sealed class BSPrim : BSPhysObject
1410 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", 1413 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1411 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); 1414 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1412 1415
1413 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
1414
1415 base.RequestPhysicsterseUpdate(); 1416 base.RequestPhysicsterseUpdate();
1416 } 1417 }
1417 /* 1418 /*
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index b94dcf6..e77b6ba 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -65,9 +65,16 @@ public sealed class BSShapeCollection : IDisposable
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>(); 65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>(); 66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67 67
68 private bool DDetail = false;
69
68 public BSShapeCollection(BSScene physScene) 70 public BSShapeCollection(BSScene physScene)
69 { 71 {
70 PhysicsScene = physScene; 72 PhysicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
74 // While detailed debugging is still active, this is better than commenting out all the
75 // DetailLog statements. When debugging slows down, this and the protected logging
76 // statements can be commented/removed.
77 DDetail = true;
71 } 78 }
72 79
73 public void Dispose() 80 public void Dispose()
@@ -126,13 +133,13 @@ public sealed class BSShapeCollection : IDisposable
126 { 133 {
127 lock (m_collectionActivityLock) 134 lock (m_collectionActivityLock)
128 { 135 {
129 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); 136 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
130 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() 137 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
131 { 138 {
132 if (!BulletSimAPI.IsInWorld2(body.ptr)) 139 if (!BulletSimAPI.IsInWorld2(body.ptr))
133 { 140 {
134 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); 141 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
135 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); 142 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
136 } 143 }
137 }); 144 });
138 } 145 }
@@ -149,7 +156,7 @@ public sealed class BSShapeCollection : IDisposable
149 { 156 {
150 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() 157 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
151 { 158 {
152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", 159 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
153 body.ID, body, inTaintTime); 160 body.ID, body, inTaintTime);
154 // If the caller needs to know the old body is going away, pass the event up. 161 // If the caller needs to know the old body is going away, pass the event up.
155 if (bodyCallback != null) bodyCallback(body); 162 if (bodyCallback != null) bodyCallback(body);
@@ -157,7 +164,7 @@ public sealed class BSShapeCollection : IDisposable
157 if (BulletSimAPI.IsInWorld2(body.ptr)) 164 if (BulletSimAPI.IsInWorld2(body.ptr))
158 { 165 {
159 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); 166 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
160 DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); 167 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
161 } 168 }
162 169
163 // Zero any reference to the shape so it is not freed when the body is deleted. 170 // Zero any reference to the shape so it is not freed when the body is deleted.
@@ -184,7 +191,7 @@ public sealed class BSShapeCollection : IDisposable
184 { 191 {
185 // There is an existing instance of this mesh. 192 // There is an existing instance of this mesh.
186 meshDesc.referenceCount++; 193 meshDesc.referenceCount++;
187 DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", 194 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
188 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 195 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
189 } 196 }
190 else 197 else
@@ -194,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable
194 meshDesc.shapeKey = shape.shapeKey; 201 meshDesc.shapeKey = shape.shapeKey;
195 // We keep a reference to the underlying IMesh data so a hull can be built 202 // We keep a reference to the underlying IMesh data so a hull can be built
196 meshDesc.referenceCount = 1; 203 meshDesc.referenceCount = 1;
197 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", 204 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
198 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 205 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
199 ret = true; 206 ret = true;
200 } 207 }
@@ -207,7 +214,7 @@ public sealed class BSShapeCollection : IDisposable
207 { 214 {
208 // There is an existing instance of this hull. 215 // There is an existing instance of this hull.
209 hullDesc.referenceCount++; 216 hullDesc.referenceCount++;
210 DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", 217 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
211 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 218 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
212 } 219 }
213 else 220 else
@@ -216,7 +223,7 @@ public sealed class BSShapeCollection : IDisposable
216 hullDesc.ptr = shape.ptr; 223 hullDesc.ptr = shape.ptr;
217 hullDesc.shapeKey = shape.shapeKey; 224 hullDesc.shapeKey = shape.shapeKey;
218 hullDesc.referenceCount = 1; 225 hullDesc.referenceCount = 1;
219 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", 226 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
220 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 227 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
221 ret = true; 228 ret = true;
222 229
@@ -246,7 +253,7 @@ public sealed class BSShapeCollection : IDisposable
246 if (shape.isNativeShape) 253 if (shape.isNativeShape)
247 { 254 {
248 // Native shapes are not tracked and are released immediately 255 // Native shapes are not tracked and are released immediately
249 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", 256 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
250 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); 257 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
251 if (shapeCallback != null) shapeCallback(shape); 258 if (shapeCallback != null) shapeCallback(shape);
252 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 259 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
@@ -286,7 +293,7 @@ public sealed class BSShapeCollection : IDisposable
286 if (shapeCallback != null) shapeCallback(shape); 293 if (shapeCallback != null) shapeCallback(shape);
287 meshDesc.lastReferenced = System.DateTime.Now; 294 meshDesc.lastReferenced = System.DateTime.Now;
288 Meshes[shape.shapeKey] = meshDesc; 295 Meshes[shape.shapeKey] = meshDesc;
289 DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", 296 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
290 BSScene.DetailLogZero, shape, meshDesc.referenceCount); 297 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
291 298
292 } 299 }
@@ -307,7 +314,7 @@ public sealed class BSShapeCollection : IDisposable
307 314
308 hullDesc.lastReferenced = System.DateTime.Now; 315 hullDesc.lastReferenced = System.DateTime.Now;
309 Hulls[shape.shapeKey] = hullDesc; 316 Hulls[shape.shapeKey] = hullDesc;
310 DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", 317 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
311 BSScene.DetailLogZero, shape, hullDesc.referenceCount); 318 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
312 } 319 }
313 } 320 }
@@ -325,13 +332,13 @@ public sealed class BSShapeCollection : IDisposable
325 // Failed the sanity check!! 332 // Failed the sanity check!!
326 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", 333 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
327 LogHeader, shape.type, shape.ptr.ToString("X")); 334 LogHeader, shape.type, shape.ptr.ToString("X"));
328 DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", 335 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
329 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); 336 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X"));
330 return; 337 return;
331 } 338 }
332 339
333 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); 340 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);
334 DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); 341 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
335 342
336 for (int ii = numChildren - 1; ii >= 0; ii--) 343 for (int ii = numChildren - 1; ii >= 0; ii--)
337 { 344 {
@@ -379,7 +386,7 @@ public sealed class BSShapeCollection : IDisposable
379 } 386 }
380 } 387 }
381 388
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); 389 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383 390
384 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) 391 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
385 { 392 {
@@ -410,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable
410 // an avatar capsule is close to a native shape (it is not shared) 417 // an avatar capsule is close to a native shape (it is not shared)
411 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, 418 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE,
412 FixedShapeKey.KEY_CAPSULE, shapeCallback); 419 FixedShapeKey.KEY_CAPSULE, shapeCallback);
413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); 420 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
414 ret = true; 421 ret = true;
415 haveShape = true; 422 haveShape = true;
416 } 423 }
@@ -420,7 +427,7 @@ public sealed class BSShapeCollection : IDisposable
420 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) 427 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
421 { 428 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback); 429 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); 430 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
424 haveShape = true; 431 haveShape = true;
425 } 432 }
426 433
@@ -465,7 +472,7 @@ public sealed class BSShapeCollection : IDisposable
465 { 472 {
466 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, 473 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
467 FixedShapeKey.KEY_SPHERE, shapeCallback); 474 FixedShapeKey.KEY_SPHERE, shapeCallback);
468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", 475 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
469 prim.LocalID, forceRebuild, prim.PhysShape); 476 prim.LocalID, forceRebuild, prim.PhysShape);
470 } 477 }
471 } 478 }
@@ -479,7 +486,7 @@ public sealed class BSShapeCollection : IDisposable
479 { 486 {
480 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, 487 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
481 FixedShapeKey.KEY_BOX, shapeCallback); 488 FixedShapeKey.KEY_BOX, shapeCallback);
482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", 489 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
483 prim.LocalID, forceRebuild, prim.PhysShape); 490 prim.LocalID, forceRebuild, prim.PhysShape);
484 } 491 }
485 } 492 }
@@ -504,13 +511,13 @@ public sealed class BSShapeCollection : IDisposable
504 { 511 {
505 // Update prim.BSShape to reference a hull of this shape. 512 // Update prim.BSShape to reference a hull of this shape.
506 ret = GetReferenceToHull(prim,shapeCallback); 513 ret = GetReferenceToHull(prim,shapeCallback);
507 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", 514 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
508 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 515 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
509 } 516 }
510 else 517 else
511 { 518 {
512 ret = GetReferenceToMesh(prim, shapeCallback); 519 ret = GetReferenceToMesh(prim, shapeCallback);
513 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", 520 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
514 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 521 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
515 } 522 }
516 return ret; 523 return ret;
@@ -528,7 +535,7 @@ public sealed class BSShapeCollection : IDisposable
528 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); 535 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
529 536
530 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 537 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
531 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", 538 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
532 prim.LocalID, newShape, prim.Scale); 539 prim.LocalID, newShape, prim.Scale);
533 540
534 prim.PhysShape = newShape; 541 prim.PhysShape = newShape;
@@ -554,7 +561,7 @@ public sealed class BSShapeCollection : IDisposable
554 newShape = new BulletShape( 561 newShape = new BulletShape(
555 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) 562 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
556 , shapeType); 563 , shapeType);
557 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 564 if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
558 } 565 }
559 else 566 else
560 { 567 {
@@ -589,7 +596,7 @@ public sealed class BSShapeCollection : IDisposable
589 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) 596 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
590 return false; 597 return false;
591 598
592 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", 599 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
593 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); 600 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
594 601
595 // Since we're recreating new, get rid of the reference to the previous shape 602 // Since we're recreating new, get rid of the reference to the previous shape
@@ -662,7 +669,7 @@ public sealed class BSShapeCollection : IDisposable
662 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) 669 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
663 return false; 670 return false;
664 671
665 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", 672 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
666 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); 673 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
667 674
668 // Remove usage of the previous shape. 675 // Remove usage of the previous shape.
@@ -808,7 +815,7 @@ public sealed class BSShapeCollection : IDisposable
808 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 815 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
809 CreateGeomMeshOrHull(prim, shapeCallback); 816 CreateGeomMeshOrHull(prim, shapeCallback);
810 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); 817 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity);
811 DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", 818 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
812 prim.LocalID, cShape, prim.PhysShape); 819 prim.LocalID, cShape, prim.PhysShape);
813 820
814 prim.PhysShape = cShape; 821 prim.PhysShape = cShape;
@@ -935,13 +942,13 @@ public sealed class BSShapeCollection : IDisposable
935 { 942 {
936 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, 943 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
937 prim.LocalID, prim.RawPosition, prim.RawOrientation); 944 prim.LocalID, prim.RawPosition, prim.RawOrientation);
938 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 945 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
939 } 946 }
940 else 947 else
941 { 948 {
942 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, 949 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
943 prim.LocalID, prim.RawPosition, prim.RawOrientation); 950 prim.LocalID, prim.RawPosition, prim.RawOrientation);
944 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 951 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
945 } 952 }
946 aBody = new BulletBody(prim.LocalID, bodyPtr); 953 aBody = new BulletBody(prim.LocalID, bodyPtr);
947 954
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index a5acfd1..2671995 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -360,6 +360,7 @@ public enum CollisionFlags : uint
360 // Following used by BulletSim to control collisions and updates 360 // Following used by BulletSim to control collisions and updates
361 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, 361 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
362 BS_FLOATS_ON_WATER = 1 << 11, 362 BS_FLOATS_ON_WATER = 1 << 11,
363 BS_VEHICLE_COLLISIONS = 1 << 12,
363 BS_NONE = 0, 364 BS_NONE = 0,
364 BS_ALL = 0xFFFFFFFF, 365 BS_ALL = 0xFFFFFFFF,
365 366
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 68f25fc..d51003c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -6,14 +6,34 @@ CRASHES
6 Causes many errors. Doesn't stop after first error with box shape. 6 Causes many errors. Doesn't stop after first error with box shape.
7 Eventually crashes when deleting the object. 7 Eventually crashes when deleting the object.
8 8
9BULLETSIM TODO LIST: 9VEHICLES TODO LIST:
10================================================= 10=================================================
11Neb car jiggling left and right 11Neb car jiggling left and right
12 Happens on terrain and any other mesh object. Flat cubes are much smoother.
12Vehicles (Move smoothly) 13Vehicles (Move smoothly)
13Light cycle falling over when driving 14Add vehicle collisions so IsColliding is properly reported.
14Light cycle not banking 15 Needed for banking, limitMotorUp, movementLimiting, ...
15Do single prim vehicles don't seem to properly vehiclize. 16Some vehicles should not be able to turn if no speed or off ground.
16Gun sending shooter flying 17For limitMotorUp, use raycast down to find if vehicle is in the air.
18Implement function efficiency for lineaar and angular motion.
19Should vehicle angular/linear movement friction happen after all the components
20 or does it only apply to the basic movement?
21After getting off a vehicle, the root prim is phantom (can be walked through)
22 Need to force a position update for the root prim after compound shape destruction
23Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
24Implement referenceFrame for all the motion routines.
25Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
26
27BULLETSIM TODO LIST:
28=================================================
29Disable activity of passive linkset children.
30 Since the linkset is a compound object, the old prims are left lying
31 around and need to be phantomized so they don't collide, ...
32Scenes with hundred of thousands of static objects take a lot of physics CPU time.
33BSPrim.Force should set a continious force on the prim. The force should be
34 applied each tick. Some limits?
35Single prim vehicles don't seem to properly vehiclize.
36Gun sending shooter flying.
17Collision margin (gap between physical objects lying on each other) 37Collision margin (gap between physical objects lying on each other)
18Boundry checking (crashes related to crossing boundry) 38Boundry checking (crashes related to crossing boundry)
19 Add check for border edge position for avatars and objects. 39 Add check for border edge position for avatars and objects.
@@ -28,10 +48,11 @@ Small physical objects do not interact correctly
28Add material type linkage and input all the material property definitions. 48Add material type linkage and input all the material property definitions.
29 Skeleton classes and table are in the sources but are not filled or used. 49 Skeleton classes and table are in the sources but are not filled or used.
30Add PID motor for avatar movement (slow to stop, ...) 50Add PID motor for avatar movement (slow to stop, ...)
31Implement function efficiency for lineaar and angular motion. 51setForce should set a constant force. Different than AddImpulse.
52Implement raycast.
53Implement ShapeCollection.Dispose()
54Implement water as a plain so raycasting and collisions can happen with same.
32 55
33After getting off a vehicle, the root prim is phantom (can be walked through)
34 Need to force a position update for the root prim after compound shape destruction
35Find/remove avatar collision with ID=0. 56Find/remove avatar collision with ID=0.
36Test avatar walking up stairs. How does compare with SL. 57Test avatar walking up stairs. How does compare with SL.
37 Radius of the capsule affects ability to climb edges. 58 Radius of the capsule affects ability to climb edges.
@@ -39,19 +60,16 @@ Tune terrain/object friction to be closer to SL.
39Debounce avatar contact so legs don't keep folding up when standing. 60Debounce avatar contact so legs don't keep folding up when standing.
40Implement LSL physics controls. Like STATUS_ROTATE_X. 61Implement LSL physics controls. Like STATUS_ROTATE_X.
41Add border extensions to terrain to help region crossings and objects leaving region. 62Add border extensions to terrain to help region crossings and objects leaving region.
42Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
43 63
44Speed up creation of large physical linksets 64Speed up creation of large physical linksets
45 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical 65 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical
46Performance test with lots of avatars. Can BulletSim support a thousand? 66Performance test with lots of avatars. Can BulletSim support a thousand?
47Optimize collisions in C++: only send up to the object subscribed to collisions. 67Optimize collisions in C++: only send up to the object subscribed to collisions.
48 Use collision subscription and remove the collsion(A,B) and collision(B,A) 68 Use collision subscription and remove the collsion(A,B) and collision(B,A)
49Check wheter SimMotionState needs large if statement (see TODO). 69Check whether SimMotionState needs large if statement (see TODO).
50 70
51Implement 'top colliders' info. 71Implement 'top colliders' info.
52Avatar jump 72Avatar jump
53Implement meshes or just verify that they work.
54Do prim hash codes work for sculpties and meshes?
55Performance measurement and changes to make quicker. 73Performance measurement and changes to make quicker.
56Implement detailed physics stats (GetStats()). 74Implement detailed physics stats (GetStats()).
57 75
@@ -67,8 +85,6 @@ Performance of closures and delegates for taint processing
67Is there are more efficient method of implementing pre and post step actions? 85Is there are more efficient method of implementing pre and post step actions?
68 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C 86 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
69 87
70Package Bullet source mods for Bullet internal stats output
71
72Physics Arena central pyramid: why is one side permiable? 88Physics Arena central pyramid: why is one side permiable?
73 89
74INTERNAL IMPROVEMENT/CLEANUP 90INTERNAL IMPROVEMENT/CLEANUP
@@ -85,33 +101,42 @@ Complete implemention of preStepActions
85 Replace vehicle step call with prestep event. 101 Replace vehicle step call with prestep event.
86 Is there a need for postStepActions? postStepTaints? 102 Is there a need for postStepActions? postStepTaints?
87Implement linkset by setting position of children when root updated. (LinksetManual) 103Implement linkset by setting position of children when root updated. (LinksetManual)
104 Linkset implementation using manual prim movement.
88LinkablePrim class? Would that simplify/centralize the linkset logic? 105LinkablePrim class? Would that simplify/centralize the linkset logic?
89Linkset implementation using manual prim movement.
90Linkset implementation using compound shapes.
91 Compound shapes will need the LocalID in the shapes and collision
92 processing to get it from there.
93BSScene.UpdateParameterSet() is broken. How to set params on objects? 106BSScene.UpdateParameterSet() is broken. How to set params on objects?
94Remove HeightmapInfo from terrain specification. 107Remove HeightmapInfo from terrain specification.
95 Since C++ code does not need terrain height, this structure et al are not needed. 108 Since C++ code does not need terrain height, this structure et al are not needed.
96Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will 109Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
97 bob at the water level. BSPrim.PositionSanityCheck(). 110 bob at the water level. BSPrim.PositionSanityCheck().
98 111
112THREADING
113=================================================
114Do taint action immediately if not actually executing Bullet.
115 Add lock around Bullet execution and just do taint actions if simulation is not happening.
116
99DONE DONE DONE DONE 117DONE DONE DONE DONE
100================================================= 118=================================================
101Cleanup code in BSDynamics by using motors. 119Cleanup code in BSDynamics by using motors. (Resolution: started)
102Consider implementing terrain with a mesh rather than heightmap. 120Consider implementing terrain with a mesh rather than heightmap. (Resolution: done)
103 Would have better and adjustable resolution. 121 Would have better and adjustable resolution.
104NOTDONE: Build terrain mesh so heighmap is height of the center of the square meter. 122Build terrain mesh so heighmap is height of the center of the square meter.
105 SL and ODE define meter square as being at one corner with one diagional. 123 Resolution: NOT DONE: SL and ODE define meter square as being at one corner with one diagional.
106Terrain as mesh. 124Terrain as mesh. (Resolution: done)
107How are static linksets seen by the physics engine? 125How are static linksets seen by the physics engine?
108 A: they are not linked in physics. When moved, all the children are repositioned. 126 Resolution: they are not linked in physics. When moved, all the children are repositioned.
109Remember to remove BSScene.DetailLog Refresh call. 127Convert BSCharacter to use all API2 (Resolution: done)
110Convert BSCharacter to use all API2
111Avatar pushing difficult (too heavy?) 128Avatar pushing difficult (too heavy?)
112Use asset service passed to BulletSim to get sculptie bodies, etc. 129Use asset service passed to BulletSim to get sculptie bodies, etc. (Resolution: done)
113Vehicles (fix bouncing on terrain) 130Remove old code in DLL (all non-API2 stuff). (Resolution: done)
114Remove old code in DLL (all non-API2 stuff). 131Measurements of mega-physical prim performance (with graph) (Resolution: done, email)
115Measurements of mega-physical prim performance (with graph)
116Debug Bullet internal stats output (why is timing all wrong?) 132Debug Bullet internal stats output (why is timing all wrong?)
117 Bullet stats logging only works with a single instance of Bullet (one region). \ No newline at end of file 133 Resolution: Bullet stats logging only works with a single instance of Bullet (one region).
134Implement meshes or just verify that they work. (Resolution: they do!)
135Do prim hash codes work for sculpties and meshes? (Resolution: yes)
136Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound)
137 Compound shapes will need the LocalID in the shapes and collision
138 processing to get it from there.
139Light cycle falling over when driving (Resolution: implemented VerticalAttractor)
140Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.)
141Package Bullet source mods for Bullet internal stats output
142 (Resolution: move code into WorldData.h rather than relying on patches) \ No newline at end of file