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.cs333
1 files changed, 333 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..253128b
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs
@@ -0,0 +1,333 @@
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 protected float m_mass;
101 public float LinksetMass
102 {
103 get
104 {
105 return m_mass;
106 }
107 }
108
109 public virtual bool LinksetIsColliding { get { return false; } }
110
111 public OMV.Vector3 CenterOfMass
112 {
113 get { return ComputeLinksetCenterOfMass(); }
114 }
115
116 public OMV.Vector3 GeometricCenter
117 {
118 get { return ComputeLinksetGeometricCenter(); }
119 }
120
121 protected BSLinkset(BSScene scene, BSPhysObject parent)
122 {
123 // A simple linkset of one (no children)
124 LinksetID = m_nextLinksetID++;
125 // We create LOTS of linksets.
126 if (m_nextLinksetID <= 0)
127 m_nextLinksetID = 1;
128 PhysicsScene = scene;
129 LinksetRoot = parent;
130 m_children = new HashSet<BSPhysObject>();
131 m_mass = parent.RawMass;
132 Rebuilding = false;
133 }
134
135 // Link to a linkset where the child knows the parent.
136 // Parent changing should not happen so do some sanity checking.
137 // We return the parent's linkset so the child can track its membership.
138 // Called at runtime.
139 public BSLinkset AddMeToLinkset(BSPhysObject child)
140 {
141 lock (m_linksetActivityLock)
142 {
143 // Don't add the root to its own linkset
144 if (!IsRoot(child))
145 AddChildToLinkset(child);
146 m_mass = ComputeLinksetMass();
147 }
148 return this;
149 }
150
151 // Remove a child from a linkset.
152 // Returns a new linkset for the child which is a linkset of one (just the
153 // orphened child).
154 // Called at runtime.
155 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
156 {
157 lock (m_linksetActivityLock)
158 {
159 if (IsRoot(child))
160 {
161 // Cannot remove the root from a linkset.
162 return this;
163 }
164 RemoveChildFromLinkset(child);
165 m_mass = ComputeLinksetMass();
166 }
167
168 // The child is down to a linkset of just itself
169 return BSLinkset.Factory(PhysicsScene, child);
170 }
171
172 // Return 'true' if the passed object is the root object of this linkset
173 public bool IsRoot(BSPhysObject requestor)
174 {
175 return (requestor.LocalID == LinksetRoot.LocalID);
176 }
177
178 public int NumberOfChildren { get { return m_children.Count; } }
179
180 // Return 'true' if this linkset has any children (more than the root member)
181 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
182
183 // Return 'true' if this child is in this linkset
184 public bool HasChild(BSPhysObject child)
185 {
186 bool ret = false;
187 lock (m_linksetActivityLock)
188 {
189 ret = m_children.Contains(child);
190 /* Safer version but the above should work
191 foreach (BSPhysObject bp in m_children)
192 {
193 if (child.LocalID == bp.LocalID)
194 {
195 ret = true;
196 break;
197 }
198 }
199 */
200 }
201 return ret;
202 }
203
204 // Perform an action on each member of the linkset including root prim.
205 // Depends on the action on whether this should be done at taint time.
206 public delegate bool ForEachMemberAction(BSPhysObject obj);
207 public virtual bool ForEachMember(ForEachMemberAction action)
208 {
209 bool ret = false;
210 lock (m_linksetActivityLock)
211 {
212 action(LinksetRoot);
213 foreach (BSPhysObject po in m_children)
214 {
215 if (action(po))
216 break;
217 }
218 }
219 return ret;
220 }
221
222 // I am the root of a linkset and a new child is being added
223 // Called while LinkActivity is locked.
224 protected abstract void AddChildToLinkset(BSPhysObject child);
225
226 // I am the root of a linkset and one of my children is being removed.
227 // Safe to call even if the child is not really in my linkset.
228 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
229
230 // When physical properties are changed the linkset needs to recalculate
231 // its internal properties.
232 // May be called at runtime or taint-time.
233 public abstract void Refresh(BSPhysObject requestor);
234
235 // Flag denoting the linkset is in the process of being rebuilt.
236 // Used to know not the schedule a rebuild in the middle of a rebuild.
237 protected bool Rebuilding { get; set; }
238
239 // The object is going dynamic (physical). Do any setup necessary
240 // for a dynamic linkset.
241 // Only the state of the passed object can be modified. The rest of the linkset
242 // has not yet been fully constructed.
243 // Return 'true' if any properties updated on the passed object.
244 // Called at taint-time!
245 public abstract bool MakeDynamic(BSPhysObject child);
246
247 // The object is going static (non-physical). Do any setup necessary
248 // for a static linkset.
249 // Return 'true' if any properties updated on the passed object.
250 // Called at taint-time!
251 public abstract bool MakeStatic(BSPhysObject child);
252
253 // Called when a parameter update comes from the physics engine for any object
254 // of the linkset is received.
255 // Passed flag is update came from physics engine (true) or the user (false).
256 // Called at taint-time!!
257 public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate);
258
259 // Routine used when rebuilding the body of the root of the linkset
260 // Destroy all the constraints have have been made to root.
261 // This is called when the root body is changing.
262 // Returns 'true' of something was actually removed and would need restoring
263 // Called at taint-time!!
264 public abstract bool RemoveBodyDependencies(BSPrim child);
265
266 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
267 // this routine will restore the removed constraints.
268 // Called at taint-time!!
269 public abstract void RestoreBodyDependencies(BSPrim child);
270
271 // ================================================================
272 protected virtual float ComputeLinksetMass()
273 {
274 float mass = LinksetRoot.RawMass;
275 if (HasAnyChildren)
276 {
277 lock (m_linksetActivityLock)
278 {
279 foreach (BSPhysObject bp in m_children)
280 {
281 mass += bp.RawMass;
282 }
283 }
284 }
285 return mass;
286 }
287
288 protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
289 {
290 OMV.Vector3 com;
291 lock (m_linksetActivityLock)
292 {
293 com = LinksetRoot.Position * LinksetRoot.RawMass;
294 float totalMass = LinksetRoot.RawMass;
295
296 foreach (BSPhysObject bp in m_children)
297 {
298 com += bp.Position * bp.RawMass;
299 totalMass += bp.RawMass;
300 }
301 if (totalMass != 0f)
302 com /= totalMass;
303 }
304
305 return com;
306 }
307
308 protected virtual OMV.Vector3 ComputeLinksetGeometricCenter()
309 {
310 OMV.Vector3 com;
311 lock (m_linksetActivityLock)
312 {
313 com = LinksetRoot.Position;
314
315 foreach (BSPhysObject bp in m_children)
316 {
317 com += bp.Position * bp.RawMass;
318 }
319 com /= (m_children.Count + 1);
320 }
321
322 return com;
323 }
324
325 // Invoke the detailed logger and output something if it's enabled.
326 protected void DetailLog(string msg, params Object[] args)
327 {
328 if (PhysicsScene.PhysicsLogging.Enabled)
329 PhysicsScene.DetailLog(msg, args);
330 }
331
332}
333}