diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 145 |
1 files changed, 78 insertions, 67 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index dff71af..4f225ae 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -43,8 +43,17 @@ public class BSLinkset | |||
43 | static int m_nextLinksetID = 1; | 43 | static int m_nextLinksetID = 1; |
44 | public int LinksetID { get; private set; } | 44 | public int LinksetID { get; private set; } |
45 | 45 | ||
46 | // The children under the root in this linkset | 46 | // The children under the root in this linkset. |
47 | // There are two lists of children: the current children at runtime | ||
48 | // and the children at taint-time. For instance, if you delink a | ||
49 | // child from the linkset, the child is removed from m_children | ||
50 | // but the constraint won't be removed until taint time. | ||
51 | // Two lists lets this track the 'current' children and | ||
52 | // the physical 'taint' children separately. | ||
53 | // After taint processing and before the simulation step, these | ||
54 | // two lists must be the same. | ||
47 | private List<BSPhysObject> m_children; | 55 | private List<BSPhysObject> m_children; |
56 | private List<BSPhysObject> m_taintChildren; | ||
48 | 57 | ||
49 | // We lock the diddling of linkset classes to prevent any badness. | 58 | // We lock the diddling of linkset classes to prevent any badness. |
50 | // This locks the modification of the instances of this class. Changes | 59 | // This locks the modification of the instances of this class. Changes |
@@ -82,6 +91,7 @@ public class BSLinkset | |||
82 | PhysicsScene = scene; | 91 | PhysicsScene = scene; |
83 | LinksetRoot = parent; | 92 | LinksetRoot = parent; |
84 | m_children = new List<BSPhysObject>(); | 93 | m_children = new List<BSPhysObject>(); |
94 | m_taintChildren = new List<BSPhysObject>(); | ||
85 | m_mass = parent.MassRaw; | 95 | m_mass = parent.MassRaw; |
86 | } | 96 | } |
87 | 97 | ||
@@ -194,30 +204,40 @@ public class BSLinkset | |||
194 | // Routine used when rebuilding the body of the root of the linkset | 204 | // Routine used when rebuilding the body of the root of the linkset |
195 | // Destroy all the constraints have have been made to root. | 205 | // Destroy all the constraints have have been made to root. |
196 | // This is called when the root body is changing. | 206 | // This is called when the root body is changing. |
207 | // Returns 'true' of something eas actually removed and would need restoring | ||
197 | // Called at taint-time!! | 208 | // Called at taint-time!! |
198 | public void RemoveBodyDependencies(BSPrim child) | 209 | public bool RemoveBodyDependencies(BSPrim child) |
199 | { | 210 | { |
211 | bool ret = false; | ||
212 | |||
200 | lock (m_linksetActivityLock) | 213 | lock (m_linksetActivityLock) |
201 | { | 214 | { |
202 | if (IsRoot(child)) | 215 | if (IsRoot(child)) |
203 | { | 216 | { |
204 | // If the one with the dependency is root, must undo all children | 217 | // If the one with the dependency is root, must undo all children |
205 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", | 218 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", |
206 | LinksetRoot.LocalID, m_children.Count); | 219 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); |
207 | foreach (BSPhysObject bpo in m_children) | 220 | foreach (BSPhysObject bpo in m_taintChildren) |
208 | { | 221 | { |
209 | PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); | 222 | PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); |
223 | ret = true; | ||
210 | } | 224 | } |
211 | } | 225 | } |
212 | else | 226 | else |
213 | { | 227 | { |
214 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", | 228 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", |
229 | child.LocalID, | ||
215 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), | 230 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), |
216 | child.LocalID, child.BSBody.ptr.ToString("X")); | 231 | child.LocalID, child.BSBody.ptr.ToString("X")); |
217 | // Remove the dependency on the body of this one | 232 | // Remove the dependency on the body of this one |
218 | PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); | 233 | if (m_taintChildren.Contains(child)) |
234 | { | ||
235 | PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); | ||
236 | ret = true; | ||
237 | } | ||
219 | } | 238 | } |
220 | } | 239 | } |
240 | return ret; | ||
221 | } | 241 | } |
222 | 242 | ||
223 | // Routine used when rebuilding the body of the root of the linkset | 243 | // Routine used when rebuilding the body of the root of the linkset |
@@ -231,8 +251,8 @@ public class BSLinkset | |||
231 | if (IsRoot(child)) | 251 | if (IsRoot(child)) |
232 | { | 252 | { |
233 | DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", | 253 | DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", |
234 | LinksetRoot.LocalID, m_children.Count); | 254 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); |
235 | foreach (BSPhysObject bpo in m_children) | 255 | foreach (BSPhysObject bpo in m_taintChildren) |
236 | { | 256 | { |
237 | PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); | 257 | PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); |
238 | } | 258 | } |
@@ -240,6 +260,7 @@ public class BSLinkset | |||
240 | else | 260 | else |
241 | { | 261 | { |
242 | DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", | 262 | DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", |
263 | LinksetRoot.LocalID, | ||
243 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), | 264 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), |
244 | child.LocalID, child.BSBody.ptr.ToString("X")); | 265 | child.LocalID, child.BSBody.ptr.ToString("X")); |
245 | PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); | 266 | PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); |
@@ -256,7 +277,7 @@ public class BSLinkset | |||
256 | lock (m_linksetActivityLock) | 277 | lock (m_linksetActivityLock) |
257 | { | 278 | { |
258 | mass = LinksetRoot.MassRaw; | 279 | mass = LinksetRoot.MassRaw; |
259 | foreach (BSPhysObject bp in m_children) | 280 | foreach (BSPhysObject bp in m_taintChildren) |
260 | { | 281 | { |
261 | mass += bp.MassRaw; | 282 | mass += bp.MassRaw; |
262 | } | 283 | } |
@@ -272,7 +293,7 @@ public class BSLinkset | |||
272 | com = LinksetRoot.Position * LinksetRoot.MassRaw; | 293 | com = LinksetRoot.Position * LinksetRoot.MassRaw; |
273 | float totalMass = LinksetRoot.MassRaw; | 294 | float totalMass = LinksetRoot.MassRaw; |
274 | 295 | ||
275 | foreach (BSPhysObject bp in m_children) | 296 | foreach (BSPhysObject bp in m_taintChildren) |
276 | { | 297 | { |
277 | com += bp.Position * bp.MassRaw; | 298 | com += bp.Position * bp.MassRaw; |
278 | totalMass += bp.MassRaw; | 299 | totalMass += bp.MassRaw; |
@@ -291,70 +312,16 @@ public class BSLinkset | |||
291 | { | 312 | { |
292 | com = LinksetRoot.Position; | 313 | com = LinksetRoot.Position; |
293 | 314 | ||
294 | foreach (BSPhysObject bp in m_children) | 315 | foreach (BSPhysObject bp in m_taintChildren) |
295 | { | 316 | { |
296 | com += bp.Position * bp.MassRaw; | 317 | com += bp.Position * bp.MassRaw; |
297 | } | 318 | } |
298 | com /= (m_children.Count + 1); | 319 | com /= (m_taintChildren.Count + 1); |
299 | } | 320 | } |
300 | 321 | ||
301 | return com; | 322 | return com; |
302 | } | 323 | } |
303 | 324 | ||
304 | // Call each of the constraints that make up this linkset and recompute the | ||
305 | // various transforms and variables. Used when objects are added or removed | ||
306 | // from a linkset to make sure the constraints know about the new mass and | ||
307 | // geometry. | ||
308 | // Must only be called at taint time!! | ||
309 | private void RecomputeLinksetConstraintVariables() | ||
310 | { | ||
311 | float linksetMass = LinksetMass; | ||
312 | lock (m_linksetActivityLock) | ||
313 | { | ||
314 | bool somethingMissing = false; | ||
315 | foreach (BSPhysObject child in m_children) | ||
316 | { | ||
317 | BSConstraint constrain; | ||
318 | if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) | ||
319 | { | ||
320 | // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", | ||
321 | // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); | ||
322 | constrain.RecomputeConstraintVariables(linksetMass); | ||
323 | } | ||
324 | else | ||
325 | { | ||
326 | // Non-fatal error that happens when children are being added to the linkset but | ||
327 | // their constraints have not been created yet. | ||
328 | // Caused by the fact that m_children is built at run time but building constraints | ||
329 | // happens at taint time. | ||
330 | somethingMissing = true; | ||
331 | break; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | // If the whole linkset is not here, doesn't make sense to recompute linkset wide values | ||
336 | if (!somethingMissing) | ||
337 | { | ||
338 | // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass | ||
339 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); | ||
340 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); | ||
341 | foreach (BSPhysObject child in m_children) | ||
342 | { | ||
343 | BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); | ||
344 | } | ||
345 | /* | ||
346 | // The root prim takes on the weight of the whole linkset | ||
347 | OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass); | ||
348 | BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia); | ||
349 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); | ||
350 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); | ||
351 | BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr); | ||
352 | */ | ||
353 | } | ||
354 | } | ||
355 | return; | ||
356 | } | ||
357 | |||
358 | // I am the root of a linkset and a new child is being added | 325 | // I am the root of a linkset and a new child is being added |
359 | // Called while LinkActivity is locked. | 326 | // Called while LinkActivity is locked. |
360 | private void AddChildToLinkset(BSPhysObject child) | 327 | private void AddChildToLinkset(BSPhysObject child) |
@@ -377,6 +344,7 @@ public class BSLinkset | |||
377 | { | 344 | { |
378 | DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); | 345 | DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); |
379 | // build the physical binding between me and the child | 346 | // build the physical binding between me and the child |
347 | m_taintChildren.Add(childx); | ||
380 | PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx); | 348 | PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx); |
381 | }); | 349 | }); |
382 | } | 350 | } |
@@ -405,13 +373,16 @@ public class BSLinkset | |||
405 | BSPhysObject childx = child; | 373 | BSPhysObject childx = child; |
406 | BulletBody childBodyx = child.BSBody; | 374 | BulletBody childBodyx = child.BSBody; |
407 | 375 | ||
408 | DetailLog("{0},RemoveChildFromLinkset,call,child={1}", | 376 | DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", |
409 | rootx.LocalID, | 377 | childx.LocalID, |
410 | rootx.LocalID, rootBodyx.ptr.ToString("X"), | 378 | rootx.LocalID, rootBodyx.ptr.ToString("X"), |
411 | childx.LocalID, childBodyx.ptr.ToString("X")); | 379 | childx.LocalID, childBodyx.ptr.ToString("X")); |
412 | 380 | ||
413 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() | 381 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() |
414 | { | 382 | { |
383 | if (m_taintChildren.Contains(childx)) | ||
384 | m_taintChildren.Remove(childx); | ||
385 | |||
415 | PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); | 386 | PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); |
416 | RecomputeLinksetConstraintVariables(); | 387 | RecomputeLinksetConstraintVariables(); |
417 | }); | 388 | }); |
@@ -551,6 +522,46 @@ public class BSLinkset | |||
551 | } | 522 | } |
552 | */ | 523 | */ |
553 | 524 | ||
525 | // Call each of the constraints that make up this linkset and recompute the | ||
526 | // various transforms and variables. Used when objects are added or removed | ||
527 | // from a linkset to make sure the constraints know about the new mass and | ||
528 | // geometry. | ||
529 | // Must only be called at taint time!! | ||
530 | private void RecomputeLinksetConstraintVariables() | ||
531 | { | ||
532 | float linksetMass = LinksetMass; | ||
533 | foreach (BSPhysObject child in m_taintChildren) | ||
534 | { | ||
535 | BSConstraint constrain; | ||
536 | if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) | ||
537 | { | ||
538 | // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", | ||
539 | // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); | ||
540 | constrain.RecomputeConstraintVariables(linksetMass); | ||
541 | } | ||
542 | else | ||
543 | { | ||
544 | // Non-fatal error that happens when children are being added to the linkset but | ||
545 | // their constraints have not been created yet. | ||
546 | break; | ||
547 | } | ||
548 | } | ||
549 | |||
550 | // If the whole linkset is not here, doesn't make sense to recompute linkset wide values | ||
551 | if (m_children.Count == m_taintChildren.Count) | ||
552 | { | ||
553 | // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass | ||
554 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); | ||
555 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); | ||
556 | foreach (BSPhysObject child in m_taintChildren) | ||
557 | { | ||
558 | BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); | ||
559 | } | ||
560 | } | ||
561 | return; | ||
562 | } | ||
563 | |||
564 | |||
554 | // Invoke the detailed logger and output something if it's enabled. | 565 | // Invoke the detailed logger and output something if it's enabled. |
555 | private void DetailLog(string msg, params Object[] args) | 566 | private void DetailLog(string msg, params Object[] args) |
556 | { | 567 | { |