aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-09-29 00:09:12 +0100
committerJustin Clark-Casey (justincc)2012-09-29 00:09:12 +0100
commitfae869c4ca0d75c217b0ba8744346e238f7be0c9 (patch)
treedadf703ef6e2b7654779090ba0e4d20f6a8d5875 /OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
parentExtend attachment regression test to check for appropriate attach event firing. (diff)
parenttesting for xml-rpc errors in git repo. (diff)
downloadopensim-SC-fae869c4ca0d75c217b0ba8744346e238f7be0c9.zip
opensim-SC-fae869c4ca0d75c217b0ba8744346e238f7be0c9.tar.gz
opensim-SC-fae869c4ca0d75c217b0ba8744346e238f7be0c9.tar.bz2
opensim-SC-fae869c4ca0d75c217b0ba8744346e238f7be0c9.tar.xz
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs378
1 files changed, 245 insertions, 133 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 7e784eb..4f225ae 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -36,17 +36,24 @@ public class BSLinkset
36{ 36{
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPhysObject m_linksetRoot; 39 public BSPhysObject LinksetRoot { get; protected set; }
40 public BSPhysObject LinksetRoot { get { return m_linksetRoot; } }
41 40
42 private BSScene m_physicsScene; 41 public BSScene PhysicsScene { get; private set; }
43 public BSScene PhysicsScene { get { return m_physicsScene; } }
44 42
45 static int m_nextLinksetID = 1; 43 static int m_nextLinksetID = 1;
46 public int LinksetID { get; private set; } 44 public int LinksetID { get; private set; }
47 45
48 // 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.
49 private List<BSPhysObject> m_children; 55 private List<BSPhysObject> m_children;
56 private List<BSPhysObject> m_taintChildren;
50 57
51 // We lock the diddling of linkset classes to prevent any badness. 58 // We lock the diddling of linkset classes to prevent any badness.
52 // This locks the modification of the instances of this class. Changes 59 // This locks the modification of the instances of this class. Changes
@@ -55,9 +62,9 @@ public class BSLinkset
55 62
56 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 63 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
57 private float m_mass; 64 private float m_mass;
58 public float LinksetMass 65 public float LinksetMass
59 { 66 {
60 get 67 get
61 { 68 {
62 m_mass = ComputeLinksetMass(); 69 m_mass = ComputeLinksetMass();
63 return m_mass; 70 return m_mass;
@@ -79,22 +86,26 @@ public class BSLinkset
79 // A simple linkset of one (no children) 86 // A simple linkset of one (no children)
80 LinksetID = m_nextLinksetID++; 87 LinksetID = m_nextLinksetID++;
81 // We create LOTS of linksets. 88 // We create LOTS of linksets.
82 if (m_nextLinksetID < 0) 89 if (m_nextLinksetID <= 0)
83 m_nextLinksetID = 1; 90 m_nextLinksetID = 1;
84 m_physicsScene = scene; 91 PhysicsScene = scene;
85 m_linksetRoot = parent; 92 LinksetRoot = parent;
86 m_children = new List<BSPhysObject>(); 93 m_children = new List<BSPhysObject>();
94 m_taintChildren = new List<BSPhysObject>();
87 m_mass = parent.MassRaw; 95 m_mass = parent.MassRaw;
88 } 96 }
89 97
90 // Link to a linkset where the child knows the parent. 98 // Link to a linkset where the child knows the parent.
91 // Parent changing should not happen so do some sanity checking. 99 // Parent changing should not happen so do some sanity checking.
92 // We return the parent's linkset so the child can track its membership. 100 // We return the parent's linkset so the child can track its membership.
101 // Called at runtime.
93 public BSLinkset AddMeToLinkset(BSPhysObject child) 102 public BSLinkset AddMeToLinkset(BSPhysObject child)
94 { 103 {
95 lock (m_linksetActivityLock) 104 lock (m_linksetActivityLock)
96 { 105 {
97 AddChildToLinkset(child); 106 // Don't add the root to its own linkset
107 if (!IsRoot(child))
108 AddChildToLinkset(child);
98 } 109 }
99 return this; 110 return this;
100 } 111 }
@@ -102,26 +113,18 @@ public class BSLinkset
102 // Remove a child from a linkset. 113 // Remove a child from a linkset.
103 // Returns a new linkset for the child which is a linkset of one (just the 114 // Returns a new linkset for the child which is a linkset of one (just the
104 // orphened child). 115 // orphened child).
116 // Called at runtime.
105 public BSLinkset RemoveMeFromLinkset(BSPhysObject child) 117 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
106 { 118 {
107 lock (m_linksetActivityLock) 119 lock (m_linksetActivityLock)
108 { 120 {
109 if (IsRoot(child)) 121 if (IsRoot(child))
110 { 122 {
111 // if root of linkset, take the linkset apart 123 // Cannot remove the root from a linkset.
112 while (m_children.Count > 0) 124 return this;
113 {
114 // Note that we don't do a foreach because the remove routine
115 // takes it out of the list.
116 RemoveChildFromOtherLinkset(m_children[0]);
117 }
118 m_children.Clear(); // just to make sure
119 }
120 else
121 {
122 // Just removing a child from an existing linkset
123 RemoveChildFromLinkset(child);
124 } 125 }
126
127 RemoveChildFromLinkset(child);
125 } 128 }
126 129
127 // The child is down to a linkset of just itself 130 // The child is down to a linkset of just itself
@@ -131,7 +134,7 @@ public class BSLinkset
131 // Return 'true' if the passed object is the root object of this linkset 134 // Return 'true' if the passed object is the root object of this linkset
132 public bool IsRoot(BSPhysObject requestor) 135 public bool IsRoot(BSPhysObject requestor)
133 { 136 {
134 return (requestor.LocalID == m_linksetRoot.LocalID); 137 return (requestor.LocalID == LinksetRoot.LocalID);
135 } 138 }
136 139
137 public int NumberOfChildren { get { return m_children.Count; } } 140 public int NumberOfChildren { get { return m_children.Count; } }
@@ -157,51 +160,6 @@ public class BSLinkset
157 return ret; 160 return ret;
158 } 161 }
159 162
160 private float ComputeLinksetMass()
161 {
162 float mass = m_linksetRoot.MassRaw;
163 foreach (BSPhysObject bp in m_children)
164 {
165 mass += bp.MassRaw;
166 }
167 return mass;
168 }
169
170 private OMV.Vector3 ComputeLinksetCenterOfMass()
171 {
172 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
173 float totalMass = m_linksetRoot.MassRaw;
174
175 lock (m_linksetActivityLock)
176 {
177 foreach (BSPhysObject bp in m_children)
178 {
179 com += bp.Position * bp.MassRaw;
180 totalMass += bp.MassRaw;
181 }
182 if (totalMass != 0f)
183 com /= totalMass;
184 }
185
186 return com;
187 }
188
189 private OMV.Vector3 ComputeLinksetGeometricCenter()
190 {
191 OMV.Vector3 com = m_linksetRoot.Position;
192
193 lock (m_linksetActivityLock)
194 {
195 foreach (BSPhysObject bp in m_children)
196 {
197 com += bp.Position * bp.MassRaw;
198 }
199 com /= (m_children.Count + 1);
200 }
201
202 return com;
203 }
204
205 // The object is going dynamic (physical). Do any setup necessary 163 // The object is going dynamic (physical). Do any setup necessary
206 // for a dynamic linkset. 164 // for a dynamic linkset.
207 // Only the state of the passed object can be modified. The rest of the linkset 165 // Only the state of the passed object can be modified. The rest of the linkset
@@ -210,8 +168,8 @@ public class BSLinkset
210 // Called at taint-time! 168 // Called at taint-time!
211 public bool MakeDynamic(BSPhysObject child) 169 public bool MakeDynamic(BSPhysObject child)
212 { 170 {
213 bool ret = false; 171 // What is done for each object in BSPrim is what we want.
214 return ret; 172 return false;
215 } 173 }
216 174
217 // The object is going static (non-physical). Do any setup necessary 175 // The object is going static (non-physical). Do any setup necessary
@@ -226,6 +184,7 @@ public class BSLinkset
226 184
227 // When physical properties are changed the linkset needs to recalculate 185 // When physical properties are changed the linkset needs to recalculate
228 // its internal properties. 186 // its internal properties.
187 // Called at runtime.
229 public void Refresh(BSPhysObject requestor) 188 public void Refresh(BSPhysObject requestor)
230 { 189 {
231 // If there are no children, there can't be any constraints to recompute 190 // If there are no children, there can't be any constraints to recompute
@@ -242,58 +201,125 @@ public class BSLinkset
242 } 201 }
243 } 202 }
244 203
245 // Call each of the constraints that make up this linkset and recompute the 204 // Routine used when rebuilding the body of the root of the linkset
246 // various transforms and variables. Used when objects are added or removed 205 // Destroy all the constraints have have been made to root.
247 // from a linkset to make sure the constraints know about the new mass and 206 // This is called when the root body is changing.
248 // geometry. 207 // Returns 'true' of something eas actually removed and would need restoring
249 // Must only be called at taint time!! 208 // Called at taint-time!!
250 private void RecomputeLinksetConstraintVariables() 209 public bool RemoveBodyDependencies(BSPrim child)
251 { 210 {
252 float linksetMass = LinksetMass; 211 bool ret = false;
212
253 lock (m_linksetActivityLock) 213 lock (m_linksetActivityLock)
254 { 214 {
255 bool somethingMissing = false; 215 if (IsRoot(child))
256 foreach (BSPhysObject child in m_children)
257 { 216 {
258 BSConstraint constrain; 217 // If the one with the dependency is root, must undo all children
259 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) 218 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}",
219 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
220 foreach (BSPhysObject bpo in m_taintChildren)
260 { 221 {
261 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", 222 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
262 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); 223 ret = true;
263 constrain.RecomputeConstraintVariables(linksetMass);
264 } 224 }
265 else 225 }
226 else
227 {
228 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}",
229 child.LocalID,
230 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
231 child.LocalID, child.BSBody.ptr.ToString("X"));
232 // Remove the dependency on the body of this one
233 if (m_taintChildren.Contains(child))
266 { 234 {
267 // Non-fatal error that happens when children are being added to the linkset but 235 PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
268 // their constraints have not been created yet. 236 ret = true;
269 // Caused by the fact that m_children is built at run time but building constraints
270 // happens at taint time.
271 somethingMissing = true;
272 break;
273 } 237 }
274 } 238 }
239 }
240 return ret;
241 }
275 242
276 // If the whole linkset is not here, doesn't make sense to recompute linkset wide values 243 // Routine used when rebuilding the body of the root of the linkset
277 if (!somethingMissing) 244 // This is called after RemoveAllLinksToRoot() to restore all the constraints.
245 // This is called when the root body has been changed.
246 // Called at taint-time!!
247 public void RestoreBodyDependencies(BSPrim child)
248 {
249 lock (m_linksetActivityLock)
250 {
251 if (IsRoot(child))
278 { 252 {
279 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass 253 DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}",
280 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); 254 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
281 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); 255 foreach (BSPhysObject bpo in m_taintChildren)
282 foreach (BSPhysObject child in m_children)
283 { 256 {
284 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); 257 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
285 } 258 }
286 /* 259 }
287 // The root prim takes on the weight of the whole linkset 260 else
288 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass); 261 {
289 BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia); 262 DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}",
290 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); 263 LinksetRoot.LocalID,
291 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); 264 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
292 BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr); 265 child.LocalID, child.BSBody.ptr.ToString("X"));
293 */ 266 PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
294 } 267 }
295 } 268 }
296 return; 269 }
270
271 // ================================================================
272 // Below this point is internal magic
273
274 private float ComputeLinksetMass()
275 {
276 float mass;
277 lock (m_linksetActivityLock)
278 {
279 mass = LinksetRoot.MassRaw;
280 foreach (BSPhysObject bp in m_taintChildren)
281 {
282 mass += bp.MassRaw;
283 }
284 }
285 return mass;
286 }
287
288 private OMV.Vector3 ComputeLinksetCenterOfMass()
289 {
290 OMV.Vector3 com;
291 lock (m_linksetActivityLock)
292 {
293 com = LinksetRoot.Position * LinksetRoot.MassRaw;
294 float totalMass = LinksetRoot.MassRaw;
295
296 foreach (BSPhysObject bp in m_taintChildren)
297 {
298 com += bp.Position * bp.MassRaw;
299 totalMass += bp.MassRaw;
300 }
301 if (totalMass != 0f)
302 com /= totalMass;
303 }
304
305 return com;
306 }
307
308 private OMV.Vector3 ComputeLinksetGeometricCenter()
309 {
310 OMV.Vector3 com;
311 lock (m_linksetActivityLock)
312 {
313 com = LinksetRoot.Position;
314
315 foreach (BSPhysObject bp in m_taintChildren)
316 {
317 com += bp.Position * bp.MassRaw;
318 }
319 com /= (m_taintChildren.Count + 1);
320 }
321
322 return com;
297 } 323 }
298 324
299 // 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
@@ -304,12 +330,22 @@ public class BSLinkset
304 { 330 {
305 m_children.Add(child); 331 m_children.Add(child);
306 332
307 BSPhysObject rootx = LinksetRoot; // capture the root as of now 333 BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
334 BulletBody rootBodyx = LinksetRoot.BSBody;
308 BSPhysObject childx = child; 335 BSPhysObject childx = child;
309 m_physicsScene.TaintedObject("AddChildToLinkset", delegate() 336 BulletBody childBodyx = child.BSBody;
337
338 DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
339 rootx.LocalID,
340 rootx.LocalID, rootBodyx.ptr.ToString("X"),
341 childx.LocalID, childBodyx.ptr.ToString("X"));
342
343 PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
310 { 344 {
311 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 345 DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID);
312 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child 346 // build the physical binding between me and the child
347 m_taintChildren.Add(childx);
348 PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx);
313 }); 349 });
314 } 350 }
315 return; 351 return;
@@ -319,10 +355,10 @@ public class BSLinkset
319 // This is not being called by the child so we have to make sure the child doesn't think 355 // This is not being called by the child so we have to make sure the child doesn't think
320 // it's still connected to the linkset. 356 // it's still connected to the linkset.
321 // Normal OpenSimulator operation will never do this because other SceneObjectPart information 357 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
322 // has to be updated also (like pointer to prim's parent). 358 // also has to be updated (like pointer to prim's parent).
323 private void RemoveChildFromOtherLinkset(BSPhysObject pchild) 359 private void RemoveChildFromOtherLinkset(BSPhysObject pchild)
324 { 360 {
325 pchild.Linkset = new BSLinkset(m_physicsScene, pchild); 361 pchild.Linkset = new BSLinkset(PhysicsScene, pchild);
326 RemoveChildFromLinkset(pchild); 362 RemoveChildFromLinkset(pchild);
327 } 363 }
328 364
@@ -332,13 +368,22 @@ public class BSLinkset
332 { 368 {
333 if (m_children.Remove(child)) 369 if (m_children.Remove(child))
334 { 370 {
335 BSPhysObject rootx = LinksetRoot; // capture the root as of now 371 BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
372 BulletBody rootBodyx = LinksetRoot.BSBody;
336 BSPhysObject childx = child; 373 BSPhysObject childx = child;
337 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 374 BulletBody childBodyx = child.BSBody;
375
376 DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
377 childx.LocalID,
378 rootx.LocalID, rootBodyx.ptr.ToString("X"),
379 childx.LocalID, childBodyx.ptr.ToString("X"));
380
381 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
338 { 382 {
339 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 383 if (m_taintChildren.Contains(childx))
384 m_taintChildren.Remove(childx);
340 385
341 PhysicallyUnlinkAChildFromRoot(rootx, childx); 386 PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx);
342 RecomputeLinksetConstraintVariables(); 387 RecomputeLinksetConstraintVariables();
343 }); 388 });
344 389
@@ -353,7 +398,8 @@ public class BSLinkset
353 398
354 // Create a constraint between me (root of linkset) and the passed prim (the child). 399 // Create a constraint between me (root of linkset) and the passed prim (the child).
355 // Called at taint time! 400 // Called at taint time!
356 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) 401 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody,
402 BSPhysObject childPrim, BulletBody childBody)
357 { 403 {
358 // Zero motion for children so they don't interpolate 404 // Zero motion for children so they don't interpolate
359 childPrim.ZeroMotion(); 405 childPrim.ZeroMotion();
@@ -365,18 +411,36 @@ public class BSLinkset
365 // real world coordinate of midpoint between the two objects 411 // real world coordinate of midpoint between the two objects
366 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); 412 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
367 413
414 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
415 rootPrim.LocalID,
416 rootPrim.LocalID, rootBody.ptr.ToString("X"),
417 childPrim.LocalID, childBody.ptr.ToString("X"),
418 rootPrim.Position, childPrim.Position, midPoint);
419
368 // create a constraint that allows no freedom of movement between the two objects 420 // create a constraint that allows no freedom of movement between the two objects
369 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 421 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
370 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", 422
371 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); 423 // There is great subtlty in these paramters. Notice the check for a ptr of zero.
424 // We pass the BulletBody structure into the taint in order to capture the pointer
425 // of the body at the time of constraint creation. This doesn't work for the very first
426 // construction because there is no body yet. The body
427 // is constructed later at taint time. Thus we use the body address at time of the
428 // taint creation but, if it is zero, use what's in the prim at the moment.
429 // There is a possible race condition since shape can change without a taint call
430 // (like changing to a mesh that is already constructed). The fix for that would be
431 // to only change BSShape at taint time thus syncronizing these operations at
432 // the cost of efficiency and lag.
372 BS6DofConstraint constrain = new BS6DofConstraint( 433 BS6DofConstraint constrain = new BS6DofConstraint(
373 m_physicsScene.World, rootPrim.BSBody, childPrim.BSBody, 434 PhysicsScene.World,
435 rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody,
436 childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody,
374 midPoint, 437 midPoint,
375 true, 438 true,
376 true 439 true
377 ); 440 );
441
378 /* NOTE: below is an attempt to build constraint with full frame computation, etc. 442 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
379 * Using the midpoint is easier since it lets the Bullet code use the transforms 443 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
380 * of the objects. 444 * of the objects.
381 * Code left as a warning to future programmers. 445 * Code left as a warning to future programmers.
382 // ================================================================================== 446 // ==================================================================================
@@ -408,7 +472,7 @@ public class BSLinkset
408 // ================================================================================== 472 // ==================================================================================
409 */ 473 */
410 474
411 m_physicsScene.Constraints.AddConstraint(constrain); 475 PhysicsScene.Constraints.AddConstraint(constrain);
412 476
413 // zero linear and angular limits makes the objects unable to move in relation to each other 477 // zero linear and angular limits makes the objects unable to move in relation to each other
414 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 478 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
@@ -429,31 +493,79 @@ public class BSLinkset
429 } 493 }
430 494
431 // Remove linkage between myself and a particular child 495 // Remove linkage between myself and a particular child
496 // The root and child bodies are passed in because we need to remove the constraint between
497 // the bodies that were at unlink time.
432 // Called at taint time! 498 // Called at taint time!
433 private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) 499 private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody,
500 BSPhysObject childPrim, BulletBody childBody)
434 { 501 {
435 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 502 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
503 rootPrim.LocalID,
504 rootPrim.LocalID, rootBody.ptr.ToString("X"),
505 childPrim.LocalID, childBody.ptr.ToString("X"));
436 506
437 // Find the constraint for this link and get rid of it from the overall collection and from my list 507 // Find the constraint for this link and get rid of it from the overall collection and from my list
438 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody); 508 PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody);
439 509
440 // Make the child refresh its location 510 // Make the child refresh its location
441 BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr); 511 BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
442 } 512 }
443 513
444 // Remove linkage between myself and any possible children I might have 514 /*
515 // Remove linkage between myself and any possible children I might have.
445 // Called at taint time! 516 // Called at taint time!
446 private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) 517 private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
447 { 518 {
448 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 519 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
449 520
450 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); 521 PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody);
522 }
523 */
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;
451 } 562 }
452 563
564
453 // Invoke the detailed logger and output something if it's enabled. 565 // Invoke the detailed logger and output something if it's enabled.
454 private void DetailLog(string msg, params Object[] args) 566 private void DetailLog(string msg, params Object[] args)
455 { 567 {
456 m_physicsScene.PhysicsLogging.Write(msg, args); 568 PhysicsScene.PhysicsLogging.Write(msg, args);
457 } 569 }
458 570
459} 571}