diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 114 |
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. |