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.3KB

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