diff options
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs | 260 |
1 files changed, 101 insertions, 159 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 8a750b5..d2387fb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs | |||
@@ -32,7 +32,7 @@ using OMV = OpenMetaverse; | |||
32 | 32 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | public class BSLinksetConstraints : BSLinkset | 35 | public sealed class BSLinksetConstraints : BSLinkset |
36 | { | 36 | { |
37 | // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; | 37 | // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; |
38 | 38 | ||
@@ -43,23 +43,16 @@ public class BSLinksetConstraints : BSLinkset | |||
43 | 43 | ||
44 | // When physical properties are changed the linkset needs to recalculate | 44 | // When physical properties are changed the linkset needs to recalculate |
45 | // its internal properties. | 45 | // its internal properties. |
46 | // May be called at runtime or taint-time (just pass the appropriate flag). | 46 | // This is queued in the 'post taint' queue so the |
47 | public override void Refresh(BSPhysObject requestor, bool inTaintTime) | 47 | // refresh will happen once after all the other taints are applied. |
48 | public override void Refresh(BSPhysObject requestor) | ||
48 | { | 49 | { |
49 | // If there are no children or not root, I am not the one that recomputes the constraints | 50 | // Queue to happen after all the other taint processing |
50 | if (!HasAnyChildren || !IsRoot(requestor)) | 51 | PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() |
51 | return; | ||
52 | |||
53 | BSScene.TaintCallback refreshOperation = delegate() | ||
54 | { | 52 | { |
55 | RecomputeLinksetConstraintVariables(); | 53 | if (HasAnyChildren && IsRoot(requestor)) |
56 | DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", | 54 | RecomputeLinksetConstraints(); |
57 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); | 55 | }); |
58 | }; | ||
59 | if (inTaintTime) | ||
60 | refreshOperation(); | ||
61 | else | ||
62 | PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); | ||
63 | } | 56 | } |
64 | 57 | ||
65 | // The object is going dynamic (physical). Do any setup necessary | 58 | // The object is going dynamic (physical). Do any setup necessary |
@@ -74,9 +67,10 @@ public class BSLinksetConstraints : BSLinkset | |||
74 | return false; | 67 | return false; |
75 | } | 68 | } |
76 | 69 | ||
77 | // The object is going static (non-physical). Do any setup necessary | 70 | // The object is going static (non-physical). Do any setup necessary for a static linkset. |
78 | // for a static linkset. | ||
79 | // Return 'true' if any properties updated on the passed object. | 71 | // Return 'true' if any properties updated on the passed object. |
72 | // This doesn't normally happen -- OpenSim removes the objects from the physical | ||
73 | // world if it is a static linkset. | ||
80 | // Called at taint-time! | 74 | // Called at taint-time! |
81 | public override bool MakeStatic(BSPhysObject child) | 75 | public override bool MakeStatic(BSPhysObject child) |
82 | { | 76 | { |
@@ -90,35 +84,36 @@ public class BSLinksetConstraints : BSLinkset | |||
90 | // Nothing to do for constraints on property updates | 84 | // Nothing to do for constraints on property updates |
91 | } | 85 | } |
92 | 86 | ||
93 | // Routine used when rebuilding the body of the root of the linkset | 87 | // The children of the linkset are moved around by the constraints. |
94 | // Destroy all the constraints have have been made to root. | 88 | // Just grab the current values of wherever it is right now. |
95 | // This is called when the root body is changing. | 89 | public override OMV.Vector3 Position(BSPhysObject member) |
96 | // Returns 'true' of something eas actually removed and would need restoring | 90 | { |
91 | return BulletSimAPI.GetPosition2(member.PhysBody.ptr); | ||
92 | } | ||
93 | |||
94 | public override OMV.Quaternion Orientation(BSPhysObject member) | ||
95 | { | ||
96 | return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); | ||
97 | } | ||
98 | |||
99 | // Routine called when rebuilding the body of some member of the linkset. | ||
100 | // Destroy all the constraints have have been made to root and set | ||
101 | // up to rebuild the constraints before the next simulation step. | ||
102 | // Returns 'true' of something was actually removed and would need restoring | ||
97 | // Called at taint-time!! | 103 | // Called at taint-time!! |
98 | public override bool RemoveBodyDependencies(BSPrim child) | 104 | public override bool RemoveBodyDependencies(BSPrim child) |
99 | { | 105 | { |
100 | bool ret = false; | 106 | bool ret = false; |
101 | 107 | ||
108 | DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", | ||
109 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); | ||
110 | |||
102 | lock (m_linksetActivityLock) | 111 | lock (m_linksetActivityLock) |
103 | { | 112 | { |
104 | if (IsRoot(child)) | 113 | // Just undo all the constraints for this linkset. Rebuild at the end of the step. |
105 | { | 114 | ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); |
106 | // If the one with the dependency is root, must undo all children | 115 | // Cause the constraints, et al to be rebuilt before the next simulation step. |
107 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", | 116 | Refresh(LinksetRoot); |
108 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); | ||
109 | |||
110 | ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); | ||
111 | } | ||
112 | else | ||
113 | { | ||
114 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", | ||
115 | child.LocalID, | ||
116 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), | ||
117 | child.LocalID, child.BSBody.ptr.ToString("X")); | ||
118 | // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); | ||
119 | // Despite the function name, this removes any link to the specified object. | ||
120 | ret = PhysicallyUnlinkAllChildrenFromRoot(child); | ||
121 | } | ||
122 | } | 117 | } |
123 | return ret; | 118 | return ret; |
124 | } | 119 | } |
@@ -128,32 +123,12 @@ public class BSLinksetConstraints : BSLinkset | |||
128 | // Called at taint-time!! | 123 | // Called at taint-time!! |
129 | public override void RestoreBodyDependencies(BSPrim child) | 124 | public override void RestoreBodyDependencies(BSPrim child) |
130 | { | 125 | { |
131 | lock (m_linksetActivityLock) | 126 | // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. |
132 | { | ||
133 | if (IsRoot(child)) | ||
134 | { | ||
135 | DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", | ||
136 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); | ||
137 | foreach (BSPhysObject bpo in m_taintChildren) | ||
138 | { | ||
139 | PhysicallyLinkAChildToRoot(LinksetRoot, bpo); | ||
140 | } | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", | ||
145 | LinksetRoot.LocalID, | ||
146 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), | ||
147 | child.LocalID, child.BSBody.ptr.ToString("X")); | ||
148 | PhysicallyLinkAChildToRoot(LinksetRoot, child); | ||
149 | } | ||
150 | } | ||
151 | } | 127 | } |
152 | 128 | ||
153 | // ================================================================ | 129 | // ================================================================ |
154 | // Below this point is internal magic | ||
155 | 130 | ||
156 | // I am the root of a linkset and a new child is being added | 131 | // Add a new child to the linkset. |
157 | // Called while LinkActivity is locked. | 132 | // Called while LinkActivity is locked. |
158 | protected override void AddChildToLinkset(BSPhysObject child) | 133 | protected override void AddChildToLinkset(BSPhysObject child) |
159 | { | 134 | { |
@@ -161,39 +136,15 @@ public class BSLinksetConstraints : BSLinkset | |||
161 | { | 136 | { |
162 | m_children.Add(child); | 137 | m_children.Add(child); |
163 | 138 | ||
164 | BSPhysObject rootx = LinksetRoot; // capture the root as of now | 139 | DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); |
165 | BSPhysObject childx = child; | ||
166 | |||
167 | DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); | ||
168 | 140 | ||
169 | PhysicsScene.TaintedObject("AddChildToLinkset", delegate() | 141 | // Cause constraints and assorted properties to be recomputed before the next simulation step. |
170 | { | 142 | Refresh(LinksetRoot); |
171 | DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", | ||
172 | rootx.LocalID, | ||
173 | rootx.LocalID, rootx.BSBody.ptr.ToString("X"), | ||
174 | childx.LocalID, childx.BSBody.ptr.ToString("X")); | ||
175 | // Since this is taint-time, the body and shape could have changed for the child | ||
176 | rootx.ForcePosition = rootx.Position; // DEBUG | ||
177 | childx.ForcePosition = childx.Position; // DEBUG | ||
178 | PhysicallyLinkAChildToRoot(rootx, childx); | ||
179 | m_taintChildren.Add(child); | ||
180 | }); | ||
181 | } | 143 | } |
182 | return; | 144 | return; |
183 | } | 145 | } |
184 | 146 | ||
185 | // Forcefully removing a child from a linkset. | 147 | // Remove the specified child from the linkset. |
186 | // This is not being called by the child so we have to make sure the child doesn't think | ||
187 | // it's still connected to the linkset. | ||
188 | // Normal OpenSimulator operation will never do this because other SceneObjectPart information | ||
189 | // also has to be updated (like pointer to prim's parent). | ||
190 | protected override void RemoveChildFromOtherLinkset(BSPhysObject pchild) | ||
191 | { | ||
192 | pchild.Linkset = BSLinkset.Factory(PhysicsScene, pchild); | ||
193 | RemoveChildFromLinkset(pchild); | ||
194 | } | ||
195 | |||
196 | // I am the root of a linkset and one of my children is being removed. | ||
197 | // Safe to call even if the child is not really in my linkset. | 148 | // Safe to call even if the child is not really in my linkset. |
198 | protected override void RemoveChildFromLinkset(BSPhysObject child) | 149 | protected override void RemoveChildFromLinkset(BSPhysObject child) |
199 | { | 150 | { |
@@ -202,22 +153,21 @@ public class BSLinksetConstraints : BSLinkset | |||
202 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now | 153 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now |
203 | BSPhysObject childx = child; | 154 | BSPhysObject childx = child; |
204 | 155 | ||
205 | DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | 156 | DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", |
206 | childx.LocalID, | 157 | childx.LocalID, |
207 | rootx.LocalID, rootx.BSBody.ptr.ToString("X"), | 158 | rootx.LocalID, rootx.PhysBody.ptr.ToString("X"), |
208 | childx.LocalID, childx.BSBody.ptr.ToString("X")); | 159 | childx.LocalID, childx.PhysBody.ptr.ToString("X")); |
209 | 160 | ||
210 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() | 161 | PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() |
211 | { | 162 | { |
212 | m_taintChildren.Remove(child); | ||
213 | PhysicallyUnlinkAChildFromRoot(rootx, childx); | 163 | PhysicallyUnlinkAChildFromRoot(rootx, childx); |
214 | RecomputeLinksetConstraintVariables(); | ||
215 | }); | 164 | }); |
216 | 165 | // See that the linkset parameters are recomputed at the end of the taint time. | |
166 | Refresh(LinksetRoot); | ||
217 | } | 167 | } |
218 | else | 168 | else |
219 | { | 169 | { |
220 | // This will happen if we remove the root of the linkset first. Non-fatal occurance. | 170 | // Non-fatal occurance. |
221 | // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); | 171 | // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); |
222 | } | 172 | } |
223 | return; | 173 | return; |
@@ -227,6 +177,12 @@ public class BSLinksetConstraints : BSLinkset | |||
227 | // Called at taint time! | 177 | // Called at taint time! |
228 | private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) | 178 | private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) |
229 | { | 179 | { |
180 | // Don't build the constraint when asked. Put it off until just before the simulation step. | ||
181 | Refresh(rootPrim); | ||
182 | } | ||
183 | |||
184 | private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) | ||
185 | { | ||
230 | // Zero motion for children so they don't interpolate | 186 | // Zero motion for children so they don't interpolate |
231 | childPrim.ZeroMotion(); | 187 | childPrim.ZeroMotion(); |
232 | 188 | ||
@@ -237,22 +193,23 @@ public class BSLinksetConstraints : BSLinkset | |||
237 | // real world coordinate of midpoint between the two objects | 193 | // real world coordinate of midpoint between the two objects |
238 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); | 194 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); |
239 | 195 | ||
240 | DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", | 196 | DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", |
241 | rootPrim.LocalID, | 197 | rootPrim.LocalID, |
242 | rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), | 198 | rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), |
243 | childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), | 199 | childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"), |
244 | rootPrim.Position, childPrim.Position, midPoint); | 200 | rootPrim.Position, childPrim.Position, midPoint); |
245 | 201 | ||
246 | // create a constraint that allows no freedom of movement between the two objects | 202 | // create a constraint that allows no freedom of movement between the two objects |
247 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | 203 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 |
248 | 204 | ||
249 | BS6DofConstraint constrain = new BS6DofConstraint( | 205 | BSConstraint6Dof constrain = new BSConstraint6Dof( |
250 | PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); | 206 | PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); |
207 | // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); | ||
251 | 208 | ||
252 | /* NOTE: below is an attempt to build constraint with full frame computation, etc. | 209 | /* NOTE: below is an attempt to build constraint with full frame computation, etc. |
253 | * Using the midpoint is easier since it lets the Bullet code manipulate the transforms | 210 | * Using the midpoint is easier since it lets the Bullet code manipulate the transforms |
254 | * of the objects. | 211 | * of the objects. |
255 | * Code left as a warning to future programmers. | 212 | * Code left for future programmers. |
256 | // ================================================================================== | 213 | // ================================================================================== |
257 | // relative position normalized to the root prim | 214 | // relative position normalized to the root prim |
258 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); | 215 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); |
@@ -262,20 +219,13 @@ public class BSLinksetConstraints : BSLinkset | |||
262 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; | 219 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; |
263 | OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); | 220 | OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); |
264 | 221 | ||
265 | // create a constraint that allows no freedom of movement between the two objects | 222 | DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); |
266 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
267 | DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); | ||
268 | BS6DofConstraint constrain = new BS6DofConstraint( | 223 | BS6DofConstraint constrain = new BS6DofConstraint( |
269 | PhysicsScene.World, rootPrim.Body, childPrim.Body, | 224 | PhysicsScene.World, rootPrim.Body, childPrim.Body, |
270 | OMV.Vector3.Zero, | 225 | OMV.Vector3.Zero, |
271 | OMV.Quaternion.Inverse(rootPrim.Orientation), | 226 | OMV.Quaternion.Inverse(rootPrim.Orientation), |
272 | OMV.Vector3.Zero, | 227 | OMV.Vector3.Zero, |
273 | OMV.Quaternion.Inverse(childPrim.Orientation), | 228 | OMV.Quaternion.Inverse(childPrim.Orientation), |
274 | // A point half way between the parent and child | ||
275 | // childRelativePosition/2, | ||
276 | // childRelativeRotation, | ||
277 | // childRelativePosition/2, | ||
278 | // inverseChildRelativeRotation, | ||
279 | true, | 229 | true, |
280 | true | 230 | true |
281 | ); | 231 | ); |
@@ -298,25 +248,26 @@ public class BSLinksetConstraints : BSLinkset | |||
298 | { | 248 | { |
299 | constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); | 249 | constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); |
300 | } | 250 | } |
251 | return constrain; | ||
301 | } | 252 | } |
302 | 253 | ||
303 | // Remove linkage between myself and a particular child | 254 | // Remove linkage between the linkset root and a particular child |
304 | // The root and child bodies are passed in because we need to remove the constraint between | 255 | // The root and child bodies are passed in because we need to remove the constraint between |
305 | // the bodies that were at unlink time. | 256 | // the bodies that were present at unlink time. |
306 | // Called at taint time! | 257 | // Called at taint time! |
307 | private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) | 258 | private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) |
308 | { | 259 | { |
309 | bool ret = false; | 260 | bool ret = false; |
310 | DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", | 261 | DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", |
311 | rootPrim.LocalID, | 262 | rootPrim.LocalID, |
312 | rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), | 263 | rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), |
313 | childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); | 264 | childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X")); |
314 | 265 | ||
315 | // Find the constraint for this link and get rid of it from the overall collection and from my list | 266 | // Find the constraint for this link and get rid of it from the overall collection and from my list |
316 | if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) | 267 | if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) |
317 | { | 268 | { |
318 | // Make the child refresh its location | 269 | // Make the child refresh its location |
319 | BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); | 270 | BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr); |
320 | ret = true; | 271 | ret = true; |
321 | } | 272 | } |
322 | 273 | ||
@@ -324,62 +275,53 @@ public class BSLinksetConstraints : BSLinkset | |||
324 | } | 275 | } |
325 | 276 | ||
326 | // Remove linkage between myself and any possible children I might have. | 277 | // Remove linkage between myself and any possible children I might have. |
278 | // Returns 'true' of any constraints were destroyed. | ||
327 | // Called at taint time! | 279 | // Called at taint time! |
328 | private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) | 280 | private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) |
329 | { | 281 | { |
330 | DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); | 282 | DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); |
331 | bool ret = false; | ||
332 | 283 | ||
333 | if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) | 284 | return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); |
334 | { | ||
335 | ret = true; | ||
336 | } | ||
337 | return ret; | ||
338 | } | 285 | } |
339 | 286 | ||
340 | // Call each of the constraints that make up this linkset and recompute the | 287 | // Call each of the constraints that make up this linkset and recompute the |
341 | // various transforms and variables. Used when objects are added or removed | 288 | // various transforms and variables. Create constraints of not created yet. |
342 | // from a linkset to make sure the constraints know about the new mass and | 289 | // Called before the simulation step to make sure the constraint based linkset |
343 | // geometry. | 290 | // is all initialized. |
344 | // Must only be called at taint time!! | 291 | // Called at taint time!! |
345 | private void RecomputeLinksetConstraintVariables() | 292 | private void RecomputeLinksetConstraints() |
346 | { | 293 | { |
347 | float linksetMass = LinksetMass; | 294 | float linksetMass = LinksetMass; |
348 | foreach (BSPhysObject child in m_taintChildren) | 295 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); |
296 | |||
297 | // DEBUG: see of inter-linkset collisions are causing problems | ||
298 | // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, | ||
299 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); | ||
300 | DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", | ||
301 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); | ||
302 | |||
303 | foreach (BSPhysObject child in m_children) | ||
349 | { | 304 | { |
305 | // A child in the linkset physically shows the mass of the whole linkset. | ||
306 | // This allows Bullet to apply enough force on the child to move the whole linkset. | ||
307 | // (Also do the mass stuff before recomputing the constraint so mass is not zero.) | ||
308 | child.UpdatePhysicalMassProperties(linksetMass); | ||
309 | |||
350 | BSConstraint constrain; | 310 | BSConstraint constrain; |
351 | if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) | 311 | if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) |
352 | { | ||
353 | // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", | ||
354 | // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); | ||
355 | constrain.RecomputeConstraintVariables(linksetMass); | ||
356 | } | ||
357 | else | ||
358 | { | 312 | { |
359 | // Non-fatal error that happens when children are being added to the linkset but | 313 | // If constraint doesn't exist yet, create it. |
360 | // their constraints have not been created yet. | 314 | constrain = BuildConstraint(LinksetRoot, child); |
361 | break; | ||
362 | } | 315 | } |
363 | } | 316 | constrain.RecomputeConstraintVariables(linksetMass); |
364 | 317 | ||
365 | // If the whole linkset is not here, doesn't make sense to recompute linkset wide values | 318 | // DEBUG: see of inter-linkset collisions are causing problems |
366 | if (m_children.Count == m_taintChildren.Count) | 319 | // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, |
367 | { | 320 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); |
368 | // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass | ||
369 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); | ||
370 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, | ||
371 | centerOfMass, OMV.Quaternion.Identity); | ||
372 | DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", | ||
373 | LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); | ||
374 | foreach (BSPhysObject child in m_taintChildren) | ||
375 | { | ||
376 | BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, | ||
377 | centerOfMass, OMV.Quaternion.Identity); | ||
378 | } | ||
379 | 321 | ||
380 | // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG | 322 | // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG |
381 | } | 323 | } |
382 | return; | 324 | |
383 | } | 325 | } |
384 | } | 326 | } |
385 | } | 327 | } |