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

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