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 7.2KB

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