aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs114
1 files changed, 64 insertions, 50 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 6f8430c..4a71612 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -40,6 +40,7 @@ public class BSLinkset
40 public BSPrim Root { get { return m_linksetRoot; } } 40 public BSPrim Root { get { return m_linksetRoot; } }
41 41
42 private BSScene m_scene; 42 private BSScene m_scene;
43 public BSScene Scene { get { return m_scene; } }
43 44
44 private List<BSPrim> m_children; 45 private List<BSPrim> m_children;
45 46
@@ -80,14 +81,14 @@ public class BSLinkset
80 81
81 // Link to a linkset where the child knows the parent. 82 // Link to a linkset where the child knows the parent.
82 // Parent changing should not happen so do some sanity checking. 83 // Parent changing should not happen so do some sanity checking.
83 // We return the parent's linkset so the child can track it's membership. 84 // We return the parent's linkset so the child can track its membership.
84 public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) 85 public BSLinkset AddMeToLinkset(BSPrim child)
85 { 86 {
86 lock (m_linksetActivityLock) 87 lock (m_linksetActivityLock)
87 { 88 {
88 parent.Linkset.AddChildToLinkset(child); 89 AddChildToLinkset(child);
89 } 90 }
90 return parent.Linkset; 91 return this;
91 } 92 }
92 93
93 public BSLinkset RemoveMeFromLinkset(BSPrim child) 94 public BSLinkset RemoveMeFromLinkset(BSPrim child)
@@ -101,7 +102,7 @@ public class BSLinkset
101 { 102 {
102 // Note that we don't do a foreach because the remove routine 103 // Note that we don't do a foreach because the remove routine
103 // takes it out of the list. 104 // takes it out of the list.
104 RemoveChildFromLinkset(m_children[0]); 105 RemoveChildFromOtherLinkset(m_children[0]);
105 } 106 }
106 m_children.Clear(); // just to make sure 107 m_children.Clear(); // just to make sure
107 } 108 }
@@ -113,9 +114,10 @@ public class BSLinkset
113 } 114 }
114 115
115 // The child is down to a linkset of just itself 116 // The child is down to a linkset of just itself
116 return new BSLinkset(m_scene, child); 117 return new BSLinkset(Scene, child);
117 } 118 }
118 119
120 /* DEPRECATED: this is really bad in that it trys to unlink other prims.
119 // An existing linkset had one of its members rebuilt or something. 121 // An existing linkset had one of its members rebuilt or something.
120 // Go through the linkset and rebuild the pointers to the bodies of the linkset members. 122 // Go through the linkset and rebuild the pointers to the bodies of the linkset members.
121 public BSLinkset RefreshLinkset(BSPrim requestor) 123 public BSLinkset RefreshLinkset(BSPrim requestor)
@@ -124,6 +126,7 @@ public class BSLinkset
124 126
125 lock (m_linksetActivityLock) 127 lock (m_linksetActivityLock)
126 { 128 {
129 // The body pointer is refetched in case anything has moved.
127 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID); 130 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID);
128 if (aPtr == System.IntPtr.Zero) 131 if (aPtr == System.IntPtr.Zero)
129 { 132 {
@@ -155,13 +158,14 @@ public class BSLinkset
155 } 158 }
156 foreach (BSPrim bsp in toRemove) 159 foreach (BSPrim bsp in toRemove)
157 { 160 {
158 RemoveChildFromLinkset(bsp); 161 RemoveChildFromOtherLinkset(bsp);
159 } 162 }
160 } 163 }
161 } 164 }
162 165
163 return ret; 166 return ret;
164 } 167 }
168 */
165 169
166 170
167 // Return 'true' if the passed object is the root object of this linkset 171 // Return 'true' if the passed object is the root object of this linkset
@@ -170,6 +174,8 @@ public class BSLinkset
170 return (requestor.LocalID == m_linksetRoot.LocalID); 174 return (requestor.LocalID == m_linksetRoot.LocalID);
171 } 175 }
172 176
177 public int NumberOfChildren { get { return m_children.Count; } }
178
173 // Return 'true' if this linkset has any children (more than the root member) 179 // Return 'true' if this linkset has any children (more than the root member)
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 180 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175 181
@@ -208,7 +214,8 @@ public class BSLinkset
208 com += bp.Position * bp.MassRaw; 214 com += bp.Position * bp.MassRaw;
209 totalMass += bp.MassRaw; 215 totalMass += bp.MassRaw;
210 } 216 }
211 com /= totalMass; 217 if (totalMass != 0f)
218 com /= totalMass;
212 219
213 return com; 220 return com;
214 } 221 }
@@ -221,51 +228,54 @@ public class BSLinkset
221 { 228 {
222 com += bp.Position * bp.MassRaw; 229 com += bp.Position * bp.MassRaw;
223 } 230 }
224 com /= m_children.Count + 1; 231 com /= (m_children.Count + 1);
225 232
226 return com; 233 return com;
227 } 234 }
228 235
229 // I am the root of a linkset and a new child is being added 236 // I am the root of a linkset and a new child is being added
230 public void AddChildToLinkset(BSPrim pchild) 237 // Called while LinkActivity is locked.
238 public void AddChildToLinkset(BSPrim child)
231 { 239 {
232 BSPrim child = pchild;
233 if (!HasChild(child)) 240 if (!HasChild(child))
234 { 241 {
235 m_children.Add(child); 242 m_children.Add(child);
236 243
237 m_scene.TaintedObject(delegate() 244 BSPrim root = Root; // capture the root as of now
245 m_scene.TaintedObject("AddChildToLinkset", delegate()
238 { 246 {
239 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 247 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
240 DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 248 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
241 PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child 249 PhysicallyLinkAChildToRoot(root, child); // build the physical binding between me and the child
242 }); 250 });
243 } 251 }
244 return; 252 return;
245 } 253 }
246 254
255 // Forcefully removing a child from a linkset.
256 // This is not being called by the child so we have to make sure the child doesn't think
257 // it's still connected to the linkset.
258 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
259 // has to be updated also (like pointer to prim's parent).
260 public void RemoveChildFromOtherLinkset(BSPrim pchild)
261 {
262 pchild.Linkset = new BSLinkset(m_scene, pchild);
263 RemoveChildFromLinkset(pchild);
264 }
265
247 // I am the root of a linkset and one of my children is being removed. 266 // I am the root of a linkset and one of my children is being removed.
248 // Safe to call even if the child is not really in my linkset. 267 // Safe to call even if the child is not really in my linkset.
249 public void RemoveChildFromLinkset(BSPrim pchild) 268 public void RemoveChildFromLinkset(BSPrim child)
250 { 269 {
251 BSPrim child = pchild;
252
253 if (m_children.Remove(child)) 270 if (m_children.Remove(child))
254 { 271 {
255 m_scene.TaintedObject(delegate() 272 BSPrim root = Root; // capture the root as of now
273 m_scene.TaintedObject("RemoveChildFromLinkset", delegate()
256 { 274 {
257 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 275 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
258 DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 276 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
259 277
260 if (m_children.Count == 0) 278 PhysicallyUnlinkAChildFromRoot(root, child);
261 {
262 // if the linkset is empty, make sure all linkages have been removed
263 PhysicallyUnlinkAllChildrenFromRoot();
264 }
265 else
266 {
267 PhysicallyUnlinkAChildFromRoot(pchild);
268 }
269 }); 279 });
270 } 280 }
271 else 281 else
@@ -278,14 +288,14 @@ public class BSLinkset
278 288
279 // Create a constraint between me (root of linkset) and the passed prim (the child). 289 // Create a constraint between me (root of linkset) and the passed prim (the child).
280 // Called at taint time! 290 // Called at taint time!
281 private void PhysicallyLinkAChildToRoot(BSPrim childPrim) 291 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
282 { 292 {
283 // Zero motion for children so they don't interpolate 293 // Zero motion for children so they don't interpolate
284 childPrim.ZeroMotion(); 294 childPrim.ZeroMotion();
285 295
286 // relative position normalized to the root prim 296 // relative position normalized to the root prim
287 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); 297 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
288 OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; 298 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
289 299
290 // relative rotation of the child to the parent 300 // relative rotation of the child to the parent
291 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; 301 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
@@ -293,16 +303,17 @@ public class BSLinkset
293 // create a constraint that allows no freedom of movement between the two objects 303 // create a constraint that allows no freedom of movement between the two objects
294 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 304 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
295 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); 305 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
296 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 306 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
297 BSConstraint constrain = m_scene.Constraints.CreateConstraint( 307 BS6DofConstraint constrain = new BS6DofConstraint(
298 m_scene.World, m_linksetRoot.Body, childPrim.Body, 308 m_scene.World, rootPrim.Body, childPrim.Body,
299 // childRelativePosition, 309 childRelativePosition,
300 // childRelativeRotation, 310 childRelativeRotation,
301 OMV.Vector3.Zero,
302 OMV.Quaternion.Identity,
303 OMV.Vector3.Zero, 311 OMV.Vector3.Zero,
304 OMV.Quaternion.Identity 312 -childRelativeRotation
305 ); 313 );
314 m_scene.Constraints.AddConstraint(constrain);
315
316 // zero linear and angular limits makes the objects unable to move in relation to each other
306 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 317 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
307 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 318 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
308 319
@@ -317,29 +328,32 @@ public class BSLinkset
317 328
318 // Remove linkage between myself and a particular child 329 // Remove linkage between myself and a particular child
319 // Called at taint time! 330 // Called at taint time!
320 private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim) 331 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
321 { 332 {
322 DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", 333 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
323 LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); 334 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
324 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 335 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
325 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); 336
326 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body); 337 m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
338 // Make the child refresh its location
339 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
327 } 340 }
328 341
329 // Remove linkage between myself and any possible children I might have 342 // Remove linkage between myself and any possible children I might have
330 // Called at taint time! 343 // Called at taint time!
331 private void PhysicallyUnlinkAllChildrenFromRoot() 344 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
332 { 345 {
333 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); 346 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
334 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); 347 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
335 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body); 348
336 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); 349 m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
337 } 350 }
338 351
339 // Invoke the detailed logger and output something if it's enabled. 352 // Invoke the detailed logger and output something if it's enabled.
340 private void DebugLog(string msg, params Object[] args) 353 private void DebugLog(string msg, params Object[] args)
341 { 354 {
342 m_scene.Logger.DebugFormat(msg, args); 355 if (m_scene.ShouldDebugLog)
356 m_scene.Logger.DebugFormat(msg, args);
343 } 357 }
344 358
345 // Invoke the detailed logger and output something if it's enabled. 359 // Invoke the detailed logger and output something if it's enabled.