aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
diff options
context:
space:
mode:
authorRobert Adams2012-08-15 11:36:21 -0700
committerRobert Adams2012-08-15 12:08:17 -0700
commit9efe7bf7ba741b0d61ef71c09b5848c424e3c258 (patch)
treee0222568715cfffb32c619520c1dc4e4c393a05a /OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
parentBulletSim: clean up detail logging by adding many more debug log statements a... (diff)
downloadopensim-SC-9efe7bf7ba741b0d61ef71c09b5848c424e3c258.zip
opensim-SC-9efe7bf7ba741b0d61ef71c09b5848c424e3c258.tar.gz
opensim-SC-9efe7bf7ba741b0d61ef71c09b5848c424e3c258.tar.bz2
opensim-SC-9efe7bf7ba741b0d61ef71c09b5848c424e3c258.tar.xz
BulletSim: add locking to constraintCollection and rename some of the public method variables to reduce confusion between a physics scene and the real scene.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs250
1 files changed, 152 insertions, 98 deletions
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}