aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorRobert Adams2012-10-29 14:33:31 -0700
committerRobert Adams2012-11-03 21:14:41 -0700
commit93fe384cce42e91337f446fd658ef29ca3d9f733 (patch)
tree8ed885f7b33d929a73a8742063b5a7f9e32a98bb
parentBulletSim: Add gravity force to vehicle. Some debugging additions. (diff)
downloadopensim-SC-93fe384cce42e91337f446fd658ef29ca3d9f733.zip
opensim-SC-93fe384cce42e91337f446fd658ef29ca3d9f733.tar.gz
opensim-SC-93fe384cce42e91337f446fd658ef29ca3d9f733.tar.bz2
opensim-SC-93fe384cce42e91337f446fd658ef29ca3d9f733.tar.xz
BulletSim: Use the PostTaints operation to build the linkset once before the next simulation step. This eliminates the management of children vs taintChildren and simplifies the constratin creation code.
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs52
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs140
2 files changed, 68 insertions, 124 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 569d2e7..187951e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -61,16 +61,7 @@ public abstract class BSLinkset
61 public int LinksetID { get; private set; } 61 public int LinksetID { get; private set; }
62 62
63 // The children under the root in this linkset. 63 // The children under the root in this linkset.
64 // There are two lists of children: the current children at runtime
65 // and the children at taint-time. For instance, if you delink a
66 // child from the linkset, the child is removed from m_children
67 // but the constraint won't be removed until taint time.
68 // Two lists lets this track the 'current' children and
69 // the physical 'taint' children separately.
70 // After taint processing and before the simulation step, these
71 // two lists must be the same.
72 protected HashSet<BSPhysObject> m_children; 64 protected HashSet<BSPhysObject> m_children;
73 protected HashSet<BSPhysObject> m_taintChildren;
74 65
75 // We lock the diddling of linkset classes to prevent any badness. 66 // We lock the diddling of linkset classes to prevent any badness.
76 // This locks the modification of the instances of this class. Changes 67 // This locks the modification of the instances of this class. Changes
@@ -110,7 +101,6 @@ public abstract class BSLinkset
110 PhysicsScene = scene; 101 PhysicsScene = scene;
111 LinksetRoot = parent; 102 LinksetRoot = parent;
112 m_children = new HashSet<BSPhysObject>(); 103 m_children = new HashSet<BSPhysObject>();
113 m_taintChildren = new HashSet<BSPhysObject>();
114 m_mass = parent.MassRaw; 104 m_mass = parent.MassRaw;
115 } 105 }
116 106
@@ -192,7 +182,7 @@ public abstract class BSLinkset
192 lock (m_linksetActivityLock) 182 lock (m_linksetActivityLock)
193 { 183 {
194 action(LinksetRoot); 184 action(LinksetRoot);
195 foreach (BSPhysObject po in m_taintChildren) 185 foreach (BSPhysObject po in m_children)
196 { 186 {
197 if (action(po)) 187 if (action(po))
198 break; 188 break;
@@ -201,9 +191,24 @@ public abstract class BSLinkset
201 return ret; 191 return ret;
202 } 192 }
203 193
194 // I am the root of a linkset and a new child is being added
195 // Called while LinkActivity is locked.
196 protected abstract void AddChildToLinkset(BSPhysObject child);
197
198 // Forcefully removing a child from a linkset.
199 // This is not being called by the child so we have to make sure the child doesn't think
200 // it's still connected to the linkset.
201 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
202 // also has to be updated (like pointer to prim's parent).
203 protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild);
204
205 // I am the root of a linkset and one of my children is being removed.
206 // Safe to call even if the child is not really in my linkset.
207 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
208
204 // When physical properties are changed the linkset needs to recalculate 209 // When physical properties are changed the linkset needs to recalculate
205 // its internal properties. 210 // its internal properties.
206 // May be called at runtime or taint-time (just pass the appropriate flag). 211 // May be called at runtime or taint-time.
207 public abstract void Refresh(BSPhysObject requestor); 212 public abstract void Refresh(BSPhysObject requestor);
208 213
209 // The object is going dynamic (physical). Do any setup necessary 214 // The object is going dynamic (physical). Do any setup necessary
@@ -238,8 +243,6 @@ public abstract class BSLinkset
238 public abstract void RestoreBodyDependencies(BSPrim child); 243 public abstract void RestoreBodyDependencies(BSPrim child);
239 244
240 // ================================================================ 245 // ================================================================
241 // Below this point is internal magic
242
243 protected virtual float ComputeLinksetMass() 246 protected virtual float ComputeLinksetMass()
244 { 247 {
245 float mass = LinksetRoot.MassRaw; 248 float mass = LinksetRoot.MassRaw;
@@ -264,7 +267,7 @@ public abstract class BSLinkset
264 com = LinksetRoot.Position * LinksetRoot.MassRaw; 267 com = LinksetRoot.Position * LinksetRoot.MassRaw;
265 float totalMass = LinksetRoot.MassRaw; 268 float totalMass = LinksetRoot.MassRaw;
266 269
267 foreach (BSPhysObject bp in m_taintChildren) 270 foreach (BSPhysObject bp in m_children)
268 { 271 {
269 com += bp.Position * bp.MassRaw; 272 com += bp.Position * bp.MassRaw;
270 totalMass += bp.MassRaw; 273 totalMass += bp.MassRaw;
@@ -283,31 +286,16 @@ public abstract class BSLinkset
283 { 286 {
284 com = LinksetRoot.Position; 287 com = LinksetRoot.Position;
285 288
286 foreach (BSPhysObject bp in m_taintChildren) 289 foreach (BSPhysObject bp in m_children)
287 { 290 {
288 com += bp.Position * bp.MassRaw; 291 com += bp.Position * bp.MassRaw;
289 } 292 }
290 com /= (m_taintChildren.Count + 1); 293 com /= (m_children.Count + 1);
291 } 294 }
292 295
293 return com; 296 return com;
294 } 297 }
295 298
296 // I am the root of a linkset and a new child is being added
297 // Called while LinkActivity is locked.
298 protected abstract void AddChildToLinkset(BSPhysObject child);
299
300 // Forcefully removing a child from a linkset.
301 // This is not being called by the child so we have to make sure the child doesn't think
302 // it's still connected to the linkset.
303 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
304 // also has to be updated (like pointer to prim's parent).
305 protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild);
306
307 // I am the root of a linkset and one of my children is being removed.
308 // Safe to call even if the child is not really in my linkset.
309 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
310
311 // Invoke the detailed logger and output something if it's enabled. 299 // Invoke the detailed logger and output something if it's enabled.
312 protected void DetailLog(string msg, params Object[] args) 300 protected void DetailLog(string msg, params Object[] args)
313 { 301 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 086aa12..6c1fa2a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -54,7 +54,7 @@ public sealed class BSLinksetConstraints : BSLinkset
54 // Queue to happen after all the other taint processing 54 // Queue to happen after all the other taint processing
55 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() 55 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
56 { 56 {
57 RecomputeLinksetConstraintVariables(); 57 RecomputeLinksetConstraints();
58 }); 58 });
59 59
60 } 60 }
@@ -98,24 +98,13 @@ public sealed class BSLinksetConstraints : BSLinkset
98 98
99 lock (m_linksetActivityLock) 99 lock (m_linksetActivityLock)
100 { 100 {
101 if (IsRoot(child)) 101 // Just undo all the constraints for this linkset. Rebuild at the end of the step.
102 { 102 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
103 // If the one with the dependency is root, must undo all children 103 child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
104 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
105 child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
106 104
107 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); 105 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
108 } 106 // Cause the constraints, et al to be rebuilt before the next simulation step.
109 else 107 Refresh(LinksetRoot);
110 {
111 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}",
112 child.LocalID,
113 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
114 child.LocalID, child.BSBody.ptr.ToString("X"));
115 // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child);
116 // Despite the function name, this removes any link to the specified object.
117 ret = PhysicallyUnlinkAllChildrenFromRoot(child);
118 }
119 } 108 }
120 return ret; 109 return ret;
121 } 110 }
@@ -125,26 +114,7 @@ public sealed class BSLinksetConstraints : BSLinkset
125 // Called at taint-time!! 114 // Called at taint-time!!
126 public override void RestoreBodyDependencies(BSPrim child) 115 public override void RestoreBodyDependencies(BSPrim child)
127 { 116 {
128 lock (m_linksetActivityLock) 117 // The Refresh operation will build any missing constraints.
129 {
130 if (IsRoot(child))
131 {
132 DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}",
133 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
134 foreach (BSPhysObject bpo in m_taintChildren)
135 {
136 PhysicallyLinkAChildToRoot(LinksetRoot, bpo);
137 }
138 }
139 else
140 {
141 DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}",
142 LinksetRoot.LocalID,
143 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
144 child.LocalID, child.BSBody.ptr.ToString("X"));
145 PhysicallyLinkAChildToRoot(LinksetRoot, child);
146 }
147 }
148 } 118 }
149 119
150 // ================================================================ 120 // ================================================================
@@ -163,18 +133,7 @@ public sealed class BSLinksetConstraints : BSLinkset
163 133
164 DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 134 DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
165 135
166 PhysicsScene.TaintedObject("AddChildToLinkset", delegate() 136 // Cause constraints and assorted properties to be recomputed before the next simulation step.
167 {
168 DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}",
169 rootx.LocalID,
170 rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
171 childx.LocalID, childx.BSBody.ptr.ToString("X"));
172 // Since this is taint-time, the body and shape could have changed for the child
173 rootx.ForcePosition = rootx.Position; // DEBUG
174 childx.ForcePosition = childx.Position; // DEBUG
175 PhysicallyLinkAChildToRoot(rootx, childx);
176 m_taintChildren.Add(child);
177 });
178 Refresh(LinksetRoot); 137 Refresh(LinksetRoot);
179 } 138 }
180 return; 139 return;
@@ -207,7 +166,6 @@ public sealed class BSLinksetConstraints : BSLinkset
207 166
208 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 167 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
209 { 168 {
210 m_taintChildren.Remove(child);
211 PhysicallyUnlinkAChildFromRoot(rootx, childx); 169 PhysicallyUnlinkAChildFromRoot(rootx, childx);
212 }); 170 });
213 // See that the linkset parameters are recomputed at the end of the taint time. 171 // See that the linkset parameters are recomputed at the end of the taint time.
@@ -225,6 +183,12 @@ public sealed class BSLinksetConstraints : BSLinkset
225 // Called at taint time! 183 // Called at taint time!
226 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) 184 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
227 { 185 {
186 // Don't build the constraint when asked. Put it off until just before the simulation step.
187 Refresh(rootPrim);
188 }
189
190 private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim)
191 {
228 // Zero motion for children so they don't interpolate 192 // Zero motion for children so they don't interpolate
229 childPrim.ZeroMotion(); 193 childPrim.ZeroMotion();
230 194
@@ -235,7 +199,7 @@ public sealed class BSLinksetConstraints : BSLinkset
235 // real world coordinate of midpoint between the two objects 199 // real world coordinate of midpoint between the two objects
236 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); 200 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
237 201
238 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", 202 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
239 rootPrim.LocalID, 203 rootPrim.LocalID,
240 rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), 204 rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
241 childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), 205 childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"),
@@ -297,6 +261,7 @@ public sealed class BSLinksetConstraints : BSLinkset
297 { 261 {
298 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); 262 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
299 } 263 }
264 return constrain;
300 } 265 }
301 266
302 // Remove linkage between myself and a particular child 267 // Remove linkage between myself and a particular child
@@ -337,56 +302,47 @@ public sealed class BSLinksetConstraints : BSLinkset
337 } 302 }
338 303
339 // Call each of the constraints that make up this linkset and recompute the 304 // Call each of the constraints that make up this linkset and recompute the
340 // various transforms and variables. Used when objects are added or removed 305 // various transforms and variables. Create constraints of not created yet.
341 // from a linkset to make sure the constraints know about the new mass and 306 // Called before the simulation step to make sure the constraint based linkset
342 // geometry. 307 // is all initialized.
343 // Must only be called at taint time!! 308 // Must only be called at taint time!!
344 private void RecomputeLinksetConstraintVariables() 309 private void RecomputeLinksetConstraints()
345 { 310 {
346 float linksetMass = LinksetMass; 311 float linksetMass = LinksetMass;
347 foreach (BSPhysObject child in m_taintChildren) 312 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
313
314 // For a multiple object linkset, set everybody's center of mass to the set's center of mass
315 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
316 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
317
318 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
319 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
320 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,COM={1},rBody={2},linksetMass={3}",
321 LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass);
322
323 foreach (BSPhysObject child in m_children)
348 { 324 {
325 // A child in the linkset physically shows the mass of the whole linkset.
326 // This allows Bullet to apply enough force on the child to move the whole linkset.
327 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
328 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
329 child.UpdatePhysicalMassProperties(linksetMass);
330
349 BSConstraint constrain; 331 BSConstraint constrain;
350 if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) 332 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
351 {
352 // DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
353 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
354 constrain.RecomputeConstraintVariables(linksetMass);
355 }
356 else
357 { 333 {
358 // Non-fatal error that happens when children are being added to the linkset but 334 // If constraint doesn't exist yet, create it.
359 // their constraints have not been created yet. 335 constrain = BuildConstraint(LinksetRoot, child);
360 break;
361 } 336 }
362 } 337 constrain.RecomputeConstraintVariables(linksetMass);
363 338
364 // If the whole linkset is not here, doesn't make sense to recompute linkset wide values 339 // DEBUG: see of inter-linkset collisions are causing problems
365 if (m_children.Count == m_taintChildren.Count) 340 // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr,
366 { 341 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
367 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
368 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
369 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
370 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
371 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
372 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2},linksetMass={3}",
373 LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass);
374 foreach (BSPhysObject child in m_taintChildren)
375 {
376 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
377 // A child in the linkset physically shows the mass of the whole linkset.
378 // This allows Bullet to apply enough force on the child to move the whole linkset.
379 child.UpdatePhysicalMassProperties(linksetMass);
380 // DEBUG: see of inter-linkset collisions are causing problems
381 // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr,
382 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
383 }
384 // Also update the root's physical mass to the whole linkset
385 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
386 342
387 // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG 343 // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG
388 } 344 }
389 return; 345
390 } 346 }
391} 347}
392} 348}