Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

MatMath.cpp 6.2KB

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. }