aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs272
1 files changed, 93 insertions, 179 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index e05562a..1f16cc8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -35,6 +35,7 @@ using OMV = OpenMetaverse;
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37 37
38 /*
38// When a child is linked, the relationship position of the child to the parent 39// When a child is linked, the relationship position of the child to the parent
39// is remembered so the child's world position can be recomputed when it is 40// is remembered so the child's world position can be recomputed when it is
40// removed from the linkset. 41// removed from the linkset.
@@ -88,6 +89,7 @@ sealed class BSLinksetCompoundInfo : BSLinksetInfo
88 return buff.ToString(); 89 return buff.ToString();
89 } 90 }
90}; 91};
92 */
91 93
92public sealed class BSLinksetCompound : BSLinkset 94public sealed class BSLinksetCompound : BSLinkset
93{ 95{
@@ -98,19 +100,6 @@ public sealed class BSLinksetCompound : BSLinkset
98 { 100 {
99 } 101 }
100 102
101 // For compound implimented linksets, if there are children, use compound shape for the root.
102 public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
103 {
104 // Returning 'unknown' means we don't have a preference.
105 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
106 if (IsRoot(requestor) && HasAnyChildren)
107 {
108 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
109 }
110 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
111 return ret;
112 }
113
114 // When physical properties are changed the linkset needs to recalculate 103 // When physical properties are changed the linkset needs to recalculate
115 // its internal properties. 104 // its internal properties.
116 public override void Refresh(BSPrimLinkable requestor) 105 public override void Refresh(BSPrimLinkable requestor)
@@ -124,14 +113,14 @@ public sealed class BSLinksetCompound : BSLinkset
124 // Schedule a refresh to happen after all the other taint processing. 113 // Schedule a refresh to happen after all the other taint processing.
125 private void ScheduleRebuild(BSPrimLinkable requestor) 114 private void ScheduleRebuild(BSPrimLinkable requestor)
126 { 115 {
127 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", 116 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
128 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); 117 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
129 // When rebuilding, it is possible to set properties that would normally require a rebuild. 118 // When rebuilding, it is possible to set properties that would normally require a rebuild.
130 // If already rebuilding, don't request another rebuild. 119 // If already rebuilding, don't request another rebuild.
131 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. 120 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
132 if (!Rebuilding && HasAnyChildren) 121 if (!Rebuilding && HasAnyChildren)
133 { 122 {
134 PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate() 123 m_physicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
135 { 124 {
136 if (HasAnyChildren) 125 if (HasAnyChildren)
137 RecomputeLinksetCompound(); 126 RecomputeLinksetCompound();
@@ -153,26 +142,11 @@ public sealed class BSLinksetCompound : BSLinkset
153 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. 142 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
154 ScheduleRebuild(LinksetRoot); 143 ScheduleRebuild(LinksetRoot);
155 } 144 }
156 else
157 {
158 // The origional prims are removed from the world as the shape of the root compound
159 // shape takes over.
160 PhysicsScene.PE.AddToCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
161 PhysicsScene.PE.ForceActivationState(child.PhysBody, ActivationState.DISABLE_SIMULATION);
162 // We don't want collisions from the old linkset children.
163 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
164
165 child.PhysBody.collisionType = CollisionType.LinksetChild;
166
167 ret = true;
168 }
169 return ret; 145 return ret;
170 } 146 }
171 147
172 // The object is going static (non-physical). Do any setup necessary for a static linkset. 148 // The object is going static (non-physical). We do not do anything for static linksets.
173 // Return 'true' if any properties updated on the passed object. 149 // Return 'true' if any properties updated on the passed object.
174 // This doesn't normally happen -- OpenSim removes the objects from the physical
175 // world if it is a static linkset.
176 // Called at taint-time! 150 // Called at taint-time!
177 public override bool MakeStatic(BSPrimLinkable child) 151 public override bool MakeStatic(BSPrimLinkable child)
178 { 152 {
@@ -180,19 +154,9 @@ public sealed class BSLinksetCompound : BSLinkset
180 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); 154 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
181 if (IsRoot(child)) 155 if (IsRoot(child))
182 { 156 {
157 // Schedule a rebuild to verify that the root shape is set to the real shape.
183 ScheduleRebuild(LinksetRoot); 158 ScheduleRebuild(LinksetRoot);
184 } 159 }
185 else
186 {
187 // The non-physical children can come back to life.
188 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
189
190 child.PhysBody.collisionType = CollisionType.LinksetChild;
191
192 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
193 PhysicsScene.PE.Activate(child.PhysBody, false);
194 ret = true;
195 }
196 return ret; 160 return ret;
197 } 161 }
198 162
@@ -200,13 +164,20 @@ public sealed class BSLinksetCompound : BSLinkset
200 // Called at taint-time. 164 // Called at taint-time.
201 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated) 165 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated)
202 { 166 {
167 if (!LinksetRoot.IsPhysicallyActive)
168 {
169 // No reason to do this physical stuff for static linksets.
170 DetailLog("{0},BSLinksetCompound.UpdateProperties,notPhysical", LinksetRoot.LocalID);
171 return;
172 }
173
203 // The user moving a child around requires the rebuilding of the linkset compound shape 174 // The user moving a child around requires the rebuilding of the linkset compound shape
204 // One problem is this happens when a border is crossed -- the simulator implementation 175 // One problem is this happens when a border is crossed -- the simulator implementation
205 // stores the position into the group which causes the move of the object 176 // stores the position into the group which causes the move of the object
206 // but it also means all the child positions get updated. 177 // but it also means all the child positions get updated.
207 // What would cause an unnecessary rebuild so we make sure the linkset is in a 178 // What would cause an unnecessary rebuild so we make sure the linkset is in a
208 // region before bothering to do a rebuild. 179 // region before bothering to do a rebuild.
209 if (!IsRoot(updated) && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) 180 if (!IsRoot(updated) && m_physicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
210 { 181 {
211 // If a child of the linkset is updating only the position or rotation, that can be done 182 // If a child of the linkset is updating only the position or rotation, that can be done
212 // without rebuilding the linkset. 183 // without rebuilding the linkset.
@@ -218,22 +189,22 @@ public sealed class BSLinksetCompound : BSLinkset
218 // and that is caused by us updating the object. 189 // and that is caused by us updating the object.
219 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) 190 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
220 { 191 {
221 // Find the physical instance of the child 192 // Find the physical instance of the child
222 if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) 193 if (LinksetRoot.PhysShape.HasPhysicalShape && m_physicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
223 { 194 {
224 // It is possible that the linkset is still under construction and the child is not yet 195 // It is possible that the linkset is still under construction and the child is not yet
225 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will 196 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
226 // build the whole thing with the new position or rotation. 197 // build the whole thing with the new position or rotation.
227 // The index must be checked because Bullet references the child array but does no validity 198 // The index must be checked because Bullet references the child array but does no validity
228 // checking of the child index passed. 199 // checking of the child index passed.
229 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); 200 int numLinksetChildren = m_physicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
230 if (updated.LinksetChildIndex < numLinksetChildren) 201 if (updated.LinksetChildIndex < numLinksetChildren)
231 { 202 {
232 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex); 203 BulletShape linksetChildShape = m_physicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex);
233 if (linksetChildShape.HasPhysicalShape) 204 if (linksetChildShape.HasPhysicalShape)
234 { 205 {
235 // Found the child shape within the compound shape 206 // Found the child shape within the compound shape
236 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex, 207 m_physicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex,
237 updated.RawPosition - LinksetRoot.RawPosition, 208 updated.RawPosition - LinksetRoot.RawPosition,
238 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), 209 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
239 true /* shouldRecalculateLocalAabb */); 210 true /* shouldRecalculateLocalAabb */);
@@ -275,75 +246,22 @@ public sealed class BSLinksetCompound : BSLinkset
275 } 246 }
276 247
277 // Routine called when rebuilding the body of some member of the linkset. 248 // Routine called when rebuilding the body of some member of the linkset.
278 // Since we don't keep in world relationships, do nothing unless it's a child changing. 249 // If one of the bodies is being changed, the linkset needs rebuilding.
250 // For instance, a linkset is built and then a mesh asset is read in and the mesh is recreated.
279 // Returns 'true' of something was actually removed and would need restoring 251 // Returns 'true' of something was actually removed and would need restoring
280 // Called at taint-time!! 252 // Called at taint-time!!
281 public override bool RemoveBodyDependencies(BSPrimLinkable child) 253 public override bool RemoveDependencies(BSPrimLinkable child)
282 { 254 {
283 bool ret = false; 255 bool ret = false;
284 256
285 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", 257 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
286 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child)); 258 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
287 259
288 if (!IsRoot(child)) 260 ScheduleRebuild(child);
289 {
290 // Because it is a convenient time, recompute child world position and rotation based on
291 // its position in the linkset.
292 RecomputeChildWorldPosition(child, true /* inTaintTime */);
293 child.LinksetInfo = null;
294 }
295
296 // Cannot schedule a refresh/rebuild here because this routine is called when
297 // the linkset is being rebuilt.
298 // InternalRefresh(LinksetRoot);
299 261
300 return ret; 262 return ret;
301 } 263 }
302 264
303 // When the linkset is built, the child shape is added to the compound shape relative to the
304 // root shape. The linkset then moves around but this does not move the actual child
305 // prim. The child prim's location must be recomputed based on the location of the root shape.
306 private void RecomputeChildWorldPosition(BSPrimLinkable child, bool inTaintTime)
307 {
308 // For the moment (20130201), disable this computation (converting the child physical addr back to
309 // a region address) until we have a good handle on center-of-mass offsets and what the physics
310 // engine moving a child actually means.
311 // The simulator keeps track of where children should be as the linkset moves. Setting
312 // the pos/rot here does not effect that knowledge as there is no good way for the
313 // physics engine to send the simulator an update for a child.
314
315 /*
316 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
317 if (lci != null)
318 {
319 if (inTaintTime)
320 {
321 OMV.Vector3 oldPos = child.RawPosition;
322 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
323 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
324 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
325 child.LocalID, oldPos, lci, child.RawPosition);
326 }
327 else
328 {
329 // TaintedObject is not used here so the raw position is set now and not at taint-time.
330 child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
331 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
332 }
333 }
334 else
335 {
336 // This happens when children have been added to the linkset but the linkset
337 // has not been constructed yet. So like, at taint time, adding children to a linkset
338 // and then changing properties of the children (makePhysical, for instance)
339 // but the post-print action of actually rebuilding the linkset has not yet happened.
340 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
341 // LogHeader, child.LocalID);
342 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
343 }
344 */
345 }
346
347 // ================================================================ 265 // ================================================================
348 266
349 // Add a new child to the linkset. 267 // Add a new child to the linkset.
@@ -376,7 +294,6 @@ public sealed class BSLinksetCompound : BSLinkset
376 child.LocalID, child.PhysBody.AddrString); 294 child.LocalID, child.PhysBody.AddrString);
377 295
378 // Cause the child's body to be rebuilt and thus restored to normal operation 296 // Cause the child's body to be rebuilt and thus restored to normal operation
379 RecomputeChildWorldPosition(child, false);
380 child.LinksetInfo = null; 297 child.LinksetInfo = null;
381 child.ForceBodyShapeRebuild(false); 298 child.ForceBodyShapeRebuild(false);
382 299
@@ -399,108 +316,105 @@ public sealed class BSLinksetCompound : BSLinkset
399 // Constraint linksets are rebuilt every time. 316 // Constraint linksets are rebuilt every time.
400 // Note that this works for rebuilding just the root after a linkset is taken apart. 317 // Note that this works for rebuilding just the root after a linkset is taken apart.
401 // Called at taint time!! 318 // Called at taint time!!
402 private bool disableCOM = true; // DEBUG DEBUG: disable until we get this debugged 319 private bool UseBulletSimRootOffsetHack = false; // Attempt to have Bullet track the coords of root compound shape
320 private bool disableCOM = true; // For basic linkset debugging, turn off the center-of-mass setting
403 private void RecomputeLinksetCompound() 321 private void RecomputeLinksetCompound()
404 { 322 {
405 try 323 try
406 { 324 {
407 // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
408 Rebuilding = true; 325 Rebuilding = true;
409 326
410 // Cause the root shape to be rebuilt as a compound object with just the root in it 327 // No matter what is being done, force the root prim's PhysBody and PhysShape to get set
411 LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */); 328 // to what they should be as if the root was not in a linkset.
329 // Not that bad since we only get into this routine if there are children in the linkset and
330 // something has been updated/changed.
331 LinksetRoot.ForceBodyShapeRebuild(true);
332
333 // There is no reason to build all this physical stuff for a non-physical linkset.
334 if (!LinksetRoot.IsPhysicallyActive)
335 {
336 // Clean up any old linkset shape and make sure the root shape is set to the root object.
337 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID);
338
339 return; // Note the 'finally' clause at the botton which will get executed.
340 }
341
342 // Get a new compound shape to build the linkset shape in.
343 BSShape linksetShape = BSShapeCompound.GetReference(m_physicsScene);
412 344
413 // The center of mass for the linkset is the geometric center of the group. 345 // The center of mass for the linkset is the geometric center of the group.
414 // Compute a displacement for each component so it is relative to the center-of-mass. 346 // Compute a displacement for each component so it is relative to the center-of-mass.
415 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass 347 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
416 OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition; 348 OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass();
417 if (!disableCOM) // DEBUG DEBUG
418 {
419 // Compute a center-of-mass in world coordinates.
420 centerOfMassW = ComputeLinksetCenterOfMass();
421 }
422 349
423 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 350 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
424 351
425 // 'centerDisplacement' is the value to subtract from children to give physical offset position 352 // 'centerDisplacement' is the value to subtract from children to give physical offset position
426 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation; 353 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
427 LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement); 354 if (UseBulletSimRootOffsetHack || disableCOM)
428 355 {
429 // This causes the physical position of the root prim to be offset to accomodate for the displacements 356 centerDisplacement = OMV.Vector3.Zero;
430 LinksetRoot.ForcePosition = LinksetRoot.RawPosition; 357 LinksetRoot.ClearDisplacement();
431 358 }
432 // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM 359 else
433 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */, 360 {
434 -centerDisplacement, 361 LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacement);
435 OMV.Quaternion.Identity, // LinksetRoot.RawOrientation, 362 }
436 false /* shouldRecalculateLocalAabb (is done later after linkset built) */); 363 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}",
437 364 LinksetRoot.LocalID, LinksetRoot.RawPosition, centerOfMassW, centerDisplacement);
438 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
439 LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement);
440
441 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
442 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
443 365
444 // Add a shape for each of the other children in the linkset 366 // Add the shapes of all the components of the linkset
445 int memberIndex = 1; 367 int memberIndex = 1;
446 ForEachMember(delegate(BSPrimLinkable cPrim) 368 ForEachMember(delegate(BSPrimLinkable cPrim)
447 { 369 {
448 if (IsRoot(cPrim)) 370 // Root shape is always index zero.
371 cPrim.LinksetChildIndex = IsRoot(cPrim) ? 0 : memberIndex;
372
373 // Get a reference to the shape of the child and add that shape to the linkset compound shape
374 BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim);
375 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
376 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
377 m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot);
378 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}",
379 LinksetRoot.LocalID, memberIndex, childShape, offsetPos, offsetRot);
380
381 // Since we are borrowing the shape of the child, disable the origional child body
382 if (!IsRoot(cPrim))
449 { 383 {
450 cPrim.LinksetChildIndex = 0; 384 m_physicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
385 m_physicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION);
386 // We don't want collisions from the old linkset children.
387 m_physicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
388 cPrim.PhysBody.collisionType = CollisionType.LinksetChild;
451 } 389 }
452 else
453 {
454 cPrim.LinksetChildIndex = memberIndex;
455 390
456 if (cPrim.PhysShape.isNativeShape) 391 memberIndex++;
457 {
458 // A native shape is turned into a hull collision shape because native
459 // shapes are not shared so we have to hullify it so it will be tracked
460 // and freed at the correct time. This also solves the scaling problem
461 // (native shapes scale but hull/meshes are assumed to not be).
462 // TODO: decide of the native shape can just be used in the compound shape.
463 // Use call to CreateGeomNonSpecial().
464 BulletShape saveShape = cPrim.PhysShape;
465 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
466 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
467 BulletShape newShape = cPrim.PhysShape;
468 cPrim.PhysShape = saveShape;
469
470 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
471 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
472 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
473 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
474 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
475 }
476 else
477 {
478 // For the shared shapes (meshes and hulls), just use the shape in the child.
479 // The reference count added here will be decremented when the compound shape
480 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
481 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
482 {
483 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
484 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
485 }
486 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
487 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
488 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
489 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
490 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
491 392
492 }
493 memberIndex++;
494 }
495 return false; // 'false' says to move onto the next child in the list 393 return false; // 'false' says to move onto the next child in the list
496 }); 394 });
497 395
396 // Replace the root shape with the built compound shape.
397 // Object removed and added to world to get collision cache rebuilt for new shape.
398 LinksetRoot.PhysShape.Dereference(m_physicsScene);
399 LinksetRoot.PhysShape = linksetShape;
400 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, LinksetRoot.PhysBody);
401 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo);
402 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody);
403 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}",
404 LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape);
405
498 // With all of the linkset packed into the root prim, it has the mass of everyone. 406 // With all of the linkset packed into the root prim, it has the mass of everyone.
499 LinksetMass = ComputeLinksetMass(); 407 LinksetMass = ComputeLinksetMass();
500 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); 408 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
501 409
502 // Enable the physical position updator to return the position and rotation of the root shape 410 if (UseBulletSimRootOffsetHack)
503 PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); 411 {
412 // Enable the physical position updator to return the position and rotation of the root shape.
413 // This enables a feature in the C++ code to return the world coordinates of the first shape in the
414 // compound shape. This eleviates the need to offset the returned physical position by the
415 // center-of-mass offset.
416 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
417 }
504 } 418 }
505 finally 419 finally
506 { 420 {
@@ -508,7 +422,7 @@ public sealed class BSLinksetCompound : BSLinkset
508 } 422 }
509 423
510 // See that the Aabb surrounds the new shape 424 // See that the Aabb surrounds the new shape
511 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); 425 m_physicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
512 } 426 }
513} 427}
514} \ No newline at end of file 428} \ No newline at end of file