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.cs275
1 files changed, 275 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
new file mode 100755
index 0000000..b9c2cf9
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -0,0 +1,275 @@
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 OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public sealed class BSLinksetCompound : BSLinkset
36{
37 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
38
39 public BSLinksetCompound(BSScene scene, BSPhysObject parent)
40 {
41 base.Initialize(scene, parent);
42 }
43
44 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 {
47 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren)
49 {
50 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
51 }
52 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
53 return ret;
54 }
55
56 // When physical properties are changed the linkset needs to recalculate
57 // its internal properties.
58 // This is queued in the 'post taint' queue so the
59 // refresh will happen once after all the other taints are applied.
60 public override void Refresh(BSPhysObject requestor)
61 {
62 // External request for Refresh (from BSPrim) is not necessary
63 // InternalRefresh(requestor);
64 }
65
66 private void InternalRefresh(BSPhysObject requestor)
67 {
68 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
69 // Queue to happen after all the other taint processing
70 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
71 {
72 if (IsRoot(requestor) && HasAnyChildren)
73 RecomputeLinksetCompound();
74 });
75 }
76
77 // The object is going dynamic (physical). Do any setup necessary
78 // for a dynamic linkset.
79 // Only the state of the passed object can be modified. The rest of the linkset
80 // has not yet been fully constructed.
81 // Return 'true' if any properties updated on the passed object.
82 // Called at taint-time!
83 public override bool MakeDynamic(BSPhysObject child)
84 {
85 bool ret = false;
86 DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
87 if (!IsRoot(child))
88 {
89 // Physical children are removed from the world as the shape ofthe root compound
90 // shape takes over.
91 BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
92 BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
93 ret = true;
94 }
95 return ret;
96 }
97
98 // The object is going static (non-physical). Do any setup necessary for a static linkset.
99 // Return 'true' if any properties updated on the passed object.
100 // This doesn't normally happen -- OpenSim removes the objects from the physical
101 // world if it is a static linkset.
102 // Called at taint-time!
103 public override bool MakeStatic(BSPhysObject child)
104 {
105 bool ret = false;
106 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
107 if (!IsRoot(child))
108 {
109 // The non-physical children can come back to life.
110 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
111 // Don't force activation so setting of DISABLE_SIMULATION can stay.
112 BulletSimAPI.Activate2(child.PhysBody.ptr, false);
113 ret = true;
114 }
115 return ret;
116 }
117
118 // Called at taint-time!!
119 public override void UpdateProperties(BSPhysObject updated)
120 {
121 // Nothing to do for constraints on property updates
122 }
123
124 // The children move around in relationship to the root.
125 // Just grab the current values of wherever it is right now.
126 public override OMV.Vector3 Position(BSPhysObject member)
127 {
128 return BulletSimAPI.GetPosition2(member.PhysBody.ptr);
129 }
130
131 public override OMV.Quaternion Orientation(BSPhysObject member)
132 {
133 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr);
134 }
135
136 // Routine called when rebuilding the body of some member of the linkset.
137 // Since we don't keep in world relationships, do nothing unless it's a child changing.
138 // Returns 'true' of something was actually removed and would need restoring
139 // Called at taint-time!!
140 public override bool RemoveBodyDependencies(BSPrim child)
141 {
142 bool ret = false;
143
144 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
145 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child));
146
147 if (!IsRoot(child))
148 {
149 // Cause the current shape to be freed and the new one to be built.
150 InternalRefresh(LinksetRoot);
151 ret = true;
152 }
153
154 return ret;
155 }
156
157 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
158 // this routine will restore the removed constraints.
159 // Called at taint-time!!
160 public override void RestoreBodyDependencies(BSPrim child)
161 {
162 // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints.
163 }
164
165 // ================================================================
166
167 // Add a new child to the linkset.
168 // Called while LinkActivity is locked.
169 protected override void AddChildToLinkset(BSPhysObject child)
170 {
171 if (!HasChild(child))
172 {
173 m_children.Add(child);
174
175 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
176
177 // Cause constraints and assorted properties to be recomputed before the next simulation step.
178 InternalRefresh(LinksetRoot);
179 }
180 return;
181 }
182
183 // Remove the specified child from the linkset.
184 // Safe to call even if the child is not really in my linkset.
185 protected override void RemoveChildFromLinkset(BSPhysObject child)
186 {
187 if (m_children.Remove(child))
188 {
189 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
190 child.LocalID,
191 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"),
192 child.LocalID, child.PhysBody.ptr.ToString("X"));
193
194 // Cause the child's body to be rebuilt and thus restored to normal operation
195 child.ForceBodyShapeRebuild(false);
196
197 if (!HasAnyChildren)
198 {
199 // The linkset is now empty. The root needs rebuilding.
200 LinksetRoot.ForceBodyShapeRebuild(false);
201 }
202 else
203 {
204 // Schedule a rebuild of the linkset before the next simulation tick.
205 InternalRefresh(LinksetRoot);
206 }
207 }
208 return;
209 }
210
211 // Called before the simulation step to make sure the compound based linkset
212 // is all initialized.
213 // Constraint linksets are rebuilt every time.
214 // Note that this works for rebuilding just the root after a linkset is taken apart.
215 // Called at taint time!!
216 private void RecomputeLinksetCompound()
217 {
218 // Cause the root shape to be rebuilt as a compound object with just the root in it
219 LinksetRoot.ForceBodyShapeRebuild(true);
220
221 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
222 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
223
224 // Add a shape for each of the other children in the linkset
225 ForEachMember(delegate(BSPhysObject cPrim)
226 {
227 if (!IsRoot(cPrim))
228 {
229 // Each child position and rotation is given relative to the root.
230 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
231 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
232 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
233
234 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
235 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot);
236
237 if (cPrim.PhysShape.isNativeShape)
238 {
239 // Native shapes are not shared so we need to create a new one.
240 // A mesh or hull is created because scale is not available on a native shape.
241 // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?)
242 BulletShape saveShape = cPrim.PhysShape;
243 cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape
244 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
245 BulletShape newShape = cPrim.PhysShape;
246 cPrim.PhysShape = saveShape;
247 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot);
248 }
249 else
250 {
251 // For the shared shapes (meshes and hulls), just use the shape in the child.
252 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
253 {
254 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
255 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
256 }
257 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot);
258 }
259 }
260 return false; // 'false' says to move onto the next child in the list
261 });
262
263 // With all of the linkset packed into the root prim, it has the mass of everyone.
264 float linksetMass = LinksetMass;
265 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
266
267 BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr);
268
269 // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets.
270 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
271 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
272
273 }
274}
275} \ No newline at end of file