aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs
diff options
context:
space:
mode:
authorRobert Adams2015-09-08 04:54:16 -0700
committerRobert Adams2015-09-08 04:54:16 -0700
commite5367d822be9b05e74c859afe2d2956a3e95aa33 (patch)
treee904050a30715df587aa527d7f313755177726a7 /OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs
parentadd lost admin_reset_land method (diff)
parentDeleted access control spec from [LoginService] section of standalone config.... (diff)
downloadopensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.zip
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.gz
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.bz2
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.xz
Merge of ubitworkvarnew with opensim/master as of 20150905.
This integrates the OpenSim refactoring to make physics, etc into modules. AVN physics hasn't been moved to new location. Does not compile yet. Merge branch 'osmaster' into mbworknew1
Diffstat (limited to 'OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs')
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs477
1 files changed, 477 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs b/OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs
new file mode 100755
index 0000000..953ddee
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs
@@ -0,0 +1,477 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32
33using OMV = OpenMetaverse;
34
35namespace OpenSim.Region.PhysicsModule.BulletS
36{
37
38public sealed class BSLinksetCompound : BSLinkset
39{
40#pragma warning disable 414
41 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
42#pragma warning restore 414
43
44 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
45 : base(scene, parent)
46 {
47 LinksetImpl = LinksetImplementation.Compound;
48 }
49
50 // ================================================================
51 // Changing the physical property of the linkset only needs to change the root
52 public override void SetPhysicalFriction(float friction)
53 {
54 if (LinksetRoot.PhysBody.HasPhysicalBody)
55 m_physicsScene.PE.SetFriction(LinksetRoot.PhysBody, friction);
56 }
57 public override void SetPhysicalRestitution(float restitution)
58 {
59 if (LinksetRoot.PhysBody.HasPhysicalBody)
60 m_physicsScene.PE.SetRestitution(LinksetRoot.PhysBody, restitution);
61 }
62 public override void SetPhysicalGravity(OMV.Vector3 gravity)
63 {
64 if (LinksetRoot.PhysBody.HasPhysicalBody)
65 m_physicsScene.PE.SetGravity(LinksetRoot.PhysBody, gravity);
66 }
67 public override void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
68 {
69 OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(LinksetRoot.PhysShape.physShapeInfo, linksetMass);
70 LinksetRoot.Inertia = inertia * inertiaFactor;
71 m_physicsScene.PE.SetMassProps(LinksetRoot.PhysBody, linksetMass, LinksetRoot.Inertia);
72 m_physicsScene.PE.UpdateInertiaTensor(LinksetRoot.PhysBody);
73 }
74 public override void SetPhysicalCollisionFlags(CollisionFlags collFlags)
75 {
76 if (LinksetRoot.PhysBody.HasPhysicalBody)
77 m_physicsScene.PE.SetCollisionFlags(LinksetRoot.PhysBody, collFlags);
78 }
79 public override void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
80 {
81 if (LinksetRoot.PhysBody.HasPhysicalBody)
82 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, collFlags);
83 }
84 public override void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
85 {
86 if (LinksetRoot.PhysBody.HasPhysicalBody)
87 m_physicsScene.PE.RemoveFromCollisionFlags(LinksetRoot.PhysBody, collFlags);
88 }
89 // ================================================================
90
91 // When physical properties are changed the linkset needs to recalculate
92 // its internal properties.
93 public override void Refresh(BSPrimLinkable requestor)
94 {
95 // Something changed so do the rebuilding thing
96 ScheduleRebuild(requestor);
97 base.Refresh(requestor);
98 }
99
100 // Schedule a refresh to happen after all the other taint processing.
101 private void ScheduleRebuild(BSPrimLinkable requestor)
102 {
103 // When rebuilding, it is possible to set properties that would normally require a rebuild.
104 // If already rebuilding, don't request another rebuild.
105 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
106 lock (m_linksetActivityLock)
107 {
108 if (!RebuildScheduled && !Rebuilding && HasAnyChildren)
109 {
110 InternalScheduleRebuild(requestor);
111 }
112 }
113 }
114
115 // Must be called with m_linksetActivityLock or race conditions will haunt you.
116 private void InternalScheduleRebuild(BSPrimLinkable requestor)
117 {
118 DetailLog("{0},BSLinksetCompound.InternalScheduleRebuild,,rebuilding={1},hasChildren={2}",
119 requestor.LocalID, Rebuilding, HasAnyChildren);
120 RebuildScheduled = true;
121 m_physicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
122 {
123 if (HasAnyChildren)
124 {
125 if (this.AllPartsComplete)
126 {
127 RecomputeLinksetCompound();
128 }
129 else
130 {
131 DetailLog("{0},BSLinksetCompound.InternalScheduleRebuild,,rescheduling because not all children complete",
132 requestor.LocalID);
133 InternalScheduleRebuild(requestor);
134 }
135 }
136 RebuildScheduled = false;
137 });
138 }
139
140 // The object is going dynamic (physical). Do any setup necessary for a dynamic linkset.
141 // Only the state of the passed object can be modified. The rest of the linkset
142 // has not yet been fully constructed.
143 // Return 'true' if any properties updated on the passed object.
144 // Called at taint-time!
145 public override bool MakeDynamic(BSPrimLinkable child)
146 {
147 bool ret = false;
148 DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
149 if (IsRoot(child))
150 {
151 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
152 Refresh(LinksetRoot);
153 }
154 return ret;
155 }
156
157 // The object is going static (non-physical). We do not do anything for static linksets.
158 // Return 'true' if any properties updated on the passed object.
159 // Called at taint-time!
160 public override bool MakeStatic(BSPrimLinkable child)
161 {
162 bool ret = false;
163
164 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
165 child.ClearDisplacement();
166 if (IsRoot(child))
167 {
168 // Schedule a rebuild to verify that the root shape is set to the real shape.
169 Refresh(LinksetRoot);
170 }
171 return ret;
172 }
173
174 // 'physicalUpdate' is true if these changes came directly from the physics engine. Don't need to rebuild then.
175 // Called at taint-time.
176 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated)
177 {
178 if (!LinksetRoot.IsPhysicallyActive)
179 {
180 // No reason to do this physical stuff for static linksets.
181 DetailLog("{0},BSLinksetCompound.UpdateProperties,notPhysical", LinksetRoot.LocalID);
182 return;
183 }
184
185 // The user moving a child around requires the rebuilding of the linkset compound shape
186 // One problem is this happens when a border is crossed -- the simulator implementation
187 // stores the position into the group which causes the move of the object
188 // but it also means all the child positions get updated.
189 // What would cause an unnecessary rebuild so we make sure the linkset is in a
190 // region before bothering to do a rebuild.
191 if (!IsRoot(updated) && m_physicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
192 {
193 // If a child of the linkset is updating only the position or rotation, that can be done
194 // without rebuilding the linkset.
195 // If a handle for the child can be fetch, we update the child here. If a rebuild was
196 // scheduled by someone else, the rebuild will just replace this setting.
197
198 bool updatedChild = false;
199 // Anything other than updating position or orientation usually means a physical update
200 // and that is caused by us updating the object.
201 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
202 {
203 // Find the physical instance of the child
204 if (!RebuildScheduled // if rebuilding, let the rebuild do it
205 && !LinksetRoot.IsIncomplete // if waiting for assets or whatever, don't change
206 && LinksetRoot.PhysShape.HasPhysicalShape // there must be a physical shape assigned
207 && m_physicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
208 {
209 // It is possible that the linkset is still under construction and the child is not yet
210 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
211 // build the whole thing with the new position or rotation.
212 // The index must be checked because Bullet references the child array but does no validity
213 // checking of the child index passed.
214 int numLinksetChildren = m_physicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
215 if (updated.LinksetChildIndex < numLinksetChildren)
216 {
217 BulletShape linksetChildShape = m_physicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex);
218 if (linksetChildShape.HasPhysicalShape)
219 {
220 // Found the child shape within the compound shape
221 m_physicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex,
222 updated.RawPosition - LinksetRoot.RawPosition,
223 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
224 true /* shouldRecalculateLocalAabb */);
225 updatedChild = true;
226 DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},pos={2},rot={3}",
227 updated.LocalID, whichUpdated, updated.RawPosition, updated.RawOrientation);
228 }
229 else // DEBUG DEBUG
230 { // DEBUG DEBUG
231 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
232 updated.LocalID, linksetChildShape);
233 } // DEBUG DEBUG
234 }
235 else // DEBUG DEBUG
236 { // DEBUG DEBUG
237 // the child is not yet in the compound shape. This is non-fatal.
238 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
239 updated.LocalID, numLinksetChildren, updated.LinksetChildIndex);
240 } // DEBUG DEBUG
241 }
242 else // DEBUG DEBUG
243 { // DEBUG DEBUG
244 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
245 } // DEBUG DEBUG
246
247 if (!updatedChild)
248 {
249 // If couldn't do the individual child, the linkset needs a rebuild to incorporate the new child info.
250 // Note: there are several ways through this code that will not update the child if
251 // the linkset is being rebuilt. In this case, scheduling a rebuild is a NOOP since
252 // there will already be a rebuild scheduled.
253 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
254 updated.LocalID, whichUpdated);
255 Refresh(updated);
256 }
257 }
258 }
259 }
260
261 // Routine called when rebuilding the body of some member of the linkset.
262 // If one of the bodies is being changed, the linkset needs rebuilding.
263 // For instance, a linkset is built and then a mesh asset is read in and the mesh is recreated.
264 // Returns 'true' of something was actually removed and would need restoring
265 // Called at taint-time!!
266 public override bool RemoveDependencies(BSPrimLinkable child)
267 {
268 bool ret = false;
269
270 DetailLog("{0},BSLinksetCompound.RemoveDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
271 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
272
273 Refresh(child);
274
275 return ret;
276 }
277
278 // ================================================================
279
280 // Add a new child to the linkset.
281 // Called while LinkActivity is locked.
282 protected override void AddChildToLinkset(BSPrimLinkable child)
283 {
284 if (!HasChild(child))
285 {
286 m_children.Add(child, new BSLinkInfo(child));
287
288 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
289
290 // Rebuild the compound shape with the new child shape included
291 Refresh(child);
292 }
293 return;
294 }
295
296 // Remove the specified child from the linkset.
297 // Safe to call even if the child is not really in the linkset.
298 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
299 {
300 child.ClearDisplacement();
301
302 if (m_children.Remove(child))
303 {
304 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
305 child.LocalID,
306 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString,
307 child.LocalID, child.PhysBody.AddrString);
308
309 // Cause the child's body to be rebuilt and thus restored to normal operation
310 child.ForceBodyShapeRebuild(inTaintTime);
311
312 if (!HasAnyChildren)
313 {
314 // The linkset is now empty. The root needs rebuilding.
315 LinksetRoot.ForceBodyShapeRebuild(inTaintTime);
316 }
317 else
318 {
319 // Rebuild the compound shape with the child removed
320 Refresh(LinksetRoot);
321 }
322 }
323 return;
324 }
325
326 // Called before the simulation step to make sure the compound based linkset
327 // is all initialized.
328 // Constraint linksets are rebuilt every time.
329 // Note that this works for rebuilding just the root after a linkset is taken apart.
330 // Called at taint time!!
331 private bool UseBulletSimRootOffsetHack = false; // Attempt to have Bullet track the coords of root compound shape
332 private void RecomputeLinksetCompound()
333 {
334 try
335 {
336 Rebuilding = true;
337
338 // No matter what is being done, force the root prim's PhysBody and PhysShape to get set
339 // to what they should be as if the root was not in a linkset.
340 // Not that bad since we only get into this routine if there are children in the linkset and
341 // something has been updated/changed.
342 // Have to do the rebuild before checking for physical because this might be a linkset
343 // being destructed and going non-physical.
344 LinksetRoot.ForceBodyShapeRebuild(true);
345
346 // There is no reason to build all this physical stuff for a non-physical or empty linkset.
347 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
348 {
349 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
350 return; // Note the 'finally' clause at the botton which will get executed.
351 }
352
353 // Get a new compound shape to build the linkset shape in.
354 BSShape linksetShape = BSShapeCompound.GetReference(m_physicsScene);
355
356 // Compute a displacement for each component so it is relative to the center-of-mass.
357 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
358 OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass();
359
360 OMV.Quaternion invRootOrientation = OMV.Quaternion.Normalize(OMV.Quaternion.Inverse(LinksetRoot.RawOrientation));
361 OMV.Vector3 origRootPosition = LinksetRoot.RawPosition;
362
363 // 'centerDisplacementV' is the vehicle relative distance from the simulator root position to the center-of-mass
364 OMV.Vector3 centerDisplacementV = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
365 if (UseBulletSimRootOffsetHack || !BSParam.LinksetOffsetCenterOfMass)
366 {
367 // Zero everything if center-of-mass displacement is not being done.
368 centerDisplacementV = OMV.Vector3.Zero;
369 LinksetRoot.ClearDisplacement();
370 }
371 else
372 {
373 // The actual center-of-mass could have been set by the user.
374 centerDisplacementV = LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacementV);
375 }
376
377 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}",
378 LinksetRoot.LocalID, origRootPosition, centerOfMassW, centerDisplacementV);
379
380 // Add the shapes of all the components of the linkset
381 int memberIndex = 1;
382 ForEachMember((cPrim) =>
383 {
384 if (IsRoot(cPrim))
385 {
386 // Root shape is always index zero.
387 cPrim.LinksetChildIndex = 0;
388 }
389 else
390 {
391 cPrim.LinksetChildIndex = memberIndex;
392 memberIndex++;
393 }
394
395 // Get a reference to the shape of the child for adding of that shape to the linkset compound shape
396 BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim);
397
398 // Offset the child shape from the center-of-mass and rotate it to root relative.
399 OMV.Vector3 offsetPos = (cPrim.RawPosition - origRootPosition) * invRootOrientation - centerDisplacementV;
400 OMV.Quaternion offsetRot = OMV.Quaternion.Normalize(cPrim.RawOrientation) * invRootOrientation;
401
402 // Add the child shape to the compound shape being built
403 if (childShape.physShapeInfo.HasPhysicalShape)
404 {
405 m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot);
406 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}",
407 LinksetRoot.LocalID, cPrim.LinksetChildIndex, childShape, offsetPos, offsetRot);
408
409 // Since we are borrowing the shape of the child, disable the origional child body
410 if (!IsRoot(cPrim))
411 {
412 m_physicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
413 m_physicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION);
414 // We don't want collisions from the old linkset children.
415 m_physicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
416 cPrim.PhysBody.collisionType = CollisionType.LinksetChild;
417 }
418 }
419 else
420 {
421 // The linkset must be in an intermediate state where all the children have not yet
422 // been constructed. This sometimes happens on startup when everything is getting
423 // built and some shapes have to wait for assets to be read in.
424 // Just skip this linkset for the moment and cause the shape to be rebuilt next tick.
425 // One problem might be that the shape is broken somehow and it never becomes completely
426 // available. This might cause the rebuild to happen over and over.
427 InternalScheduleRebuild(LinksetRoot);
428 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChildWithNoShape,indx={1},cShape={2},offPos={3},offRot={4}",
429 LinksetRoot.LocalID, cPrim.LinksetChildIndex, childShape, offsetPos, offsetRot);
430 // Output an annoying warning. It should only happen once but if it keeps coming out,
431 // the user knows there is something wrong and will report it.
432 m_physicsScene.Logger.WarnFormat("{0} Linkset rebuild warning. If this happens more than one or two times, please report in Mantis 7191", LogHeader);
433 m_physicsScene.Logger.WarnFormat("{0} pName={1}, childIdx={2}, shape={3}",
434 LogHeader, LinksetRoot.Name, cPrim.LinksetChildIndex, childShape);
435
436 // This causes the loop to bail on building the rest of this linkset.
437 // The rebuild operation will fix it up next tick or declare the object unbuildable.
438 return true;
439 }
440
441 return false; // 'false' says to move onto the next child in the list
442 });
443
444 // Replace the root shape with the built compound shape.
445 // Object removed and added to world to get collision cache rebuilt for new shape.
446 LinksetRoot.PhysShape.Dereference(m_physicsScene);
447 LinksetRoot.PhysShape = linksetShape;
448 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, LinksetRoot.PhysBody);
449 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo);
450 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody);
451 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}",
452 LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape);
453
454 // With all of the linkset packed into the root prim, it has the mass of everyone.
455 LinksetMass = ComputeLinksetMass();
456 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
457
458 if (UseBulletSimRootOffsetHack)
459 {
460 // Enable the physical position updator to return the position and rotation of the root shape.
461 // This enables a feature in the C++ code to return the world coordinates of the first shape in the
462 // compound shape. This aleviates the need to offset the returned physical position by the
463 // center-of-mass offset.
464 // TODO: either debug this feature or remove it.
465 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
466 }
467 }
468 finally
469 {
470 Rebuilding = false;
471 }
472
473 // See that the Aabb surrounds the new shape
474 m_physicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
475 }
476}
477} \ No newline at end of file