diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | 193 |
1 files changed, 108 insertions, 85 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index d2abdb4..2189468 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | |||
@@ -61,9 +61,8 @@ public sealed class BSLinksetCompound : BSLinkset | |||
61 | { | 61 | { |
62 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; | 62 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; |
63 | 63 | ||
64 | public BSLinksetCompound(BSScene scene, BSPhysObject parent) | 64 | public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent) |
65 | { | 65 | { |
66 | base.Initialize(scene, parent); | ||
67 | } | 66 | } |
68 | 67 | ||
69 | // For compound implimented linksets, if there are children, use compound shape for the root. | 68 | // For compound implimented linksets, if there are children, use compound shape for the root. |
@@ -81,8 +80,6 @@ public sealed class BSLinksetCompound : BSLinkset | |||
81 | 80 | ||
82 | // When physical properties are changed the linkset needs to recalculate | 81 | // When physical properties are changed the linkset needs to recalculate |
83 | // its internal properties. | 82 | // its internal properties. |
84 | // This is queued in the 'post taint' queue so the | ||
85 | // refresh will happen once after all the other taints are applied. | ||
86 | public override void Refresh(BSPhysObject requestor) | 83 | public override void Refresh(BSPhysObject requestor) |
87 | { | 84 | { |
88 | // External request for Refresh (from BSPrim) doesn't need to do anything | 85 | // External request for Refresh (from BSPrim) doesn't need to do anything |
@@ -92,12 +89,18 @@ public sealed class BSLinksetCompound : BSLinkset | |||
92 | // Schedule a refresh to happen after all the other taint processing. | 89 | // Schedule a refresh to happen after all the other taint processing. |
93 | private void InternalRefresh(BSPhysObject requestor) | 90 | private void InternalRefresh(BSPhysObject requestor) |
94 | { | 91 | { |
95 | DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); | 92 | DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1},rebuilding={2}", |
96 | PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() | 93 | LinksetRoot.LocalID, requestor.LocalID, Rebuilding); |
94 | // When rebuilding, it is possible to set properties that would normally require a rebuild. | ||
95 | // If already rebuilding, don't request another rebuild. | ||
96 | if (!Rebuilding) | ||
97 | { | 97 | { |
98 | if (IsRoot(requestor) && HasAnyChildren) | 98 | PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() |
99 | RecomputeLinksetCompound(); | 99 | { |
100 | }); | 100 | if (IsRoot(requestor) && HasAnyChildren) |
101 | RecomputeLinksetCompound(); | ||
102 | }); | ||
103 | } | ||
101 | } | 104 | } |
102 | 105 | ||
103 | // The object is going dynamic (physical). Do any setup necessary | 106 | // The object is going dynamic (physical). Do any setup necessary |
@@ -114,6 +117,8 @@ public sealed class BSLinksetCompound : BSLinkset | |||
114 | { | 117 | { |
115 | // The root is going dynamic. Make sure mass is properly set. | 118 | // The root is going dynamic. Make sure mass is properly set. |
116 | m_mass = ComputeLinksetMass(); | 119 | m_mass = ComputeLinksetMass(); |
120 | if (HasAnyChildren) | ||
121 | InternalRefresh(LinksetRoot); | ||
117 | } | 122 | } |
118 | else | 123 | else |
119 | { | 124 | { |
@@ -123,6 +128,9 @@ public sealed class BSLinksetCompound : BSLinkset | |||
123 | BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); | 128 | BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); |
124 | // We don't want collisions from the old linkset children. | 129 | // We don't want collisions from the old linkset children. |
125 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 130 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
131 | |||
132 | child.PhysBody.collisionType = CollisionType.LinksetChild; | ||
133 | |||
126 | ret = true; | 134 | ret = true; |
127 | } | 135 | } |
128 | return ret; | 136 | return ret; |
@@ -137,10 +145,18 @@ public sealed class BSLinksetCompound : BSLinkset | |||
137 | { | 145 | { |
138 | bool ret = false; | 146 | bool ret = false; |
139 | DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); | 147 | DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); |
140 | if (!IsRoot(child)) | 148 | if (IsRoot(child)) |
149 | { | ||
150 | if (HasAnyChildren) | ||
151 | InternalRefresh(LinksetRoot); | ||
152 | } | ||
153 | else | ||
141 | { | 154 | { |
142 | // The non-physical children can come back to life. | 155 | // The non-physical children can come back to life. |
143 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 156 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
157 | |||
158 | child.PhysBody.collisionType = CollisionType.LinksetChild; | ||
159 | |||
144 | // Don't force activation so setting of DISABLE_SIMULATION can stay if used. | 160 | // Don't force activation so setting of DISABLE_SIMULATION can stay if used. |
145 | BulletSimAPI.Activate2(child.PhysBody.ptr, false); | 161 | BulletSimAPI.Activate2(child.PhysBody.ptr, false); |
146 | ret = true; | 162 | ret = true; |
@@ -182,19 +198,25 @@ public sealed class BSLinksetCompound : BSLinkset | |||
182 | // Because it is a convenient time, recompute child world position and rotation based on | 198 | // Because it is a convenient time, recompute child world position and rotation based on |
183 | // its position in the linkset. | 199 | // its position in the linkset. |
184 | RecomputeChildWorldPosition(child, true); | 200 | RecomputeChildWorldPosition(child, true); |
185 | |||
186 | // Cause the current shape to be freed and the new one to be built. | ||
187 | InternalRefresh(LinksetRoot); | ||
188 | ret = true; | ||
189 | } | 201 | } |
190 | 202 | ||
203 | // Cannot schedule a refresh/rebuild here because this routine is called when | ||
204 | // the linkset is being rebuilt. | ||
205 | // InternalRefresh(LinksetRoot); | ||
206 | |||
191 | return ret; | 207 | return ret; |
192 | } | 208 | } |
193 | 209 | ||
194 | // When the linkset is built, the child shape is added | 210 | // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', |
195 | // to the compound shape relative to the root shape. The linkset then moves around but | 211 | // this routine will restore the removed constraints. |
196 | // this does not move the actual child prim. The child prim's location must be recomputed | 212 | // Called at taint-time!! |
197 | // based on the location of the root shape. | 213 | public override void RestoreBodyDependencies(BSPrim child) |
214 | { | ||
215 | } | ||
216 | |||
217 | // When the linkset is built, the child shape is added to the compound shape relative to the | ||
218 | // root shape. The linkset then moves around but this does not move the actual child | ||
219 | // prim. The child prim's location must be recomputed based on the location of the root shape. | ||
198 | private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime) | 220 | private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime) |
199 | { | 221 | { |
200 | BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo; | 222 | BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo; |
@@ -227,14 +249,6 @@ public sealed class BSLinksetCompound : BSLinkset | |||
227 | } | 249 | } |
228 | } | 250 | } |
229 | 251 | ||
230 | // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', | ||
231 | // this routine will restore the removed constraints. | ||
232 | // Called at taint-time!! | ||
233 | public override void RestoreBodyDependencies(BSPrim child) | ||
234 | { | ||
235 | // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. | ||
236 | } | ||
237 | |||
238 | // ================================================================ | 252 | // ================================================================ |
239 | 253 | ||
240 | // Add a new child to the linkset. | 254 | // Add a new child to the linkset. |
@@ -254,7 +268,7 @@ public sealed class BSLinksetCompound : BSLinkset | |||
254 | } | 268 | } |
255 | 269 | ||
256 | // Remove the specified child from the linkset. | 270 | // Remove the specified child from the linkset. |
257 | // Safe to call even if the child is not really in my linkset. | 271 | // Safe to call even if the child is not really in the linkset. |
258 | protected override void RemoveChildFromLinkset(BSPhysObject child) | 272 | protected override void RemoveChildFromLinkset(BSPhysObject child) |
259 | { | 273 | { |
260 | if (m_children.Remove(child)) | 274 | if (m_children.Remove(child)) |
@@ -289,74 +303,83 @@ public sealed class BSLinksetCompound : BSLinkset | |||
289 | // Called at taint time!! | 303 | // Called at taint time!! |
290 | private void RecomputeLinksetCompound() | 304 | private void RecomputeLinksetCompound() |
291 | { | 305 | { |
292 | // Cause the root shape to be rebuilt as a compound object with just the root in it | 306 | try |
293 | LinksetRoot.ForceBodyShapeRebuild(true); | 307 | { |
308 | // Suppress rebuilding while rebuilding | ||
309 | Rebuilding = true; | ||
294 | 310 | ||
295 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", | 311 | // Cause the root shape to be rebuilt as a compound object with just the root in it |
296 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); | 312 | LinksetRoot.ForceBodyShapeRebuild(true); |
297 | 313 | ||
298 | // Add a shape for each of the other children in the linkset | 314 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", |
299 | ForEachMember(delegate(BSPhysObject cPrim) | 315 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); |
300 | { | 316 | |
301 | if (!IsRoot(cPrim)) | 317 | // Add a shape for each of the other children in the linkset |
318 | ForEachMember(delegate(BSPhysObject cPrim) | ||
302 | { | 319 | { |
303 | // Compute the displacement of the child from the root of the linkset. | 320 | if (!IsRoot(cPrim)) |
304 | // This info is saved in the child prim so the relationship does not | ||
305 | // change over time and the new child position can be computed | ||
306 | // when the linkset is being disassembled (the linkset may have moved). | ||
307 | BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; | ||
308 | if (lci == null) | ||
309 | { | 321 | { |
310 | // Each child position and rotation is given relative to the root. | 322 | // Compute the displacement of the child from the root of the linkset. |
311 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); | 323 | // This info is saved in the child prim so the relationship does not |
312 | OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; | 324 | // change over time and the new child position can be computed |
313 | OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; | 325 | // when the linkset is being disassembled (the linkset may have moved). |
314 | 326 | BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; | |
315 | // Save relative position for recomputing child's world position after moving linkset. | 327 | if (lci == null) |
316 | lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); | 328 | { |
317 | cPrim.LinksetInfo = lci; | 329 | // Each child position and rotation is given relative to the root. |
318 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); | 330 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); |
319 | } | 331 | OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; |
332 | OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; | ||
333 | |||
334 | // Save relative position for recomputing child's world position after moving linkset. | ||
335 | lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); | ||
336 | cPrim.LinksetInfo = lci; | ||
337 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); | ||
338 | } | ||
320 | 339 | ||
321 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", | 340 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", |
322 | LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); | 341 | LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); |
323 | 342 | ||
324 | if (cPrim.PhysShape.isNativeShape) | 343 | if (cPrim.PhysShape.isNativeShape) |
325 | { | 344 | { |
326 | // A native shape is turning into a hull collision shape because native | 345 | // A native shape is turning into a hull collision shape because native |
327 | // shapes are not shared so we have to hullify it so it will be tracked | 346 | // shapes are not shared so we have to hullify it so it will be tracked |
328 | // and freed at the correct time. This also solves the scaling problem | 347 | // and freed at the correct time. This also solves the scaling problem |
329 | // (native shapes scaled but hull/meshes are assumed to not be). | 348 | // (native shapes scaled but hull/meshes are assumed to not be). |
330 | // TODO: decide of the native shape can just be used in the compound shape. | 349 | // TODO: decide of the native shape can just be used in the compound shape. |
331 | // Use call to CreateGeomNonSpecial(). | 350 | // Use call to CreateGeomNonSpecial(). |
332 | BulletShape saveShape = cPrim.PhysShape; | 351 | BulletShape saveShape = cPrim.PhysShape; |
333 | cPrim.PhysShape.Clear(); // Don't let the create free the child's shape | 352 | cPrim.PhysShape.Clear(); // Don't let the create free the child's shape |
334 | // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); | 353 | // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); |
335 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); | 354 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); |
336 | BulletShape newShape = cPrim.PhysShape; | 355 | BulletShape newShape = cPrim.PhysShape; |
337 | cPrim.PhysShape = saveShape; | 356 | cPrim.PhysShape = saveShape; |
338 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos , lci.OffsetRot); | 357 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos, lci.OffsetRot); |
339 | } | 358 | } |
340 | else | 359 | else |
341 | { | ||
342 | // For the shared shapes (meshes and hulls), just use the shape in the child. | ||
343 | // The reference count added here will be decremented when the compound shape | ||
344 | // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced). | ||
345 | if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) | ||
346 | { | 360 | { |
347 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", | 361 | // For the shared shapes (meshes and hulls), just use the shape in the child. |
348 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); | 362 | // The reference count added here will be decremented when the compound shape |
363 | // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced). | ||
364 | if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) | ||
365 | { | ||
366 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", | ||
367 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); | ||
368 | } | ||
369 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos, lci.OffsetRot); | ||
349 | } | 370 | } |
350 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos , lci.OffsetRot); | ||
351 | } | 371 | } |
352 | } | 372 | return false; // 'false' says to move onto the next child in the list |
353 | 373 | }); | |
354 | return false; // 'false' says to move onto the next child in the list | ||
355 | }); | ||
356 | 374 | ||
357 | // With all of the linkset packed into the root prim, it has the mass of everyone. | 375 | // With all of the linkset packed into the root prim, it has the mass of everyone. |
358 | float linksetMass = LinksetMass; | 376 | float linksetMass = LinksetMass; |
359 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); | 377 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); |
378 | } | ||
379 | finally | ||
380 | { | ||
381 | Rebuilding = false; | ||
382 | } | ||
360 | 383 | ||
361 | BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); | 384 | BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); |
362 | 385 | ||