aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs94
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs250
2 files changed, 197 insertions, 147 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index 862b744..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,17 +110,16 @@ 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)
110
111 if (this.TryGetConstraint(body1, body2, out constrain))
112 { 115 {
113 m_world.scene.DetailLog("{0},BSConstraintCollection.RemoveAndDestroyConstraint,taint,body1={1},body2={2}", BSScene.DetailLogZero, body1.ID, body2.ID); 116 BSConstraint constrain;
114 // remove the constraint from our collection 117 if (this.TryGetConstraint(body1, body2, out constrain))
115 RemoveAndDestroyConstraint(constrain); 118 {
116 ret = true; 119 // remove the constraint from our collection
120 RemoveAndDestroyConstraint(constrain);
121 ret = true;
122 }
117 } 123 }
118 124
119 return ret; 125 return ret;
@@ -122,8 +128,11 @@ public class BSConstraintCollection : IDisposable
122 // The constraint MUST exist in the collection 128 // The constraint MUST exist in the collection
123 public bool RemoveAndDestroyConstraint(BSConstraint constrain) 129 public bool RemoveAndDestroyConstraint(BSConstraint constrain)
124 { 130 {
125 // remove the constraint from our collection 131 lock (m_constraints)
126 m_constraints.Remove(constrain); 132 {
133 // remove the constraint from our collection
134 m_constraints.Remove(constrain);
135 }
127 // tell the engine that all its structures need to be freed 136 // tell the engine that all its structures need to be freed
128 constrain.Dispose(); 137 constrain.Dispose();
129 // we destroyed something 138 // we destroyed something
@@ -138,16 +147,15 @@ public class BSConstraintCollection : IDisposable
138 147
139 List<BSConstraint> toRemove = new List<BSConstraint>(); 148 List<BSConstraint> toRemove = new List<BSConstraint>();
140 uint lookingID = body1.ID; 149 uint lookingID = body1.ID;
141 ForEachConstraint(delegate(BSConstraint constrain) 150 lock (m_constraints)
142 { 151 {
143 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) 152 foreach (BSConstraint constrain in m_constraints)
144 { 153 {
145 toRemove.Add(constrain); 154 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
155 {
156 toRemove.Add(constrain);
157 }
146 } 158 }
147 return false;
148 });
149 lock (m_constraints)
150 {
151 foreach (BSConstraint constrain in toRemove) 159 foreach (BSConstraint constrain in toRemove)
152 { 160 {
153 m_constraints.Remove(constrain); 161 m_constraints.Remove(constrain);
@@ -159,28 +167,16 @@ public class BSConstraintCollection : IDisposable
159 167
160 public bool RecalculateAllConstraints() 168 public bool RecalculateAllConstraints()
161 { 169 {
162 ForEachConstraint(delegate(BSConstraint constrain) 170 bool ret = false;
163 {
164 constrain.CalculateTransforms();
165 return false;
166 });
167 return true;
168 }
169
170 // Lock the constraint list and loop through it.
171 // The constraint action returns 'true' if it wants the loop aborted.
172 private void ForEachConstraint(ConstraintAction action)
173 {
174 lock (m_constraints) 171 lock (m_constraints)
175 { 172 {
176 foreach (BSConstraint constrain in m_constraints) 173 foreach (BSConstraint constrain in m_constraints)
177 { 174 {
178 if (action(constrain)) 175 constrain.CalculateTransforms();
179 break; 176 ret = true;
180 } 177 }
181 } 178 }
179 return ret;
182 } 180 }
183
184
185} 181}
186} 182}
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}