diff options
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 302 |
1 files changed, 185 insertions, 117 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 6f8430c..087b9bb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -37,10 +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 PhysicsScene { get { return m_physicsScene; } } | ||
43 | 44 | ||
45 | // The children under the root in this linkset | ||
44 | private List<BSPrim> m_children; | 46 | private List<BSPrim> m_children; |
45 | 47 | ||
46 | // We lock the diddling of linkset classes to prevent any badness. | 48 | // We lock the diddling of linkset classes to prevent any badness. |
@@ -72,7 +74,7 @@ public class BSLinkset | |||
72 | public BSLinkset(BSScene scene, BSPrim parent) | 74 | public BSLinkset(BSScene scene, BSPrim parent) |
73 | { | 75 | { |
74 | // A simple linkset of one (no children) | 76 | // A simple linkset of one (no children) |
75 | m_scene = scene; | 77 | m_physicsScene = scene; |
76 | m_linksetRoot = parent; | 78 | m_linksetRoot = parent; |
77 | m_children = new List<BSPrim>(); | 79 | m_children = new List<BSPrim>(); |
78 | m_mass = parent.MassRaw; | 80 | m_mass = parent.MassRaw; |
@@ -80,16 +82,19 @@ public class BSLinkset | |||
80 | 82 | ||
81 | // Link to a linkset where the child knows the parent. | 83 | // Link to a linkset where the child knows the parent. |
82 | // Parent changing should not happen so do some sanity checking. | 84 | // Parent changing should not happen so do some sanity checking. |
83 | // We return the parent's linkset so the child can track it's membership. | 85 | // We return the parent's linkset so the child can track its membership. |
84 | public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) | 86 | public BSLinkset AddMeToLinkset(BSPrim child) |
85 | { | 87 | { |
86 | lock (m_linksetActivityLock) | 88 | lock (m_linksetActivityLock) |
87 | { | 89 | { |
88 | parent.Linkset.AddChildToLinkset(child); | 90 | AddChildToLinkset(child); |
89 | } | 91 | } |
90 | return parent.Linkset; | 92 | return this; |
91 | } | 93 | } |
92 | 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). | ||
93 | public BSLinkset RemoveMeFromLinkset(BSPrim child) | 98 | public BSLinkset RemoveMeFromLinkset(BSPrim child) |
94 | { | 99 | { |
95 | lock (m_linksetActivityLock) | 100 | lock (m_linksetActivityLock) |
@@ -101,7 +106,7 @@ public class BSLinkset | |||
101 | { | 106 | { |
102 | // Note that we don't do a foreach because the remove routine | 107 | // Note that we don't do a foreach because the remove routine |
103 | // takes it out of the list. | 108 | // takes it out of the list. |
104 | RemoveChildFromLinkset(m_children[0]); | 109 | RemoveChildFromOtherLinkset(m_children[0]); |
105 | } | 110 | } |
106 | m_children.Clear(); // just to make sure | 111 | m_children.Clear(); // just to make sure |
107 | } | 112 | } |
@@ -113,63 +118,17 @@ public class BSLinkset | |||
113 | } | 118 | } |
114 | 119 | ||
115 | // The child is down to a linkset of just itself | 120 | // The child is down to a linkset of just itself |
116 | return new BSLinkset(m_scene, child); | 121 | return new BSLinkset(PhysicsScene, child); |
117 | } | 122 | } |
118 | 123 | ||
119 | // An existing linkset had one of its members rebuilt or something. | ||
120 | // Go through the linkset and rebuild the pointers to the bodies of the linkset members. | ||
121 | public BSLinkset RefreshLinkset(BSPrim requestor) | ||
122 | { | ||
123 | BSLinkset ret = requestor.Linkset; | ||
124 | |||
125 | lock (m_linksetActivityLock) | ||
126 | { | ||
127 | System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID); | ||
128 | if (aPtr == System.IntPtr.Zero) | ||
129 | { | ||
130 | // That's odd. We can't find the root of the linkset. | ||
131 | // The linkset is somehow dead. The requestor is now a member of a linkset of one. | ||
132 | DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID); | ||
133 | ret = RemoveMeFromLinkset(m_linksetRoot); | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | // Reconstruct the pointer to the body of the linkset root. | ||
138 | DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr); | ||
139 | m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr); | ||
140 | |||
141 | List<BSPrim> toRemove = new List<BSPrim>(); | ||
142 | foreach (BSPrim bsp in m_children) | ||
143 | { | ||
144 | aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID); | ||
145 | if (aPtr == System.IntPtr.Zero) | ||
146 | { | ||
147 | toRemove.Add(bsp); | ||
148 | } | ||
149 | else | ||
150 | { | ||
151 | // Reconstruct the pointer to the body of the linkset root. | ||
152 | DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr); | ||
153 | bsp.Body = new BulletBody(bsp.LocalID, aPtr); | ||
154 | } | ||
155 | } | ||
156 | foreach (BSPrim bsp in toRemove) | ||
157 | { | ||
158 | RemoveChildFromLinkset(bsp); | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | |||
167 | // 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 |
168 | public bool IsRoot(BSPrim requestor) | 125 | public bool IsRoot(BSPrim requestor) |
169 | { | 126 | { |
170 | return (requestor.LocalID == m_linksetRoot.LocalID); | 127 | return (requestor.LocalID == m_linksetRoot.LocalID); |
171 | } | 128 | } |
172 | 129 | ||
130 | public int NumberOfChildren { get { return m_children.Count; } } | ||
131 | |||
173 | // Return 'true' if this linkset has any children (more than the root member) | 132 | // Return 'true' if this linkset has any children (more than the root member) |
174 | public bool HasAnyChildren { get { return (m_children.Count > 0); } } | 133 | public bool HasAnyChildren { get { return (m_children.Count > 0); } } |
175 | 134 | ||
@@ -177,12 +136,15 @@ public class BSLinkset | |||
177 | public bool HasChild(BSPrim child) | 136 | public bool HasChild(BSPrim child) |
178 | { | 137 | { |
179 | bool ret = false; | 138 | bool ret = false; |
180 | foreach (BSPrim bp in m_children) | 139 | lock (m_linksetActivityLock) |
181 | { | 140 | { |
182 | if (child.LocalID == bp.LocalID) | 141 | foreach (BSPrim bp in m_children) |
183 | { | 142 | { |
184 | ret = true; | 143 | if (child.LocalID == bp.LocalID) |
185 | break; | 144 | { |
145 | ret = true; | ||
146 | break; | ||
147 | } | ||
186 | } | 148 | } |
187 | } | 149 | } |
188 | return ret; | 150 | return ret; |
@@ -203,12 +165,16 @@ public class BSLinkset | |||
203 | OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; | 165 | OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; |
204 | float totalMass = m_linksetRoot.MassRaw; | 166 | float totalMass = m_linksetRoot.MassRaw; |
205 | 167 | ||
206 | foreach (BSPrim bp in m_children) | 168 | lock (m_linksetActivityLock) |
207 | { | 169 | { |
208 | com += bp.Position * bp.MassRaw; | 170 | foreach (BSPrim bp in m_children) |
209 | totalMass += bp.MassRaw; | 171 | { |
172 | com += bp.Position * bp.MassRaw; | ||
173 | totalMass += bp.MassRaw; | ||
174 | } | ||
175 | if (totalMass != 0f) | ||
176 | com /= totalMass; | ||
210 | } | 177 | } |
211 | com /= totalMass; | ||
212 | 178 | ||
213 | return com; | 179 | return com; |
214 | } | 180 | } |
@@ -217,135 +183,237 @@ public class BSLinkset | |||
217 | { | 183 | { |
218 | OMV.Vector3 com = m_linksetRoot.Position; | 184 | OMV.Vector3 com = m_linksetRoot.Position; |
219 | 185 | ||
220 | foreach (BSPrim bp in m_children) | 186 | lock (m_linksetActivityLock) |
221 | { | 187 | { |
222 | 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); | ||
223 | } | 193 | } |
224 | com /= m_children.Count + 1; | ||
225 | 194 | ||
226 | return com; | 195 | return com; |
227 | } | 196 | } |
228 | 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 | |||
229 | // 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 |
230 | public void AddChildToLinkset(BSPrim pchild) | 250 | // Called while LinkActivity is locked. |
251 | private void AddChildToLinkset(BSPrim child) | ||
231 | { | 252 | { |
232 | BSPrim child = pchild; | ||
233 | if (!HasChild(child)) | 253 | if (!HasChild(child)) |
234 | { | 254 | { |
235 | m_children.Add(child); | 255 | m_children.Add(child); |
236 | 256 | ||
237 | m_scene.TaintedObject(delegate() | 257 | BSPrim rootx = LinksetRoot; // capture the root as of now |
258 | BSPrim childx = child; | ||
259 | m_physicsScene.TaintedObject("AddChildToLinkset", delegate() | ||
238 | { | 260 | { |
239 | 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); |
240 | DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); | 262 | // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); |
241 | PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child | 263 | PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child |
242 | }); | 264 | }); |
243 | } | 265 | } |
244 | return; | 266 | return; |
245 | } | 267 | } |
246 | 268 | ||
269 | // Forcefully removing a child from a linkset. | ||
270 | // This is not being called by the child so we have to make sure the child doesn't think | ||
271 | // it's still connected to the linkset. | ||
272 | // Normal OpenSimulator operation will never do this because other SceneObjectPart information | ||
273 | // has to be updated also (like pointer to prim's parent). | ||
274 | private void RemoveChildFromOtherLinkset(BSPrim pchild) | ||
275 | { | ||
276 | pchild.Linkset = new BSLinkset(m_physicsScene, pchild); | ||
277 | RemoveChildFromLinkset(pchild); | ||
278 | } | ||
279 | |||
247 | // 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. |
248 | // 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. |
249 | public void RemoveChildFromLinkset(BSPrim pchild) | 282 | private void RemoveChildFromLinkset(BSPrim child) |
250 | { | 283 | { |
251 | BSPrim child = pchild; | ||
252 | |||
253 | if (m_children.Remove(child)) | 284 | if (m_children.Remove(child)) |
254 | { | 285 | { |
255 | m_scene.TaintedObject(delegate() | 286 | BSPrim rootx = LinksetRoot; // capture the root as of now |
287 | BSPrim childx = child; | ||
288 | m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() | ||
256 | { | 289 | { |
257 | DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); | 290 | // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); |
258 | DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); | 291 | // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); |
259 | 292 | ||
260 | if (m_children.Count == 0) | 293 | PhysicallyUnlinkAChildFromRoot(rootx, childx); |
261 | { | ||
262 | // if the linkset is empty, make sure all linkages have been removed | ||
263 | PhysicallyUnlinkAllChildrenFromRoot(); | ||
264 | } | ||
265 | else | ||
266 | { | ||
267 | PhysicallyUnlinkAChildFromRoot(pchild); | ||
268 | } | ||
269 | }); | 294 | }); |
295 | |||
296 | RecomputeLinksetConstraintVariables(); | ||
270 | } | 297 | } |
271 | else | 298 | else |
272 | { | 299 | { |
273 | // 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. |
274 | // 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); |
275 | } | 302 | } |
276 | return; | 303 | return; |
277 | } | 304 | } |
278 | 305 | ||
279 | // Create a constraint between me (root of linkset) and the passed prim (the child). | 306 | // Create a constraint between me (root of linkset) and the passed prim (the child). |
280 | // Called at taint time! | 307 | // Called at taint time! |
281 | private void PhysicallyLinkAChildToRoot(BSPrim childPrim) | 308 | private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim) |
282 | { | 309 | { |
283 | // Zero motion for children so they don't interpolate | 310 | // Zero motion for children so they don't interpolate |
284 | childPrim.ZeroMotion(); | 311 | childPrim.ZeroMotion(); |
285 | 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 | // ================================================================================== | ||
286 | // relative position normalized to the root prim | 336 | // relative position normalized to the root prim |
287 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); | 337 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); |
288 | OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; | 338 | OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; |
289 | 339 | ||
290 | // relative rotation of the child to the parent | 340 | // relative rotation of the child to the parent |
291 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; | 341 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; |
342 | OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); | ||
292 | 343 | ||
293 | // 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 |
294 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | 345 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 |
295 | // 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); |
296 | DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); | 347 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); |
297 | BSConstraint constrain = m_scene.Constraints.CreateConstraint( | 348 | BS6DofConstraint constrain = new BS6DofConstraint( |
298 | m_scene.World, m_linksetRoot.Body, childPrim.Body, | 349 | PhysicsScene.World, rootPrim.Body, childPrim.Body, |
299 | // childRelativePosition, | ||
300 | // childRelativeRotation, | ||
301 | OMV.Vector3.Zero, | 350 | OMV.Vector3.Zero, |
302 | OMV.Quaternion.Identity, | 351 | OMV.Quaternion.Inverse(rootPrim.Orientation), |
303 | OMV.Vector3.Zero, | 352 | OMV.Vector3.Zero, |
304 | OMV.Quaternion.Identity | 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 | ||
305 | ); | 361 | ); |
362 | // ================================================================================== | ||
363 | */ | ||
364 | |||
365 | m_physicsScene.Constraints.AddConstraint(constrain); | ||
366 | |||
367 | // zero linear and angular limits makes the objects unable to move in relation to each other | ||
306 | constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | 368 | constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); |
307 | constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | 369 | constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); |
308 | 370 | ||
309 | // tweek the constraint to increase stability | 371 | // tweek the constraint to increase stability |
310 | constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); | 372 | constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); |
311 | constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), | 373 | constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), |
312 | m_scene.Params.linkConstraintTransMotorMaxVel, | 374 | PhysicsScene.Params.linkConstraintTransMotorMaxVel, |
313 | m_scene.Params.linkConstraintTransMotorMaxForce); | 375 | PhysicsScene.Params.linkConstraintTransMotorMaxForce); |
314 | constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); | 376 | constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); |
315 | 377 | ||
378 | RecomputeLinksetConstraintVariables(); | ||
316 | } | 379 | } |
317 | 380 | ||
318 | // Remove linkage between myself and a particular child | 381 | // Remove linkage between myself and a particular child |
319 | // Called at taint time! | 382 | // Called at taint time! |
320 | private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim) | 383 | private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) |
321 | { | 384 | { |
322 | DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", | 385 | // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", |
323 | LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); | 386 | // LogHeader, rootPrim.LocalID, childPrim.LocalID); |
324 | DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); | 387 | DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); |
325 | // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); | 388 | |
326 | m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.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 | |||
392 | // Make the child refresh its location | ||
393 | BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); | ||
327 | } | 394 | } |
328 | 395 | ||
329 | // Remove linkage between myself and any possible children I might have | 396 | // Remove linkage between myself and any possible children I might have |
330 | // Called at taint time! | 397 | // Called at taint time! |
331 | private void PhysicallyUnlinkAllChildrenFromRoot() | 398 | private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) |
332 | { | 399 | { |
333 | // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); | 400 | // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); |
334 | DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); | 401 | DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); |
335 | m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body); | 402 | |
336 | // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); | 403 | m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); |
337 | } | 404 | } |
338 | 405 | ||
339 | // Invoke the detailed logger and output something if it's enabled. | 406 | // Invoke the detailed logger and output something if it's enabled. |
340 | private void DebugLog(string msg, params Object[] args) | 407 | private void DebugLog(string msg, params Object[] args) |
341 | { | 408 | { |
342 | m_scene.Logger.DebugFormat(msg, args); | 409 | if (m_physicsScene.ShouldDebugLog) |
410 | m_physicsScene.Logger.DebugFormat(msg, args); | ||
343 | } | 411 | } |
344 | 412 | ||
345 | // Invoke the detailed logger and output something if it's enabled. | 413 | // Invoke the detailed logger and output something if it's enabled. |
346 | private void DetailLog(string msg, params Object[] args) | 414 | private void DetailLog(string msg, params Object[] args) |
347 | { | 415 | { |
348 | m_scene.PhysicsLogging.Write(msg, args); | 416 | m_physicsScene.PhysicsLogging.Write(msg, args); |
349 | } | 417 | } |
350 | 418 | ||
351 | } | 419 | } |