aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs
diff options
context:
space:
mode:
authorteravus2012-12-23 15:21:25 -0500
committerteravus2012-12-23 15:21:25 -0500
commit92e4f9f412046f8f7926c99c9e56c3a8b6b2edbf (patch)
treeeabcbb758a7512222e84cb51b51b6822cdbf561b /OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs
parentRevert "Whitespace change to trigger bot" (diff)
downloadopensim-SC-92e4f9f412046f8f7926c99c9e56c3a8b6b2edbf.zip
opensim-SC-92e4f9f412046f8f7926c99c9e56c3a8b6b2edbf.tar.gz
opensim-SC-92e4f9f412046f8f7926c99c9e56c3a8b6b2edbf.tar.bz2
opensim-SC-92e4f9f412046f8f7926c99c9e56c3a8b6b2edbf.tar.xz
* Initial commit of BulletSimN (BulletSNPlugin). Purely C# implementation of BulletSim. This is designed to be /as close as possible/ to the BulletSim plugin while still being entirely in the managed space to make keeping it up to date easy as possible (no thinking work). This implementation is /slower/ then the c++ version just because it's fully managed, so it's not appropriate for huge sims, but it will run small ones OK. At the moment, it supports all known features of BulletSim. Think of it like.. POS but everything works. To use this plugin, set the physics plugin to BulletSimN.
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}