aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/BulletS/BSLinkset.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules/BulletS/BSLinkset.cs')
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSLinkset.cs503
1 files changed, 503 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSLinkset.cs b/OpenSim/Region/PhysicsModules/BulletS/BSLinkset.cs
new file mode 100755
index 0000000..87eba33
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSLinkset.cs
@@ -0,0 +1,503 @@
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{
35
36public abstract class BSLinkset
37{
38 // private static string LogHeader = "[BULLETSIM LINKSET]";
39
40 public enum LinksetImplementation
41 {
42 Constraint = 0, // linkset tied together with constraints
43 Compound = 1, // linkset tied together as a compound object
44 Manual = 2 // linkset tied together manually (code moves all the pieces)
45 }
46 // Create the correct type of linkset for this child
47 public static BSLinkset Factory(BSScene physScene, BSPrimLinkable parent)
48 {
49 BSLinkset ret = null;
50
51 switch (parent.LinksetType)
52 {
53 case LinksetImplementation.Constraint:
54 ret = new BSLinksetConstraints(physScene, parent);
55 break;
56 case LinksetImplementation.Compound:
57 ret = new BSLinksetCompound(physScene, parent);
58 break;
59 case LinksetImplementation.Manual:
60 // ret = new BSLinksetManual(physScene, parent);
61 break;
62 default:
63 ret = new BSLinksetCompound(physScene, parent);
64 break;
65 }
66 if (ret == null)
67 {
68 physScene.Logger.ErrorFormat("[BULLETSIM LINKSET] Factory could not create linkset. Parent name={1}, ID={2}", parent.Name, parent.LocalID);
69 }
70 return ret;
71 }
72
73 public class BSLinkInfo
74 {
75 public BSPrimLinkable member;
76 public BSLinkInfo(BSPrimLinkable pMember)
77 {
78 member = pMember;
79 }
80 public virtual void ResetLink() { }
81 public virtual void SetLinkParameters(BSConstraint constrain) { }
82 // Returns 'true' if physical property updates from the child should be reported to the simulator
83 public virtual bool ShouldUpdateChildProperties() { return false; }
84 }
85
86 public LinksetImplementation LinksetImpl { get; protected set; }
87
88 public BSPrimLinkable LinksetRoot { get; protected set; }
89
90 protected BSScene m_physicsScene { get; private set; }
91
92 static int m_nextLinksetID = 1;
93 public int LinksetID { get; private set; }
94
95 // The children under the root in this linkset.
96 // protected HashSet<BSPrimLinkable> m_children;
97 protected Dictionary<BSPrimLinkable, BSLinkInfo> m_children;
98
99 // We lock the diddling of linkset classes to prevent any badness.
100 // This locks the modification of the instances of this class. Changes
101 // to the physical representation is done via the tainting mechenism.
102 protected object m_linksetActivityLock = new Object();
103
104 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
105 public float LinksetMass { get; protected set; }
106
107 public virtual bool LinksetIsColliding { get { return false; } }
108
109 public OMV.Vector3 CenterOfMass
110 {
111 get { return ComputeLinksetCenterOfMass(); }
112 }
113
114 public OMV.Vector3 GeometricCenter
115 {
116 get { return ComputeLinksetGeometricCenter(); }
117 }
118
119 protected BSLinkset(BSScene scene, BSPrimLinkable parent)
120 {
121 // A simple linkset of one (no children)
122 LinksetID = m_nextLinksetID++;
123 // We create LOTS of linksets.
124 if (m_nextLinksetID <= 0)
125 m_nextLinksetID = 1;
126 m_physicsScene = scene;
127 LinksetRoot = parent;
128 m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>();
129 LinksetMass = parent.RawMass;
130 Rebuilding = false;
131 RebuildScheduled = false;
132
133 parent.ClearDisplacement();
134 }
135
136 // Link to a linkset where the child knows the parent.
137 // Parent changing should not happen so do some sanity checking.
138 // We return the parent's linkset so the child can track its membership.
139 // Called at runtime.
140 public BSLinkset AddMeToLinkset(BSPrimLinkable child)
141 {
142 lock (m_linksetActivityLock)
143 {
144 // Don't add the root to its own linkset
145 if (!IsRoot(child))
146 AddChildToLinkset(child);
147 LinksetMass = ComputeLinksetMass();
148 }
149 return this;
150 }
151
152 // Remove a child from a linkset.
153 // Returns a new linkset for the child which is a linkset of one (just the
154 // orphened child).
155 // Called at runtime.
156 public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child, bool inTaintTime)
157 {
158 lock (m_linksetActivityLock)
159 {
160 if (IsRoot(child))
161 {
162 // Cannot remove the root from a linkset.
163 return this;
164 }
165 RemoveChildFromLinkset(child, inTaintTime);
166 LinksetMass = ComputeLinksetMass();
167 }
168
169 // The child is down to a linkset of just itself
170 return BSLinkset.Factory(m_physicsScene, child);
171 }
172
173 // Return 'true' if the passed object is the root object of this linkset
174 public bool IsRoot(BSPrimLinkable requestor)
175 {
176 return (requestor.LocalID == LinksetRoot.LocalID);
177 }
178
179 public int NumberOfChildren { get { return m_children.Count; } }
180
181 // Return 'true' if this linkset has any children (more than the root member)
182 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
183
184 // Return 'true' if this child is in this linkset
185 public bool HasChild(BSPrimLinkable child)
186 {
187 bool ret = false;
188 lock (m_linksetActivityLock)
189 {
190 ret = m_children.ContainsKey(child);
191 }
192 return ret;
193 }
194
195 // Perform an action on each member of the linkset including root prim.
196 // Depends on the action on whether this should be done at taint time.
197 public delegate bool ForEachMemberAction(BSPrimLinkable obj);
198 public virtual bool ForEachMember(ForEachMemberAction action)
199 {
200 bool ret = false;
201 lock (m_linksetActivityLock)
202 {
203 action(LinksetRoot);
204 foreach (BSPrimLinkable po in m_children.Keys)
205 {
206 if (action(po))
207 break;
208 }
209 }
210 return ret;
211 }
212
213 public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
214 {
215 bool ret = false;
216 BSLinkInfo found = null;
217 lock (m_linksetActivityLock)
218 {
219 ret = m_children.TryGetValue(child, out found);
220 }
221 foundInfo = found;
222 return ret;
223 }
224 // Perform an action on each member of the linkset including root prim.
225 // Depends on the action on whether this should be done at taint time.
226 public delegate bool ForEachLinkInfoAction(BSLinkInfo obj);
227 public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action)
228 {
229 bool ret = false;
230 lock (m_linksetActivityLock)
231 {
232 foreach (BSLinkInfo po in m_children.Values)
233 {
234 if (action(po))
235 break;
236 }
237 }
238 return ret;
239 }
240
241 // Check the type of the link and return 'true' if the link is flexible and the
242 // updates from the child should be sent to the simulator so things change.
243 public virtual bool ShouldReportPropertyUpdates(BSPrimLinkable child)
244 {
245 bool ret = false;
246
247 BSLinkInfo linkInfo;
248 if (m_children.TryGetValue(child, out linkInfo))
249 {
250 ret = linkInfo.ShouldUpdateChildProperties();
251 }
252
253 return ret;
254 }
255
256 // Called after a simulation step to post a collision with this object.
257 // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have
258 // anything to add for the collision and it should be passed through normal processing.
259 // Default processing for a linkset.
260 public virtual bool HandleCollide(uint collidingWith, BSPhysObject collidee,
261 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
262 {
263 bool ret = false;
264
265 // prims in the same linkset cannot collide with each other
266 BSPrimLinkable convCollidee = collidee as BSPrimLinkable;
267 if (convCollidee != null && (LinksetID == convCollidee.Linkset.LinksetID))
268 {
269 // By returning 'true', we tell the caller the collision has been 'handled' so it won't
270 // do anything about this collision and thus, effectivily, ignoring the collision.
271 ret = true;
272 }
273 else
274 {
275 // Not a collision between members of the linkset. Must be a real collision.
276 // So the linkset root can know if there is a collision anywhere in the linkset.
277 LinksetRoot.SomeCollisionSimulationStep = m_physicsScene.SimulationStep;
278 }
279
280 return ret;
281 }
282
283 // I am the root of a linkset and a new child is being added
284 // Called while LinkActivity is locked.
285 protected abstract void AddChildToLinkset(BSPrimLinkable child);
286
287 // I am the root of a linkset and one of my children is being removed.
288 // Safe to call even if the child is not really in my linkset.
289 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime);
290
291 // When physical properties are changed the linkset needs to recalculate
292 // its internal properties.
293 // May be called at runtime or taint-time.
294 public virtual void Refresh(BSPrimLinkable requestor)
295 {
296 LinksetMass = ComputeLinksetMass();
297 }
298
299 // Flag denoting the linkset is in the process of being rebuilt.
300 // Used to know not the schedule a rebuild in the middle of a rebuild.
301 // Because of potential update calls that could want to schedule another rebuild.
302 protected bool Rebuilding { get; set; }
303
304 // Flag saying a linkset rebuild has been scheduled.
305 // This is turned on when the rebuild is requested and turned off when
306 // the rebuild is complete. Used to limit modifications to the
307 // linkset parameters while the linkset is in an intermediate state.
308 // Protected by a "lock(m_linsetActivityLock)" on the BSLinkset object
309 public bool RebuildScheduled { get; protected set; }
310
311 // The object is going dynamic (physical). Do any setup necessary
312 // for a dynamic linkset.
313 // Only the state of the passed object can be modified. The rest of the linkset
314 // has not yet been fully constructed.
315 // Return 'true' if any properties updated on the passed object.
316 // Called at taint-time!
317 public abstract bool MakeDynamic(BSPrimLinkable child);
318
319 public virtual bool AllPartsComplete
320 {
321 get {
322 bool ret = true;
323 this.ForEachMember((member) =>
324 {
325 if ((!member.IsInitialized) || member.IsIncomplete || member.PrimAssetState == BSPhysObject.PrimAssetCondition.Waiting)
326 {
327 ret = false;
328 return true; // exit loop
329 }
330 return false; // continue loop
331 });
332 return ret;
333 }
334 }
335
336 // The object is going static (non-physical). Do any setup necessary
337 // for a static linkset.
338 // Return 'true' if any properties updated on the passed object.
339 // Called at taint-time!
340 public abstract bool MakeStatic(BSPrimLinkable child);
341
342 // Called when a parameter update comes from the physics engine for any object
343 // of the linkset is received.
344 // Passed flag is update came from physics engine (true) or the user (false).
345 // Called at taint-time!!
346 public abstract void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable physObject);
347
348 // Routine used when rebuilding the body of the root of the linkset
349 // Destroy all the constraints have have been made to root.
350 // This is called when the root body is changing.
351 // Returns 'true' of something was actually removed and would need restoring
352 // Called at taint-time!!
353 public abstract bool RemoveDependencies(BSPrimLinkable child);
354
355 // ================================================================
356 // Some physical setting happen to all members of the linkset
357 public virtual void SetPhysicalFriction(float friction)
358 {
359 ForEachMember((member) =>
360 {
361 if (member.PhysBody.HasPhysicalBody)
362 m_physicsScene.PE.SetFriction(member.PhysBody, friction);
363 return false; // 'false' says to continue looping
364 }
365 );
366 }
367 public virtual void SetPhysicalRestitution(float restitution)
368 {
369 ForEachMember((member) =>
370 {
371 if (member.PhysBody.HasPhysicalBody)
372 m_physicsScene.PE.SetRestitution(member.PhysBody, restitution);
373 return false; // 'false' says to continue looping
374 }
375 );
376 }
377 public virtual void SetPhysicalGravity(OMV.Vector3 gravity)
378 {
379 ForEachMember((member) =>
380 {
381 if (member.PhysBody.HasPhysicalBody)
382 m_physicsScene.PE.SetGravity(member.PhysBody, gravity);
383 return false; // 'false' says to continue looping
384 }
385 );
386 }
387 public virtual void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
388 {
389 ForEachMember((member) =>
390 {
391 if (member.PhysBody.HasPhysicalBody)
392 {
393 OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, linksetMass);
394 member.Inertia = inertia * inertiaFactor;
395 m_physicsScene.PE.SetMassProps(member.PhysBody, linksetMass, member.Inertia);
396 m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody);
397 DetailLog("{0},BSLinkset.ComputeAndSetLocalInertia,m.mass={1}, inertia={2}", member.LocalID, linksetMass, member.Inertia);
398
399 }
400 return false; // 'false' says to continue looping
401 }
402 );
403 }
404 public virtual void SetPhysicalCollisionFlags(CollisionFlags collFlags)
405 {
406 ForEachMember((member) =>
407 {
408 if (member.PhysBody.HasPhysicalBody)
409 m_physicsScene.PE.SetCollisionFlags(member.PhysBody, collFlags);
410 return false; // 'false' says to continue looping
411 }
412 );
413 }
414 public virtual void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
415 {
416 ForEachMember((member) =>
417 {
418 if (member.PhysBody.HasPhysicalBody)
419 m_physicsScene.PE.AddToCollisionFlags(member.PhysBody, collFlags);
420 return false; // 'false' says to continue looping
421 }
422 );
423 }
424 public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
425 {
426 ForEachMember((member) =>
427 {
428 if (member.PhysBody.HasPhysicalBody)
429 m_physicsScene.PE.RemoveFromCollisionFlags(member.PhysBody, collFlags);
430 return false; // 'false' says to continue looping
431 }
432 );
433 }
434 // ================================================================
435 protected virtual float ComputeLinksetMass()
436 {
437 float mass = LinksetRoot.RawMass;
438 if (HasAnyChildren)
439 {
440 lock (m_linksetActivityLock)
441 {
442 foreach (BSPrimLinkable bp in m_children.Keys)
443 {
444 mass += bp.RawMass;
445 }
446 }
447 }
448 return mass;
449 }
450
451 // Computes linkset's center of mass in world coordinates.
452 protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
453 {
454 OMV.Vector3 com;
455 lock (m_linksetActivityLock)
456 {
457 com = LinksetRoot.Position * LinksetRoot.RawMass;
458 float totalMass = LinksetRoot.RawMass;
459
460 foreach (BSPrimLinkable bp in m_children.Keys)
461 {
462 com += bp.Position * bp.RawMass;
463 totalMass += bp.RawMass;
464 }
465 if (totalMass != 0f)
466 com /= totalMass;
467 }
468
469 return com;
470 }
471
472 protected virtual OMV.Vector3 ComputeLinksetGeometricCenter()
473 {
474 OMV.Vector3 com;
475 lock (m_linksetActivityLock)
476 {
477 com = LinksetRoot.Position;
478
479 foreach (BSPrimLinkable bp in m_children.Keys)
480 {
481 com += bp.Position;
482 }
483 com /= (m_children.Count + 1);
484 }
485
486 return com;
487 }
488
489 #region Extension
490 public virtual object Extension(string pFunct, params object[] pParams)
491 {
492 return null;
493 }
494 #endregion // Extension
495
496 // Invoke the detailed logger and output something if it's enabled.
497 protected void DetailLog(string msg, params Object[] args)
498 {
499 if (m_physicsScene.PhysicsLogging.Enabled)
500 m_physicsScene.DetailLog(msg, args);
501 }
502}
503}