aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs329
1 files changed, 329 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs
new file mode 100644
index 0000000..845a113
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs
@@ -0,0 +1,329 @@
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.BulletSNPlugin
34{
35
36// A BSPrim can get individual information about its linkedness attached
37// to it through an instance of a subclass of LinksetInfo.
38// Each type of linkset will define the information needed for its type.
39public abstract class BSLinksetInfo
40{
41 public virtual void Clear() { }
42}
43
44public abstract class BSLinkset
45{
46 // private static string LogHeader = "[BULLETSIM LINKSET]";
47
48 public enum LinksetImplementation
49 {
50 Constraint = 0, // linkset tied together with constraints
51 Compound = 1, // linkset tied together as a compound object
52 Manual = 2 // linkset tied together manually (code moves all the pieces)
53 }
54 // Create the correct type of linkset for this child
55 public static BSLinkset Factory(BSScene physScene, BSPhysObject parent)
56 {
57 BSLinkset ret = null;
58
59 switch ((int)BSParam.LinksetImplementation)
60 {
61 case (int)LinksetImplementation.Constraint:
62 ret = new BSLinksetConstraints(physScene, parent);
63 break;
64 case (int)LinksetImplementation.Compound:
65 ret = new BSLinksetCompound(physScene, parent);
66 break;
67 case (int)LinksetImplementation.Manual:
68 // ret = new BSLinksetManual(physScene, parent);
69 break;
70 default:
71 ret = new BSLinksetCompound(physScene, parent);
72 break;
73 }
74 return ret;
75 }
76
77 public BSPhysObject LinksetRoot { get; protected set; }
78
79 public BSScene PhysicsScene { get; private set; }
80
81 static int m_nextLinksetID = 1;
82 public int LinksetID { get; private set; }
83
84 // The children under the root in this linkset.
85 protected HashSet<BSPhysObject> m_children;
86
87 // We lock the diddling of linkset classes to prevent any badness.
88 // This locks the modification of the instances of this class. Changes
89 // to the physical representation is done via the tainting mechenism.
90 protected object m_linksetActivityLock = new Object();
91
92 // Some linksets have a preferred physical shape.
93 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
94 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
95 {
96 return BSPhysicsShapeType.SHAPE_UNKNOWN;
97 }
98
99 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
100 public float LinksetMass { get; protected set; }
101
102 public virtual bool LinksetIsColliding { get { return false; } }
103
104 public OMV.Vector3 CenterOfMass
105 {
106 get { return ComputeLinksetCenterOfMass(); }
107 }
108
109 public OMV.Vector3 GeometricCenter
110 {
111 get { return ComputeLinksetGeometricCenter(); }
112 }
113
114 protected BSLinkset(BSScene scene, BSPhysObject parent)
115 {
116 // A simple linkset of one (no children)
117 LinksetID = m_nextLinksetID++;
118 // We create LOTS of linksets.
119 if (m_nextLinksetID <= 0)
120 m_nextLinksetID = 1;
121 PhysicsScene = scene;
122 LinksetRoot = parent;
123 m_children = new HashSet<BSPhysObject>();
124 LinksetMass = parent.RawMass;
125 Rebuilding = false;
126 }
127
128 // Link to a linkset where the child knows the parent.
129 // Parent changing should not happen so do some sanity checking.
130 // We return the parent's linkset so the child can track its membership.
131 // Called at runtime.
132 public BSLinkset AddMeToLinkset(BSPhysObject child)
133 {
134 lock (m_linksetActivityLock)
135 {
136 // Don't add the root to its own linkset
137 if (!IsRoot(child))
138 AddChildToLinkset(child);
139 LinksetMass = ComputeLinksetMass();
140 }
141 return this;
142 }
143
144 // Remove a child from a linkset.
145 // Returns a new linkset for the child which is a linkset of one (just the
146 // orphened child).
147 // Called at runtime.
148 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
149 {
150 lock (m_linksetActivityLock)
151 {
152 if (IsRoot(child))
153 {
154 // Cannot remove the root from a linkset.
155 return this;
156 }
157 RemoveChildFromLinkset(child);
158 LinksetMass = ComputeLinksetMass();
159 }
160
161 // The child is down to a linkset of just itself
162 return BSLinkset.Factory(PhysicsScene, child);
163 }
164
165 // Return 'true' if the passed object is the root object of this linkset
166 public bool IsRoot(BSPhysObject requestor)
167 {
168 return (requestor.LocalID == LinksetRoot.LocalID);
169 }
170
171 public int NumberOfChildren { get { return m_children.Count; } }
172
173 // Return 'true' if this linkset has any children (more than the root member)
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175
176 // Return 'true' if this child is in this linkset
177 public bool HasChild(BSPhysObject child)
178 {
179 bool ret = false;
180 lock (m_linksetActivityLock)
181 {
182 ret = m_children.Contains(child);
183 /* Safer version but the above should work
184 foreach (BSPhysObject bp in m_children)
185 {
186 if (child.LocalID == bp.LocalID)
187 {
188 ret = true;
189 break;
190 }
191 }
192 */
193 }
194 return ret;
195 }
196
197 // Perform an action on each member of the linkset including root prim.
198 // Depends on the action on whether this should be done at taint time.
199 public delegate bool ForEachMemberAction(BSPhysObject obj);
200 public virtual bool ForEachMember(ForEachMemberAction action)
201 {
202 bool ret = false;
203 lock (m_linksetActivityLock)
204 {
205 action(LinksetRoot);
206 foreach (BSPhysObject po in m_children)
207 {
208 if (action(po))
209 break;
210 }
211 }
212 return ret;
213 }
214
215 // I am the root of a linkset and a new child is being added
216 // Called while LinkActivity is locked.
217 protected abstract void AddChildToLinkset(BSPhysObject child);
218
219 // I am the root of a linkset and one of my children is being removed.
220 // Safe to call even if the child is not really in my linkset.
221 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
222
223 // When physical properties are changed the linkset needs to recalculate
224 // its internal properties.
225 // May be called at runtime or taint-time.
226 public virtual void Refresh(BSPhysObject requestor)
227 {
228 LinksetMass = ComputeLinksetMass();
229 }
230
231 // Flag denoting the linkset is in the process of being rebuilt.
232 // Used to know not the schedule a rebuild in the middle of a rebuild.
233 protected bool Rebuilding { get; set; }
234
235 // The object is going dynamic (physical). Do any setup necessary
236 // for a dynamic linkset.
237 // Only the state of the passed object can be modified. The rest of the linkset
238 // has not yet been fully constructed.
239 // Return 'true' if any properties updated on the passed object.
240 // Called at taint-time!
241 public abstract bool MakeDynamic(BSPhysObject child);
242
243 // The object is going static (non-physical). Do any setup necessary
244 // for a static linkset.
245 // Return 'true' if any properties updated on the passed object.
246 // Called at taint-time!
247 public abstract bool MakeStatic(BSPhysObject child);
248
249 // Called when a parameter update comes from the physics engine for any object
250 // of the linkset is received.
251 // Passed flag is update came from physics engine (true) or the user (false).
252 // Called at taint-time!!
253 public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate);
254
255 // Routine used when rebuilding the body of the root of the linkset
256 // Destroy all the constraints have have been made to root.
257 // This is called when the root body is changing.
258 // Returns 'true' of something was actually removed and would need restoring
259 // Called at taint-time!!
260 public abstract bool RemoveBodyDependencies(BSPrim child);
261
262 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
263 // this routine will restore the removed constraints.
264 // Called at taint-time!!
265 public abstract void RestoreBodyDependencies(BSPrim child);
266
267 // ================================================================
268 protected virtual float ComputeLinksetMass()
269 {
270 float mass = LinksetRoot.RawMass;
271 if (HasAnyChildren)
272 {
273 lock (m_linksetActivityLock)
274 {
275 foreach (BSPhysObject bp in m_children)
276 {
277 mass += bp.RawMass;
278 }
279 }
280 }
281 return mass;
282 }
283
284 protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
285 {
286 OMV.Vector3 com;
287 lock (m_linksetActivityLock)
288 {
289 com = LinksetRoot.Position * LinksetRoot.RawMass;
290 float totalMass = LinksetRoot.RawMass;
291
292 foreach (BSPhysObject bp in m_children)
293 {
294 com += bp.Position * bp.RawMass;
295 totalMass += bp.RawMass;
296 }
297 if (totalMass != 0f)
298 com /= totalMass;
299 }
300
301 return com;
302 }
303
304 protected virtual OMV.Vector3 ComputeLinksetGeometricCenter()
305 {
306 OMV.Vector3 com;
307 lock (m_linksetActivityLock)
308 {
309 com = LinksetRoot.Position;
310
311 foreach (BSPhysObject bp in m_children)
312 {
313 com += bp.Position * bp.RawMass;
314 }
315 com /= (m_children.Count + 1);
316 }
317
318 return com;
319 }
320
321 // Invoke the detailed logger and output something if it's enabled.
322 protected void DetailLog(string msg, params Object[] args)
323 {
324 if (PhysicsScene.PhysicsLogging.Enabled)
325 PhysicsScene.DetailLog(msg, args);
326 }
327
328}
329}