BSLinkset.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Text;
  30. using OMV = OpenMetaverse;
  31. namespace OpenSim.Region.Physics.BulletSPlugin
  32. {
  33. public abstract class BSLinkset
  34. {
  35. // private static string LogHeader = "[BULLETSIM LINKSET]";
  36. // Create the correct type of linkset for this child
  37. public static BSLinkset Factory(BSScene physScene, BSPhysObject parent)
  38. {
  39. BSLinkset ret = null;
  40. /*
  41. if (parent.IsPhysical)
  42. ret = new BSLinksetConstraints(physScene, parent);
  43. else
  44. ret = new BSLinksetManual(physScene, parent);
  45. */
  46. // at the moment, there is only one
  47. ret = new BSLinksetConstraints(physScene, parent);
  48. return ret;
  49. }
  50. public BSPhysObject LinksetRoot { get; protected set; }
  51. public BSScene PhysicsScene { get; private set; }
  52. static int m_nextLinksetID = 1;
  53. public int LinksetID { get; private set; }
  54. // The children under the root in this linkset.
  55. // There are two lists of children: the current children at runtime
  56. // and the children at taint-time. For instance, if you delink a
  57. // child from the linkset, the child is removed from m_children
  58. // but the constraint won't be removed until taint time.
  59. // Two lists lets this track the 'current' children and
  60. // the physical 'taint' children separately.
  61. // After taint processing and before the simulation step, these
  62. // two lists must be the same.
  63. protected HashSet<BSPhysObject> m_children;
  64. protected HashSet<BSPhysObject> m_taintChildren;
  65. // We lock the diddling of linkset classes to prevent any badness.
  66. // This locks the modification of the instances of this class. Changes
  67. // to the physical representation is done via the tainting mechenism.
  68. protected object m_linksetActivityLock = new Object();
  69. // We keep the prim's mass in the linkset structure since it could be dependent on other prims
  70. protected float m_mass;
  71. public float LinksetMass
  72. {
  73. get
  74. {
  75. m_mass = ComputeLinksetMass();
  76. return m_mass;
  77. }
  78. }
  79. public virtual bool LinksetIsColliding { get { return false; } }
  80. public OMV.Vector3 CenterOfMass
  81. {
  82. get { return ComputeLinksetCenterOfMass(); }
  83. }
  84. public OMV.Vector3 GeometricCenter
  85. {
  86. get { return ComputeLinksetGeometricCenter(); }
  87. }
  88. protected void Initialize(BSScene scene, BSPhysObject parent)
  89. {
  90. // A simple linkset of one (no children)
  91. LinksetID = m_nextLinksetID++;
  92. // We create LOTS of linksets.
  93. if (m_nextLinksetID <= 0)
  94. m_nextLinksetID = 1;
  95. PhysicsScene = scene;
  96. LinksetRoot = parent;
  97. m_children = new HashSet<BSPhysObject>();
  98. m_taintChildren = new HashSet<BSPhysObject>();
  99. m_mass = parent.MassRaw;
  100. }
  101. // Link to a linkset where the child knows the parent.
  102. // Parent changing should not happen so do some sanity checking.
  103. // We return the parent's linkset so the child can track its membership.
  104. // Called at runtime.
  105. public BSLinkset AddMeToLinkset(BSPhysObject child)
  106. {
  107. lock (m_linksetActivityLock)
  108. {
  109. // Don't add the root to its own linkset
  110. if (!IsRoot(child))
  111. AddChildToLinkset(child);
  112. }
  113. return this;
  114. }
  115. // Remove a child from a linkset.
  116. // Returns a new linkset for the child which is a linkset of one (just the
  117. // orphened child).
  118. // Called at runtime.
  119. public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
  120. {
  121. lock (m_linksetActivityLock)
  122. {
  123. if (IsRoot(child))
  124. {
  125. // Cannot remove the root from a linkset.
  126. return this;
  127. }
  128. RemoveChildFromLinkset(child);
  129. }
  130. // The child is down to a linkset of just itself
  131. return BSLinkset.Factory(PhysicsScene, child);
  132. }
  133. // Return 'true' if the passed object is the root object of this linkset
  134. public bool IsRoot(BSPhysObject requestor)
  135. {
  136. return (requestor.LocalID == LinksetRoot.LocalID);
  137. }
  138. public int NumberOfChildren { get { return m_children.Count; } }
  139. // Return 'true' if this linkset has any children (more than the root member)
  140. public bool HasAnyChildren { get { return (m_children.Count > 0); } }
  141. // Return 'true' if this child is in this linkset
  142. public bool HasChild(BSPhysObject child)
  143. {
  144. bool ret = false;
  145. lock (m_linksetActivityLock)
  146. {
  147. if (m_children.Contains(child))
  148. ret = true;
  149. /*
  150. foreach (BSPhysObject bp in m_children)
  151. {
  152. if (child.LocalID == bp.LocalID)
  153. {
  154. ret = true;
  155. break;
  156. }
  157. }
  158. */
  159. }
  160. return ret;
  161. }
  162. // When physical properties are changed the linkset needs to recalculate
  163. // its internal properties.
  164. // May be called at runtime or taint-time (just pass the appropriate flag).
  165. public abstract void Refresh(BSPhysObject requestor, bool inTaintTime);
  166. // The object is going dynamic (physical). Do any setup necessary
  167. // for a dynamic linkset.
  168. // Only the state of the passed object can be modified. The rest of the linkset
  169. // has not yet been fully constructed.
  170. // Return 'true' if any properties updated on the passed object.
  171. // Called at taint-time!
  172. public abstract bool MakeDynamic(BSPhysObject child);
  173. // The object is going static (non-physical). Do any setup necessary
  174. // for a static linkset.
  175. // Return 'true' if any properties updated on the passed object.
  176. // Called at taint-time!
  177. public abstract bool MakeStatic(BSPhysObject child);
  178. // Called when a parameter update comes from the physics engine for any object
  179. // of the linkset is received.
  180. // Called at taint-time!!
  181. public abstract void UpdateProperties(BSPhysObject physObject);
  182. // Routine used when rebuilding the body of the root of the linkset
  183. // Destroy all the constraints have have been made to root.
  184. // This is called when the root body is changing.
  185. // Returns 'true' of something was actually removed and would need restoring
  186. // Called at taint-time!!
  187. public abstract bool RemoveBodyDependencies(BSPrim child);
  188. // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
  189. // this routine will restore the removed constraints.
  190. // Called at taint-time!!
  191. public abstract void RestoreBodyDependencies(BSPrim child);
  192. // ================================================================
  193. // Below this point is internal magic
  194. protected virtual float ComputeLinksetMass()
  195. {
  196. float mass;
  197. lock (m_linksetActivityLock)
  198. {
  199. mass = LinksetRoot.MassRaw;
  200. foreach (BSPhysObject bp in m_taintChildren)
  201. {
  202. mass += bp.MassRaw;
  203. }
  204. }
  205. return mass;
  206. }
  207. protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
  208. {
  209. OMV.Vector3 com;
  210. lock (m_linksetActivityLock)
  211. {
  212. com = LinksetRoot.Position * LinksetRoot.MassRaw;
  213. float totalMass = LinksetRoot.MassRaw;
  214. foreach (BSPhysObject bp in m_taintChildren)
  215. {
  216. com += bp.Position * bp.MassRaw;
  217. totalMass += bp.MassRaw;
  218. }
  219. if (totalMass != 0f)
  220. com /= totalMass;
  221. }
  222. return com;
  223. }
  224. protected virtual OMV.Vector3 ComputeLinksetGeometricCenter()
  225. {
  226. OMV.Vector3 com;
  227. lock (m_linksetActivityLock)
  228. {
  229. com = LinksetRoot.Position;
  230. foreach (BSPhysObject bp in m_taintChildren)
  231. {
  232. com += bp.Position * bp.MassRaw;
  233. }
  234. com /= (m_taintChildren.Count + 1);
  235. }
  236. return com;
  237. }
  238. // I am the root of a linkset and a new child is being added
  239. // Called while LinkActivity is locked.
  240. protected abstract void AddChildToLinkset(BSPhysObject child);
  241. // Forcefully removing a child from a linkset.
  242. // This is not being called by the child so we have to make sure the child doesn't think
  243. // it's still connected to the linkset.
  244. // Normal OpenSimulator operation will never do this because other SceneObjectPart information
  245. // also has to be updated (like pointer to prim's parent).
  246. protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild);
  247. // I am the root of a linkset and one of my children is being removed.
  248. // Safe to call even if the child is not really in my linkset.
  249. protected abstract void RemoveChildFromLinkset(BSPhysObject child);
  250. // Invoke the detailed logger and output something if it's enabled.
  251. protected void DetailLog(string msg, params Object[] args)
  252. {
  253. if (PhysicsScene.PhysicsLogging.Enabled)
  254. PhysicsScene.DetailLog(msg, args);
  255. }
  256. }
  257. }