/WhackAGarbage/Utilities/Physics/Collision/CollisionInfo.cs

# · C# · 299 lines · 187 code · 49 blank · 63 comment · 16 complexity · c0bd5c57200c99903ddf84e53b3154f5 MD5 · raw file

  1. #region Using Statements
  2. using Microsoft.Xna.Framework;
  3. using Utilities;
  4. #endregion
  5. namespace JigLibX.Collision
  6. {
  7. #region public struct CollDetectInfo
  8. /// <summary>
  9. /// Details about which parts of the skins are colliding.
  10. /// </summary>
  11. public struct CollDetectInfo
  12. {
  13. public int IndexPrim0; // index into skin0 primitive
  14. public int IndexPrim1; // index into skin1 primitive
  15. public CollisionSkin Skin0;
  16. public CollisionSkin Skin1;
  17. public CollDetectInfo(CollisionSkin skin0, CollisionSkin skin1, int indexPrim0, int indexPrim1)
  18. {
  19. this.IndexPrim0 = indexPrim0;
  20. this.IndexPrim1 = indexPrim1;
  21. this.Skin0 = skin0;
  22. this.Skin1 = skin1;
  23. }
  24. public static CollDetectInfo Empty
  25. {
  26. get { return new CollDetectInfo(null, null, 0, 0); }
  27. }
  28. }
  29. #endregion
  30. public struct SmallCollPointInfo
  31. {
  32. /// <summary>
  33. /// Estimated Penetration before the objects collide (can be -ve)
  34. /// </summary>
  35. public float InitialPenetration;
  36. /// <summary>
  37. /// Positions relative to body 0 (in world space)
  38. /// </summary>
  39. public Vector3 R0;
  40. /// <summary>
  41. /// positions relative to body 1 (if there is a body1)
  42. /// </summary>
  43. public Vector3 R1;
  44. public SmallCollPointInfo(ref Vector3 R0, ref Vector3 R1, float initialPenetration)
  45. {
  46. this.R0 = R0;
  47. this.R1 = R1;
  48. this.InitialPenetration = initialPenetration;
  49. }
  50. public SmallCollPointInfo(Vector3 R0, Vector3 R1, float initialPenetration)
  51. {
  52. this.R0 = R0;
  53. this.R1 = R1;
  54. this.InitialPenetration = initialPenetration;
  55. }
  56. }
  57. #region public class CollPointInfo
  58. public class CollPointInfo
  59. {
  60. public SmallCollPointInfo info;
  61. /// <summary>
  62. /// Estimated Penetration before the objects collide (can be -ve)
  63. /// </summary>
  64. public float InitialPenetration
  65. {
  66. get
  67. {
  68. return info.InitialPenetration;
  69. }
  70. }
  71. /// <summary>
  72. /// Positions relative to body 0 (in world space)
  73. /// </summary>
  74. public Vector3 R0
  75. {
  76. get
  77. {
  78. return info.R0;
  79. }
  80. }
  81. /// <summary>
  82. /// positions relative to body 1 (if there is a body1)
  83. /// </summary>
  84. public Vector3 R1
  85. {
  86. get
  87. {
  88. return info.R1;
  89. }
  90. }
  91. /// <summary>
  92. /// Used by physics to cache desired minimum separation velocity
  93. /// in the normal direction
  94. /// </summary>
  95. public float MinSeparationVel;
  96. /// <summary>
  97. /// Used by physics to cache value used in calculating impulse
  98. /// </summary>
  99. public float Denominator;
  100. /// <summary>
  101. /// Used by physics to accumulated the normal impulse
  102. /// </summary>
  103. public float AccumulatedNormalImpulse;
  104. /// <summary>
  105. /// Used by physics to accumulated the normal impulse
  106. /// </summary>
  107. public Vector3 AccumulatedFrictionImpulse;
  108. /// <summary>
  109. /// Used by physics to accumulated the normal impulse
  110. /// </summary>
  111. public float AccumulatedNormalImpulseAux;
  112. /// <summary>
  113. /// Used by physics to cache the world position (not really
  114. /// needed? pretty useful in debugging!)
  115. /// </summary>
  116. public Vector3 Position;
  117. public void Init(SmallCollPointInfo info)
  118. {
  119. this.info = info;
  120. this.Denominator = 0.0f;
  121. this.AccumulatedNormalImpulse = 0.0f;
  122. this.AccumulatedNormalImpulseAux = 0.0f;
  123. this.AccumulatedFrictionImpulse = Vector3.Zero;
  124. this.Position = Vector3.Zero;
  125. this.MinSeparationVel = 0.0f;
  126. }
  127. }
  128. #endregion
  129. /// <summary>
  130. /// Contains all the details about a collision between two skins,
  131. /// each of which may be associated with a tBody. Each collision
  132. /// can have a number of points associated with it
  133. /// </summary>
  134. public class CollisionInfo
  135. {
  136. public const int MaxCollisionPoints = 10;
  137. public MaterialPairProperties MatPairProperties;
  138. public CollDetectInfo SkinInfo;
  139. internal Vector3 dirToBody0; // hack
  140. private bool satisfied;
  141. public const int InitialCollisionInfoStack = 64;
  142. public const int InitialCollisionPointInfoStack = 4096;
  143. private static ArrayStack<CollisionInfo> freeInfos = new ArrayStack<CollisionInfo>(InitialCollisionInfoStack);
  144. private static ArrayStack<CollPointInfo> freePtInfos = new ArrayStack<CollPointInfo>(InitialCollisionPointInfoStack);
  145. private CollisionInfo() { }
  146. static CollisionInfo()
  147. {
  148. // prep our collision info free ArrayList
  149. for (int i = 0; i < InitialCollisionInfoStack; ++i)
  150. {
  151. freeInfos.Push(new CollisionInfo());
  152. }
  153. for (int i = 0; i < InitialCollisionPointInfoStack; ++i)
  154. {
  155. freePtInfos.Push(new CollPointInfo());
  156. }
  157. }
  158. #region Properties
  159. public bool Satisfied
  160. {
  161. get { return satisfied; }
  162. set { satisfied = value; }
  163. }
  164. public Vector3 DirToBody0
  165. {
  166. get { return dirToBody0; }
  167. set { dirToBody0 = value; }
  168. }
  169. public CollPointInfo[] PointInfo = new CollPointInfo[MaxCollisionPoints];
  170. public int NumCollPts = 0;
  171. #endregion
  172. private void Init(CollDetectInfo info, Vector3 dirToBody0, ArrayList<SmallCollPointInfo> pointInfos, int numPointInfos)
  173. {
  174. this.SkinInfo = info;
  175. this.dirToBody0 = dirToBody0;
  176. int ID0 = info.Skin0.GetMaterialID(info.IndexPrim0);
  177. int ID1 = info.Skin1.GetMaterialID(info.IndexPrim1);
  178. MaterialTable matTable = info.Skin0.CollisionSystem.MaterialTable;
  179. if (ID0 == (int)MaterialTable.MaterialID.UserDefined || (int)ID1 == (int)MaterialTable.MaterialID.UserDefined)
  180. {
  181. MaterialProperties prop0, prop1;
  182. if (ID0 == (int)MaterialTable.MaterialID.UserDefined)
  183. prop0 = info.Skin0.GetMaterialProperties(info.IndexPrim0);
  184. else
  185. prop0 = matTable.GetMaterialProperties(ID0);
  186. if (ID1 == (int)MaterialTable.MaterialID.UserDefined)
  187. prop1 = info.Skin1.GetMaterialProperties(info.IndexPrim1);
  188. else
  189. prop1 = matTable.GetMaterialProperties(ID1);
  190. MatPairProperties.Restitution = prop0.Elasticity * prop1.Elasticity;
  191. MatPairProperties.StaticFriction = prop0.StaticRoughness * prop1.StaticRoughness;
  192. MatPairProperties.DynamicFriction = prop0.DynamicRoughness * prop1.DynamicRoughness;
  193. }
  194. else
  195. {
  196. MatPairProperties = matTable.GetPairProperties(ID0, ID1);
  197. }
  198. numPointInfos = (numPointInfos > MaxCollisionPoints) ? MaxCollisionPoints : numPointInfos;
  199. NumCollPts = 0;
  200. for (int i = 0; i < numPointInfos; ++i)
  201. {
  202. if (freePtInfos.Count == 0)
  203. {
  204. freePtInfos.Push(new CollPointInfo());
  205. }
  206. this.PointInfo[NumCollPts] = freePtInfos.Pop();
  207. this.PointInfo[NumCollPts++].Init( pointInfos[i] );
  208. }
  209. }
  210. // public ArrayList<CollPointInfo>
  211. private void Destroy()
  212. {
  213. for (int i = 0; i < NumCollPts; ++i)
  214. {
  215. freePtInfos.Push( this.PointInfo[i] );
  216. }
  217. SkinInfo.Skin0 = null;
  218. SkinInfo.Skin1 = null;
  219. }
  220. /// <summary>
  221. /// CollisionInfos will be given out from a pool. If more than
  222. /// MaxCollisionPoints are passed in, the input positions will
  223. /// be silently truncated!
  224. /// </summary>
  225. /// <param name="info"></param>
  226. /// <param name="dirToBody0"></param>
  227. /// <param name="pointInfos"></param>
  228. /// <param name="numPointInfos"></param>
  229. /// <returns></returns>
  230. public static CollisionInfo GetCollisionInfo(CollDetectInfo info,
  231. Vector3 dirToBody0, ArrayList<SmallCollPointInfo> pointInfos, int numCollPts)
  232. {
  233. if (freeInfos.Count == 0)
  234. freeInfos.Push(new CollisionInfo());
  235. CollisionInfo collInfo = freeInfos.Pop();//[freeInfos.Count - 1];
  236. collInfo.Init(info, dirToBody0, pointInfos, numCollPts);
  237. //freeInfos.RemoveAt(freeInfos.Count - 1);
  238. return collInfo;
  239. }
  240. /// <summary>
  241. /// Return this info to the pool.
  242. /// </summary>
  243. /// <param name="info"></param>
  244. public static void FreeCollisionInfo(CollisionInfo info)
  245. {
  246. info.Destroy();
  247. freeInfos.Push(info);
  248. }
  249. }
  250. }