aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs150
1 files changed, 95 insertions, 55 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 087b9bb..7e784eb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -36,14 +36,17 @@ public class BSLinkset
36{ 36{
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPrim m_linksetRoot; 39 private BSPhysObject m_linksetRoot;
40 public BSPrim LinksetRoot { get { return m_linksetRoot; } } 40 public BSPhysObject LinksetRoot { get { return m_linksetRoot; } }
41 41
42 private BSScene m_physicsScene; 42 private BSScene m_physicsScene;
43 public BSScene PhysicsScene { get { return m_physicsScene; } } 43 public BSScene PhysicsScene { get { return m_physicsScene; } }
44 44
45 static int m_nextLinksetID = 1;
46 public int LinksetID { get; private set; }
47
45 // The children under the root in this linkset 48 // The children under the root in this linkset
46 private List<BSPrim> m_children; 49 private List<BSPhysObject> m_children;
47 50
48 // We lock the diddling of linkset classes to prevent any badness. 51 // We lock the diddling of linkset classes to prevent any badness.
49 // This locks the modification of the instances of this class. Changes 52 // This locks the modification of the instances of this class. Changes
@@ -71,19 +74,23 @@ public class BSLinkset
71 get { return ComputeLinksetGeometricCenter(); } 74 get { return ComputeLinksetGeometricCenter(); }
72 } 75 }
73 76
74 public BSLinkset(BSScene scene, BSPrim parent) 77 public BSLinkset(BSScene scene, BSPhysObject parent)
75 { 78 {
76 // A simple linkset of one (no children) 79 // A simple linkset of one (no children)
80 LinksetID = m_nextLinksetID++;
81 // We create LOTS of linksets.
82 if (m_nextLinksetID < 0)
83 m_nextLinksetID = 1;
77 m_physicsScene = scene; 84 m_physicsScene = scene;
78 m_linksetRoot = parent; 85 m_linksetRoot = parent;
79 m_children = new List<BSPrim>(); 86 m_children = new List<BSPhysObject>();
80 m_mass = parent.MassRaw; 87 m_mass = parent.MassRaw;
81 } 88 }
82 89
83 // Link to a linkset where the child knows the parent. 90 // Link to a linkset where the child knows the parent.
84 // Parent changing should not happen so do some sanity checking. 91 // Parent changing should not happen so do some sanity checking.
85 // We return the parent's linkset so the child can track its membership. 92 // We return the parent's linkset so the child can track its membership.
86 public BSLinkset AddMeToLinkset(BSPrim child) 93 public BSLinkset AddMeToLinkset(BSPhysObject child)
87 { 94 {
88 lock (m_linksetActivityLock) 95 lock (m_linksetActivityLock)
89 { 96 {
@@ -95,7 +102,7 @@ public class BSLinkset
95 // Remove a child from a linkset. 102 // Remove a child from a linkset.
96 // Returns a new linkset for the child which is a linkset of one (just the 103 // Returns a new linkset for the child which is a linkset of one (just the
97 // orphened child). 104 // orphened child).
98 public BSLinkset RemoveMeFromLinkset(BSPrim child) 105 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
99 { 106 {
100 lock (m_linksetActivityLock) 107 lock (m_linksetActivityLock)
101 { 108 {
@@ -122,7 +129,7 @@ public class BSLinkset
122 } 129 }
123 130
124 // Return 'true' if the passed object is the root object of this linkset 131 // Return 'true' if the passed object is the root object of this linkset
125 public bool IsRoot(BSPrim requestor) 132 public bool IsRoot(BSPhysObject requestor)
126 { 133 {
127 return (requestor.LocalID == m_linksetRoot.LocalID); 134 return (requestor.LocalID == m_linksetRoot.LocalID);
128 } 135 }
@@ -133,12 +140,12 @@ public class BSLinkset
133 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 140 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
134 141
135 // Return 'true' if this child is in this linkset 142 // Return 'true' if this child is in this linkset
136 public bool HasChild(BSPrim child) 143 public bool HasChild(BSPhysObject child)
137 { 144 {
138 bool ret = false; 145 bool ret = false;
139 lock (m_linksetActivityLock) 146 lock (m_linksetActivityLock)
140 { 147 {
141 foreach (BSPrim bp in m_children) 148 foreach (BSPhysObject bp in m_children)
142 { 149 {
143 if (child.LocalID == bp.LocalID) 150 if (child.LocalID == bp.LocalID)
144 { 151 {
@@ -153,7 +160,7 @@ public class BSLinkset
153 private float ComputeLinksetMass() 160 private float ComputeLinksetMass()
154 { 161 {
155 float mass = m_linksetRoot.MassRaw; 162 float mass = m_linksetRoot.MassRaw;
156 foreach (BSPrim bp in m_children) 163 foreach (BSPhysObject bp in m_children)
157 { 164 {
158 mass += bp.MassRaw; 165 mass += bp.MassRaw;
159 } 166 }
@@ -167,7 +174,7 @@ public class BSLinkset
167 174
168 lock (m_linksetActivityLock) 175 lock (m_linksetActivityLock)
169 { 176 {
170 foreach (BSPrim bp in m_children) 177 foreach (BSPhysObject bp in m_children)
171 { 178 {
172 com += bp.Position * bp.MassRaw; 179 com += bp.Position * bp.MassRaw;
173 totalMass += bp.MassRaw; 180 totalMass += bp.MassRaw;
@@ -185,7 +192,7 @@ public class BSLinkset
185 192
186 lock (m_linksetActivityLock) 193 lock (m_linksetActivityLock)
187 { 194 {
188 foreach (BSPrim bp in m_children) 195 foreach (BSPhysObject bp in m_children)
189 { 196 {
190 com += bp.Position * bp.MassRaw; 197 com += bp.Position * bp.MassRaw;
191 } 198 }
@@ -195,11 +202,33 @@ public class BSLinkset
195 return com; 202 return com;
196 } 203 }
197 204
205 // The object is going dynamic (physical). Do any setup necessary
206 // for a dynamic linkset.
207 // Only the state of the passed object can be modified. The rest of the linkset
208 // has not yet been fully constructed.
209 // Return 'true' if any properties updated on the passed object.
210 // Called at taint-time!
211 public bool MakeDynamic(BSPhysObject child)
212 {
213 bool ret = false;
214 return ret;
215 }
216
217 // The object is going static (non-physical). Do any setup necessary
218 // for a static linkset.
219 // Return 'true' if any properties updated on the passed object.
220 // Called at taint-time!
221 public bool MakeStatic(BSPhysObject child)
222 {
223 // What is done for each object in BSPrim is what we want.
224 return false;
225 }
226
198 // When physical properties are changed the linkset needs to recalculate 227 // When physical properties are changed the linkset needs to recalculate
199 // its internal properties. 228 // its internal properties.
200 public void Refresh(BSPrim requestor) 229 public void Refresh(BSPhysObject requestor)
201 { 230 {
202 // If there are no children, there aren't any constraints to recompute 231 // If there are no children, there can't be any constraints to recompute
203 if (!HasAnyChildren) 232 if (!HasAnyChildren)
204 return; 233 return;
205 234
@@ -218,15 +247,16 @@ public class BSLinkset
218 // from a linkset to make sure the constraints know about the new mass and 247 // from a linkset to make sure the constraints know about the new mass and
219 // geometry. 248 // geometry.
220 // Must only be called at taint time!! 249 // Must only be called at taint time!!
221 private bool RecomputeLinksetConstraintVariables() 250 private void RecomputeLinksetConstraintVariables()
222 { 251 {
223 float linksetMass = LinksetMass; 252 float linksetMass = LinksetMass;
224 lock (m_linksetActivityLock) 253 lock (m_linksetActivityLock)
225 { 254 {
226 foreach (BSPrim child in m_children) 255 bool somethingMissing = false;
256 foreach (BSPhysObject child in m_children)
227 { 257 {
228 BSConstraint constrain; 258 BSConstraint constrain;
229 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) 259 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
230 { 260 {
231 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", 261 // 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); 262 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
@@ -234,32 +264,51 @@ public class BSLinkset
234 } 264 }
235 else 265 else
236 { 266 {
237 // Non-fatal error that can happen when children are being added to the linkset but 267 // Non-fatal error that happens when children are being added to the linkset but
238 // their constraints have not been created yet. 268 // their constraints have not been created yet.
239 // Caused by the fact that m_children is built at run time but building constraints 269 // Caused by the fact that m_children is built at run time but building constraints
240 // happens at taint time. 270 // happens at taint time.
241 // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", 271 somethingMissing = true;
242 // m_linksetRoot.Body.ID, child.Body.ID); 272 break;
243 } 273 }
244 } 274 }
275
276 // If the whole linkset is not here, doesn't make sense to recompute linkset wide values
277 if (!somethingMissing)
278 {
279 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
280 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
281 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
282 foreach (BSPhysObject child in m_children)
283 {
284 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
285 }
286 /*
287 // The root prim takes on the weight of the whole linkset
288 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass);
289 BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia);
290 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
291 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
292 BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr);
293 */
294 }
245 } 295 }
246 return false; 296 return;
247 } 297 }
248 298
249 // I am the root of a linkset and a new child is being added 299 // I am the root of a linkset and a new child is being added
250 // Called while LinkActivity is locked. 300 // Called while LinkActivity is locked.
251 private void AddChildToLinkset(BSPrim child) 301 private void AddChildToLinkset(BSPhysObject child)
252 { 302 {
253 if (!HasChild(child)) 303 if (!HasChild(child))
254 { 304 {
255 m_children.Add(child); 305 m_children.Add(child);
256 306
257 BSPrim rootx = LinksetRoot; // capture the root as of now 307 BSPhysObject rootx = LinksetRoot; // capture the root as of now
258 BSPrim childx = child; 308 BSPhysObject childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate() 309 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
260 { 310 {
261 // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 311 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child 312 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
264 }); 313 });
265 } 314 }
@@ -271,7 +320,7 @@ public class BSLinkset
271 // it's still connected to the linkset. 320 // it's still connected to the linkset.
272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information 321 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
273 // has to be updated also (like pointer to prim's parent). 322 // has to be updated also (like pointer to prim's parent).
274 private void RemoveChildFromOtherLinkset(BSPrim pchild) 323 private void RemoveChildFromOtherLinkset(BSPhysObject pchild)
275 { 324 {
276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild); 325 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
277 RemoveChildFromLinkset(pchild); 326 RemoveChildFromLinkset(pchild);
@@ -279,21 +328,20 @@ public class BSLinkset
279 328
280 // I am the root of a linkset and one of my children is being removed. 329 // I am the root of a linkset and one of my children is being removed.
281 // Safe to call even if the child is not really in my linkset. 330 // Safe to call even if the child is not really in my linkset.
282 private void RemoveChildFromLinkset(BSPrim child) 331 private void RemoveChildFromLinkset(BSPhysObject child)
283 { 332 {
284 if (m_children.Remove(child)) 333 if (m_children.Remove(child))
285 { 334 {
286 BSPrim rootx = LinksetRoot; // capture the root as of now 335 BSPhysObject rootx = LinksetRoot; // capture the root as of now
287 BSPrim childx = child; 336 BSPhysObject childx = child;
288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 337 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
289 { 338 {
290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 339 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
292 340
293 PhysicallyUnlinkAChildFromRoot(rootx, childx); 341 PhysicallyUnlinkAChildFromRoot(rootx, childx);
342 RecomputeLinksetConstraintVariables();
294 }); 343 });
295 344
296 RecomputeLinksetConstraintVariables();
297 } 345 }
298 else 346 else
299 { 347 {
@@ -305,7 +353,7 @@ public class BSLinkset
305 353
306 // Create a constraint between me (root of linkset) and the passed prim (the child). 354 // Create a constraint between me (root of linkset) and the passed prim (the child).
307 // Called at taint time! 355 // Called at taint time!
308 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim) 356 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
309 { 357 {
310 // Zero motion for children so they don't interpolate 358 // Zero motion for children so they don't interpolate
311 childPrim.ZeroMotion(); 359 childPrim.ZeroMotion();
@@ -319,19 +367,18 @@ public class BSLinkset
319 367
320 // create a constraint that allows no freedom of movement between the two objects 368 // create a constraint that allows no freedom of movement between the two objects
321 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 369 // 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}", 370 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); 371 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
325 BS6DofConstraint constrain = new BS6DofConstraint( 372 BS6DofConstraint constrain = new BS6DofConstraint(
326 m_physicsScene.World, rootPrim.Body, childPrim.Body, 373 m_physicsScene.World, rootPrim.BSBody, childPrim.BSBody,
327 midPoint, 374 midPoint,
328 true, 375 true,
329 true 376 true
330 ); 377 );
331 /* NOTE: attempt to build constraint with full frame computation, etc. 378 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
332 * Using the midpoint is easier since it lets the Bullet code use the transforms 379 * Using the midpoint is easier since it lets the Bullet code use the transforms
333 * of the objects. 380 * of the objects.
334 * Code left here as an example. 381 * Code left as a warning to future programmers.
335 // ================================================================================== 382 // ==================================================================================
336 // relative position normalized to the root prim 383 // relative position normalized to the root prim
337 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); 384 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
@@ -343,7 +390,6 @@ public class BSLinkset
343 390
344 // create a constraint that allows no freedom of movement between the two objects 391 // create a constraint that allows no freedom of movement between the two objects
345 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 392 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
346 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
347 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 393 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
348 BS6DofConstraint constrain = new BS6DofConstraint( 394 BS6DofConstraint constrain = new BS6DofConstraint(
349 PhysicsScene.World, rootPrim.Body, childPrim.Body, 395 PhysicsScene.World, rootPrim.Body, childPrim.Body,
@@ -374,40 +420,34 @@ public class BSLinkset
374 PhysicsScene.Params.linkConstraintTransMotorMaxVel, 420 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
375 PhysicsScene.Params.linkConstraintTransMotorMaxForce); 421 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
376 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); 422 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
423 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
424 {
425 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
426 }
377 427
378 RecomputeLinksetConstraintVariables(); 428 RecomputeLinksetConstraintVariables();
379 } 429 }
380 430
381 // Remove linkage between myself and a particular child 431 // Remove linkage between myself and a particular child
382 // Called at taint time! 432 // Called at taint time!
383 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) 433 private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
384 { 434 {
385 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
386 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
387 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 435 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
388 436
389 // Find the constraint for this link and get rid of it from the overall collection and from my list 437 // 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); 438 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody);
391 439
392 // Make the child refresh its location 440 // Make the child refresh its location
393 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); 441 BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr);
394 } 442 }
395 443
396 // Remove linkage between myself and any possible children I might have 444 // Remove linkage between myself and any possible children I might have
397 // Called at taint time! 445 // Called at taint time!
398 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) 446 private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
399 { 447 {
400 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 448 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
402 449
403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); 450 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody);
404 }
405
406 // Invoke the detailed logger and output something if it's enabled.
407 private void DebugLog(string msg, params Object[] args)
408 {
409 if (m_physicsScene.ShouldDebugLog)
410 m_physicsScene.Logger.DebugFormat(msg, args);
411 } 451 }
412 452
413 // Invoke the detailed logger and output something if it's enabled. 453 // Invoke the detailed logger and output something if it's enabled.