c3dlas.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <float.h>
  4. #include <math.h>
  5. #include "c3dlas.h"
  6. // vector operations
  7. int vEq(Vector* a, Vector* b) {
  8. return vEqEp(a, b, FLT_CMP_EPSILON);
  9. }
  10. int vEqEp(Vector* a, Vector* b, float epsilon) {
  11. float x, y, z, n;
  12. x = a->x - b->x;
  13. y = a->y - b->y;
  14. z = a->z - b->z;
  15. n = fabs(x * x + y * y + z * z);
  16. return n <= epsilon * epsilon;
  17. }
  18. void vCopy(const Vector* src, Vector* dst) {
  19. dst->x = src->x;
  20. dst->y = src->y;
  21. dst->z = src->z;
  22. }
  23. void vSwap(Vector* a, Vector* b) { // swap two vectors
  24. float x, y, z;
  25. x = a->x;
  26. y = a->y;
  27. z = a->z;
  28. a->x = b->x;
  29. a->y = b->y;
  30. a->z = b->z;
  31. b->x = x;
  32. b->y = y;
  33. b->z = z;
  34. }
  35. void vAdd(Vector* a, Vector* b, Vector* out) {
  36. out->x = a->x + b->x;
  37. out->y = a->y + b->y;
  38. out->z = a->z + b->z;
  39. }
  40. void vSub(Vector* from, Vector* what, Vector* diff) { // diff = from - what
  41. diff->x = from->x - what->x;
  42. diff->y = from->y - what->y;
  43. diff->z = from->z - what->z;
  44. }
  45. void vScale(Vector* v, float scalar, Vector* out) {
  46. out->x = v->x * scalar;
  47. out->y = v->y * scalar;
  48. out->z = v->z * scalar;
  49. }
  50. void vLerp(Vector* a, Vector* b, float t, Vector* out) { // Linear interpolation between two vectors
  51. out->x = a->x + ((b->x - a->x) * t);
  52. out->y = a->y + ((b->y - a->y) * t);
  53. out->z = a->z + ((b->z - a->z) * t);
  54. }
  55. void vInverse(Vector* v, Vector* out) {
  56. // yeah yeah yeah shut up. in games, pesky details are just annoying. this function does what you mean rather than sucking Gauss and Euclid.
  57. out->x = v->x == 0.0f ? FLT_MAX : 1.0f / v->x;
  58. out->y = v->y == 0.0f ? FLT_MAX : 1.0f / v->y;
  59. out->z = v->z == 0.0f ? FLT_MAX : 1.0f / v->z;
  60. }
  61. float vMag(Vector* v) {
  62. return sqrt((float)((v->x * v->x) + (v->y * v->y) + (v->z * v->z)));
  63. }
  64. float vDot(Vector* a, Vector* b) {
  65. return (float)((a->x * b->x) + (a->y * b->y) + (a->z * b->z));
  66. }
  67. // distance from one point to another
  68. float vDist(Vector* from, Vector* to) {
  69. float dx = (from->x - to->x);
  70. float dy = (from->y - to->y);
  71. float dz = (from->z - to->z);
  72. return sqrt(dx*dx + dy*dy + dz*dz);
  73. }
  74. void vNorm(Vector* v, Vector* out) {
  75. vUnit(v, out);
  76. }
  77. void vUnit(Vector* v, Vector* out) {
  78. float n;
  79. n = (v->x * v->x) + (v->y * v->y) + (v->z * v->z);
  80. if(n >= 1.0f - FLT_EPSILON && n <= 1.0f + FLT_EPSILON) return; // very exact here
  81. n = 1.0f / sqrtf(n);
  82. out->x = v->x * n;
  83. out->y = v->y * n;
  84. out->z = v->z * n;
  85. }
  86. void vCross(Vector* a, Vector* b, Vector* out) { // c = a x b
  87. out->x = (a->y * b->z) - (a->z * b->y);
  88. out->y = (a->z * b->x) - (a->x * b->z);
  89. out->z = (a->x * b->y) - (a->y * b->x);
  90. }
  91. float vScalarTriple(Vector* a, Vector* b, Vector* c) { // a . (b x c)
  92. return (float)((a->x * b->y * c->z) - (a->x * b->z * c->y) - (a->y * b->x * c->z)
  93. + (a->z * b->x * c->y) + (a->y * b->z * c->x) - (a->z * b->y * c->x));
  94. }
  95. // feeding a zero vector into this will cause div/0 and you will deserve it
  96. void vProject(Vector* what, Vector* onto, Vector* out) { // slower; onto may not be normalized
  97. float wdo = vDot(what, onto);
  98. float odo = vDot(onto, onto);
  99. vScale(onto, wdo / odo, out);
  100. }
  101. void vProjectNorm(Vector* what, Vector* onto, Vector* out) { // faster; onto must be normalized
  102. float wdo = vDot(what, onto);
  103. vScale(onto, wdo, out);
  104. }
  105. // returns the minimum values of each component
  106. void vMin(Vector* a, Vector* b, Vector* out) {
  107. out->x = fmin(a->x, b->x);
  108. out->y = fmin(a->y, b->y);
  109. out->z = fmin(a->z, b->z);
  110. }
  111. // returns the maximum values of each component
  112. void vMax(Vector* a, Vector* b, Vector* out) {
  113. out->x = fmax(a->x, b->x);
  114. out->y = fmax(a->y, b->y);
  115. out->z = fmax(a->z, b->z);
  116. }
  117. void inline vSet(float x, float y, float z, Vector* out) {
  118. out->x = x;
  119. out->y = y;
  120. out->z = z;
  121. }
  122. void vRandom(Vector* end1, Vector* end2, Vector* out) {
  123. out->x = frand(fmin(end1->x, end2->x), fmax(end1->x, end2->x));
  124. out->y = frand(fmin(end1->y, end2->y), fmax(end1->y, end2->y));
  125. out->z = frand(fmin(end1->z, end2->z), fmax(end1->z, end2->z));
  126. }
  127. void vRandomNorm(Vector* out) {
  128. float x = frand(-1, 1);
  129. float y = frand(-1, 1);
  130. float z = frand(-1, 1);
  131. float r = sqrt(x*x + y*y + z*z);
  132. if(r == 0.0) {
  133. vRandomNorm(out); // in the rare case of a zero-length vector, try again
  134. return;
  135. }
  136. out->x = x / r;
  137. out->y = y / r;
  138. out->z = z / r;
  139. }
  140. void vLerp4(Vector4* a, Vector4* b, float t, Vector4* out) { // Linear interpolation between two vectors
  141. out->x = a->x + ((b->x - a->x) * t);
  142. out->y = a->y + ((b->y - a->y) * t);
  143. out->z = a->z + ((b->z - a->z) * t);
  144. out->w = a->w + ((b->w - a->w) * t);
  145. }
  146. // reflects the distance from v to pivot across pivot.
  147. // out, pivot, and v will form a straight line with pivot exactly in the middle.
  148. void vReflectAcross(Vector* v, Vector* pivot, Vector* out) {
  149. Vector diff;
  150. vSub(pivot, v, &diff);
  151. vAdd(pivot, &diff, out);
  152. }
  153. // calculate a unit vector normal to a triangle's face.
  154. void vTriFaceNormal(Vector* a, Vector* b, Vector* c, Vector* out) {
  155. Vector a_b, a_c;
  156. vSub(a, b, &a_b);
  157. vSub(a, c, &a_c);
  158. vCross(&a_b, &a_b, out);
  159. vNorm(out, out);
  160. }
  161. void vProjectOntoPlane(Vector* v, Plane* p, Vector* out) {
  162. Vector v_ortho;
  163. // get the component of v that's perpendicular to the plane
  164. vProjectNorm(v, &p->n, &v_ortho);
  165. // subtract it from v
  166. vSub(v, &v_ortho, out);
  167. }
  168. void vProjectOntoPlaneNormalized(Vector* v, Plane* p, Vector* out) {
  169. vProjectOntoPlane(v, p, out);
  170. vNorm(out, out);
  171. }
  172. // calculates a plane from a triangle
  173. void planeFromTriangle(Vector* v1, Vector* v2, Vector* v3, Plane* out) {
  174. vTriFaceNormal(v1, v2, v3, &out->n);
  175. out->d = vDot(&out->n, v1);
  176. }
  177. // copy a plane
  178. void planeCopy(Plane* in, Plane* out) {
  179. vCopy(&in->n, &out->n);
  180. out->d = in->d;
  181. }
  182. // reverses the plane's direction
  183. void planeInverse(Plane* in, Plane* out) {
  184. vInverse(&in->n, &out->n);
  185. out->d = -in->d;
  186. }
  187. // classifies a point by which side of the plane it's on, default espilon
  188. int planeClassifyPoint(Plane* p, Vector* pt) {
  189. return planeClassifyPointEps(p, pt, FLT_CMP_EPSILON);
  190. }
  191. // classifies a point by which side of the plane it's on, custom espilon
  192. int planeClassifyPointEps(Plane* p, Vector* pt, float epsilon) {
  193. float dist = vDot(&p->n, pt);
  194. if(fabs(dist - p->d) < epsilon)
  195. return C3DLAS_COPLANAR;
  196. else if (dist < p->d)
  197. return C3DLAS_BACK;
  198. else
  199. return C3DLAS_FRONT;
  200. }
  201. // 2d vector stuff
  202. int vEq2(Vector2* a, Vector2* b) {
  203. return vEqEp2(a, b, FLT_CMP_EPSILON);
  204. }
  205. int vEqEp2(Vector2* a, Vector2* b, float epsilon) {
  206. float x, y, n;
  207. x = a->x - b->x;
  208. y = a->y - b->y;
  209. n = fabs(x * x + y * y);
  210. return n <= epsilon * epsilon;
  211. }
  212. void vCopy2(const Vector2* src, Vector2* dst) {
  213. dst->x = src->x;
  214. dst->y = src->y;
  215. }
  216. void vSwap2(Vector2* a, Vector2* b) { // swap two vectors
  217. float x, y;
  218. x = a->x;
  219. y = a->y;
  220. a->x = b->x;
  221. a->y = b->y;
  222. b->x = x;
  223. b->y = y;
  224. }
  225. void vAdd2(Vector2* a, Vector2* b, Vector2* out) {
  226. out->x = a->x + b->x;
  227. out->y = a->y + b->y;
  228. }
  229. void vSub2(Vector2* from, Vector2* what, Vector2* diff) { // diff = from - what
  230. diff->x = from->x - what->x;
  231. diff->y = from->y - what->y;
  232. }
  233. void vScale2(Vector2* v, float scalar, Vector2* out) {
  234. out->x = v->x * scalar;
  235. out->y = v->y * scalar;
  236. }
  237. float vDist2(Vector2* a, Vector2* b) {
  238. float x = a->x - b->x;
  239. float y = a->y - b->y;
  240. return sqrt(x * x + y * y);
  241. }
  242. void vLerp2(Vector2* a, Vector2* b, float t, Vector2* out) {
  243. out->x = a->x + ((b->x - a->x) * t);
  244. out->y = a->y + ((b->y - a->y) * t);
  245. }
  246. void vInverse2(Vector2* v, Vector2* out) {
  247. // see vInverse for snark
  248. out->x = v->x == 0.0f ? FLT_MAX : 1.0f / v->x;
  249. out->y = v->y == 0.0f ? FLT_MAX : 1.0f / v->y;
  250. }
  251. float vMag2(Vector2* v) {
  252. return sqrt((float)((v->x * v->x) + (v->y * v->y)));
  253. }
  254. float vDot2(Vector2* a, Vector2* b) {
  255. return (float)((a->x * b->x) + (a->y * b->y));
  256. }
  257. void vNorm2(Vector2* v, Vector2* out) {
  258. vUnit2(v, out);
  259. }
  260. void vUnit2(Vector2* v, Vector2* out) {
  261. float n;
  262. n = (v->x * v->x) + (v->y * v->y);
  263. if(n >= 1.0f - FLT_EPSILON && n <= 1.0f + FLT_EPSILON) return; // very exact here
  264. n = 1.0f / sqrtf(n);
  265. out->x = v->x * n;
  266. out->y = v->y * n;
  267. }
  268. // returns the minimum values of each component
  269. void vMin2(Vector2* a, Vector2* b, Vector2* out) {
  270. out->x = fmin(a->x, b->x);
  271. out->y = fmin(a->y, b->y);
  272. }
  273. // returns the maximum values of each component
  274. void vMax2(Vector2* a, Vector2* b, Vector2* out) {
  275. out->x = fmax(a->x, b->x);
  276. out->y = fmax(a->y, b->y);
  277. }
  278. void inline vSet2(float x, float y, Vector2* out) {
  279. out->x = x;
  280. out->y = y;
  281. }
  282. // reflects the distance from v to pivot across pivot.
  283. // out, pivot, and v will form a straight line with pivot exactly in the middle.
  284. void vReflectAcross2(Vector2* v, Vector2* pivot, Vector2* out) {
  285. Vector2 diff;
  286. vSub2(pivot, v, &diff);
  287. vAdd2(pivot, &diff, out);
  288. }
  289. // degenerate cases may not give desired results. GIGO.
  290. void vRoundAway2(const Vector2* in, const Vector2* center, Vector2i* out) {
  291. if(in->x > center->x) out->x = ceilf(in->x);
  292. else out->x = floorf(in->x);
  293. if(in->y > center->y) out->y = ceilf(in->y);
  294. else out->y = floorf(in->y);
  295. }
  296. // degenerate cases may not give desired results. GIGO.
  297. void vRoundToward2(const Vector2* in, const Vector2* center, Vector2i* out) {
  298. if(in->x > center->x) out->x = floorf(in->x);
  299. else out->x = ceilf(in->x);
  300. if(in->y > center->y) out->y = floorf(in->y);
  301. else out->y = ceilf(in->y);
  302. }
  303. // returns the *signed* area of a triangle. useful for determining winding
  304. // positive values mean a clockwise triangle
  305. float triArea2(Vector2* a, Vector2* b, Vector2* c) {
  306. return 0.5 * (
  307. ((b->x - a->x) * (b->y + a->y)) +
  308. ((c->x - b->x) * (c->y + b->y)) +
  309. ((a->x - c->x) * (a->y + c->y)));
  310. }
  311. // determines if a point is inside a triangle
  312. int triPointInside2(Vector2* p, Vector2* a, Vector2* b, Vector2* c) {
  313. int d = signbit((p->x - b->x) * (a->y - b->y) - (a->x - b->x) * (p->y - b->y));
  314. int e = signbit((p->x - c->x) * (b->y - c->y) - (b->x - c->x) * (p->y - c->y));
  315. if(d != e) return 0;
  316. int f = signbit((p->x - a->x) * (c->y - a->y) - (c->x - a->x) * (p->y - a->y));
  317. return e == f;
  318. }
  319. // 2d integer vector stuff
  320. int vEq2i(Vector2i* a, Vector2i* b) {
  321. return a->x == b->x && a->y == b->y;
  322. }
  323. void vCopy2i(const Vector2i* src, Vector2i* dst) {
  324. dst->x = src->x;
  325. dst->y = src->y;
  326. }
  327. void vSwap2i(Vector2i* a, Vector2i* b) { // swap two vectors
  328. int x, y;
  329. x = a->x;
  330. y = a->y;
  331. a->x = b->x;
  332. a->y = b->y;
  333. b->x = x;
  334. b->y = y;
  335. }
  336. void vAdd2i(Vector2i* a, Vector2i* b, Vector2i* out) {
  337. out->x = a->x + b->x;
  338. out->y = a->y + b->y;
  339. }
  340. void vSub2i(Vector2i* from, Vector2i* what, Vector2i* diff) { // diff = from - what
  341. diff->x = from->x - what->x;
  342. diff->y = from->y - what->y;
  343. }
  344. void vScale2i(Vector2i* v, int scalar, Vector2i* out) {
  345. out->x = v->x * scalar;
  346. out->y = v->y * scalar;
  347. }
  348. int vDot2i(Vector2i* a, Vector2i* b) {
  349. return ((a->x * b->x) + (a->y * b->y));
  350. }
  351. // returns the minimum values of each component
  352. void vMin2i(Vector2i* a, Vector2i* b, Vector2i* out) {
  353. out->x = MIN(a->x, b->x);
  354. out->y = MIN(a->y, b->y);
  355. }
  356. // returns the maximum values of each component
  357. void vMax2i(Vector2i* a, Vector2i* b, Vector2i* out) {
  358. out->x = MAX(a->x, b->x);
  359. out->y = MAX(a->y, b->y);
  360. }
  361. void inline vSet2i(int x, int y, Vector2i* out) {
  362. out->x = x;
  363. out->y = y;
  364. }
  365. // returns the absolute distance between two vectors
  366. float vDist2i(Vector2i* a, Vector2i* b) {
  367. float x = (float)a->x - (float)b->x;
  368. float y = (float)a->y - (float)b->y;
  369. return sqrt(x * x + y * y);
  370. }
  371. // plane-vector operations
  372. // distance from point to plane
  373. float pvDist(Plane* p, Vector* v) {
  374. return vDot(v, &p->n) + p->d;
  375. }
  376. // matrix-vector operations
  377. // multiply a vector by a matrix
  378. void vMatrixMul(Vector* in, Matrix* m, Vector* out) {
  379. vMatrixMulf(in->x, in->y, in->z, m, out);
  380. }
  381. void vMatrixMulf(float x, float y, float z, Matrix* m, Vector* out) {
  382. Vector4 v;
  383. v.x = x * m->m[0+0] + y * m->m[4+0] + z * m->m[8+0] + 1 * m->m[12+0];
  384. v.y = x * m->m[0+1] + y * m->m[4+1] + z * m->m[8+1] + 1 * m->m[12+1];
  385. v.z = x * m->m[0+2] + y * m->m[4+2] + z * m->m[8+2] + 1 * m->m[12+2];
  386. v.w = x * m->m[0+3] + y * m->m[4+3] + z * m->m[8+3] + 1 * m->m[12+3];
  387. out->x = v.x / v.w;
  388. out->y = v.y / v.w;
  389. out->z = v.z / v.w;
  390. }
  391. // matrix operations
  392. const Matrix IDENT_MATRIX = { { 1, 0, 0, 0,
  393. 0, 1, 0, 0,
  394. 0, 0, 1, 0,
  395. 0, 0, 0, 1 } };
  396. void mIdent(Matrix* m) {
  397. *m = IDENT_MATRIX;
  398. }
  399. void mCopy(Matrix* in, Matrix* out) {
  400. memcpy(in->m, out->m, sizeof(out->m));
  401. }
  402. // out cannot overlap with a or b
  403. void mFastMul(Matrix* a, Matrix* b, Matrix* out) {
  404. int r, c;
  405. for(r = 0; r < 4; r++) {
  406. for(c = 0; c < 4; c++) {
  407. out->m[c + r * 4] =
  408. (a->m[r * 4 + 0] * b->m[c + 0]) +
  409. (a->m[r * 4 + 1] * b->m[c + 4]) +
  410. (a->m[r * 4 + 2] * b->m[c + 8]) +
  411. (a->m[r * 4 + 3] * b->m[c + 12]);
  412. }
  413. }
  414. }
  415. // out cannot overlap with a. make a copy first if you want to do weird stuff.
  416. void mMul(Matrix* a, Matrix* out) {
  417. Matrix b;
  418. mCopy(&b, out);
  419. mFastMul(a, &b, out);
  420. }
  421. void mTransv(Vector* v, Matrix* out) {
  422. mTrans3f(v->x, v->y, v->z, out);
  423. }
  424. void mTrans3f(float x, float y, float z, Matrix* out) {
  425. Matrix t;
  426. t = IDENT_MATRIX;
  427. t.m[12] = x;
  428. t.m[13] = y;
  429. t.m[14] = z;
  430. mMul(&t, out);
  431. }
  432. void mScalev(Vector* v, Matrix* out) {
  433. mScale3f(v->x, v->y, v->z, out);
  434. }
  435. void mScale3f(float x, float y, float z, Matrix* out) {
  436. Matrix t;
  437. t = IDENT_MATRIX;
  438. t.m[0] = x;
  439. t.m[5] = y;
  440. t.m[10] = z;
  441. mMul(&t, out);
  442. }
  443. void mRotv(Vector* v, float theta, Matrix* out) {
  444. mRot3f(v->x, v->y, v->z, theta, out);
  445. }
  446. void mRot3f(float x, float y, float z, float theta, Matrix* out) {
  447. float costh, omcosth;
  448. float sinth;
  449. Matrix r;
  450. costh = cos(theta);
  451. omcosth = 1 - costh;
  452. sinth = sin(theta);
  453. r.m[0] = costh + (x * x * omcosth);
  454. r.m[1] = (z * sinth) + (x * y * omcosth);
  455. r.m[2] = (-y * sinth) + (x * z * omcosth);
  456. r.m[3] = 0;
  457. r.m[4] = (x * y * omcosth) - (z * sinth);
  458. r.m[5] = costh + (y * y * omcosth);
  459. r.m[6] = (x * sinth) + (y * z * omcosth);
  460. r.m[7] = 0;
  461. r.m[8] = (y * sinth) + (x * z * omcosth);
  462. r.m[9] = (-x * sinth) + (y * z * omcosth);
  463. r.m[10] = costh + (z * z * omcosth);
  464. r.m[11] = 0;
  465. r.m[12] = 0;
  466. r.m[13] = 0;
  467. r.m[14] = 0;
  468. r.m[15] = 1;
  469. mMul(&r, out);
  470. }
  471. void mRotX(float theta, Matrix* out) {
  472. mRot3f(1,0,0, theta, out);
  473. }
  474. void mRotY(float theta, Matrix* out) {
  475. mRot3f(0,1,0, theta, out);
  476. }
  477. void mRotZ(float theta, Matrix* out) {
  478. mRot3f(0,0,1, theta, out);
  479. }
  480. void mTransposeFast(Matrix* in, Matrix* out) {
  481. int i;
  482. for(i = 0; i < 4; i++) {
  483. out->m[i] = in->m[i * 4];
  484. out->m[i + 4] = in->m[(i * 4) + 1];
  485. out->m[i + 8] = in->m[(i * 4) + 2];
  486. out->m[i + 12] = in->m[(i * 4) + 3];
  487. }
  488. }
  489. void mTranspose(Matrix* in, Matrix* out) {
  490. Matrix t;
  491. int i;
  492. mTransposeFast(in, &t);
  493. *out = t;
  494. }
  495. float mDeterminate(Matrix* m) {
  496. return
  497. m->m[3] * m->m[6] * m->m[9] * m->m[12] - m->m[2] * m->m[7] * m->m[9] * m->m[12] -
  498. m->m[3] * m->m[5] * m->m[10] * m->m[12] + m->m[1] * m->m[7] * m->m[10] * m->m[12] +
  499. m->m[2] * m->m[5] * m->m[11] * m->m[12] - m->m[1] * m->m[6] * m->m[11] * m->m[12] -
  500. m->m[3] * m->m[6] * m->m[8] * m->m[13] + m->m[2] * m->m[7] * m->m[8] * m->m[13] +
  501. m->m[3] * m->m[4] * m->m[10] * m->m[13] - m->m[0] * m->m[7] * m->m[10] * m->m[13] -
  502. m->m[2] * m->m[4] * m->m[11] * m->m[13] + m->m[0] * m->m[6] * m->m[11] * m->m[13] +
  503. m->m[3] * m->m[5] * m->m[8] * m->m[14] - m->m[1] * m->m[7] * m->m[8] * m->m[14] -
  504. m->m[3] * m->m[4] * m->m[9] * m->m[14] + m->m[0] * m->m[7] * m->m[9] * m->m[14] +
  505. m->m[1] * m->m[4] * m->m[11] * m->m[14] - m->m[0] * m->m[5] * m->m[11] * m->m[14] -
  506. m->m[2] * m->m[5] * m->m[8] * m->m[15] + m->m[1] * m->m[6] * m->m[8] * m->m[15] +
  507. m->m[2] * m->m[4] * m->m[9] * m->m[15] - m->m[0] * m->m[6] * m->m[9] * m->m[15] -
  508. m->m[1] * m->m[4] * m->m[10] * m->m[15] + m->m[0] * m->m[5] * m->m[10] * m->m[15];
  509. }
  510. // shamelessly lifted from this SO post and modified into C, added error checking, and transposed for column major ordering:
  511. // http://stackoverflow.com/a/7596981
  512. // matrix inversions suck. maybe one day i'll lift intel's super fast SSE one instead.
  513. // functions returns 0 if sucessful, 1 if there is no inverse
  514. int mInverse(Matrix* in, Matrix* out) {
  515. float s0, s1, s2, s3, s4, s5;
  516. float c0, c1, c2, c3, c4, c5;
  517. float invdet;
  518. s0 = in->m[0] * in->m[5] - in->m[1] * in->m[4];
  519. s1 = in->m[0] * in->m[9] - in->m[1] * in->m[8];
  520. s2 = in->m[0] * in->m[13] - in->m[1] * in->m[12];
  521. s3 = in->m[4] * in->m[9] - in->m[5] * in->m[8];
  522. s4 = in->m[4] * in->m[13] - in->m[5] * in->m[12];
  523. s5 = in->m[8] * in->m[13] - in->m[9] * in->m[12];
  524. c5 = in->m[10] * in->m[15] - in->m[11] * in->m[14];
  525. c4 = in->m[6] * in->m[15] - in->m[7] * in->m[14];
  526. c3 = in->m[6] * in->m[11] - in->m[7] * in->m[10];
  527. c2 = in->m[2] * in->m[15] - in->m[3] * in->m[14];
  528. c1 = in->m[2] * in->m[11] - in->m[3] * in->m[10];
  529. c0 = in->m[2] * in->m[7] - in->m[3] * in->m[6];
  530. // Should check for 0 determinant
  531. invdet = (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0);
  532. if(invdet == 0.0) {
  533. fprintf(stderr, "ERROR: Matrix has no inverse!!!\n");
  534. return 1;
  535. }
  536. invdet = 1.0 / invdet;
  537. out->m[0] = ( in->m[5] * c5 - in->m[9] * c4 + in->m[13] * c3) * invdet;
  538. out->m[4] = (-in->m[4] * c5 + in->m[8] * c4 - in->m[12] * c3) * invdet;
  539. out->m[8] = ( in->m[7] * s5 - in->m[11] * s4 + in->m[15] * s3) * invdet;
  540. out->m[12] = (-in->m[6] * s5 + in->m[10] * s4 - in->m[14] * s3) * invdet;
  541. out->m[1] = (-in->m[1] * c5 + in->m[9] * c2 - in->m[13] * c1) * invdet;
  542. out->m[5] = ( in->m[0] * c5 - in->m[8] * c2 + in->m[12] * c1) * invdet;
  543. out->m[9] = (-in->m[3] * s5 + in->m[11] * s2 - in->m[15] * s1) * invdet;
  544. out->m[13] = ( in->m[2] * s5 - in->m[10] * s2 + in->m[14] * s1) * invdet;
  545. out->m[2] = ( in->m[1] * c4 - in->m[5] * c2 + in->m[13] * c0) * invdet;
  546. out->m[6] = (-in->m[0] * c4 + in->m[4] * c2 - in->m[12] * c0) * invdet;
  547. out->m[10] = ( in->m[3] * s4 - in->m[7] * s2 + in->m[15] * s0) * invdet;
  548. out->m[14] = (-in->m[2] * s4 + in->m[6] * s2 - in->m[14] * s0) * invdet;
  549. out->m[3] = (-in->m[1] * c3 + in->m[5] * c1 - in->m[9] * c0) * invdet;
  550. out->m[7] = ( in->m[0] * c3 - in->m[4] * c1 + in->m[8] * c0) * invdet;
  551. out->m[11] = (-in->m[3] * s3 + in->m[7] * s1 - in->m[11] * s0) * invdet;
  552. out->m[15] = ( in->m[2] * s3 - in->m[6] * s1 + in->m[10] * s0) * invdet;
  553. return 0;
  554. }
  555. // analogous to glFrustum
  556. // no div/0 checking here for right == left etc. just don't be an idiot.
  557. void mFrustum(float left, float right, float top, float bottom, float near, float far, Matrix* out) {
  558. Matrix m;
  559. m = IDENT_MATRIX;
  560. m.m[0] = (2 * near) / (right - left);
  561. m.m[5] = (2 * near) / (top - bottom);
  562. m.m[8] = (right + left) / (right - left);
  563. m.m[9] = (top + bottom) / (top - bottom);
  564. m.m[10] = -(far + near) / (far - near);
  565. m.m[11] = -1;
  566. m.m[14] = (-2 * far * near) / (far - near);
  567. m.m[15] = 0;
  568. mMul(&m, out);
  569. }
  570. // analogous to gluPerspective
  571. // same div/0 warnings apply. if you get an FP exception you deserve it.
  572. // use a double for fov; the precision matters often.
  573. // https://www.opengl.org/archives/resources/faq/technical/transformations.htm
  574. // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
  575. void mPerspective(double fov, float aspect, float near, float far, Matrix* out) {
  576. Matrix m;
  577. double f;
  578. m = IDENT_MATRIX;
  579. f = 1.0 / tan(fov * DEG2RAD / 2);
  580. m.m[0] = f / aspect;
  581. m.m[5] = f;
  582. m.m[10] = (far + near) / (near - far);
  583. m.m[11] = -1;
  584. m.m[14] = (2 * far * near) / (near - far);
  585. m.m[15] = 1;
  586. mMul(&m, out);
  587. }
  588. // orthographic projection. use this for a "2D" look.
  589. void mOrtho(float left, float right, float top, float bottom, float near, float far, Matrix* out) {
  590. Matrix m;
  591. m = IDENT_MATRIX;
  592. m.m[0] = 2 / (right - left);
  593. m.m[5] = 2 / (top - bottom);
  594. m.m[10] = -2 / (far - near);
  595. m.m[12] = -(right + left) / (right - left);
  596. m.m[13] = -(top + bottom) / (top - bottom);
  597. m.m[14] = -(far + near) / (far - near);
  598. m.m[15] = 1;
  599. mMul(&m, out);
  600. }
  601. // analgous to gluLookAt
  602. // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
  603. void mLookAt(Vector* eye, Vector* center, Vector* up, Matrix* out) {
  604. Vector f, upn, s, u, sn;
  605. Matrix m, m2;
  606. vSub(center, eye, &f);
  607. vNorm(&f, &f);
  608. vNorm(up, &upn);
  609. vCross(&f, &upn, &s);
  610. vNorm(&s, &sn);
  611. vCross(&sn, &f, &u);
  612. m.m[0] = s.x;
  613. m.m[1] = u.x;
  614. m.m[2] = -f.x;
  615. m.m[3] = 0;
  616. m.m[4] = s.y;
  617. m.m[5] = u.y;
  618. m.m[6] = -f.y;
  619. m.m[7] = 0;
  620. m.m[8] = s.z;
  621. m.m[9] = u.z;
  622. m.m[10] = -f.z;
  623. m.m[11] = 0;
  624. m.m[12] = 0;
  625. m.m[13] = 0;
  626. m.m[14] = 0;
  627. m.m[15] = 1;
  628. mTrans3f(-eye->x, -eye->y, -eye->z, &m2);
  629. mFastMul(&m, &m2, out);
  630. }
  631. void mPrint(Matrix* m, FILE* f) {
  632. int r, c;
  633. if(!f) f = stdout;
  634. for(r = 0; r < 4; r++) {
  635. fprintf(f, "% .3e % .3e % .3e % .3e\n", m->m[r*4], m->m[r*4+1], m->m[r*4+2], m->m[r*4+3]);
  636. }
  637. fprintf(f, "\n");
  638. }
  639. // make sure you allocate enough. when it's out, it's out. no surprise mallocs later on. (yet)
  640. void msAlloc(int size, MatrixStack* ms) {
  641. ms->stack = (Matrix*)malloc(size * sizeof(Matrix));
  642. ms->size = size;
  643. ms->top = 0;
  644. };
  645. void msFree(MatrixStack* ms) {
  646. free(ms->stack);
  647. ms->stack = NULL;
  648. }
  649. // push a new matrix on the stack. if m is null, push an identity matrix
  650. int msPush(MatrixStack* ms) {
  651. if(ms->top == ms->size - 1) {
  652. fprintf(stderr, "Matrix Stack overflowed.\n");
  653. return 1;
  654. }
  655. ms->top++;
  656. mCopy(&ms->stack[ms->top], &ms->stack[ms->top - 1]);
  657. return 0;
  658. }
  659. void msPop(MatrixStack* ms) {
  660. if(ms->top == 0) return;
  661. ms->top--;
  662. }
  663. Matrix* msGetTop(MatrixStack* ms) {
  664. return &ms->stack[ms->top];
  665. }
  666. void msPrintAll(MatrixStack* ms, FILE* f) {
  667. int i;
  668. if(!f) f = stdout;
  669. for(i = 0; i <= ms->top; i++) {
  670. fprintf(f, "--%3d--------------------------\n", i);
  671. mPrint(&ms->stack[i], f);
  672. }
  673. fprintf(f, "-------------------------------\n");
  674. }
  675. void msIdent(MatrixStack* ms) {
  676. mIdent(msGetTop(ms));
  677. }
  678. void msCopy(Matrix* in, MatrixStack* ms) {
  679. mCopy(in, msGetTop(ms));
  680. }
  681. void msMul(Matrix* a, MatrixStack* ms) { // makes a copy of out before multiplying over it
  682. mMul(a, msGetTop(ms));
  683. }
  684. void msTransv(Vector* v, MatrixStack* ms) { // translation
  685. mTransv(v, msGetTop(ms));
  686. }
  687. void msTrans3f(float x, float y, float z, MatrixStack* ms) { // translation
  688. mTrans3f(x, y, z, msGetTop(ms));
  689. }
  690. void msScalev(Vector* v, MatrixStack* ms) {
  691. mScalev(v, msGetTop(ms));
  692. }
  693. void msScale3f(float x, float y, float z, MatrixStack* ms) {
  694. mScale3f(x, y, z, msGetTop(ms));
  695. }
  696. void msRotv(Vector* v, float theta, MatrixStack* ms) { // rotate about a vector
  697. mRotv(v, theta, msGetTop(ms));
  698. }
  699. void msRot3f(float x, float y, float z, float theta, MatrixStack* ms) { // rotate about a vector
  700. mRot3f(x, y, z, theta, msGetTop(ms));
  701. }
  702. void msFrustum(float left, float right, float top, float bottom, float near, float far, MatrixStack* ms) {
  703. mFrustum(left, right, top, bottom, near, far, msGetTop(ms));
  704. }
  705. void msPerspective(double fov, float aspect, float near, float far, MatrixStack* ms) {
  706. mPerspective(fov, aspect, near, far, msGetTop(ms));
  707. }
  708. void msOrtho(float left, float right, float top, float bottom, float near, float far, MatrixStack* ms) {
  709. mOrtho(left, right, top, bottom, near, far, msGetTop(ms));
  710. }
  711. void msLookAt(Vector* eye, Vector* center, Vector* up, MatrixStack* ms) {
  712. mLookAt(eye, center, up, msGetTop(ms));
  713. }
  714. void evalBezier(Vector* e1, Vector* e2, Vector* c1, Vector* c2, float t, Vector* out) {
  715. out->x = evalBezier1D(e1->x, e2->x, c1->x, c2->x, t);
  716. out->y = evalBezier1D(e1->y, e2->y, c1->y, c2->y, t);
  717. out->z = evalBezier1D(e1->z, e2->z, c1->z, c2->z, t);
  718. }
  719. void evalBezier2D(Vector2* e1, Vector2* e2, Vector2* c1, Vector2* c2, float t, Vector2* out) {
  720. out->x = evalBezier1D(e1->x, e2->x, c1->x, c2->x, t);
  721. out->y = evalBezier1D(e1->y, e2->y, c1->y, c2->y, t);
  722. }
  723. float evalBezier1D(float e1, float e2, float c1, float c2, float t) {
  724. float mt, mt2, t2;
  725. mt = 1 - t;
  726. mt2 = mt * mt;
  727. t2 = t * t;
  728. return (mt2 * mt * e1) + (3 * mt2 * t * c1) + (3 * t2 * mt * c2) + (t2 * t * e2);
  729. }
  730. void evalBezierTangent(Vector* e1, Vector* e2, Vector* c1, Vector* c2, float t, Vector* out) {
  731. out->x = evalBezier1D_dt(e1->x, e2->x, c1->x, c2->x, t);
  732. out->y = evalBezier1D_dt(e1->y, e2->y, c1->y, c2->y, t);
  733. out->z = evalBezier1D_dt(e1->z, e2->z, c1->z, c2->z, t);
  734. }
  735. float evalBezier1D_dt(float e1, float e2, float c1, float c2, float t) {
  736. float mt, mt2, t2;
  737. mt = 1 - t;
  738. mt2 = mt * mt;
  739. t2 = t * t;
  740. return (3 * mt2 * (c1 - e1)) + (6 * mt * t * (c2 - c1)) + (3 * t2 * (e2 - c2));
  741. }
  742. float evalBezier1D_ddt(float e1, float e2, float c1, float c2, float t) {
  743. return (6 * (1 - t) * (c2 - c1 - c1 + e1)) + (6 * t * (e2 - c2 - c2 - c1));
  744. }
  745. void evalBezierNorm(Vector* e1, Vector* e2, Vector* c1, Vector* c2, float t, Vector* out) {
  746. out->x = evalBezier1D_ddt(e1->x, e2->x, c1->x, c2->x, t);
  747. out->y = evalBezier1D_ddt(e1->y, e2->y, c1->y, c2->y, t);
  748. out->z = evalBezier1D_ddt(e1->z, e2->z, c1->z, c2->z, t);
  749. }
  750. // Quadratic bezier functions
  751. float evalQBezier1D(float e1, float e2, float c1, float t) {
  752. float mt, mt2;
  753. mt = 1 - t;
  754. mt2 = mt * mt;
  755. return (mt2 * e1) + (2 * mt * t * c1) + (t * t * e2);
  756. }
  757. void evalQBezier2D(Vector2* e1, Vector2* e2, Vector2* c1, float t, Vector2* out) {
  758. out->x = evalQBezier1D(e1->x, e2->x, c1->x, t);
  759. out->y = evalQBezier1D(e1->y, e2->y, c1->y, t);
  760. }
  761. void evalQBezier(Vector* e1, Vector* e2, Vector* c1, float t, Vector* out) {
  762. out->x = evalQBezier1D(e1->x, e2->x, c1->x, t);
  763. out->y = evalQBezier1D(e1->y, e2->y, c1->y, t);
  764. out->z = evalQBezier1D(e1->z, e2->z, c1->z, t);
  765. }
  766. ///// bounding box functions
  767. // 3D versions
  768. int boxDisjoint(const AABB* a, const AABB* b) {
  769. return a->max.x < b->min.x || b->max.x < a->min.x
  770. || a->max.y < b->min.y || b->max.y < a->min.y
  771. || a->max.z < b->min.z || b->max.z < a->min.z;
  772. }
  773. int boxOverlaps(const AABB* a, const AABB* b) {
  774. return !boxDisjoint(a, b);
  775. }
  776. int boxContainsPoint(const AABB* b, const Vector* p) {
  777. return b->min.x <= p->x && b->max.x >= p->x
  778. && b->min.y <= p->y && b->max.y >= p->y
  779. && b->min.z <= p->z && b->max.z >= p->z;
  780. }
  781. void boxCenter(const AABB* b, Vector* out) {
  782. out->x = (b->max.x + b->min.x) / 2;
  783. out->y = (b->max.y + b->min.y) / 2;
  784. out->z = (b->max.z + b->min.z) / 2;
  785. }
  786. void boxSize(const AABB* b, Vector* out) {
  787. out->x = b->max.x - b->min.x;
  788. out->y = b->max.y - b->min.y;
  789. out->z = b->max.z - b->min.z;
  790. }
  791. // 2D versions
  792. int boxDisjoint2(const AABB2* a, const AABB2* b) {
  793. return a->max.x < b->min.x || b->max.x < a->min.x
  794. || a->max.y < b->min.y || b->max.y < a->min.y;
  795. }
  796. int boxOverlaps2(const AABB2* a, const AABB2* b) {
  797. return !boxDisjoint2(a, b);
  798. }
  799. int boxContainsPoint2(const AABB2* b, const Vector2* p) {
  800. return b->min.x <= p->x && b->max.x >= p->x
  801. && b->min.y <= p->y && b->max.y >= p->y;
  802. }
  803. void boxCenter2(const AABB2* b, Vector2* out) {
  804. out->x = (b->max.x + b->min.x) / 2;
  805. out->y = (b->max.y + b->min.y) / 2;
  806. }
  807. void boxSize2(const AABB2* b, Vector2* out) {
  808. out->x = b->max.x - b->min.x;
  809. out->y = b->max.y - b->min.y;
  810. }
  811. void boxQuadrant2(const AABB2* in, char ix, char iy, AABB2* out) {
  812. Vector2 sz, c;
  813. boxCenter2(in, &c);
  814. boxSize2(in, &sz);
  815. sz.x *= .5;
  816. sz.y *= .5;
  817. out->min.x = c.x - (ix ? 0.0f : sz.x);
  818. out->min.y = c.y - (iy ? 0.0f : sz.y);
  819. out->max.x = c.x + (ix ? sz.x : 0.0f);
  820. out->max.y = c.y + (iy ? sz.y : 0.0f);
  821. }
  822. // 2D integer versions
  823. int boxDisjoint2i(const AABB2i* a, const AABB2i* b) {
  824. return a->max.x < b->min.x || b->max.x < a->min.x
  825. || a->max.y < b->min.y || b->max.y < a->min.y;
  826. }
  827. int boxOverlaps2i(const AABB2i* a, const AABB2i* b) {
  828. return !boxDisjoint2i(a, b);
  829. }
  830. int boxContainsPoint2i(const AABB2i* b, const Vector2i* p) {
  831. return b->min.x <= p->x && b->max.x >= p->x
  832. && b->min.y <= p->y && b->max.y >= p->y;
  833. }
  834. void boxCenter2i(const AABB2i* b, Vector2* out) {
  835. out->x = (b->max.x + b->min.x) / 2.0f;
  836. out->y = (b->max.y + b->min.y) / 2.0f;
  837. }
  838. void boxSize2i(const AABB2i* b, Vector2* out) {
  839. out->x = b->max.x - b->min.x;
  840. out->y = b->max.y - b->min.y;
  841. }
  842. // BUG: needs some fancy math work to keep everything tight. integers don't split nicely
  843. void boxQuadrant2i(const AABB2i* in, char ix, char iy, AABB2i* out) {
  844. Vector2 sz, c;
  845. printf("fix me: %s:%d", __FILE__, __LINE__);
  846. exit(666);
  847. boxCenter2i(in, &c);
  848. boxSize2i(in, &sz);
  849. sz.x *= .5;
  850. sz.y *= .5;
  851. out->min.x = c.x - (ix ? 0.0f : sz.x);
  852. out->min.y = c.y - (iy ? 0.0f : sz.y);
  853. out->max.x = c.x + (ix ? sz.x : 0.0f);
  854. out->max.y = c.y + (iy ? sz.y : 0.0f);
  855. }
  856. // find the center of a quad
  857. void quadCenter2(const Quad2* q, Vector2* out) {
  858. Vector2 c;
  859. int i;
  860. for(i = 0; i < 4; i++) {
  861. c.x += q->v[i].x;
  862. c.y += q->v[i].y;
  863. }
  864. out->x = c.x / 4;
  865. out->y = c.y / 4;
  866. }
  867. void quadRoundOutward2(const Quad2* in, Quad2i* out) {
  868. Vector2 c;
  869. int i;
  870. quadCenter2(in, &c);
  871. for(i = 0; i < 4; i++)
  872. vRoundAway2(&in->v[i], &c, &out->v[i]);
  873. }
  874. void quadRoundInward2(const Quad2* in, Quad2i* out) {
  875. Vector2 c;
  876. int i;
  877. quadCenter2(in, &c);
  878. for(i = 0; i < 4; i++)
  879. vRoundToward2(&in->v[i], &c, &out->v[i]);
  880. }
  881. int quadIsPoint2i(const Quad2i* q) {
  882. return (
  883. q->v[0].x == q->v[1].x == q->v[2].x == q->v[3].x &&
  884. q->v[0].y == q->v[1].y == q->v[2].y == q->v[3].y);
  885. }
  886. int quadIsAARect2i(const Quad2i* q) {
  887. return (
  888. q->v[0].x == q->v[3].x && q->v[1].x == q->v[2].x &&
  889. q->v[0].y == q->v[1].y && q->v[2].y == q->v[3].y);
  890. }
  891. // ray stuff
  892. void makeRay(Vector* origin, Vector* direction, Ray* out) {
  893. out->o.x = origin->x;
  894. out->o.y = origin->y;
  895. out->o.z = origin->z;
  896. vNorm(direction, &out->d);
  897. vInverse(&out->d, &out->id);
  898. }
  899. // this version has no branching, but only answers yes or no.
  900. // algorithm explanation here. hopefully my extrapolation into 3 dimensions is correct.
  901. // http://tavianator.com/fast-branchless-raybounding-box-intersections/
  902. int boxRayIntersectFast(const AABB* b, const Ray* r) {
  903. Vector t1, t2;
  904. float tmin, tmax;
  905. t1.x = (b->min.x - r->o.x) * r->id.x;
  906. t2.x = (b->max.x - r->o.x) * r->id.x;
  907. tmin = fmin(t1.x, t2.x);
  908. tmax = fmax(t1.x, t2.x);
  909. t1.y = (b->min.y - r->o.y) * r->id.y;
  910. t2.y = (b->max.y - r->o.y) * r->id.y;
  911. tmin = fmax(tmin, fmin(t1.y, t2.y));
  912. tmax = fmin(tmax, fmax(t1.y, t2.y));
  913. t1.z = (b->min.z - r->o.z) * r->id.z;
  914. t2.z = (b->max.z - r->o.z) * r->id.z;
  915. tmin = fmax(tmin, fmin(t1.z, t2.z));
  916. tmax = fmin(tmax, fmax(t1.z, t2.z));
  917. return tmax >= tmin;
  918. }
  919. // this version gives the point of intersection as well as distance
  920. // algorithm explanation here. hopefully my extrapolation into 3 dimensions is correct.
  921. // http://tavianator.com/fast-branchless-raybounding-box-intersections/
  922. int boxRayIntersect(const AABB* b, const Ray* r, Vector* ipoint, float* idist) {
  923. Vector t1, t2;
  924. float tmin, tmax;
  925. t1.x = (b->min.x - r->o.x) * r->id.x;
  926. t2.x = (b->max.x - r->o.x) * r->id.x;
  927. tmin = fmin(t1.x, t2.x);
  928. tmax = fmax(t1.x, t2.x);
  929. t1.y = (b->min.y - r->o.y) * r->id.y;
  930. t2.y = (b->max.y - r->o.y) * r->id.y;
  931. tmin = fmax(tmin, fmin(t1.y, t2.y));
  932. tmax = fmin(tmax, fmax(t1.y, t2.y));
  933. t1.z = (b->min.z - r->o.z) * r->id.z;
  934. t2.z = (b->max.z - r->o.z) * r->id.z;
  935. tmin = fmax(tmin, fmin(t1.z, t2.z));
  936. tmax = fmin(tmax, fmax(t1.z, t2.z));
  937. if(tmax < tmin) return 0;
  938. if(idist) *idist = tmin;
  939. if(ipoint) {
  940. ipoint->x = r->o.x + (r->d.x * tmin);
  941. ipoint->y = r->o.y + (r->d.y * tmin);
  942. ipoint->z = r->o.z + (r->d.z * tmin);
  943. }
  944. return 1;
  945. }
  946. // returns a local t value for the segment the normalized value falls into
  947. static float bsNormalToLocalT2(BezierSpline2* bs, float normalT, int* segNum) {
  948. float segT = 1.0 / (bs->length - (!bs->isLoop));
  949. if(segNum) *segNum = (int)(normalT / segT);
  950. return fmod(normalT, segT) / segT;
  951. }
  952. // returns which segment a normalized t falls in
  953. static int bsSegNum2(BezierSpline2* bs, float normalT) {
  954. float segT = 1.0 / (bs->length - (!bs->isLoop));
  955. return (int)(normalT / segT);
  956. }
  957. // returns a full set of control points for the segment t falls into
  958. // out's order is e1, c1, c2, e2
  959. static void bsSegmentForT2(BezierSpline2* bs, float normalT, Vector2* out) {
  960. BezierSplineSegment2* p, *n;
  961. int segN, i;
  962. segN = i = bsSegNum2(bs, normalT);
  963. p = bs->segments;
  964. while(i--) p = p->next;
  965. // a loop wraps around at the end
  966. n = (bs->isLoop && (segN == (bs->length - 1))) ? bs->segments : p->next;
  967. // end 1
  968. out[0].x = p->e.x;
  969. out[0].y = p->e.y;
  970. // control 1
  971. out[1].x = p->c.x;
  972. out[1].y = p->c.y;
  973. // control 2 - this one is reflected across e2
  974. vReflectAcross2(&n->c, &n->e, &out[2]);
  975. // end 2
  976. out[3].x = n->e.x;
  977. out[3].y = n->e.y;
  978. }
  979. // BUG: this function is probably horribly broken
  980. // this function evaluates a spline with a [0,1] normalized value of t across the whole spline
  981. void bsEvalPoint2(BezierSpline2* bs, float normalT, Vector2* out) {
  982. int segN;
  983. float localT;
  984. // find which spline segment the t is in
  985. localT = bsNormalToLocalT2(bs, normalT, &segN);
  986. // find the local value of t
  987. Vector2 cp[4];
  988. bsSegmentForT2(bs, normalT, cp);
  989. evalBezier2D(&cp[0], &cp[3], &cp[1], &cp[2], localT, out);
  990. }
  991. // subdivide a spline into a set of line segments. linePoints must be allocated externally.
  992. // this function is faster than more accurate ones.
  993. void bsEvenLines(BezierSpline2* bs, int lineCount, Vector2* linePoints) {
  994. float tIncrement;
  995. tIncrement = (float)(bs->length - (!bs->isLoop)) / (float)lineCount;
  996. }