diff options
author | Robert Adams | 2015-09-08 04:54:16 -0700 |
---|---|---|
committer | Robert Adams | 2015-09-08 04:54:16 -0700 |
commit | e5367d822be9b05e74c859afe2d2956a3e95aa33 (patch) | |
tree | e904050a30715df587aa527d7f313755177726a7 /OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs | |
parent | add lost admin_reset_land method (diff) | |
parent | Deleted access control spec from [LoginService] section of standalone config.... (diff) | |
download | opensim-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-x | OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs | 477 |
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 | */ | ||
27 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | |||
31 | using OpenSim.Framework; | ||
32 | |||
33 | using OMV = OpenMetaverse; | ||
34 | |||
35 | namespace OpenSim.Region.PhysicsModule.BulletS | ||
36 | { | ||
37 | |||
38 | public 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 | ||