aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorMelanie2012-08-16 02:46:48 +0100
committerMelanie2012-08-16 02:46:48 +0100
commit90ad98370aead53e886832a83a3e8793f361426e (patch)
treeb7076c5fb7ecf75d1ad31f7756543ade8fbf1b49 /OpenSim
parentRemove AreUpdatesSuspended flag because it does nothing (diff)
parentDo a proper null check to avoid the overloaded operator == trap (diff)
downloadopensim-SC-90ad98370aead53e886832a83a3e8793f361426e.zip
opensim-SC-90ad98370aead53e886832a83a3e8793f361426e.tar.gz
opensim-SC-90ad98370aead53e886832a83a3e8793f361426e.tar.bz2
opensim-SC-90ad98370aead53e886832a83a3e8793f361426e.tar.xz
Merge branch 'master' into careminster
Conflicts: OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs31
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs9
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs50
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs18
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs23
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs102
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs55
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs250
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs86
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs32
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs27
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs2
14 files changed, 466 insertions, 223 deletions
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index e4db964..b709baa 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -97,6 +97,32 @@ namespace OpenSim.Framework.Monitoring
97 /// /summary> 97 /// /summary>
98 public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout; 98 public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout;
99 99
100 /// <summary>
101 /// Is this watchdog active?
102 /// </summary>
103 public static bool Enabled
104 {
105 get { return m_enabled; }
106 set
107 {
108// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value);
109
110 if (value == m_enabled)
111 return;
112
113 m_enabled = value;
114
115 if (m_enabled)
116 {
117 // Set now so we don't get alerted on the first run
118 LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
119 }
120
121 m_watchdogTimer.Enabled = m_enabled;
122 }
123 }
124 private static bool m_enabled;
125
100 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 126 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
101 private static Dictionary<int, ThreadWatchdogInfo> m_threads; 127 private static Dictionary<int, ThreadWatchdogInfo> m_threads;
102 private static System.Timers.Timer m_watchdogTimer; 128 private static System.Timers.Timer m_watchdogTimer;
@@ -115,11 +141,6 @@ namespace OpenSim.Framework.Monitoring
115 m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); 141 m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
116 m_watchdogTimer.AutoReset = false; 142 m_watchdogTimer.AutoReset = false;
117 m_watchdogTimer.Elapsed += WatchdogTimerElapsed; 143 m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
118
119 // Set now so we don't get alerted on the first run
120 LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
121
122 m_watchdogTimer.Start();
123 } 144 }
124 145
125 /// <summary> 146 /// <summary>
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index aed10f6..d107b7a 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -320,8 +320,13 @@ namespace OpenSim
320 m_httpServerPort = m_networkServersInfo.HttpListenerPort; 320 m_httpServerPort = m_networkServersInfo.HttpListenerPort;
321 SceneManager.OnRestartSim += handleRestartRegion; 321 SceneManager.OnRestartSim += handleRestartRegion;
322 322
323 // Only start the memory watchdog once all regions are ready 323 // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
324 SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady; 324 // heavily used during initial startup.
325 //
326 // FIXME: It's also possible that region ready status should be flipped during an OAR load since this
327 // also makes heavy use of the CPU.
328 SceneManager.OnRegionsReadyStatusChange
329 += sm => { MemoryWatchdog.Enabled = sm.AllRegionsReady; Watchdog.Enabled = sm.AllRegionsReady; };
325 } 330 }
326 331
327 /// <summary> 332 /// <summary>
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
index 72df6b9..683bc51 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
@@ -37,7 +37,8 @@ public class BS6DofConstraint : BSConstraint
37 // Create a btGeneric6DofConstraint 37 // Create a btGeneric6DofConstraint
38 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 38 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
39 Vector3 frame1, Quaternion frame1rot, 39 Vector3 frame1, Quaternion frame1rot,
40 Vector3 frame2, Quaternion frame2rot ) 40 Vector3 frame2, Quaternion frame2rot,
41 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
41 { 42 {
42 m_world = world; 43 m_world = world;
43 m_body1 = obj1; 44 m_body1 = obj1;
@@ -46,16 +47,45 @@ public class BS6DofConstraint : BSConstraint
46 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, 47 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
47 frame1, frame1rot, 48 frame1, frame1rot,
48 frame2, frame2rot, 49 frame2, frame2rot,
49 true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/)); 50 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
50 m_enabled = true; 51 m_enabled = true;
51 } 52 }
52 53
54 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
55 Vector3 joinPoint,
56 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
57 {
58 m_world = world;
59 m_body1 = obj1;
60 m_body2 = obj2;
61 m_constraint = new BulletConstraint(
62 BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
63 joinPoint,
64 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
65 m_enabled = true;
66 }
67
68 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
69 {
70 bool ret = false;
71 if (m_enabled)
72 {
73 BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot);
74 ret = true;
75 }
76 return ret;
77 }
78
53 public bool SetCFMAndERP(float cfm, float erp) 79 public bool SetCFMAndERP(float cfm, float erp)
54 { 80 {
55 bool ret = true; 81 bool ret = false;
56 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 82 if (m_enabled)
57 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); 83 {
58 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 84 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
85 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
86 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
87 ret = true;
88 }
59 return ret; 89 return ret;
60 } 90 }
61 91
@@ -76,5 +106,13 @@ public class BS6DofConstraint : BSConstraint
76 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); 106 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
77 return ret; 107 return ret;
78 } 108 }
109
110 public bool SetBreakingImpulseThreshold(float threshold)
111 {
112 bool ret = false;
113 if (m_enabled)
114 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold);
115 return ret;
116 }
79} 117}
80} 118}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index f164afe..e2f7af9 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -137,7 +137,7 @@ public class BSCharacter : PhysicsActor
137 // called when this character is being destroyed and the resources should be released 137 // called when this character is being destroyed and the resources should be released
138 public void Destroy() 138 public void Destroy()
139 { 139 {
140 // DetailLog("{0},Destroy", LocalID); 140 // DetailLog("{0},BSCharacter.Destroy", LocalID);
141 _scene.TaintedObject("BSCharacter.destroy", delegate() 141 _scene.TaintedObject("BSCharacter.destroy", delegate()
142 { 142 {
143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
@@ -209,7 +209,7 @@ public class BSCharacter : PhysicsActor
209 209
210 _scene.TaintedObject("BSCharacter.setPosition", delegate() 210 _scene.TaintedObject("BSCharacter.setPosition", delegate()
211 { 211 {
212 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 212 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
214 }); 214 });
215 } 215 }
@@ -226,7 +226,7 @@ public class BSCharacter : PhysicsActor
226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); 226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
227 if (_position.Z < terrainHeight) 227 if (_position.Z < terrainHeight)
228 { 228 {
229 DetailLog("{0},PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); 229 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
230 _position.Z = terrainHeight + 2.0f; 230 _position.Z = terrainHeight + 2.0f;
231 ret = true; 231 ret = true;
232 } 232 }
@@ -368,7 +368,7 @@ public class BSCharacter : PhysicsActor
368 set { _buoyancy = value; 368 set { _buoyancy = value;
369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() 369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
370 { 370 {
371 DetailLog("{0},setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 371 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); 372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
373 }); 373 });
374 } 374 }
@@ -415,7 +415,7 @@ public class BSCharacter : PhysicsActor
415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
416 _scene.TaintedObject("BSCharacter.AddForce", delegate() 416 _scene.TaintedObject("BSCharacter.AddForce", delegate()
417 { 417 {
418 DetailLog("{0},setAddForce,taint,addedForce={1}", LocalID, _force); 418 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force); 419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
420 }); 420 });
421 } 421 }
@@ -488,9 +488,11 @@ public class BSCharacter : PhysicsActor
488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
489 // base.RequestPhysicsterseUpdate(); 489 // base.RequestPhysicsterseUpdate();
490 490
491 /*
491 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 492 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
492 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 493 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
493 entprop.Acceleration, entprop.RotationalVelocity); 494 entprop.Acceleration, entprop.RotationalVelocity);
495 */
494 } 496 }
495 497
496 // Called by the scene when a collision with this object is reported 498 // Called by the scene when a collision with this object is reported
@@ -507,6 +509,7 @@ public class BSCharacter : PhysicsActor
507 { 509 {
508 _collidingGroundStep = _scene.SimulationStep; 510 _collidingGroundStep = _scene.SimulationStep;
509 } 511 }
512 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
510 513
511 // throttle collisions to the rate specified in the subscription 514 // throttle collisions to the rate specified in the subscription
512 if (_subscribedEventsMs != 0) { 515 if (_subscribedEventsMs != 0) {
@@ -535,7 +538,10 @@ public class BSCharacter : PhysicsActor
535 if (collisionCollection == null) 538 if (collisionCollection == null)
536 collisionCollection = new CollisionEventUpdate(); 539 collisionCollection = new CollisionEventUpdate();
537 base.SendCollisionUpdate(collisionCollection); 540 base.SendCollisionUpdate(collisionCollection);
538 collisionCollection.Clear(); 541 // If there were any collisions in the collection, make sure we don't use the
542 // same instance next time.
543 if (collisionCollection.Count > 0)
544 collisionCollection = null;
539 // End kludge 545 // End kludge
540 } 546 }
541 547
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index da26b72..25084d8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -80,10 +80,33 @@ public abstract class BSConstraint : IDisposable
80 bool ret = false; 80 bool ret = false;
81 if (m_enabled) 81 if (m_enabled)
82 { 82 {
83 // Recompute the internal transforms
83 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); 84 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
84 ret = true; 85 ret = true;
85 } 86 }
86 return ret; 87 return ret;
87 } 88 }
89
90 // Reset this constraint making sure it has all its internal structures
91 // recomputed and is enabled and ready to go.
92 public virtual bool RecomputeConstraintVariables(float mass)
93 {
94 bool ret = false;
95 if (m_enabled)
96 {
97 ret = CalculateTransforms();
98 if (ret)
99 {
100 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}",
101 // BSScene.DetailLogZero, Body1.ID, Body2.ID);
102 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
103 }
104 else
105 {
106 m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID);
107 }
108 }
109 return ret;
110 }
88} 111}
89} 112}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index 3df2ddc..22ea367 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -56,21 +56,25 @@ public class BSConstraintCollection : IDisposable
56 56
57 public void Clear() 57 public void Clear()
58 { 58 {
59 foreach (BSConstraint cons in m_constraints) 59 lock (m_constraints)
60 { 60 {
61 cons.Dispose(); 61 foreach (BSConstraint cons in m_constraints)
62 {
63 cons.Dispose();
64 }
65 m_constraints.Clear();
62 } 66 }
63 m_constraints.Clear();
64 } 67 }
65 68
66 public bool AddConstraint(BSConstraint cons) 69 public bool AddConstraint(BSConstraint cons)
67 { 70 {
68 // There is only one constraint between any bodies. Remove any old just to make sure. 71 lock (m_constraints)
69 RemoveAndDestroyConstraint(cons.Body1, cons.Body2); 72 {
70 73 // There is only one constraint between any bodies. Remove any old just to make sure.
71 m_world.scene.DetailLog("{0},BSConstraintCollection.AddConstraint,call,body1={1},body2={2}", BSScene.DetailLogZero, cons.Body1.ID, cons.Body2.ID); 74 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
72 75
73 m_constraints.Add(cons); 76 m_constraints.Add(cons);
77 }
74 78
75 return true; 79 return true;
76 } 80 }
@@ -84,16 +88,19 @@ public class BSConstraintCollection : IDisposable
84 88
85 uint lookingID1 = body1.ID; 89 uint lookingID1 = body1.ID;
86 uint lookingID2 = body2.ID; 90 uint lookingID2 = body2.ID;
87 ForEachConstraint(delegate(BSConstraint constrain) 91 lock (m_constraints)
88 { 92 {
89 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) 93 foreach (BSConstraint constrain in m_constraints)
90 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
91 { 94 {
92 foundConstraint = constrain; 95 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
93 found = true; 96 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
97 {
98 foundConstraint = constrain;
99 found = true;
100 break;
101 }
94 } 102 }
95 return found; 103 }
96 });
97 returnConstraint = foundConstraint; 104 returnConstraint = foundConstraint;
98 return found; 105 return found;
99 } 106 }
@@ -103,23 +110,33 @@ public class BSConstraintCollection : IDisposable
103 // Return 'true' if a constraint was found and destroyed. 110 // Return 'true' if a constraint was found and destroyed.
104 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) 111 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
105 { 112 {
106 // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
107
108 bool ret = false; 113 bool ret = false;
109 BSConstraint constrain; 114 lock (m_constraints)
115 {
116 BSConstraint constrain;
117 if (this.TryGetConstraint(body1, body2, out constrain))
118 {
119 // remove the constraint from our collection
120 RemoveAndDestroyConstraint(constrain);
121 ret = true;
122 }
123 }
124
125 return ret;
126 }
110 127
111 if (this.TryGetConstraint(body1, body2, out constrain)) 128 // The constraint MUST exist in the collection
129 public bool RemoveAndDestroyConstraint(BSConstraint constrain)
130 {
131 lock (m_constraints)
112 { 132 {
113 m_world.scene.DetailLog("{0},BSConstraintCollection.RemoveAndDestroyConstraint,taint,body1={1},body2={2}", BSScene.DetailLogZero, body1.ID, body2.ID);
114 // remove the constraint from our collection 133 // remove the constraint from our collection
115 m_constraints.Remove(constrain); 134 m_constraints.Remove(constrain);
116 // tell the engine that all its structures need to be freed
117 constrain.Dispose();
118 // we destroyed something
119 ret = true;
120 } 135 }
121 136 // tell the engine that all its structures need to be freed
122 return ret; 137 constrain.Dispose();
138 // we destroyed something
139 return true;
123 } 140 }
124 141
125 // Remove all constraints that reference the passed body. 142 // Remove all constraints that reference the passed body.
@@ -130,16 +147,15 @@ public class BSConstraintCollection : IDisposable
130 147
131 List<BSConstraint> toRemove = new List<BSConstraint>(); 148 List<BSConstraint> toRemove = new List<BSConstraint>();
132 uint lookingID = body1.ID; 149 uint lookingID = body1.ID;
133 ForEachConstraint(delegate(BSConstraint constrain) 150 lock (m_constraints)
134 { 151 {
135 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) 152 foreach (BSConstraint constrain in m_constraints)
136 { 153 {
137 toRemove.Add(constrain); 154 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
155 {
156 toRemove.Add(constrain);
157 }
138 } 158 }
139 return false;
140 });
141 lock (m_constraints)
142 {
143 foreach (BSConstraint constrain in toRemove) 159 foreach (BSConstraint constrain in toRemove)
144 { 160 {
145 m_constraints.Remove(constrain); 161 m_constraints.Remove(constrain);
@@ -151,28 +167,16 @@ public class BSConstraintCollection : IDisposable
151 167
152 public bool RecalculateAllConstraints() 168 public bool RecalculateAllConstraints()
153 { 169 {
154 ForEachConstraint(delegate(BSConstraint constrain) 170 bool ret = false;
155 {
156 constrain.CalculateTransforms();
157 return false;
158 });
159 return true;
160 }
161
162 // Lock the constraint list and loop through it.
163 // The constraint action returns 'true' if it wants the loop aborted.
164 private void ForEachConstraint(ConstraintAction action)
165 {
166 lock (m_constraints) 171 lock (m_constraints)
167 { 172 {
168 foreach (BSConstraint constrain in m_constraints) 173 foreach (BSConstraint constrain in m_constraints)
169 { 174 {
170 if (action(constrain)) 175 constrain.CalculateTransforms();
171 break; 176 ret = true;
172 } 177 }
173 } 178 }
179 return ret;
174 } 180 }
175
176
177} 181}
178} 182}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index c197e61..5a9f135 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -613,7 +613,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
613 MoveAngular(pTimestep); 613 MoveAngular(pTimestep);
614 LimitRotation(pTimestep); 614 LimitRotation(pTimestep);
615 615
616 DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}", 616 DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); 617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
618 }// end Step 618 }// end Step
619 619
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
new file mode 100755
index 0000000..d68048b
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
@@ -0,0 +1,55 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35class BSHingeConstraint : BSConstraint
36{
37 public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
38 Vector3 pivotInA, Vector3 pivotInB,
39 Vector3 axisInA, Vector3 axisInB,
40 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
41 {
42 m_world = world;
43 m_body1 = obj1;
44 m_body2 = obj2;
45 m_constraint = new BulletConstraint(
46 BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
47 pivotInA, pivotInB,
48 axisInA, axisInB,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
50 m_enabled = true;
51 }
52
53}
54
55}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 4a71612..087b9bb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -37,11 +37,12 @@ public class BSLinkset
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPrim m_linksetRoot; 39 private BSPrim m_linksetRoot;
40 public BSPrim Root { get { return m_linksetRoot; } } 40 public BSPrim LinksetRoot { get { return m_linksetRoot; } }
41 41
42 private BSScene m_scene; 42 private BSScene m_physicsScene;
43 public BSScene Scene { get { return m_scene; } } 43 public BSScene PhysicsScene { get { return m_physicsScene; } }
44 44
45 // The children under the root in this linkset
45 private List<BSPrim> m_children; 46 private List<BSPrim> m_children;
46 47
47 // We lock the diddling of linkset classes to prevent any badness. 48 // We lock the diddling of linkset classes to prevent any badness.
@@ -73,7 +74,7 @@ public class BSLinkset
73 public BSLinkset(BSScene scene, BSPrim parent) 74 public BSLinkset(BSScene scene, BSPrim parent)
74 { 75 {
75 // A simple linkset of one (no children) 76 // A simple linkset of one (no children)
76 m_scene = scene; 77 m_physicsScene = scene;
77 m_linksetRoot = parent; 78 m_linksetRoot = parent;
78 m_children = new List<BSPrim>(); 79 m_children = new List<BSPrim>();
79 m_mass = parent.MassRaw; 80 m_mass = parent.MassRaw;
@@ -91,6 +92,9 @@ public class BSLinkset
91 return this; 92 return this;
92 } 93 }
93 94
95 // Remove a child from a linkset.
96 // Returns a new linkset for the child which is a linkset of one (just the
97 // orphened child).
94 public BSLinkset RemoveMeFromLinkset(BSPrim child) 98 public BSLinkset RemoveMeFromLinkset(BSPrim child)
95 { 99 {
96 lock (m_linksetActivityLock) 100 lock (m_linksetActivityLock)
@@ -114,60 +118,9 @@ public class BSLinkset
114 } 118 }
115 119
116 // The child is down to a linkset of just itself 120 // The child is down to a linkset of just itself
117 return new BSLinkset(Scene, child); 121 return new BSLinkset(PhysicsScene, child);
118 } 122 }
119 123
120 /* DEPRECATED: this is really bad in that it trys to unlink other prims.
121 // An existing linkset had one of its members rebuilt or something.
122 // Go through the linkset and rebuild the pointers to the bodies of the linkset members.
123 public BSLinkset RefreshLinkset(BSPrim requestor)
124 {
125 BSLinkset ret = requestor.Linkset;
126
127 lock (m_linksetActivityLock)
128 {
129 // The body pointer is refetched in case anything has moved.
130 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID);
131 if (aPtr == System.IntPtr.Zero)
132 {
133 // That's odd. We can't find the root of the linkset.
134 // The linkset is somehow dead. The requestor is now a member of a linkset of one.
135 DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID);
136 ret = RemoveMeFromLinkset(m_linksetRoot);
137 }
138 else
139 {
140 // Reconstruct the pointer to the body of the linkset root.
141 DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr);
142 m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr);
143
144 List<BSPrim> toRemove = new List<BSPrim>();
145 foreach (BSPrim bsp in m_children)
146 {
147 aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID);
148 if (aPtr == System.IntPtr.Zero)
149 {
150 toRemove.Add(bsp);
151 }
152 else
153 {
154 // Reconstruct the pointer to the body of the linkset root.
155 DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr);
156 bsp.Body = new BulletBody(bsp.LocalID, aPtr);
157 }
158 }
159 foreach (BSPrim bsp in toRemove)
160 {
161 RemoveChildFromOtherLinkset(bsp);
162 }
163 }
164 }
165
166 return ret;
167 }
168 */
169
170
171 // Return 'true' if the passed object is the root object of this linkset 124 // Return 'true' if the passed object is the root object of this linkset
172 public bool IsRoot(BSPrim requestor) 125 public bool IsRoot(BSPrim requestor)
173 { 126 {
@@ -183,12 +136,15 @@ public class BSLinkset
183 public bool HasChild(BSPrim child) 136 public bool HasChild(BSPrim child)
184 { 137 {
185 bool ret = false; 138 bool ret = false;
186 foreach (BSPrim bp in m_children) 139 lock (m_linksetActivityLock)
187 { 140 {
188 if (child.LocalID == bp.LocalID) 141 foreach (BSPrim bp in m_children)
189 { 142 {
190 ret = true; 143 if (child.LocalID == bp.LocalID)
191 break; 144 {
145 ret = true;
146 break;
147 }
192 } 148 }
193 } 149 }
194 return ret; 150 return ret;
@@ -209,13 +165,16 @@ public class BSLinkset
209 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; 165 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
210 float totalMass = m_linksetRoot.MassRaw; 166 float totalMass = m_linksetRoot.MassRaw;
211 167
212 foreach (BSPrim bp in m_children) 168 lock (m_linksetActivityLock)
213 { 169 {
214 com += bp.Position * bp.MassRaw; 170 foreach (BSPrim bp in m_children)
215 totalMass += bp.MassRaw; 171 {
172 com += bp.Position * bp.MassRaw;
173 totalMass += bp.MassRaw;
174 }
175 if (totalMass != 0f)
176 com /= totalMass;
216 } 177 }
217 if (totalMass != 0f)
218 com /= totalMass;
219 178
220 return com; 179 return com;
221 } 180 }
@@ -224,29 +183,84 @@ public class BSLinkset
224 { 183 {
225 OMV.Vector3 com = m_linksetRoot.Position; 184 OMV.Vector3 com = m_linksetRoot.Position;
226 185
227 foreach (BSPrim bp in m_children) 186 lock (m_linksetActivityLock)
228 { 187 {
229 com += bp.Position * bp.MassRaw; 188 foreach (BSPrim bp in m_children)
189 {
190 com += bp.Position * bp.MassRaw;
191 }
192 com /= (m_children.Count + 1);
230 } 193 }
231 com /= (m_children.Count + 1);
232 194
233 return com; 195 return com;
234 } 196 }
235 197
198 // When physical properties are changed the linkset needs to recalculate
199 // its internal properties.
200 public void Refresh(BSPrim requestor)
201 {
202 // If there are no children, there aren't any constraints to recompute
203 if (!HasAnyChildren)
204 return;
205
206 // Only the root does the recomputation
207 if (IsRoot(requestor))
208 {
209 PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate()
210 {
211 RecomputeLinksetConstraintVariables();
212 });
213 }
214 }
215
216 // Call each of the constraints that make up this linkset and recompute the
217 // various transforms and variables. Used when objects are added or removed
218 // from a linkset to make sure the constraints know about the new mass and
219 // geometry.
220 // Must only be called at taint time!!
221 private bool RecomputeLinksetConstraintVariables()
222 {
223 float linksetMass = LinksetMass;
224 lock (m_linksetActivityLock)
225 {
226 foreach (BSPrim child in m_children)
227 {
228 BSConstraint constrain;
229 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
230 {
231 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
232 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
233 constrain.RecomputeConstraintVariables(linksetMass);
234 }
235 else
236 {
237 // Non-fatal error that can happen when children are being added to the linkset but
238 // their constraints have not been created yet.
239 // Caused by the fact that m_children is built at run time but building constraints
240 // happens at taint time.
241 // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}",
242 // m_linksetRoot.Body.ID, child.Body.ID);
243 }
244 }
245 }
246 return false;
247 }
248
236 // I am the root of a linkset and a new child is being added 249 // I am the root of a linkset and a new child is being added
237 // Called while LinkActivity is locked. 250 // Called while LinkActivity is locked.
238 public void AddChildToLinkset(BSPrim child) 251 private void AddChildToLinkset(BSPrim child)
239 { 252 {
240 if (!HasChild(child)) 253 if (!HasChild(child))
241 { 254 {
242 m_children.Add(child); 255 m_children.Add(child);
243 256
244 BSPrim root = Root; // capture the root as of now 257 BSPrim rootx = LinksetRoot; // capture the root as of now
245 m_scene.TaintedObject("AddChildToLinkset", delegate() 258 BSPrim childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
246 { 260 {
247 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 261 // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
248 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
249 PhysicallyLinkAChildToRoot(root, child); // build the physical binding between me and the child 263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
250 }); 264 });
251 } 265 }
252 return; 266 return;
@@ -257,31 +271,34 @@ public class BSLinkset
257 // it's still connected to the linkset. 271 // it's still connected to the linkset.
258 // Normal OpenSimulator operation will never do this because other SceneObjectPart information 272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
259 // has to be updated also (like pointer to prim's parent). 273 // has to be updated also (like pointer to prim's parent).
260 public void RemoveChildFromOtherLinkset(BSPrim pchild) 274 private void RemoveChildFromOtherLinkset(BSPrim pchild)
261 { 275 {
262 pchild.Linkset = new BSLinkset(m_scene, pchild); 276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
263 RemoveChildFromLinkset(pchild); 277 RemoveChildFromLinkset(pchild);
264 } 278 }
265 279
266 // I am the root of a linkset and one of my children is being removed. 280 // I am the root of a linkset and one of my children is being removed.
267 // Safe to call even if the child is not really in my linkset. 281 // Safe to call even if the child is not really in my linkset.
268 public void RemoveChildFromLinkset(BSPrim child) 282 private void RemoveChildFromLinkset(BSPrim child)
269 { 283 {
270 if (m_children.Remove(child)) 284 if (m_children.Remove(child))
271 { 285 {
272 BSPrim root = Root; // capture the root as of now 286 BSPrim rootx = LinksetRoot; // capture the root as of now
273 m_scene.TaintedObject("RemoveChildFromLinkset", delegate() 287 BSPrim childx = child;
288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
274 { 289 {
275 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
276 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
277 292
278 PhysicallyUnlinkAChildFromRoot(root, child); 293 PhysicallyUnlinkAChildFromRoot(rootx, childx);
279 }); 294 });
295
296 RecomputeLinksetConstraintVariables();
280 } 297 }
281 else 298 else
282 { 299 {
283 // This will happen if we remove the root of the linkset first. Non-fatal occurance. 300 // This will happen if we remove the root of the linkset first. Non-fatal occurance.
284 // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); 301 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
285 } 302 }
286 return; 303 return;
287 } 304 }
@@ -293,37 +310,72 @@ public class BSLinkset
293 // Zero motion for children so they don't interpolate 310 // Zero motion for children so they don't interpolate
294 childPrim.ZeroMotion(); 311 childPrim.ZeroMotion();
295 312
313 // Relative position normalized to the root prim
314 // Essentually a vector pointing from center of rootPrim to center of childPrim
315 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
316
317 // real world coordinate of midpoint between the two objects
318 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
319
320 // create a constraint that allows no freedom of movement between the two objects
321 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
322 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
323 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
324 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
325 BS6DofConstraint constrain = new BS6DofConstraint(
326 m_physicsScene.World, rootPrim.Body, childPrim.Body,
327 midPoint,
328 true,
329 true
330 );
331 /* NOTE: attempt to build constraint with full frame computation, etc.
332 * Using the midpoint is easier since it lets the Bullet code use the transforms
333 * of the objects.
334 * Code left here as an example.
335 // ==================================================================================
296 // relative position normalized to the root prim 336 // relative position normalized to the root prim
297 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); 337 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
298 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; 338 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
299 339
300 // relative rotation of the child to the parent 340 // relative rotation of the child to the parent
301 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; 341 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
342 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
302 343
303 // create a constraint that allows no freedom of movement between the two objects 344 // create a constraint that allows no freedom of movement between the two objects
304 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 345 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
305 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); 346 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
306 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 347 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
307 BS6DofConstraint constrain = new BS6DofConstraint( 348 BS6DofConstraint constrain = new BS6DofConstraint(
308 m_scene.World, rootPrim.Body, childPrim.Body, 349 PhysicsScene.World, rootPrim.Body, childPrim.Body,
309 childRelativePosition,
310 childRelativeRotation,
311 OMV.Vector3.Zero, 350 OMV.Vector3.Zero,
312 -childRelativeRotation 351 OMV.Quaternion.Inverse(rootPrim.Orientation),
352 OMV.Vector3.Zero,
353 OMV.Quaternion.Inverse(childPrim.Orientation),
354 // A point half way between the parent and child
355 // childRelativePosition/2,
356 // childRelativeRotation,
357 // childRelativePosition/2,
358 // inverseChildRelativeRotation,
359 true,
360 true
313 ); 361 );
314 m_scene.Constraints.AddConstraint(constrain); 362 // ==================================================================================
363 */
364
365 m_physicsScene.Constraints.AddConstraint(constrain);
315 366
316 // zero linear and angular limits makes the objects unable to move in relation to each other 367 // zero linear and angular limits makes the objects unable to move in relation to each other
317 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 368 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
318 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 369 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
319 370
320 // tweek the constraint to increase stability 371 // tweek the constraint to increase stability
321 constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); 372 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
322 constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), 373 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
323 m_scene.Params.linkConstraintTransMotorMaxVel, 374 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
324 m_scene.Params.linkConstraintTransMotorMaxForce); 375 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
325 constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); 376 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
326 377
378 RecomputeLinksetConstraintVariables();
327 } 379 }
328 380
329 // Remove linkage between myself and a particular child 381 // Remove linkage between myself and a particular child
@@ -334,7 +386,9 @@ public class BSLinkset
334 // LogHeader, rootPrim.LocalID, childPrim.LocalID); 386 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
335 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 387 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
336 388
337 m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); 389 // Find the constraint for this link and get rid of it from the overall collection and from my list
390 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
391
338 // Make the child refresh its location 392 // Make the child refresh its location
339 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); 393 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
340 } 394 }
@@ -346,20 +400,20 @@ public class BSLinkset
346 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); 400 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
347 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
348 402
349 m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); 403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
350 } 404 }
351 405
352 // Invoke the detailed logger and output something if it's enabled. 406 // Invoke the detailed logger and output something if it's enabled.
353 private void DebugLog(string msg, params Object[] args) 407 private void DebugLog(string msg, params Object[] args)
354 { 408 {
355 if (m_scene.ShouldDebugLog) 409 if (m_physicsScene.ShouldDebugLog)
356 m_scene.Logger.DebugFormat(msg, args); 410 m_physicsScene.Logger.DebugFormat(msg, args);
357 } 411 }
358 412
359 // Invoke the detailed logger and output something if it's enabled. 413 // Invoke the detailed logger and output something if it's enabled.
360 private void DetailLog(string msg, params Object[] args) 414 private void DetailLog(string msg, params Object[] args)
361 { 415 {
362 m_scene.PhysicsLogging.Write(msg, args); 416 m_physicsScene.PhysicsLogging.Write(msg, args);
363 } 417 }
364 418
365} 419}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 05cc822..9c20004 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -163,13 +163,13 @@ public sealed class BSPrim : PhysicsActor
163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
164 164
165 // Undo any links between me and any other object 165 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.Root; 166 BSPrim parentBefore = _linkset.LinksetRoot;
167 int childrenBefore = _linkset.NumberOfChildren; 167 int childrenBefore = _linkset.NumberOfChildren;
168 168
169 _linkset = _linkset.RemoveMeFromLinkset(this); 169 _linkset = _linkset.RemoveMeFromLinkset(this);
170 170
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", 171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); 172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
173 173
174 // Undo any vehicle properties 174 // Undo any vehicle properties
175 this.VehicleType = (int)Vehicle.TYPE_NONE; 175 this.VehicleType = (int)Vehicle.TYPE_NONE;
@@ -233,13 +233,13 @@ public sealed class BSPrim : PhysicsActor
233 if (parent != null) 233 if (parent != null)
234 { 234 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); 235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID);
236 BSPrim parentBefore = _linkset.Root; 236 BSPrim parentBefore = _linkset.LinksetRoot;
237 int childrenBefore = _linkset.NumberOfChildren; 237 int childrenBefore = _linkset.NumberOfChildren;
238 238
239 _linkset = parent.Linkset.AddMeToLinkset(this); 239 _linkset = parent.Linkset.AddMeToLinkset(this);
240 240
241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); 242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
243 } 243 }
244 return; 244 return;
245 } 245 }
@@ -249,15 +249,15 @@ public sealed class BSPrim : PhysicsActor
249 // TODO: decide if this parent checking needs to happen at taint time 249 // TODO: decide if this parent checking needs to happen at taint time
250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, 251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
252 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); 252 _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
253 253
254 BSPrim parentBefore = _linkset.Root; 254 BSPrim parentBefore = _linkset.LinksetRoot;
255 int childrenBefore = _linkset.NumberOfChildren; 255 int childrenBefore = _linkset.NumberOfChildren;
256 256
257 _linkset = _linkset.RemoveMeFromLinkset(this); 257 _linkset = _linkset.RemoveMeFromLinkset(this);
258 258
259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); 260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
261 return; 261 return;
262 } 262 }
263 263
@@ -280,7 +280,7 @@ public sealed class BSPrim : PhysicsActor
280 280
281 public override void LockAngularMotion(OMV.Vector3 axis) 281 public override void LockAngularMotion(OMV.Vector3 axis)
282 { 282 {
283 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
284 return; 284 return;
285 } 285 }
286 286
@@ -299,7 +299,7 @@ public sealed class BSPrim : PhysicsActor
299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
300 _scene.TaintedObject("BSPrim.setPosition", delegate() 300 _scene.TaintedObject("BSPrim.setPosition", delegate()
301 { 301 {
302 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
304 }); 304 });
305 } 305 }
@@ -336,7 +336,7 @@ public sealed class BSPrim : PhysicsActor
336 _force = value; 336 _force = value;
337 _scene.TaintedObject("BSPrim.setForce", delegate() 337 _scene.TaintedObject("BSPrim.setForce", delegate()
338 { 338 {
339 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force); 341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
342 }); 342 });
@@ -414,7 +414,7 @@ public sealed class BSPrim : PhysicsActor
414 _velocity = value; 414 _velocity = value;
415 _scene.TaintedObject("BSPrim.setVelocity", delegate() 415 _scene.TaintedObject("BSPrim.setVelocity", delegate()
416 { 416 {
417 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
419 }); 419 });
420 } 420 }
@@ -422,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
422 public override OMV.Vector3 Torque { 422 public override OMV.Vector3 Torque {
423 get { return _torque; } 423 get { return _torque; }
424 set { _torque = value; 424 set { _torque = value;
425 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
426 } 426 }
427 } 427 }
428 public override float CollisionScore { 428 public override float CollisionScore {
@@ -449,7 +449,7 @@ public sealed class BSPrim : PhysicsActor
449 _scene.TaintedObject("BSPrim.setOrientation", delegate() 449 _scene.TaintedObject("BSPrim.setOrientation", delegate()
450 { 450 {
451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
452 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
454 }); 454 });
455 } 455 }
@@ -497,8 +497,11 @@ public sealed class BSPrim : PhysicsActor
497 497
498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
499 499
500 // recompute any linkset parameters
501 _linkset.Refresh(this);
502
500 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); 503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
501 DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); 504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
502 } 505 }
503 506
504 // prims don't fly 507 // prims don't fly
@@ -555,7 +558,7 @@ public sealed class BSPrim : PhysicsActor
555 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
556 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
557 { 560 {
558 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
559 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
560 }); 563 });
561 } 564 }
@@ -572,7 +575,7 @@ public sealed class BSPrim : PhysicsActor
572 _buoyancy = value; 575 _buoyancy = value;
573 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
574 { 577 {
575 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
576 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
577 }); 580 });
578 } 581 }
@@ -635,17 +638,17 @@ public sealed class BSPrim : PhysicsActor
635 } 638 }
636 m_accumulatedForces.Clear(); 639 m_accumulatedForces.Clear();
637 } 640 }
638 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
639 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); 642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
640 }); 643 });
641 } 644 }
642 645
643 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
644 DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
645 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 648 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
646 } 649 }
647 public override void SetMomentum(OMV.Vector3 momentum) { 650 public override void SetMomentum(OMV.Vector3 momentum) {
648 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
649 } 652 }
650 public override void SubscribeEvents(int ms) { 653 public override void SubscribeEvents(int ms) {
651 _subscribedEventsMs = ms; 654 _subscribedEventsMs = ms;
@@ -989,7 +992,7 @@ public sealed class BSPrim : PhysicsActor
989 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 992 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
990 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 993 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
991 { 994 {
992 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); 995 // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 996 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
994 // Bullet native objects are scaled by the Bullet engine so pass the size in 997 // Bullet native objects are scaled by the Bullet engine so pass the size in
995 _scale = _size; 998 _scale = _size;
@@ -1003,7 +1006,7 @@ public sealed class BSPrim : PhysicsActor
1003 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1006 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1004 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1007 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1005 { 1008 {
1006 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); 1009 // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
1007 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1010 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
1008 _scale = _size; 1011 _scale = _size;
1009 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1012 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@@ -1046,12 +1049,12 @@ public sealed class BSPrim : PhysicsActor
1046 // if this new shape is the same as last time, don't recreate the mesh 1049 // if this new shape is the same as last time, don't recreate the mesh
1047 if (_meshKey == newMeshKey) return; 1050 if (_meshKey == newMeshKey) return;
1048 1051
1049 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); 1052 // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1050 // Since we're recreating new, get rid of any previously generated shape 1053 // Since we're recreating new, get rid of any previously generated shape
1051 if (_meshKey != 0) 1054 if (_meshKey != 0)
1052 { 1055 {
1053 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1056 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1054 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1057 // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1055 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1058 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1056 _mesh = null; 1059 _mesh = null;
1057 _meshKey = 0; 1060 _meshKey = 0;
@@ -1081,7 +1084,7 @@ public sealed class BSPrim : PhysicsActor
1081 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1082 // meshes are already scaled by the meshmerizer 1085 // meshes are already scaled by the meshmerizer
1083 _scale = new OMV.Vector3(1f, 1f, 1f); 1086 _scale = new OMV.Vector3(1f, 1f, 1f);
1084 DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); 1087 // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
1085 return; 1088 return;
1086 } 1089 }
1087 1090
@@ -1095,28 +1098,21 @@ public sealed class BSPrim : PhysicsActor
1095 // if the hull hasn't changed, don't rebuild it 1098 // if the hull hasn't changed, don't rebuild it
1096 if (newHullKey == _hullKey) return; 1099 if (newHullKey == _hullKey) return;
1097 1100
1098 DetailLog("{0},BSPrim.CreateGeomHull,create,key={1}", LocalID, _meshKey); 1101 // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1099 1102
1100 // Since we're recreating new, get rid of any previously generated shape 1103 // Since we're recreating new, get rid of any previously generated shape
1101 if (_hullKey != 0) 1104 if (_hullKey != 0)
1102 { 1105 {
1103 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1106 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1104 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); 1107 // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1105 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1108 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1106 _hullKey = 0; 1109 _hullKey = 0;
1107 _hulls.Clear();
1108 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1109 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1110 _mesh = null; // the mesh cannot match either
1111 _meshKey = 0;
1112 } 1110 }
1113 1111
1114 _hullKey = newHullKey; 1112 _hullKey = newHullKey;
1115 if (_meshKey != _hullKey) 1113
1116 { 1114 // Make sure the underlying mesh exists and is correct
1117 // if the underlying mesh has changed, rebuild it 1115 CreateGeomMesh();
1118 CreateGeomMesh();
1119 }
1120 1116
1121 int[] indices = _mesh.getIndexListAsInt(); 1117 int[] indices = _mesh.getIndexListAsInt();
1122 List<OMV.Vector3> vertices = _mesh.getVertexList(); 1118 List<OMV.Vector3> vertices = _mesh.getVertexList();
@@ -1142,7 +1138,7 @@ public sealed class BSPrim : PhysicsActor
1142 // create the hull into the _hulls variable 1138 // create the hull into the _hulls variable
1143 convexBuilder.process(dcomp); 1139 convexBuilder.process(dcomp);
1144 1140
1145 // Convert the vertices and indices for passing to unmanaged 1141 // Convert the vertices and indices for passing to unmanaged.
1146 // The hull information is passed as a large floating point array. 1142 // The hull information is passed as a large floating point array.
1147 // The format is: 1143 // The format is:
1148 // convHulls[0] = number of hulls 1144 // convHulls[0] = number of hulls
@@ -1202,7 +1198,7 @@ public sealed class BSPrim : PhysicsActor
1202 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1198 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1203 // meshes are already scaled by the meshmerizer 1199 // meshes are already scaled by the meshmerizer
1204 _scale = new OMV.Vector3(1f, 1f, 1f); 1200 _scale = new OMV.Vector3(1f, 1f, 1f);
1205 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); 1201 // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1206 return; 1202 return;
1207 } 1203 }
1208 1204
@@ -1340,11 +1336,12 @@ public sealed class BSPrim : PhysicsActor
1340 1336
1341 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1337 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1342 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1343 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1339 // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1344 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1345 1341
1346 base.RequestPhysicsterseUpdate(); 1342 base.RequestPhysicsterseUpdate();
1347 } 1343 }
1344 /*
1348 else 1345 else
1349 { 1346 {
1350 // For debugging, we also report the movement of children 1347 // For debugging, we also report the movement of children
@@ -1352,10 +1349,11 @@ public sealed class BSPrim : PhysicsActor
1352 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1349 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1353 entprop.Acceleration, entprop.RotationalVelocity); 1350 entprop.Acceleration, entprop.RotationalVelocity);
1354 } 1351 }
1352 */
1355 } 1353 }
1356 1354
1357 // I've collided with something 1355 // I've collided with something
1358 CollisionEventUpdate collisionCollection = null; 1356 CollisionEventUpdate collisionCollection;
1359 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 1357 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1360 { 1358 {
1361 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 1359 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
@@ -1367,6 +1365,8 @@ public sealed class BSPrim : PhysicsActor
1367 _collidingGroundStep = _scene.SimulationStep; 1365 _collidingGroundStep = _scene.SimulationStep;
1368 } 1366 }
1369 1367
1368 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1369
1370 // if someone is subscribed to collision events.... 1370 // if someone is subscribed to collision events....
1371 if (_subscribedEventsMs != 0) { 1371 if (_subscribedEventsMs != 0) {
1372 // throttle the collisions to the number of milliseconds specified in the subscription 1372 // throttle the collisions to the number of milliseconds specified in the subscription
@@ -1387,7 +1387,9 @@ public sealed class BSPrim : PhysicsActor
1387 if (collisionCollection != null && collisionCollection.Count > 0) 1387 if (collisionCollection != null && collisionCollection.Count > 0)
1388 { 1388 {
1389 base.SendCollisionUpdate(collisionCollection); 1389 base.SendCollisionUpdate(collisionCollection);
1390 collisionCollection.Clear(); 1390 // The collisionCollection structure is passed around in the simulator.
1391 // Make sure we don't have a handle to that one and that a new one is used next time.
1392 collisionCollection = null;
1391 } 1393 }
1392 } 1394 }
1393 1395
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index beaea1f..a31c578 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -362,7 +362,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
362 BSPrim bsprim = prim as BSPrim; 362 BSPrim bsprim = prim as BSPrim;
363 if (bsprim != null) 363 if (bsprim != null)
364 { 364 {
365 DetailLog("{0},RemovePrim,call", bsprim.LocalID); 365 // DetailLog("{0},RemovePrim,call", bsprim.LocalID);
366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
367 try 367 try
368 { 368 {
@@ -388,7 +388,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
388 388
389 if (!m_initialized) return null; 389 if (!m_initialized) return null;
390 390
391 DetailLog("{0},AddPrimShape,call", localID); 391 // DetailLog("{0},AddPrimShape,call", localID);
392 392
393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
394 lock (m_prims) m_prims.Add(localID, prim); 394 lock (m_prims) m_prims.Add(localID, prim);
@@ -413,7 +413,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
413 // prevent simulation until we've been initialized 413 // prevent simulation until we've been initialized
414 if (!m_initialized) return 10.0f; 414 if (!m_initialized) return 10.0f;
415 415
416 long simulateStartTime = Util.EnvironmentTickCount(); 416 int simulateStartTime = Util.EnvironmentTickCount();
417 417
418 // update the prim states while we know the physics engine is not busy 418 // update the prim states while we know the physics engine is not busy
419 ProcessTaints(); 419 ProcessTaints();
@@ -429,12 +429,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
429 { 429 {
430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
432 DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 432 // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
433 } 433 }
434 catch (Exception e) 434 catch (Exception e)
435 { 435 {
436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); 436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
437 DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 437 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
438 // updatedEntityCount = 0; 438 // updatedEntityCount = 0;
439 collidersCount = 0; 439 collidersCount = 0;
440 } 440 }
@@ -511,8 +511,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
511 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); 511 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
512 // return (timeStep * (float)simulateTotalTime); 512 // return (timeStep * (float)simulateTotalTime);
513 513
514 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. 514 // TODO: FIX THIS: fps calculation possibly wrong.
515 return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; 515 // This calculation says 1/timeStep is the ideal frame rate. Any time added to
516 // that by the physics simulation gives a slower frame rate.
517 long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
518 if (totalSimulationTime >= timeStep)
519 return 0;
520 return 1f / (timeStep + totalSimulationTime);
516 } 521 }
517 522
518 // Something has collided 523 // Something has collided
@@ -590,12 +595,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
590 // make sure no stepping happens while we're deleting stuff 595 // make sure no stepping happens while we're deleting stuff
591 m_initialized = false; 596 m_initialized = false;
592 597
593 if (m_constraintCollection != null)
594 {
595 m_constraintCollection.Dispose();
596 m_constraintCollection = null;
597 }
598
599 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 598 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
600 { 599 {
601 kvp.Value.Destroy(); 600 kvp.Value.Destroy();
@@ -608,6 +607,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
608 } 607 }
609 m_prims.Clear(); 608 m_prims.Clear();
610 609
610 // Now that the prims are all cleaned up, there should be no constraints left
611 if (m_constraintCollection != null)
612 {
613 m_constraintCollection.Dispose();
614 m_constraintCollection = null;
615 }
616
611 // Anything left in the unmanaged code should be cleaned out 617 // Anything left in the unmanaged code should be cleaned out
612 BulletSimAPI.Shutdown(WorldID); 618 BulletSimAPI.Shutdown(WorldID);
613 619
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 6800b96..504bd3c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -416,6 +416,27 @@ public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, Int
416 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 416 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
417 417
418[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 418[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
419public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2,
420 Vector3 joinPoint,
421 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
422
423[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
424public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
425 Vector3 pivotinA, Vector3 pivotinB,
426 Vector3 axisInA, Vector3 axisInB,
427 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
428
429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
430public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
431
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
434
435[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
436public static extern bool SetFrames2(IntPtr constrain,
437 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
438
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
419public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); 440public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
420 441
421[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 442[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -428,6 +449,9 @@ public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
428public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); 449public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
429 450
430[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 451[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
452public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
453
454[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
431public static extern bool CalculateTransforms2(IntPtr constrain); 455public static extern bool CalculateTransforms2(IntPtr constrain);
432 456
433[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -518,6 +542,9 @@ public static extern bool SetGravity2(IntPtr obj, Vector3 val);
518public static extern IntPtr ClearForces2(IntPtr obj); 542public static extern IntPtr ClearForces2(IntPtr obj);
519 543
520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
545public static extern IntPtr ClearAllForces2(IntPtr obj);
546
547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
521public static extern bool SetMargin2(IntPtr obj, float val); 548public static extern bool SetMargin2(IntPtr obj, float val);
522 549
523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 5f7b95f..d6aafaf 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -12124,7 +12124,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12124 12124
12125 LSL_List remaining = SetPrimParams(obj, rules); 12125 LSL_List remaining = SetPrimParams(obj, rules);
12126 12126
12127 while (remaining != null && remaining.Length > 2) 12127 while ((object)remaining != null && remaining.Length > 2)
12128 { 12128 {
12129 LSL_Integer newLink = remaining.GetLSLIntegerItem(0); 12129 LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
12130 LSL_List newrules = remaining.GetSublist(1, -1); 12130 LSL_List newrules = remaining.GetSublist(1, -1);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index a08cc42..f989cc6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -226,6 +226,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
226 public const int ATTACH_BELLY = 28; 226 public const int ATTACH_BELLY = 28;
227 public const int ATTACH_RPEC = 29; 227 public const int ATTACH_RPEC = 29;
228 public const int ATTACH_LPEC = 30; 228 public const int ATTACH_LPEC = 30;
229 public const int ATTACH_LEFT_PEC = 29; // Same value as ATTACH_RPEC, see https://jira.secondlife.com/browse/SVC-580
230 public const int ATTACH_RIGHT_PEC = 30; // Same value as ATTACH_LPEC, see https://jira.secondlife.com/browse/SVC-580
229 public const int ATTACH_HUD_CENTER_2 = 31; 231 public const int ATTACH_HUD_CENTER_2 = 31;
230 public const int ATTACH_HUD_TOP_RIGHT = 32; 232 public const int ATTACH_HUD_TOP_RIGHT = 32;
231 public const int ATTACH_HUD_TOP_CENTER = 33; 233 public const int ATTACH_HUD_TOP_CENTER = 33;