Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <MatMath.h>
  5. #include <Vector3d.h>
  6. #include <Matrix.h>
  7. bool tmpHelSphereIntersectLine(Vector3d pos, Vector3d lastPos,
  8. Vector3d center, vec_t radius)
  9. {
  10. Vector3d seg, segToCenter, delta;
  11. vec_t s, dSquare;
  12. seg = pos - lastPos;
  13. segToCenter = center - lastPos;
  14. s = seg * segToCenter;
  15. if (s >= 1.0f || s <= 0.0f)
  16. return false;
  17. seg.normalize();
  18. seg = seg * s;
  19. seg = seg + lastPos;
  20. delta = seg - center;
  21. dSquare = delta * delta;
  22. if (radius >= dSquare)
  23. return true;
  24. else
  25. return false;
  26. }
  27. vec_t helIntersectionOfAbstractSpheres(vec3_t centerA, vec_t radiusA,
  28. vec3_t centerB, vec_t radiusB)
  29. {
  30. Vector3d a = Vector3d(centerA);
  31. Vector3d b = Vector3d(centerB);
  32. Vector3d d = a - b;
  33. vec_t dist, minDist;
  34. dist = Vector3d::dot(d, d);
  35. minDist = radiusA + radiusB;
  36. return (dist <= minDist * minDist);
  37. }
  38. inline vec_t square(vec_t a)
  39. {
  40. return a * a;
  41. }
  42. // Returns number of intersections and intersection position(s)
  43. // Got algorithm from http://astronomy.swin.edu.au/~pbourke/geometry/
  44. int helIntersectionOfAbstractSphereAndLine(vec3_t center, vec_t radius,
  45. vec3_t posA, vec3_t posB,
  46. vec3_t intersectionA,
  47. vec3_t intersectionB)
  48. {
  49. // float x , y , z;
  50. vec_t a, b, c, mu, i ;
  51. a = (square(posB[0] - posA[0]) +
  52. square(posB[1] - posA[1]) +
  53. square(posB[2] - posA[2]));
  54. b = (2 * ((posB[0] - posA[0]) * (posA[0] - center[0]) +
  55. (posB[1] - posA[1]) * (posA[1] - center[1]) +
  56. (posB[2] - posA[2]) * (posA[2] - center[2])));
  57. c = (square(center[0]) + square(center[1]) +
  58. square(center[2]) + square(posA[0]) +
  59. square(posA[1]) + square(posA[2]) -
  60. 2 * (center[0]*posA[0] + center[1]*posA[1] + center[2]*posA[2]) -
  61. square(radius));
  62. i = b * b - 4 * a * c;
  63. if (i < 0.0)
  64. {
  65. // No intersection
  66. return 0;
  67. }
  68. else if (i == 0.0)
  69. {
  70. // One intersection
  71. mu = -b/(2*a) ;
  72. intersectionA[1] = posA[0] + mu*(posB[0]-posA[0]);
  73. intersectionA[2] = posA[1] + mu*(posB[1]-posA[1]);
  74. intersectionA[3] = posA[2] + mu*(posB[2]-posA[2]);
  75. return 1;
  76. }
  77. else
  78. {
  79. // Two intersections
  80. // First intersection
  81. mu = (-b + sqrt( square(b) - 4*a*c)) / (2*a);
  82. intersectionA[1] = posA[0] + mu*(posB[0]-posA[0]);
  83. intersectionA[2] = posA[1] + mu*(posB[1]-posA[1]);
  84. intersectionA[3] = posA[2] + mu*(posB[2]-posA[2]);
  85. // Second intersection
  86. mu = (-b - sqrt(square(b) - 4*a*c)) / (2*a);
  87. intersectionB[0] = posA[0] + mu*(posB[0]-posA[0]);
  88. intersectionB[1] = posA[1] + mu*(posB[1]-posA[1]);
  89. intersectionB[2] = posA[2] + mu*(posB[2]-posA[2]);
  90. return 2;
  91. }
  92. }
  93. int helIntersectionLineAndPolygon(vec3_t intersect,
  94. vec3_t p1, vec3_t p2,
  95. unsigned int vertexCount, vec3_t *ploygon)
  96. {
  97. // vec3_t normal, a, b;
  98. Vector3d a, b, normal, pA, pB;
  99. vec_t d, denominator, mu;
  100. double theta;
  101. pA = Vector3d(p1);
  102. pB = Vector3d(p2);
  103. // Find normal
  104. //mtkVectorSubtract(ploygon[1], ploygon[0], a);
  105. a = Vector3d(ploygon[1]) - Vector3d(ploygon[0]);
  106. //mtkVectorSubtract(ploygon[2], ploygon[0], b);
  107. b = Vector3d(ploygon[2]) - Vector3d(ploygon[0]);
  108. normal = Vector3d::cross(a, b);
  109. //mtkVectorCrossProduct(a, b, normal);
  110. normal.normalize();
  111. //mtkVectorNormalize(normal, normal);
  112. // find D
  113. //d = (normal[0] * ploygon[0][0] -
  114. // normal[1] * ploygon[0][1] -
  115. // normal[2] * ploygon[0][2]);
  116. d = (normal.mVec[0] * ploygon[0][0] -
  117. normal.mVec[1] * ploygon[0][1] -
  118. normal.mVec[2] * ploygon[0][2]);
  119. // line segment parallel to plane?
  120. //mtkVectorSubtract(p2, p1, a); // cache p2 - p1 => a
  121. a = pB - pA;
  122. //denominator = (normal[0] * a[0] +
  123. // normal[1] * a[1] +
  124. // normal[2] * a[2]);
  125. denominator = Vector3d::dot(normal, a);
  126. if (denominator > 0.0)
  127. return 0;
  128. // Line segment contains intercept point?
  129. //mu = - ((d + normal[0] * p1[0] + normal[1] * p1[1] + normal[2] * p1[2]) /
  130. // denominator);
  131. mu = -((d + Vector3d::dot(normal, pA)) / denominator);
  132. if (mu < 0.0 || mu > 1.0)
  133. return 0;
  134. //intersect[0] = p1[0] + mu * a[0];
  135. //intersect[1] = p1[1] + mu * a[1];
  136. //intersect[2] = p1[2] + mu * a[2];
  137. b = pA + (a * mu);
  138. intersect[0] = b.mVec[0];
  139. intersect[1] = b.mVec[1];
  140. intersect[2] = b.mVec[2];
  141. // See if the intercept is bound by polygon by winding number
  142. #ifdef WINDING_NUMBERS_TRIANGLE
  143. mtkVectorSubtract(ploygon[0], intersect, a);
  144. mtkVectorNormalize(a, a);
  145. mtkVectorSubtract(ploygon[1], intersect, b);
  146. mtkVectorNormalize(b, b);
  147. mtkVectorSubtract(ploygon[2], intersect, c);
  148. mtkVectorNormalize(c, c);
  149. t0 = mtkVectorDotProduct(a, b);
  150. t1 = mtkVectorDotProduct(b, c);
  151. t2 = mtkVectorDotProduct(c, a);
  152. total = HEL_RAD_TO_DEG(acos(t0) + acos(t1) + acos(t2));
  153. if (total - 360 < 0.0)
  154. return 0;
  155. #else // assume convex polygons here for sure
  156. //mtkVectorSubtract(intersect, ploygon[0], a);
  157. //theta = mtkVectorDotProduct(a, normal);
  158. theta = Vector3d::dot(b - Vector3d(ploygon[0]), normal); // b = intersect
  159. if (theta >= 90.0) // Yeah I know
  160. return 0;
  161. #endif
  162. return 1;
  163. }
  164. vec_t helDistToSphereFromPlane3v(vec3_t center, vec_t radius, vec4_t plane)
  165. {
  166. vec_t d;
  167. d = (plane[0] * center[0] +
  168. plane[1] * center[1] +
  169. plane[2] * center[2] +
  170. plane[3]);
  171. if (d <= -radius)
  172. return 0;
  173. return d + radius;
  174. }
  175. vec_t helDistToBboxFromPlane3v(vec3_t min, vec3_t max, vec4_t plane)
  176. {
  177. vec3_t center;
  178. vec_t d, radius;
  179. helMidpoint3v(min, max, center);
  180. d = (plane[0] * center[0] +
  181. plane[1] * center[1] +
  182. plane[2] * center[2] +
  183. plane[3]);
  184. radius = helDist3v(max, center);
  185. if (d <= -radius)
  186. return 0;
  187. return d + radius;
  188. }
  189. vec_t helDist3v(vec3_t a, vec3_t b)
  190. {
  191. return (sqrt( ((b[0] - a[0]) * (b[0] - a[0])) +
  192. ((b[1] - a[1]) * (b[1] - a[1])) +
  193. ((b[2] - a[2]) * (b[2] - a[2]))));
  194. }
  195. void helMidpoint3v(vec3_t a, vec3_t b, vec3_t mid)
  196. {
  197. mid[0] = (a[0] + b[0]) / 2;
  198. mid[1] = (a[1] + b[1]) / 2;
  199. mid[2] = (a[2] + b[2]) / 2;
  200. }
  201. vec_t helNorm4v(vec4_t v)
  202. {
  203. return (sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3]));
  204. }
  205. vec_t helNorm3v(vec3_t v)
  206. {
  207. return (sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]));
  208. }
  209. vec_t helNorm2v(vec2_t v)
  210. {
  211. return (sqrt(v[0]*v[0] + v[1]*v[1]));
  212. }
  213. vec_t helRandomNum(vec_t from, vec_t to)
  214. {
  215. return from + (to*rand()/(RAND_MAX+1.0));
  216. }