c3dlas.c 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <float.h>
  4. #include <math.h>
  5. #include <limits.h>
  6. #include <float.h>
  7. #include <x86intrin.h>
  8. #include "c3dlas.h"
  9. #ifdef C3DLAS_USE_BUILTINS
  10. #define abs_double __builtin_fabs
  11. #define abs_float __builtin_fabsf
  12. #else
  13. #define abs_double fabs
  14. #define abs_float fabsf
  15. #endif
  16. #ifdef C3DLAS_NO_TGMATH
  17. // requires GCC probably
  18. /*
  19. #define FD_CHOOSE_1(a, b, fn_f, fn_d)\
  20. __builtin_choose_expr( \
  21. __builtin_types_compatible_p(__typeof__(a), double), \
  22. fn_d(a), \
  23. fn_f(a))
  24. #define FD_CHOOSE_2(a, b, fn_f, fn_d)\
  25. __builtin_choose_expr( \
  26. __builtin_types_compatible_p(__typeof__(a), double) || __builtin_types_compatible_p(__typeof__(b), double), \
  27. fn_d(a, b), \
  28. fn_f(a, b))
  29. #define fmax(a,b) FD_CHOOSE_2(a, b, fmaxf, fmax)
  30. #define fmin(a,b) FD_CHOOSE_2(a, b, fminf, fmin)
  31. #define fabs(a) FD_CHOOSE_1(a, fabsf, fabs)
  32. #define sqrt(a) FD_CHOOSE_1(a, sqrtf, sqrt)
  33. */
  34. #else
  35. #include <tgmath.h>
  36. #endif
  37. #ifndef _GNU_SOURCE
  38. static inline void sincosf(float x, float* s, float* c) {
  39. *s = sinf(x);
  40. *c = cosf(x);
  41. }
  42. #endif
  43. // utilities
  44. // reverses the argument
  45. uint32_t bitReverse32(uint32_t x) {
  46. x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
  47. x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
  48. x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
  49. x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
  50. return ((x >> 16) | (x << 16));
  51. }
  52. // reverses the least significant (len) bits, zeroing the top
  53. uint32_t reverseBits(uint32_t n, int len) {
  54. uint32_t rn = bitReverse32(n);
  55. return rn >> (32 - len);
  56. }
  57. // random numbers
  58. // prepare the pcg for use
  59. void pcg_init(PCG* pcg, uint64_t seed) {
  60. pcg->stream = seed;
  61. pcg->state = (seed * 6364136223846793005ULL) + (seed | 1);
  62. }
  63. // returns a random number in (-1, 1) uninclusive
  64. // Thanks to Kaslai (https://github.com/Aslai) for fixing a nasty bug in the previous version
  65. float pcg_f(uint64_t* state, uint64_t stream) {
  66. union {
  67. uint32_t fu;
  68. float ff;
  69. } u;
  70. uint64_t last = *state;
  71. *state = (last * 6364136223846793005ULL) + (stream | 1);
  72. uint32_t xs = ((last >> 18) ^ last) >> 27;
  73. uint32_t rot = last >> 59;
  74. uint32_t fin = (xs >> rot) | (xs << ((-rot) & 31));
  75. uint32_t exp = (fin & 0x3F800000);
  76. exp = (0x7F + 33 - __builtin_clzl(exp)) << 23;
  77. u.fu = ((fin) & 0x807fffff) | exp;
  78. return u.ff;
  79. }
  80. // returns a random number in [0, UINT32_MAX] inclusive
  81. uint32_t pcg_u32(uint64_t* state, uint64_t stream) {
  82. uint64_t last = *state;
  83. *state = (last * 6364136223846793005ULL) + (stream | 1);
  84. uint32_t xs = ((last >> 18) ^ last) >> 27;
  85. uint32_t rot = last >> 59;
  86. uint32_t fin = (xs >> rot) | (xs << ((-rot) & 31));
  87. return fin;
  88. }
  89. // BUG: totally untested
  90. // SIMD and C versions do not return the same values.
  91. void pcg_f8(uint64_t* state, uint64_t stream, float* out) {
  92. #if defined(C3DLAS_USE_SIMD)
  93. __m256i s1, s2, xs1, xs2, xs, r, nra, q, f;
  94. s1 = _mm256_add_epi64(_mm256_set1_epi64x(*state), _mm256_set_epi64x(1,2,3,4));
  95. s2 = _mm256_add_epi64(_mm256_set1_epi64x(*state), _mm256_set_epi64x(5,6,7,8));
  96. // cycle the state
  97. *state = (*state * 6364136223846793005ULL) + (stream | 1);
  98. xs1 = _mm256_srli_epi64(_mm256_xor_si256(_mm256_srli_epi64(s1, 18), s1), 27);
  99. xs2 = _mm256_srli_epi64(_mm256_xor_si256(_mm256_srli_epi64(s2, 18), s2), 27);
  100. xs = _mm256_unpacklo_epi32(xs1, xs2);
  101. r = _mm256_srai_epi32(xs, 59);
  102. nra = _mm256_and_si256(_mm256_sign_epi32(r, _mm256_set1_epi32(-1)), _mm256_set1_epi32(31));
  103. q = _mm256_or_si256(_mm256_srav_epi32(xs, r), _mm256_sllv_epi32(xs, nra));
  104. // q is full of random 32bit integers now
  105. // convert to (-1, 1) floats by jamming in some exponent info
  106. f = _mm256_or_si256(_mm256_and_si256(q, _mm256_set1_epi32(0x807fffff)), _mm256_set1_epi32(0x3f000000));
  107. _mm256_storeu_si256((__m256i*)out, f);
  108. #else
  109. out[0] = pcg_f(state, stream);
  110. out[1] = pcg_f(state, stream);
  111. out[2] = pcg_f(state, stream);
  112. out[3] = pcg_f(state, stream);
  113. out[4] = pcg_f(state, stream);
  114. out[5] = pcg_f(state, stream);
  115. out[6] = pcg_f(state, stream);
  116. out[7] = pcg_f(state, stream);
  117. #endif
  118. }
  119. float frandPCG(float low, float high, PCG* pcg) {
  120. return low + ((high - low) * (pcg_f(&pcg->state, pcg->stream) * 0.5 + 0.5));
  121. }
  122. uint32_t urandPCG(uint32_t low, uint32_t high, PCG* pcg) {
  123. return pcg_u32(&pcg->state, pcg->stream) % (high - low) + low;
  124. }
  125. #define FN(sz, suf, ty, ft, sufft, pref, ...) \
  126. \
  127. int vEqExact##suf(const Vector##suf a, const Vector##suf b) { \
  128. return vEqExact##suf##p(&a, &b); \
  129. } \
  130. int vEqExact##suf##p(const Vector##suf const * a, const Vector##suf const * b) { \
  131. int tmp = 0; \
  132. for(int i = 0; i < sz; i++) \
  133. tmp += ((ty*)a)[i] == ((ty*)b)[i]; \
  134. return tmp == sz; \
  135. } \
  136. \
  137. int vEq##suf(const Vector##suf a, const Vector##suf b) { \
  138. return vEqEp##suf(a, b, pref##_CMP_EPSILON); \
  139. } \
  140. int vEq##suf##p(const Vector##suf* a, const Vector##suf* b) { \
  141. return vEqEp##suf(*a, *b, pref##_CMP_EPSILON); \
  142. } \
  143. \
  144. int vEqEp##suf(const Vector##suf a, const Vector##suf b, ft epsilon) { \
  145. return vEqEp##suf##p(&a, &b, epsilon); \
  146. } \
  147. int vEqEp##suf##p(const Vector##suf* a, const Vector##suf* b, ft epsilon) { \
  148. return vDistSq##suf(*a, *b) <= epsilon * epsilon; \
  149. } \
  150. \
  151. ft vDistSq##suf(const Vector##suf a, const Vector##suf b) { \
  152. return vDistSq##suf##p(&a, &b); \
  153. } \
  154. ft vDistSq##suf##p(const Vector##suf* a, const Vector##suf* b) { \
  155. ft tmp = 0; \
  156. for(int i = 0; i < sz; i++) { \
  157. ft q = ((ty*)a)[i] - ((ty*)b)[i]; \
  158. tmp += q * q; \
  159. } \
  160. return tmp;\
  161. } \
  162. ft vDist##suf(const Vector##suf a, const Vector##suf b) { \
  163. return sqrt(vDistSq##suf##p(&a, &b)); \
  164. } \
  165. ft vDist##suf##p(const Vector##suf* a, const Vector##suf* b) { \
  166. return sqrt(vDistSq##suf##p(a, b)); \
  167. } \
  168. \
  169. Vector##suf vAdd##suf(const Vector##suf a, const Vector##suf b) { \
  170. Vector##suf out; \
  171. vAdd##suf##p(&a, &b, &out); \
  172. return out; \
  173. } \
  174. void vAdd##suf##p(const Vector##suf* a, const Vector##suf* b, Vector##suf* out) { \
  175. for(int i = 0; i < sz; i++) { \
  176. ((ty*)out)[i] = ((ty*)a)[i] + ((ty*)b)[i]; \
  177. } \
  178. } \
  179. \
  180. Vector##suf vSub##suf(const Vector##suf a, const Vector##suf b) { \
  181. Vector##suf out; \
  182. vSub##suf##p(&a, &b, &out); \
  183. return out; \
  184. } \
  185. void vSub##suf##p(const Vector##suf const * a, const Vector##suf const * b, Vector##suf* out) { \
  186. for(int i = 0; i < sz; i++) { \
  187. ((ty*)out)[i] = ((ty*)a)[i] - ((ty*)b)[i]; \
  188. } \
  189. } \
  190. \
  191. Vector##suf vMul##suf(const Vector##suf a, const Vector##suf b) { \
  192. Vector##suf out; \
  193. vMul##suf##p(&a, &b, &out); \
  194. return out; \
  195. } \
  196. void vMul##suf##p(const Vector##suf const * a, const Vector##suf const * b, Vector##suf* out) { \
  197. for(int i = 0; i < sz; i++) { \
  198. ((ty*)out)[i] = ((ty*)a)[i] * ((ty*)b)[i]; \
  199. } \
  200. } \
  201. \
  202. Vector##suf vDiv##suf(const Vector##suf top, const Vector##suf bot) { \
  203. Vector##suf out; \
  204. vDiv##suf##p(&top, &bot, &out); \
  205. return out; \
  206. } \
  207. void vDiv##suf##p(const Vector##suf const * top, const Vector##suf const * bot, Vector##suf* out) { \
  208. for(int i = 0; i < sz; i++) { \
  209. ((ty*)out)[i] = ((ty*)top)[i] / ((ty*)bot)[i]; \
  210. } \
  211. } \
  212. \
  213. ft vDot##suf(const Vector##suf a, const Vector##suf b) { \
  214. return vDot##suf##p(&a, &b); \
  215. } \
  216. ft vDot##suf##p(const Vector##suf* a, const Vector##suf* b) { \
  217. ft tmp = 0; \
  218. for(int i = 0; i < sz; i++) { \
  219. tmp += ((ty*)a)[i] * ((ty*)b)[i]; \
  220. } \
  221. return tmp;\
  222. } \
  223. \
  224. Vector##sufft vScale##suf(const Vector##suf v, ft scalar) { \
  225. Vector##sufft out; \
  226. vScale##suf##p(&v, scalar, &out); \
  227. return out; \
  228. } \
  229. void vScale##suf##p(const Vector##suf* v, ft scalar, Vector##sufft* out) { \
  230. for(int i = 0; i < sz; i++) \
  231. ((ft*)out)[i] = (ft)((ty*)v)[i] * scalar; \
  232. } \
  233. \
  234. \
  235. Vector##sufft vAvg##suf(const Vector##suf a, const Vector##suf b) { \
  236. Vector##sufft out; \
  237. vAvg##suf##p(&a, &b, &out); \
  238. return out; \
  239. } \
  240. void vAvg##suf##p(const Vector##suf* a, const Vector##suf* b, Vector##sufft* out) { \
  241. for(int i = 0; i < sz; i++) { \
  242. ((ty*)out)[i] = (((ty*)a)[i] + ((ty*)b)[i]) / (ft)2.0; \
  243. } \
  244. } \
  245. \
  246. Vector##suf vNeg##suf(const Vector##suf v) { \
  247. Vector##suf out; \
  248. vNeg##suf##p(&v, &out); \
  249. return out; \
  250. } \
  251. void vNeg##suf##p(const Vector##suf* v, Vector##suf* out) { \
  252. for(int i = 0; i < sz; i++) \
  253. ((ty*)out)[i] = -((ty*)v)[i]; \
  254. } \
  255. \
  256. Vector##sufft vLerp##suf(const Vector##suf a, const Vector##suf b, ft t) { \
  257. Vector##sufft out; \
  258. vLerp##suf##p(&a, &b, t, &out); \
  259. return out; \
  260. } \
  261. void vLerp##suf##p(const Vector##suf* a, const Vector##suf* b, ft t, Vector##sufft* out) { \
  262. for(int i = 0; i < sz; i++) \
  263. ((ft*)out)[i] = (ft)((ty*)a)[i] + ((ft)(((ty*)b)[i] - ((ty*)a)[i]) * t) ; \
  264. } \
  265. \
  266. Vector##sufft vInv##suf(const Vector##suf v) { \
  267. Vector##sufft out; \
  268. vInv##suf##p(&v, &out); \
  269. return out; \
  270. } \
  271. void vInv##suf##p(const Vector##suf* v, Vector##sufft* out) { \
  272. for(int i = 0; i < sz; i++) \
  273. ((ft*)out)[i] = (((ty*)v)[i] == 0) ? pref##_MAX : ((ft)1.0 / (ft)((ty*)v)[i]); \
  274. } \
  275. \
  276. ft vLen##suf(const Vector##suf v) { \
  277. return vLen##suf##p(&v); \
  278. } \
  279. ft vLen##suf##p(const Vector##suf* v) { \
  280. ft tmp = 0.0; \
  281. for(int i = 0; i < sz; i++) \
  282. tmp += (ft)((ty*)v)[i] * (ft)((ty*)v)[i]; \
  283. return sqrt(tmp); \
  284. } \
  285. \
  286. ft vLenSq##suf(const Vector##suf v) { \
  287. return vLenSq##suf##p(&v); \
  288. } \
  289. ft vLenSq##suf##p(const Vector##suf* v) { \
  290. return vDot##suf##p(v, v); \
  291. } \
  292. \
  293. ft vMag##suf(const Vector##suf v) { \
  294. return vLen##suf##p(&v); \
  295. } \
  296. ft vMag##suf##p(const Vector##suf* v) { \
  297. return vLen##suf##p(v); \
  298. } \
  299. \
  300. ft vInvLen##suf(const Vector##suf v) { \
  301. ft tmp = vLen##suf(v); \
  302. return tmp == 0 ? pref##_MAX : (ft)1.0 / tmp; \
  303. } \
  304. ft vInvLen##suf##p(const Vector##suf* v) { \
  305. return vInvLen##suf(*v); \
  306. } \
  307. \
  308. Vector##sufft vNorm##suf(const Vector##suf v) { \
  309. Vector##sufft out; \
  310. vNorm##suf##p(&v, &out); \
  311. return out; \
  312. } \
  313. void vNorm##suf##p(const Vector##suf* v, Vector##sufft* out) { \
  314. ft n = vLenSq##suf(*v); \
  315. \
  316. if(n >= (ft)1.0f - pref##_CMP_EPSILON && n <= (ft)1.0 + pref##_CMP_EPSILON) { \
  317. for(int i = 0; i < sz; i++) \
  318. ((ft*)out)[i] = (ft)((ty*)v)[i]; \
  319. return; \
  320. } \
  321. else if(n == 0.0) { \
  322. for(int i = 0; i < sz; i++) \
  323. ((ft*)out)[i] = 0; \
  324. return; \
  325. } \
  326. \
  327. n = (ft)1.0 / sqrt(n); \
  328. for(int i = 0; i < sz; i++) \
  329. ((ft*)out)[i] = (ft)((ty*)v)[i] * n; \
  330. } \
  331. \
  332. Vector##sufft vUnit##suf(const Vector##suf v) { \
  333. return vNorm##suf(v); \
  334. } \
  335. void vUnit##suf##p(const Vector##suf* v, Vector##sufft* out) { \
  336. return vNorm##suf##p(v, out); \
  337. } \
  338. C3DLAS_VECTOR_LIST(FN)
  339. #undef FN
  340. // swap two vectors
  341. void vSwap2ip(Vector2i* a, Vector2i* b) {
  342. Vector2i t;
  343. t = *b;
  344. *b = *a;
  345. *a = t;
  346. }
  347. void vSwap2p(Vector2* a, Vector2* b) {
  348. Vector2 t;
  349. t = *b;
  350. *b = *a;
  351. *a = t;
  352. }
  353. void vSwap3p(Vector3* a, Vector3* b) {
  354. Vector3 t;
  355. t = *b;
  356. *b = *a;
  357. *a = t;
  358. }
  359. void vSwap4p(Vector4* a, Vector4* b) {
  360. Vector4 t;
  361. t = *b;
  362. *b = *a;
  363. *a = t;
  364. }
  365. // Cross product: out = a x b
  366. // Cross products *proper* only exist in 3 and 7 dimensions
  367. Vector3 vCross3(Vector3 a, Vector3 b) {
  368. Vector3 out;
  369. vCross3p(&a, &b, &out);
  370. return out;
  371. }
  372. void vCross3p(Vector3* a, Vector3* b, Vector3* out) {
  373. out->x = (a->y * b->z) - (a->z * b->y);
  374. out->y = (a->z * b->x) - (a->x * b->z);
  375. out->z = (a->x * b->y) - (a->y * b->x);
  376. }
  377. // ... however, if you apply it to two dimensions it yields
  378. // the sine of the angle between the two vectors, and the sign
  379. // of the value determines which side of a that b is on. If
  380. // the value is zero, the vectors are parallel.
  381. float vCross2(Vector2 a, Vector2 b) {
  382. return (a.x * b.y) - (a.y * b.x);
  383. }
  384. float vCross2p(Vector2* a, Vector2* b) {
  385. return (a->x * b->y) - (a->y * b->x);
  386. }
  387. // Scalar triple product: a . (b x c)
  388. float vScalarTriple3(Vector3 a, Vector3 b, Vector3 c) {
  389. return vScalarTriple3p(&a, &b, &c);
  390. }
  391. float vScalarTriple3p(Vector3* a, Vector3* b, Vector3* c) {
  392. return (float)((a->x * b->y * c->z) - (a->x * b->z * c->y) - (a->y * b->x * c->z)
  393. + (a->z * b->x * c->y) + (a->y * b->z * c->x) - (a->z * b->y * c->x));
  394. }
  395. // Vector Inverse. Returns FLT_MAX on div/0
  396. // Vector magnitude (length)
  397. // Squared distance from one point to another
  398. // Distance from one point to another
  399. // Vector normalize (scale to unit length)
  400. // vMin(a, b) Returns the minimum values of each component
  401. // vMin(a, b) Returns the maximum values of each component
  402. #define FN(sz, suf, t, maxval) \
  403. void vMin##sz##suf##p(const Vector##sz##suf* a, const Vector##sz##suf* b, Vector##sz##suf* out) { \
  404. for(int i = 0; i < sz; i++) \
  405. ((t*)out)[i] = fmin(((t*)a)[i], ((t*)b)[i]); \
  406. } \
  407. void vMax##sz##suf##p(const Vector##sz##suf* a, const Vector##sz##suf* b, Vector##sz##suf* out) { \
  408. for(int i = 0; i < sz; i++) \
  409. ((t*)out)[i] = fmax(((t*)a)[i], ((t*)b)[i]); \
  410. } \
  411. Vector##sz##suf vMin##sz##suf(Vector##sz##suf a, Vector##sz##suf b) { \
  412. Vector##sz##suf out; \
  413. vMin##sz##suf##p(&a, &b, &out); \
  414. return out; \
  415. } \
  416. Vector##sz##suf vMax##sz##suf(Vector##sz##suf a, Vector##sz##suf b) { \
  417. Vector##sz##suf out; \
  418. vMax##sz##suf##p(&a, &b, &out); \
  419. return out; \
  420. } \
  421. \
  422. int vMinComp##sz##suf##p(const Vector##sz##suf* a) { \
  423. t best = ((t*)a)[0]; \
  424. int best_ind = 0; \
  425. for(int i = 1; i < sz; i++) { \
  426. if(((t*)a)[i] < best) { \
  427. best = ((t*)a)[i]; \
  428. best_ind = i; \
  429. } \
  430. } \
  431. return best_ind; \
  432. } \
  433. \
  434. int vMaxComp##sz##suf##p(const Vector##sz##suf* a) { \
  435. t best = ((t*)a)[0]; \
  436. int best_ind = 0; \
  437. for(int i = 1; i < sz; i++) { \
  438. if(((t*)a)[i] > best) { \
  439. best = ((t*)a)[i]; \
  440. best_ind = i; \
  441. } \
  442. } \
  443. return best_ind; \
  444. } \
  445. \
  446. int vMinComp##sz##suf(const Vector##sz##suf a) { \
  447. return vMinComp##sz##suf##p(&a); \
  448. } \
  449. \
  450. int vMaxComp##sz##suf(const Vector##sz##suf a) { \
  451. return vMaxComp##sz##suf##p(&a); \
  452. } \
  453. \
  454. Vector##sz##suf vClamp##sz##suf(Vector##sz##suf in, Vector##sz##suf min, Vector##sz##suf max) { \
  455. Vector##sz##suf out; \
  456. for(int i = 0; i < sz; i++) \
  457. ((t*)&out)[i] = fmax(((t*)&min)[i], fmin(((t*)&in)[i], ((t*)&max)[i])); \
  458. return out; \
  459. } \
  460. Vector##sz##suf vAbs##sz##suf(const Vector##sz##suf v) { \
  461. Vector##sz##suf out; \
  462. vAbs##sz##suf##p(&v, &out); \
  463. return out; \
  464. } \
  465. void vAbs##sz##suf##p(const Vector##sz##suf* v, Vector##sz##suf* out) { \
  466. for(int i = 0; i < sz; i++) \
  467. ((t*)out)[i] = abs_##t( ((t*)v)[i] ); \
  468. } \
  469. Vector##sz##suf vSign##sz##suf(const Vector##sz##suf v) { \
  470. Vector##sz##suf out; \
  471. vSign##sz##suf##p(&v, &out); \
  472. return out; \
  473. } \
  474. void vSign##sz##suf##p(const Vector##sz##suf* v, Vector##sz##suf* out) { \
  475. for(int i = 0; i < sz; i++) \
  476. ((t*)out)[i] = copysign((t)1.0, ((t*)v)[i] ); \
  477. } \
  478. Vector##sz##suf vStep##sz##suf(const Vector##sz##suf edge, const Vector##sz##suf v) { \
  479. Vector##sz##suf out; \
  480. vStep##sz##suf##p(&edge, &v, &out); \
  481. return out; \
  482. } \
  483. void vStep##sz##suf##p(const Vector##sz##suf* edge, const Vector##sz##suf* v, Vector##sz##suf* out) { \
  484. for(int i = 0; i < sz; i++) \
  485. ((t*)out)[i] = ((t*)v)[i] < ((t*)edge)[i] ? 0.0 : 1.0; \
  486. } \
  487. FN(2, , float, FLT_MAX)
  488. FN(3, , float, FLT_MAX)
  489. FN(4, , float, FLT_MAX)
  490. FN(2, d, double, DBL_MAX)
  491. FN(3, d, double, DBL_MAX)
  492. FN(4, d, double, DBL_MAX)
  493. #undef FN
  494. #define FN(sz, suf, t, maxval) \
  495. void vMin##sz##suf##p(const Vector##sz##suf* a, const Vector##sz##suf* b, Vector##sz##suf* out) { \
  496. for(int i = 0; i < sz; i++) \
  497. ((t*)out)[i] = MIN(((t*)a)[i], ((t*)b)[i]); \
  498. } \
  499. void vMax##sz##suf##p(const Vector##sz##suf* a, const Vector##sz##suf* b, Vector##sz##suf* out) { \
  500. for(int i = 0; i < sz; i++) \
  501. ((t*)out)[i] = MAX(((t*)a)[i], ((t*)b)[i]); \
  502. } \
  503. Vector##sz##suf vMin##sz##suf(Vector##sz##suf a, Vector##sz##suf b) { \
  504. Vector##sz##suf out; \
  505. vMin##sz##suf##p(&a, &b, &out); \
  506. return out; \
  507. } \
  508. Vector##sz##suf vMax##sz##suf(Vector##sz##suf a, Vector##sz##suf b) { \
  509. Vector##sz##suf out; \
  510. vMax##sz##suf##p(&a, &b, &out); \
  511. return out; \
  512. } \
  513. Vector##sz##suf vClamp##sz##suf(Vector##sz##suf in, Vector##sz##suf min, Vector##sz##suf max) { \
  514. Vector##sz##suf out; \
  515. for(int i = 0; i < sz; i++) \
  516. ((t*)&out)[i] = MAX(((t*)&min)[i], MIN(((t*)&in)[i], ((t*)&max)[i])); \
  517. return out; \
  518. } \
  519. Vector##sz##suf vAbs##sz##suf(const Vector##sz##suf v) { \
  520. Vector##sz##suf out; \
  521. vAbs##sz##suf##p(&v, &out); \
  522. return out; \
  523. } \
  524. void vAbs##sz##suf##p(const Vector##sz##suf* v, Vector##sz##suf* out) { \
  525. for(int i = 0; i < sz; i++) \
  526. ((t*)out)[i] = labs( ((t*)v)[i] ); \
  527. } \
  528. Vector##sz##suf vSign##sz##suf(const Vector##sz##suf v) { \
  529. Vector##sz##suf out; \
  530. vSign##sz##suf##p(&v, &out); \
  531. return out; \
  532. } \
  533. void vSign##sz##suf##p(const Vector##sz##suf* v, Vector##sz##suf* out) { \
  534. for(int i = 0; i < sz; i++) \
  535. ((t*)out)[i] = ((t*)v)[i] < 0 ? -1 : 1; \
  536. } \
  537. Vector##sz##suf vStep##sz##suf(const Vector##sz##suf edge, const Vector##sz##suf v) { \
  538. Vector##sz##suf out; \
  539. vStep##sz##suf##p(&edge, &v, &out); \
  540. return out; \
  541. } \
  542. void vStep##sz##suf##p(const Vector##sz##suf* edge, const Vector##sz##suf* v, Vector##sz##suf* out) { \
  543. for(int i = 0; i < sz; i++) \
  544. ((t*)out)[i] = ((t*)v)[i] < ((t*)edge)[i] ? 0.0 : 1.0; \
  545. } \
  546. FN(2, i, int, DBL_MAX)
  547. FN(3, i, int, DBL_MAX)
  548. FN(4, i, int, DBL_MAX)
  549. FN(2, l, long, DBL_MAX)
  550. FN(3, l, long, DBL_MAX)
  551. FN(4, l, long, DBL_MAX)
  552. #undef FN
  553. // Returns an arbitrary unit vector perpendicular to the input
  554. // The input vector does not need to be normalized
  555. void vPerp3p(Vector3* n, Vector3* out) {
  556. *out = vPerp3(*n);
  557. }
  558. Vector3 vPerp3(Vector3 n) {
  559. float f, d;
  560. float absx = fabs(n.x);
  561. float absy = fabs(n.y);
  562. if(absx < absy) {
  563. if(n.x < n.z) goto MIN_X;
  564. goto MIN_Z;
  565. }
  566. if(absy < fabs(n.z)) goto MIN_Y;
  567. goto MIN_Z;
  568. MIN_X:
  569. d = 1.0f / sqrtf(n.z * n.z + n.y * n.y);
  570. f = n.z;
  571. n.z = n.y * d;
  572. n.y = -f * d;
  573. n.x = 0;
  574. return n;
  575. MIN_Y:
  576. d = 1.0f / sqrtf(n.z * n.z + n.x * n.x);
  577. f = n.x;
  578. n.x = n.z * d;
  579. n.z = -f * d;
  580. n.y = 0;
  581. return n;
  582. MIN_Z:
  583. d = 1.0f / sqrtf(n.x * n.x + n.y * n.y);
  584. f = n.y;
  585. n.y = n.x * d;
  586. n.x = -f * d;
  587. n.z = 0;
  588. return n;
  589. }
  590. // Returns an arbitrary unit vector perpendicular to the input
  591. // The input vector does not need to be normalized
  592. void vPerp2p(Vector2* n, Vector2* out) {
  593. *out = vPerp2(*n);
  594. }
  595. Vector2 vPerp2(Vector2 n) {
  596. return vNorm2((Vector2){.x = -n.y, .y = n.x});
  597. }
  598. // Coordinate system conversions
  599. // Does not check for degenerate vectors
  600. // Cartesian to Spherical
  601. Vector3 vC2S3(Vector3 cart) {
  602. Vector3 sp;
  603. sp.rho = vMag3(cart);
  604. sp.theta = atan2f(cart.x, cart.y);
  605. sp.phi = acosf(cart.z / sp.rho);
  606. return sp;
  607. }
  608. // Spherical to Cartesian
  609. Vector3 vS2C3(Vector3 s) {
  610. float st, ct, sp, cp;
  611. // as of July 2022, gcc trunk is smart enough to automatically optimize to sincos, but clang isn't.
  612. sincosf(s.phi, &sp, &cp);
  613. sincosf(s.theta, &st, &ct);
  614. return (Vector3){
  615. .x = s.rho * sp * ct,
  616. .y = s.rho * sp * st,
  617. .z = s.rho * cp
  618. };
  619. }
  620. Vector3 closestPointToRay3(Vector3 p, Ray3 r) {
  621. Vector3 po = vSub3(p, r.o); // vector from the starting point to p
  622. float t = vDot3(po, r.d); // project the pa onto the ray direction
  623. fclamp(t, 0.0, 1.0); // clamp t to between the endpoints of the line segment
  624. return vSub3(po, vScale3(r.d, t));
  625. }
  626. // completely untested.
  627. // can probably be optimized
  628. // This function is poorly named. It is designed to check if a bounding sphere intersects a cone surrounding a viewing frustum.
  629. int distanceSphereToCone(Vector3 spc, float spr, Vector3 c1, Vector3 c2, float cr1, float cr2) {
  630. Vector3 cnorm = vNorm(vSub(c2, c1)); // normal pointing down the center of the cone
  631. Vector3 sp_c1 = vSub(spc, c1); // vector pointing from c1 to the sphere center
  632. Vector3 up = vCross3(spc, cnorm); // vector perpendicular to the plane containing the cone's centerline and the sphere center.
  633. Vector3 perp_toward_sp = vNorm(vCross3(cnorm, up)); // vector perpendicular to the cone's centerline within the plane, towards the sphere
  634. Vector3 outer_c1 = vAdd(c1, vScale(perp_toward_sp, cr1)); // point in the plane on the outer edge of the cone
  635. Vector3 outer_c2 = vAdd(c2, vScale(perp_toward_sp, cr2)); // point in the plane on the outer edge of the cone
  636. Vector3 closest = closestPointToRay3(spc, (Ray3){.o = outer_c1, .d = vNorm(vSub(outer_c2, outer_c1))}); // point on the cone closest to the sphere
  637. // this part is probably wrong
  638. if(vDot(perp_toward_sp, vSub(spc, closest)) < 0) return 1; // is the sphere center inside the cone?
  639. return (vDist(closest, spc) - spr) <= 0;
  640. }
  641. float distTPointRay3(Vector3 p, Ray3 r, float* T) {
  642. Vector3 pa = vSub3(p, r.o);
  643. Vector3 ba = vNeg3(r.d);// vSub3(ls.end, ls.start);
  644. float t = vDot3(pa, ba) / vDot3(ba, ba);
  645. if(T) *T = t;
  646. return vLen3(vSub3(pa, vScale3(ba, t)));
  647. }
  648. float dist2TPointRay3(Vector3 p, Ray3 r, float* T) {
  649. Vector3 pa = vSub3(p, r.o);
  650. Vector3 ba = vNeg3(r.d);// vSub3(ls.end, ls.start);
  651. float t = vDot3(pa, ba) / vDot3(ba, ba);
  652. if(T) *T = t;
  653. return vLenSq3(vSub3(pa, vScale3(ba, t)));
  654. }
  655. int vInsidePolygon(Vector2 p, Polygon* poly) {
  656. int inside = 0;
  657. int cnt = poly->pointCount;
  658. if(poly->maxRadiusSq < vDot2(poly->centroid, p)) return 0;
  659. for(int i = 0; i < cnt; i++) {
  660. Vector2 a = poly->points[i];
  661. Vector2 b = poly->points[(i + 1) % cnt];
  662. if(a.y == b.y) continue; // horizontal edges are ignored
  663. // we're testing a ray going to the right
  664. if(a.x < p.x && b.x < p.x) continue; // segment is entirely left of the point
  665. if(a.y >= p.y && b.y >= p.y) continue; // segment entirely above the point
  666. if(a.y < p.y && b.y < p.y) continue; // segment entirely below the point
  667. // segment is in the same vertical band as the point
  668. float sx = a.x + (b.x - a.x) * ((p.y - a.y) / (b.y - a.y));
  669. if(p.x > sx) continue;
  670. inside = !inside;
  671. }
  672. return inside;
  673. }
  674. // Muchas gracias, Inigo.
  675. // https://iquilezles.org/articles/distfunctions2d/
  676. float vDistPolygon(Vector2 p, Polygon* poly) {
  677. float d = vDot2(vSub2(p, poly->points[0]), vSub2(p, poly->points[0]));
  678. float s = 1.0;
  679. for(int i = 0, j = poly->pointCount - 1; i < poly->pointCount; j = i, i++) {
  680. Vector2 A = poly->points[i];
  681. Vector2 B = poly->points[j];
  682. Vector2 e = vSub2(B, A);
  683. Vector2 w = vSub2(p, A);
  684. Vector2 b = vSub2(w, vScale2(e, fclamp(vDot2(w, e) / vDot2(e, e), 0.0, 1.0)));
  685. d = fminf(d, vDot2(b, b));
  686. int c1 = p.y >= A.y;
  687. int c2 = p.y < B.y;
  688. int c3 = e.x * w.y > e.y * w.x;
  689. if((c1 && c2 && c3) || (!c1 && !c2 && !c3)) s *= -1.0;
  690. }
  691. return s * sqrtf(d);
  692. }
  693. // ----
  694. void polyCalcCentroid(Polygon* poly) {
  695. int cnt = poly->pointCount;
  696. Vector2 centroid = {0,0};
  697. for(int i = 0; i < cnt; i++) {
  698. Vector2 a = poly->points[i];
  699. centroid = vAdd2(centroid, a);
  700. }
  701. poly->centroid = vScale2(centroid, 1.0 / poly->pointCount);
  702. }
  703. void polyCalcRadiusSq(Polygon* poly) {
  704. int cnt = poly->pointCount;
  705. float d = 0;
  706. for(int i = 0; i < cnt; i++) {
  707. Vector2 a = poly->points[i];
  708. d = fmaxf(d, vDot2(poly->centroid, a));
  709. }
  710. poly->maxRadiusSq = d;
  711. }
  712. // feeding a zero vector into this will cause div/0 and you will deserve it
  713. void vProject3p(Vector3* what, Vector3* onto, Vector3* out) { // slower; onto may not be normalized
  714. float wdo = vDot3p(what, onto);
  715. float odo = vDot3p(onto, onto);
  716. vScale3p(onto, wdo / odo, out);
  717. }
  718. void vProjectNorm3p(Vector3* what, Vector3* onto, Vector3* out) { // faster; onto must be normalized
  719. float wdo = vDot3p(what, onto);
  720. vScale3p(onto, wdo, out);
  721. }
  722. void vRandomPCG2p(Vector2* end1, Vector2* end2, PCG* pcg, Vector2* out) {
  723. out->x = frandPCG(fminf(end1->x, end2->x), fmaxf(end1->x, end2->x), pcg);
  724. out->y = frandPCG(fminf(end1->y, end2->y), fmaxf(end1->y, end2->y), pcg);
  725. }
  726. Vector2 vRandomPCG2(Vector2 end1, Vector2 end2, PCG* pcg) {
  727. Vector2 o;
  728. vRandomPCG2p(&end1, &end2, pcg, &o);
  729. return o;
  730. }
  731. void vRandomNormPCG2p(PCG* pcg, Vector2* out) {
  732. float th = frandPCG(0, 2.0 * F_PI, pcg);
  733. float sth, cth;
  734. sincosf(th, &sth, &cth);
  735. out->x = cth;
  736. out->y = sth;
  737. }
  738. Vector2 vRandomNormPCG2(PCG* pcg) {
  739. Vector2 o;
  740. vRandomNormPCG2p(pcg, &o);
  741. return o;
  742. }
  743. void vRandomPCG3p(Vector3* end1, Vector3* end2, PCG* pcg, Vector3* out) {
  744. out->x = frandPCG(fminf(end1->x, end2->x), fmaxf(end1->x, end2->x), pcg);
  745. out->y = frandPCG(fminf(end1->y, end2->y), fmaxf(end1->y, end2->y), pcg);
  746. out->z = frandPCG(fminf(end1->z, end2->z), fmaxf(end1->z, end2->z), pcg);
  747. }
  748. Vector3 vRandomPCG3(Vector3 end1, Vector3 end2, PCG* pcg) {
  749. Vector3 o;
  750. vRandomPCG3p(&end1, &end2, pcg, &o);
  751. return o;
  752. }
  753. // This algorithm is uniformly distributed over the surface of a sphere. There is no clustering at the poles.
  754. void vRandomNormPCG3p(PCG* pcg, Vector3* out) {
  755. float u = frandPCG(-1.f, 1.f, pcg);
  756. float th = frandPCG(0.f, 2.f * F_PI, pcg);
  757. float q = sqrtf(1.f - u * u);
  758. float sth, cth;
  759. sincosf(th, &sth, &cth);
  760. out->x = u * cth;
  761. out->y = u * sth;
  762. out->z = u;
  763. }
  764. Vector3 vRandomNormPCG3(PCG* pcg) {
  765. Vector3 o;
  766. vRandomNormPCG3p(pcg, &o);
  767. return o;
  768. }
  769. void vRandom3p(Vector3* end1, Vector3* end2, Vector3* out) {
  770. out->x = frand(fminf(end1->x, end2->x), fmaxf(end1->x, end2->x));
  771. out->y = frand(fminf(end1->y, end2->y), fmaxf(end1->y, end2->y));
  772. out->z = frand(fminf(end1->z, end2->z), fmaxf(end1->z, end2->z));
  773. }
  774. Vector3 vRandom3(Vector3 end1, Vector3 end2) {
  775. return (Vector3){
  776. .x = frand(fminf(end1.x, end2.x), fmaxf(end1.x, end2.x)),
  777. .y = frand(fminf(end1.y, end2.y), fmaxf(end1.y, end2.y)),
  778. .z = frand(fminf(end1.z, end2.z), fmaxf(end1.z, end2.z))
  779. };
  780. }
  781. // Uniformly distributed around the unit sphere; ie, no clustering at the poles.
  782. Vector3 vRandomNorm3() {
  783. Vector3 out;
  784. vRandomNorm3p(&out);
  785. return out;
  786. }
  787. void vRandomNorm3p(Vector3* out) {
  788. float u = frand(-1.0, 1.0);
  789. float th = frand(0, 2.0 * F_PI);
  790. float q = sqrtf(1.0 - u * u);
  791. float sth, cth;
  792. sincosf(th, &sth, &cth);
  793. out->x = u * cth;
  794. out->y = u * sth;
  795. out->z = u;
  796. }
  797. Vector4i vFloor4(const Vector4 v) {
  798. return (Vector4i){.x = floorf(v.x), .y = floorf(v.y), .z = floorf(v.z), .w = floorf(v.w)};
  799. }
  800. Vector4i vCeil4(const Vector4 v) {
  801. return (Vector4i){.x = ceilf(v.x), .y = ceilf(v.y), .z = ceilf(v.z), .w = ceilf(v.w)};
  802. }
  803. Vector3i vFloor3(const Vector3 v) {
  804. return (Vector3i){.x = floorf(v.x), .y = floorf(v.y), .z = floorf(v.z)};
  805. }
  806. Vector3i vCeil3(const Vector3 v) {
  807. return (Vector3i){.x = ceilf(v.x), .y = ceilf(v.y), .z = ceilf(v.z)};
  808. }
  809. Vector2i vFloor2(const Vector2 v) {
  810. return (Vector2i){.x = floorf(v.x), .y = floorf(v.y)};
  811. }
  812. Vector2i vCeil2(const Vector2 v) {
  813. return (Vector2i){.x = ceilf(v.x), .y = ceilf(v.y)};
  814. }
  815. Vector4l vFloor4d(const Vector4d v) {
  816. return (Vector4l){.x = floor(v.x), .y = floor(v.y), .z = floor(v.z), .w = floor(v.w)};
  817. }
  818. Vector4l vCeil4d(const Vector4d v) {
  819. return (Vector4l){.x = ceil(v.x), .y = ceil(v.y), .z = ceil(v.z), .w = ceil(v.w)};
  820. }
  821. Vector3l vFloor3d(const Vector3d v) {
  822. return (Vector3l){.x = floor(v.x), .y = floor(v.y), .z = floor(v.z)};
  823. }
  824. Vector3l vCeil3d(const Vector3d v) {
  825. return (Vector3l){.x = ceil(v.x), .y = ceil(v.y), .z = ceil(v.z)};
  826. }
  827. Vector2l vFloor2d(const Vector2d v) {
  828. return (Vector2l){.x = floor(v.x), .y = floor(v.y)};
  829. }
  830. Vector2l vCeil2d(const Vector2d v) {
  831. return (Vector2l){.x = ceil(v.x), .y = ceil(v.y)};
  832. }
  833. Vector2 vModPositive2(Vector2 v, Vector2 m) {
  834. return (Vector2){
  835. .x = fmodf(fmodf(v.x, m.x) + m.x, m.x),
  836. .y = fmodf(fmodf(v.y, m.y) + m.y, m.y),
  837. };
  838. }
  839. Vector3 vModPositive3(Vector3 v, Vector3 m) {
  840. return (Vector3){
  841. .x = fmodf(fmodf(v.x, m.x) + m.x, m.x),
  842. .y = fmodf(fmodf(v.y, m.y) + m.y, m.y),
  843. .z = fmodf(fmodf(v.z, m.z) + m.z, m.z),
  844. };
  845. }
  846. Vector4 vModPositive4(Vector4 v, Vector4 m) {
  847. return (Vector4){
  848. .x = fmodf(fmodf(v.x, m.x) + m.x, m.x),
  849. .y = fmodf(fmodf(v.y, m.y) + m.y, m.y),
  850. .z = fmodf(fmodf(v.z, m.z) + m.z, m.z),
  851. .w = fmodf(fmodf(v.w, m.w) + m.w, m.w),
  852. };
  853. }
  854. // reflects the distance from v to pivot across pivot.
  855. // out, pivot, and v will all be in the same plane, with pivot half way between v and out
  856. void vReflectAcross3p(Vector3* v, Vector3* pivot, Vector3* out) {
  857. Vector3 v2 = vScale3(*v, -1);
  858. float d = vDot3(v2, *pivot) * 2.0;
  859. *out = vSub3(v2, vScale3(*pivot, d));
  860. }
  861. Vector3 vReflectAcross3(Vector3 v, Vector3 pivot) {
  862. Vector3 o;
  863. vReflectAcross3p(&v, &pivot, &o);
  864. return o;
  865. }
  866. // calculate a unit vector normal to a triangle's face.
  867. void vTriFaceNormal3p(Vector3* a, Vector3* b, Vector3* c, Vector3* out) {
  868. Vector3 b_a, c_a;
  869. vSub3p(b, a, &b_a);
  870. vSub3p(c, a, &c_a);
  871. vCross3p(&b_a, &c_a, out);
  872. vNorm3p(out, out);
  873. }
  874. // calculate a unit vector normal to a triangle's face.
  875. Vector3 vTriFaceNormal3(Vector3 a, Vector3 b, Vector3 c) {
  876. Vector3 b_a, c_a, out;
  877. b_a = vSub3(b, a);
  878. c_a = vSub3(c, a);
  879. return vNorm3(vCross3(b_a, c_a));
  880. }
  881. // calculate a unit vector normal to a triangle's face.
  882. Vector3 vTriFaceNormalArea3(Vector3 a, Vector3 b, Vector3 c, float* area) {
  883. Vector3 b_a, c_a, out;
  884. b_a = vSub3(b, a);
  885. c_a = vSub3(c, a);
  886. Vector3 n = vCross3(b_a, c_a);
  887. if(area) *area = vLen(n) * .5f;
  888. return vNorm3(n);
  889. }
  890. // calculate a unit vector normal to a triangle's face.
  891. void vpTriFaceNormal3p(Vector3* tri, Vector3* out) {
  892. vTriFaceNormal3p(tri+0, tri+1, tri+2, out);
  893. }
  894. void vProjectOntoPlane3p(Vector3* v, Plane* p, Vector3* out) {
  895. Vector3 v_ortho;
  896. // get the component of v that's perpendicular to the plane
  897. vProjectNorm3p(v, &p->n, &v_ortho);
  898. // subtract it from v
  899. vSub3p(v, &v_ortho, out);
  900. }
  901. void vProjectOntoPlaneNormalized3p(Vector3* v, Plane* p, Vector3* out) {
  902. vProjectOntoPlane3p(v, p, out);
  903. vNorm3p(out, out);
  904. }
  905. void planeFromPointNormal(Vector3* p, Vector3* norm, Plane* out) {
  906. out->n = *norm;
  907. out->d = vDot3p(norm, p);
  908. }
  909. // calculates a plane from a triangle
  910. void planeFromTriangle3p(Vector3* v1, Vector3* v2, Vector3* v3, Plane* out) {
  911. vTriFaceNormal3p(v1, v2, v3, &out->n);
  912. out->d = vDot3p(&out->n, v1);
  913. }
  914. // copy a plane
  915. void planeCopy3p(Plane* in, Plane* out) {
  916. out->n = in->n;
  917. out->d = in->d;
  918. }
  919. // reverses the plane's direction
  920. void planeInverse3p(Plane* in, Plane* out) {
  921. vInv3p(&in->n, &out->n);
  922. out->d = -in->d;
  923. }
  924. // classifies a point by which side of the plane it's on, default espilon
  925. int planeClassifyPoint3p(Plane* p, Vector3* pt) {
  926. return planeClassifyPointEps3p(p, pt, FLT_CMP_EPSILON);
  927. }
  928. // classifies a point by which side of the plane it's on, custom espilon
  929. int planeClassifyPointEps3p(Plane* p, Vector3* pt, float epsilon) {
  930. float dist = vDot3p(&p->n, pt);
  931. if(fabs(dist - p->d) < epsilon)
  932. return C3DLAS_COPLANAR;
  933. else if (dist < p->d)
  934. return C3DLAS_BACK;
  935. else
  936. return C3DLAS_FRONT;
  937. }
  938. // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
  939. // returns _INTERSECT or _DISJOINT
  940. int rayTriangleIntersect(
  941. Vector3* a, Vector3* b, Vector3* c, // triangle
  942. Vector3* ray_origin, Vector3* ray_dir, // ray
  943. float* u, float* v, float* t // barycentric out coords, t of intersection point along ray
  944. ) {
  945. Vector3 ab = vSub3(*b, *a);
  946. Vector3 ac = vSub3(*c, *a);
  947. Vector3 n = vCross3(ab, ac);
  948. float det = -vDot3(*ray_dir, n);
  949. if(fabsf(det) <= FLT_CMP_EPSILON) {
  950. return C3DLAS_DISJOINT; // the ray is parallel to the triangle
  951. }
  952. float idet = 1.0f / det;
  953. Vector3 ao = vSub3(*ray_origin, *a);
  954. Vector3 dao = vCross3(ao, *ray_dir);
  955. *u = vDot3(ac, dao) * idet;
  956. if(*u < 0.f) return C3DLAS_DISJOINT; // barycentric coord is outside the triangle
  957. *v = -vDot3(ab, dao) * idet;
  958. if(*v < 0.f || *u + *v > 1.f) return C3DLAS_DISJOINT; // barycentric coord is outside the triangle
  959. *t = vDot3(ao, n) * idet;
  960. // if(*t < 0.0f) return C3DLAS_DISJOINT; // the ray intersects the triangle behind the origin
  961. return C3DLAS_INTERSECT;
  962. }
  963. // returns _INTERSECT or _DISJOINT
  964. Vector3 triangleClosestPoint_Reference(
  965. Vector3* a, Vector3* b, Vector3* c, // triangle
  966. Vector3* p, // test point
  967. float* out_u, float* out_v // barycentric out coords of closest point
  968. ) {
  969. Vector3 ab = vSub3(*b, *a);
  970. Vector3 ac = vSub3(*c, *a);
  971. Vector3 n = vCross3(ab, ac);
  972. Vector3 ray_dir = vNeg3(vNorm(n));
  973. float idet = 1.0f / -vDot3(ray_dir, n);
  974. Vector3 ao = vSub3(*p, *a);
  975. Vector3 dao = vCross3(ao, ray_dir);
  976. // printf("idet = %f, n = %f,%f,%f\n", idet, n.x, n.y, n.z);
  977. float u = vDot3(ac, dao) * idet;
  978. float v = -vDot3(ab, dao) * idet;
  979. // printf("u,v = %f, %f\n", u, v);
  980. if(u >= 0 && v >= 0.f && u + v <= 1.f) {
  981. float nt = vDot3(ao, n);
  982. Vector3 planep = vAdd3(*p, vScale3(vNeg3(n), nt));
  983. return planep; // the ray intersects the triangle
  984. }
  985. float t_ab, t_bc, t_ca;
  986. // collect all the possible locations
  987. float dist[6];
  988. dist[0] = vDistTPointLine3(*p, (Line3){*a, *b}, &t_ab);
  989. dist[1] = vDistTPointLine3(*p, (Line3){*b, *c}, &t_bc);
  990. dist[2] = vDistTPointLine3(*p, (Line3){*c, *a}, &t_ca);
  991. dist[3] = vDist(*a, *p);
  992. dist[4] = vDist(*b, *p);
  993. dist[5] = vDist(*c, *p);
  994. // find the smallest distance
  995. float min = dist[0];
  996. int mini = 0;
  997. for(int i = 1; i < 6; i++) {
  998. if(dist[i] < min) {
  999. min = dist[i];
  1000. mini = i;
  1001. }
  1002. }
  1003. switch(mini) {
  1004. case 0: return vLerp(*a, *b, t_ab);
  1005. case 1: return vLerp(*b, *c, t_bc);
  1006. case 2: return vLerp(*c, *a, t_ca);
  1007. case 3: return *a;
  1008. case 4: return *b;
  1009. case 5: return *c;
  1010. }
  1011. return (Vector3){0,0,0}; // HACK just return something
  1012. }
  1013. /*
  1014. // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
  1015. // returns _INTERSECT or _DISJOINT
  1016. vec3 triangleClosestPoint(
  1017. Vector3* a, Vector3* b, Vector3* c, // triangle
  1018. Vector3* p, // test point
  1019. float* out_u, float* out_v // barycentric out coords of closest point
  1020. ) {
  1021. Vector3 ab = vSub3(*b, *a);
  1022. Vector3 ac = vSub3(*c, *a);
  1023. Vector3 n = vCross3(ab, ac); // triangle plane normal
  1024. Vector3 ap = vSub3(*p, *a);
  1025. Vector3 dap = vCross3(ap, vNeg(n)); // p projected onto the triangle's plane, relative to a
  1026. // p = w*a + u*b + v*c;
  1027. float u = vDot3(ac, dap); // inversely proportional to distance from _b_, aka "beta"
  1028. // u < 0 means outside the triangle past the a/c edge
  1029. // u > 1 means outside the triangle past b
  1030. // u == 0 means somewhere on the a/c edge
  1031. // if(*u < 0.f) return C3DLAS_DISJOINT; // barycentric coord is outside the triangle
  1032. float v = -vDot3(ab, dap); // inversely proportional to distance from _c_, aka "gamma"
  1033. // v < 0 means outside the triangle past the a/b edge
  1034. // v > 1 means outside the triangle past c
  1035. // v == 0 means somewhere on the a/b edge
  1036. // if(*u < 0.f || *u + *v < 1.0f) return C3DLAS_DISJOINT; // barycentric coord is outside the triangle
  1037. float w = 1.0f - u - v; // inversely proportional to distance from _a_, aka "alpha"
  1038. // w < 0 means outside the triangle past the b/c edge
  1039. // w > 1 means outside the triangle past a
  1040. // w == 0 means somewhere on the b/c edge
  1041. if(u > 0 && v > 0 && w > 0) // point inside triangle
  1042. float t = vDot3(ap, n);
  1043. vec3 closest = vAdd3(*p, vScale3(vNeg(n), t));
  1044. return closest;
  1045. }
  1046. float new_u = 0, new_v = 0, new_w = 0;
  1047. if(w < 0) {
  1048. float t = fclamp(0f, 1f, vDot3() / vDot3());
  1049. new_v = 1.f - t;
  1050. new_w = t;
  1051. }
  1052. else if(v < 0) {
  1053. float t = fclamp(0f, 1f, vDot3() / vDot3());
  1054. new_u = t;
  1055. new_w = 1.f - t;
  1056. }
  1057. else if(u < 0) {
  1058. float t = fclamp(0f, 1f, vDot3() / vDot3());
  1059. new_u = 1.f - t;
  1060. new_v = t;
  1061. }
  1062. // if(*t < 0.0f) return C3DLAS_DISJOINT; // the ray intersects the triangle behind the origin
  1063. return C3DLAS_INTERSECT;
  1064. }
  1065. */
  1066. // C3DLAS_COPLANAR, _INTERSECT, or _DISJOINT
  1067. int triPlaneTestIntersect3p(Vector3* pTri, Plane* pl) {
  1068. Vector3 a, b, c;
  1069. float da, db, dc;
  1070. // get distance of each vertex from the plane
  1071. // bail early if any of them are coplanar
  1072. a = pTri[0];
  1073. da = vDot3p(&a, &pl->n) - pl->d;
  1074. if(fabs(da) < FLT_CMP_EPSILON) {
  1075. return C3DLAS_COPLANAR;
  1076. }
  1077. b = pTri[1];
  1078. db = vDot3p(&b, &pl->n) - pl->d;
  1079. if(fabs(db) < FLT_CMP_EPSILON) {
  1080. return C3DLAS_COPLANAR;
  1081. }
  1082. c = pTri[2];
  1083. dc = vDot3p(&c, &pl->n) - pl->d;
  1084. if(fabs(dc) < FLT_CMP_EPSILON) {
  1085. return C3DLAS_COPLANAR;
  1086. }
  1087. // the triangle intersects if the sign of all the distances does not match,
  1088. // ie, on vertex is on the opposite side of the plane from the others
  1089. return (signbit(da) == signbit(db) && signbit(db) == signbit(dc)) ? C3DLAS_DISJOINT : C3DLAS_INTERSECT;
  1090. }
  1091. // C3DLAS_COPLANAR, _INTERSECT, or _DISJOINT
  1092. int triPlaneClip3p(
  1093. Vector3* pTri,
  1094. Plane* pl,
  1095. Vector3* aboveOut,
  1096. Vector3* belowOut,
  1097. int* aboveCnt,
  1098. int* belowCnt
  1099. ) {
  1100. Vector3 v0, v1, v2;
  1101. float vp_d0, vp_d1, vp_d2;
  1102. v0 = pTri[0];
  1103. v1 = pTri[1];
  1104. v2 = pTri[2];
  1105. // get distance of each vertex from the plane
  1106. vp_d0 = vDot3p(&v0, &pl->n) - pl->d;
  1107. vp_d1 = vDot3p(&v1, &pl->n) - pl->d;
  1108. vp_d2 = vDot3p(&v2, &pl->n) - pl->d;
  1109. // bail early if just one is coplanar
  1110. // split in half with single-edge intersections
  1111. if(fabs(vp_d0) < FLT_CMP_EPSILON) {
  1112. if( // single edge intersection
  1113. signbit(vp_d1) != signbit(vp_d2) &&
  1114. fabs(vp_d1) > FLT_CMP_EPSILON &&
  1115. fabs(vp_d2) > FLT_CMP_EPSILON
  1116. ) {
  1117. // get intersection point
  1118. Vector3 c;
  1119. planeLineFindIntersectFast3p(pl, &v1, &v2, &c);
  1120. if(vp_d1 > 0) { // v1 is above the plane
  1121. aboveOut[0] = c; // correct winding
  1122. aboveOut[1] = v0;
  1123. aboveOut[2] = v1;
  1124. belowOut[0] = c;
  1125. belowOut[1] = v2;
  1126. belowOut[2] = v0;
  1127. }
  1128. else {
  1129. belowOut[0] = c; // correct winding
  1130. belowOut[1] = v0;
  1131. belowOut[2] = v1;
  1132. aboveOut[0] = c;
  1133. aboveOut[1] = v2;
  1134. aboveOut[2] = v0;
  1135. }
  1136. *aboveCnt = 1;
  1137. *belowCnt = 1;
  1138. return C3DLAS_INTERSECT;
  1139. }
  1140. return C3DLAS_COPLANAR; // one vertex is on the plane, the others all above or below
  1141. }
  1142. if(fabs(vp_d1) < FLT_CMP_EPSILON) {
  1143. if( // single edge intersection
  1144. signbit(vp_d0) != signbit(vp_d2) &&
  1145. fabs(vp_d0) > FLT_CMP_EPSILON &&
  1146. fabs(vp_d2) > FLT_CMP_EPSILON
  1147. ) {
  1148. // get intersection point
  1149. Vector3 c;
  1150. planeLineFindIntersectFast3p(pl, &v0, &v2, &c);
  1151. if(vp_d0 > 0) { // v0 is above the plane
  1152. aboveOut[0] = c; // correct winding
  1153. aboveOut[1] = v0;
  1154. aboveOut[2] = v1;
  1155. belowOut[0] = c;
  1156. belowOut[1] = v1;
  1157. belowOut[2] = v2;
  1158. }
  1159. else {
  1160. belowOut[0] = c; // correct winding
  1161. belowOut[1] = v0;
  1162. belowOut[2] = v1;
  1163. aboveOut[0] = c;
  1164. aboveOut[1] = v1;
  1165. aboveOut[2] = v2;
  1166. }
  1167. *aboveCnt = 1;
  1168. *belowCnt = 1;
  1169. return C3DLAS_INTERSECT;
  1170. }
  1171. return C3DLAS_COPLANAR; // one vertex is on the plane, the others all above or below
  1172. }
  1173. if(fabs(vp_d2) < FLT_CMP_EPSILON) {
  1174. if( // single edge intersection
  1175. signbit(vp_d0) != signbit(vp_d1) &&
  1176. fabs(vp_d0) > FLT_CMP_EPSILON &&
  1177. fabs(vp_d1) > FLT_CMP_EPSILON
  1178. ) {
  1179. // get intersection point
  1180. Vector3 c;
  1181. planeLineFindIntersectFast3p(pl, &v0, &v1, &c);
  1182. if(vp_d0 > 0) { // v0 is above the plane
  1183. aboveOut[0] = c; // correct winding
  1184. aboveOut[1] = v2;
  1185. aboveOut[2] = v0;
  1186. belowOut[0] = c;
  1187. belowOut[1] = v1;
  1188. belowOut[2] = v2;
  1189. }
  1190. else {
  1191. belowOut[0] = c; // correct winding
  1192. belowOut[1] = v2;
  1193. belowOut[2] = v0;
  1194. aboveOut[0] = c;
  1195. aboveOut[1] = v1;
  1196. aboveOut[2] = v2;
  1197. }
  1198. *aboveCnt = 1;
  1199. *belowCnt = 1;
  1200. return C3DLAS_INTERSECT;
  1201. }
  1202. return C3DLAS_COPLANAR; // one vertex is on the plane, the others all above or below
  1203. }
  1204. // the triangle intersects if the sign of all the distances does not match,
  1205. // ie, on vertex is on the opposite side of the plane from the others
  1206. // bail if disjoint
  1207. if(signbit(vp_d0) == signbit(vp_d1) && signbit(vp_d1) == signbit(vp_d2)) {
  1208. return C3DLAS_DISJOINT;
  1209. }
  1210. // split on which edges intersect the plane
  1211. if(signbit(vp_d0) == signbit(vp_d1)) {
  1212. // vertex 2 is isolated; edges 0,2 and 1,2 intersect
  1213. Vector3 c0, c1;
  1214. planeLineFindIntersectFast3p(pl, &v0, &v2, &c0);
  1215. planeLineFindIntersectFast3p(pl, &v1, &v2, &c1);
  1216. if(vp_d2 > 0) { // v2 is above the plane
  1217. aboveOut[0] = v2; // correct winding
  1218. aboveOut[1] = c0;
  1219. aboveOut[2] = c1;
  1220. belowOut[0] = c1;
  1221. belowOut[1] = v0;
  1222. belowOut[2] = v1;
  1223. belowOut[3] = c1;
  1224. belowOut[4] = c0;
  1225. belowOut[5] = v1;
  1226. *aboveCnt = 1;
  1227. *belowCnt = 2;
  1228. }
  1229. else {
  1230. belowOut[0] = v2; // correct winding
  1231. belowOut[1] = c0;
  1232. belowOut[2] = c1;
  1233. aboveOut[0] = c1;
  1234. aboveOut[1] = v0;
  1235. aboveOut[2] = v1;
  1236. aboveOut[3] = c1;
  1237. aboveOut[4] = c0;
  1238. aboveOut[5] = v1;
  1239. *aboveCnt = 2;
  1240. *belowCnt = 1;
  1241. }
  1242. }
  1243. else if(signbit(vp_d1) == signbit(vp_d2)) {
  1244. // vertex 0 is isolated; edges 1,0 and 2,0 intersect
  1245. Vector3 c0, c1;
  1246. planeLineFindIntersectFast3p(pl, &v1, &v0, &c0);
  1247. planeLineFindIntersectFast3p(pl, &v2, &v0, &c1);
  1248. if(vp_d0 > 0) { // v0 is above the plane
  1249. aboveOut[0] = v0; // correct winding
  1250. aboveOut[1] = c0;
  1251. aboveOut[2] = c1;
  1252. belowOut[0] = c1;
  1253. belowOut[1] = v1;
  1254. belowOut[2] = v2;
  1255. belowOut[3] = c1;
  1256. belowOut[4] = c0;
  1257. belowOut[5] = v1;
  1258. *aboveCnt = 1;
  1259. *belowCnt = 2;
  1260. }
  1261. else {
  1262. belowOut[0] = v0; // correct winding
  1263. belowOut[1] = c0;
  1264. belowOut[2] = c1;
  1265. aboveOut[0] = c1;
  1266. aboveOut[1] = v1;
  1267. aboveOut[2] = v2;
  1268. aboveOut[3] = c1;
  1269. aboveOut[4] = c0;
  1270. aboveOut[5] = v1;
  1271. *aboveCnt = 2;
  1272. *belowCnt = 1;
  1273. }
  1274. }
  1275. else {
  1276. // vertex 1 is isolated; edges 0,1 and 2,1 intersect
  1277. Vector3 c0, c1;
  1278. planeLineFindIntersectFast3p(pl, &v0, &v1, &c0);
  1279. planeLineFindIntersectFast3p(pl, &v2, &v1, &c1);
  1280. if(vp_d1 > 0) { // v1 is above the plane
  1281. aboveOut[0] = v1; // correct winding
  1282. aboveOut[1] = c1;
  1283. aboveOut[2] = c0;
  1284. belowOut[0] = c1;
  1285. belowOut[1] = v2;
  1286. belowOut[2] = v0;
  1287. belowOut[3] = c0;
  1288. belowOut[4] = c1;
  1289. belowOut[5] = v0;
  1290. *aboveCnt = 1;
  1291. *belowCnt = 2;
  1292. }
  1293. else {
  1294. belowOut[0] = v1; // correct winding
  1295. belowOut[1] = c1;
  1296. belowOut[2] = c0;
  1297. aboveOut[0] = c1;
  1298. aboveOut[1] = v2;
  1299. aboveOut[2] = v0;
  1300. aboveOut[3] = c0;
  1301. aboveOut[4] = c1;
  1302. aboveOut[5] = v0;
  1303. *aboveCnt = 2;
  1304. *belowCnt = 1;
  1305. }
  1306. }
  1307. return C3DLAS_INTERSECT;
  1308. }
  1309. // http://geomalgorithms.com/a07-_distance.html
  1310. // _PARALLEL with no output on parallel lines
  1311. // _INTERSECT with one point of output on intersection
  1312. // _DISJOINT with two outputs otherwise
  1313. int shortestLineFromRayToRay3p(Ray3* r1, Ray3* r2, Vector3* pOut) {
  1314. Vector3 u, v, w, ps, pt;
  1315. float a, b, c, d, e, s, t;
  1316. u = r1->d;
  1317. v = r2->d;
  1318. vSub3p(&r1->o, &r2->o, &w);
  1319. a = vDot3p(&u, &u);
  1320. b = vDot3p(&u, &v);
  1321. c = vDot3p(&v, &v);
  1322. d = vDot3p(&u, &w);
  1323. e = vDot3p(&v, &w);
  1324. float ac_bb = a * c - b * b;
  1325. if(fabs(ac_bb) < FLT_CMP_EPSILON) {
  1326. return C3DLAS_PARALLEL;
  1327. }
  1328. s = (b * e - c * d) / ac_bb;
  1329. t = (a * e - b * d) / ac_bb;
  1330. vScale3p(&u, s, &ps);
  1331. vScale3p(&v, t, &pt);
  1332. vAdd3p(&r1->o, &ps, &ps);
  1333. vAdd3p(&r2->o, &pt, &pt);
  1334. pOut[0] = ps;
  1335. pOut[1] = pt;
  1336. if(vDistSq3p(&ps, &pt) < FLT_CMP_EPSILON_SQ) {
  1337. return C3DLAS_INTERSECT;
  1338. }
  1339. return C3DLAS_DISJOINT;
  1340. }
  1341. void frustumFromMatrix(Matrix* m, Frustum* out) {
  1342. Matrix inv;
  1343. mInverse(m, &inv);
  1344. // first the points
  1345. // these MUST be in this order
  1346. // near
  1347. vMatrixMulf3p(-1,-1,-1, &inv, &out->points[0]);
  1348. vMatrixMulf3p(-1, 1,-1, &inv, &out->points[1]);
  1349. vMatrixMulf3p( 1,-1,-1, &inv, &out->points[2]);
  1350. vMatrixMulf3p( 1, 1,-1, &inv, &out->points[3]);
  1351. // far
  1352. vMatrixMulf3p(-1,-1, 1, &inv, &out->points[4]);
  1353. vMatrixMulf3p(-1, 1, 1, &inv, &out->points[5]);
  1354. vMatrixMulf3p( 1,-1, 1, &inv, &out->points[6]);
  1355. vMatrixMulf3p( 1, 1, 1, &inv, &out->points[7]);
  1356. // now the planes
  1357. // near and far
  1358. planeFromTriangle3p(&out->points[0], &out->points[1], &out->points[2], &out->planes[0]);
  1359. planeFromTriangle3p(&out->points[4], &out->points[5], &out->points[6], &out->planes[1]);
  1360. // sides
  1361. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[1], &out->planes[2]);
  1362. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[2], &out->planes[3]);
  1363. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[1], &out->planes[4]);
  1364. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[2], &out->planes[5]);
  1365. }
  1366. void frustumFromMatrixVK(Matrix* m, Frustum* out) {
  1367. Matrix inv;
  1368. mInverse(m, &inv);
  1369. // first the points
  1370. // these MUST be in this order
  1371. // near
  1372. vMatrixMulf3p(-1,-1, 0, &inv, &out->points[0]);
  1373. vMatrixMulf3p(-1, 1, 0, &inv, &out->points[1]);
  1374. vMatrixMulf3p( 1,-1, 0, &inv, &out->points[2]);
  1375. vMatrixMulf3p( 1, 1, 0, &inv, &out->points[3]);
  1376. // far
  1377. vMatrixMulf3p(-1,-1, 1, &inv, &out->points[4]);
  1378. vMatrixMulf3p(-1, 1, 1, &inv, &out->points[5]);
  1379. vMatrixMulf3p( 1,-1, 1, &inv, &out->points[6]);
  1380. vMatrixMulf3p( 1, 1, 1, &inv, &out->points[7]);
  1381. // now the planes
  1382. // near and far
  1383. planeFromTriangle3p(&out->points[0], &out->points[1], &out->points[2], &out->planes[0]);
  1384. planeFromTriangle3p(&out->points[4], &out->points[5], &out->points[6], &out->planes[1]);
  1385. // sides
  1386. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[1], &out->planes[2]);
  1387. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[2], &out->planes[3]);
  1388. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[1], &out->planes[4]);
  1389. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[2], &out->planes[5]);
  1390. }
  1391. void frustumFromMatrixVK_ZUP(Matrix* m, Frustum* out) {
  1392. Matrix inv;
  1393. mInverse(m, &inv);
  1394. *out = (Frustum){0};
  1395. // first the points
  1396. // these MUST be in this order
  1397. // near
  1398. vMatrixMulf3p(-1,-1, 0, &inv, &out->points[0]); // BUG this order is likely wrong for the planes but results in a sane wireframe.
  1399. vMatrixMulf3p( 1,-1, 0, &inv, &out->points[1]);
  1400. vMatrixMulf3p(-1, 1, 0, &inv, &out->points[2]);
  1401. vMatrixMulf3p( 1, 1, 0, &inv, &out->points[3]);
  1402. // far
  1403. vMatrixMulf3p(-1,-1, 1, &inv, &out->points[4]);
  1404. vMatrixMulf3p(1, -1, 1, &inv, &out->points[5]);
  1405. vMatrixMulf3p( -1,1, 1, &inv, &out->points[6]);
  1406. vMatrixMulf3p( 1, 1, 1, &inv, &out->points[7]);
  1407. // now the planes
  1408. // near and far
  1409. planeFromTriangle3p(&out->points[0], &out->points[1], &out->points[2], &out->planes[0]);
  1410. planeFromTriangle3p(&out->points[4], &out->points[5], &out->points[6], &out->planes[1]);
  1411. // sides
  1412. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[1], &out->planes[2]);
  1413. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[2], &out->planes[3]);
  1414. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[1], &out->planes[4]);
  1415. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[2], &out->planes[5]);
  1416. }
  1417. void frustumFromMatrixVK_RDepth(Matrix* m, Frustum* out) {
  1418. Matrix inv;
  1419. mInverse(m, &inv);
  1420. // first the points
  1421. // these MUST be in this order
  1422. // near
  1423. vMatrixMulf3p(-1,-1, 1, &inv, &out->points[0]);
  1424. vMatrixMulf3p(-1, 1, 1, &inv, &out->points[1]);
  1425. vMatrixMulf3p( 1,-1, 1, &inv, &out->points[2]);
  1426. vMatrixMulf3p( 1, 1, 1, &inv, &out->points[3]);
  1427. // far
  1428. vMatrixMulf3p(-1,-1, 0, &inv, &out->points[4]);
  1429. vMatrixMulf3p(-1, 1, 0, &inv, &out->points[5]);
  1430. vMatrixMulf3p( 1,-1, 0, &inv, &out->points[6]);
  1431. vMatrixMulf3p( 1, 1, 0, &inv, &out->points[7]);
  1432. // now the planes
  1433. // near and far
  1434. planeFromTriangle3p(&out->points[0], &out->points[1], &out->points[2], &out->planes[0]);
  1435. planeFromTriangle3p(&out->points[4], &out->points[5], &out->points[6], &out->planes[1]);
  1436. // sides
  1437. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[1], &out->planes[2]);
  1438. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[2], &out->planes[3]);
  1439. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[1], &out->planes[4]);
  1440. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[2], &out->planes[5]);
  1441. }
  1442. void frustumFromMatrixVK_ZUP_RDepth(Matrix* m, Frustum* out) {
  1443. Matrix inv;
  1444. mInverse(m, &inv);
  1445. *out = (Frustum){0};
  1446. // first the points
  1447. // these MUST be in this order
  1448. // near
  1449. vMatrixMulf3p(-1,-1, 1, &inv, &out->points[0]); // BUG this order is likely wrong for the planes but results in a sane wireframe.
  1450. vMatrixMulf3p( 1,-1, 1, &inv, &out->points[1]);
  1451. vMatrixMulf3p(-1, 1, 1, &inv, &out->points[2]);
  1452. vMatrixMulf3p( 1, 1, 1, &inv, &out->points[3]);
  1453. // far
  1454. vMatrixMulf3p(-1,-1, 0, &inv, &out->points[4]);
  1455. vMatrixMulf3p(1, -1, 0, &inv, &out->points[5]);
  1456. vMatrixMulf3p( -1,1, 0, &inv, &out->points[6]);
  1457. vMatrixMulf3p( 1, 1, 0, &inv, &out->points[7]);
  1458. // now the planes
  1459. // near and far
  1460. planeFromTriangle3p(&out->points[0], &out->points[1], &out->points[2], &out->planes[0]);
  1461. planeFromTriangle3p(&out->points[4], &out->points[5], &out->points[6], &out->planes[1]);
  1462. // sides
  1463. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[1], &out->planes[2]);
  1464. planeFromTriangle3p(&out->points[0], &out->points[4], &out->points[2], &out->planes[3]);
  1465. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[1], &out->planes[4]);
  1466. planeFromTriangle3p(&out->points[3], &out->points[7], &out->points[2], &out->planes[5]);
  1467. }
  1468. void frustumCenter(Frustum* f, Vector3* out) {
  1469. Vector3 sum = {0.0f,0.0f,0.0f};
  1470. for(int i = 0; i < 8; i++) vAdd3p(&f->points[i], &sum, &sum);
  1471. vScale3p(&sum, 1.0f/8.0f, out);
  1472. }
  1473. // General idea of the algorithm:
  1474. // https://lxjk.github.io/2017/04/15/Calculate-Minimal-Bounding-Sphere-of-Frustum.html
  1475. // http://archive.is/YACj2
  1476. void frustumBoundingSphere(Frustum* f, Sphere* out) {
  1477. Vector3 f0, n0;
  1478. vPointAvg3p(&f->points[0], &f->points[3], &n0);
  1479. vPointAvg3p(&f->points[4], &f->points[7], &f0);
  1480. float Dn2 = vDistSq3p(&n0, &f->points[0]);
  1481. float Df2 = vDistSq3p(&f0, &f->points[4]);
  1482. // check for ortho
  1483. if(Dn2 - Df2 < 0.00001) {
  1484. frustumCenter(f, &out->center);
  1485. out->r = vDist3p(&out->center, &f->points[0]);
  1486. return;
  1487. }
  1488. float Dnf = vDist3p(&f0, &n0);
  1489. float Dnc = (Dn2 - Df2 - Df2) / (2 * Dnf);
  1490. // printf("\n f: %f,%f,%f\n", f->points[4].x,f->points[4].y,f->points[4].z);
  1491. // printf(" n: %f,%f,%f\n", f->points[0].x,f->points[0].y,f->points[0].z);
  1492. // printf(" f0: %f,%f,%f\n", f0.x,f0.y,f0.z);
  1493. // printf(" n0: %f,%f,%f\n", n0.x,n0.y,n0.z);
  1494. // printf(" dn2, df2, dnf, dnc: %f,%f,%f,%f\n", Dn2, Df2, Dnf, Dnc);
  1495. if(Dnc > 0 && Dnc < Dnf) {
  1496. vLerp3p(&f0, &n0, Dnc / Dnf, &out->center);
  1497. out->r = sqrt(Dnc * Dnc + Dn2);
  1498. }
  1499. else {
  1500. out->center = f0;
  1501. out->r = sqrt(Df2);
  1502. }
  1503. }
  1504. void frustumInscribeSphere(Frustum* f, Sphere* out) {
  1505. Vector3 fx, nx;
  1506. vPointAvg3p(&f->points[0], &f->points[3], &nx);
  1507. vPointAvg3p(&f->points[4], &f->points[7], &fx);
  1508. /*
  1509. float Dn2 = vDistSq3p(&n0, &f->points[0]);
  1510. float Df2 = vDistSq3p(&f0, &f->points[4]);
  1511. float Dnf = vDist3p(&f0, n0);
  1512. float Dnc = (Dn2 - Df2 - Df2) / (2 * Dnf);*/
  1513. }
  1514. void quadCenterp3p(Vector3* a, Vector3* b, Vector3* c, Vector3* d, Vector3* out) {
  1515. Vector3 sum;
  1516. vAdd3p(a, b, &sum);
  1517. vAdd3p(&sum, c, &sum);
  1518. vAdd3p(&sum, d, &sum);
  1519. vScale3p(&sum, 0.25f, out);
  1520. }
  1521. void vPointAvg3p(Vector3* a, Vector3* b, Vector3* out) {
  1522. Vector3 sum;
  1523. vAdd3p(a, b, &sum);
  1524. vScale3p(&sum, 0.5f, out);
  1525. }
  1526. // reflects the distance from v to pivot across pivot.
  1527. // out, pivot, and v will form a straight line with pivot exactly in the middle.
  1528. void vReflectAcross2p(Vector2* v, Vector2* pivot, Vector2* out) {
  1529. Vector2 diff;
  1530. vSub2p(pivot, v, &diff);
  1531. vAdd2p(pivot, &diff, out);
  1532. }
  1533. // degenerate cases may not give desired results. GIGO.
  1534. void vRoundAway2p(const Vector2* in, const Vector2* center, Vector2i* out) {
  1535. if(in->x > center->x) out->x = ceilf(in->x);
  1536. else out->x = floorf(in->x);
  1537. if(in->y > center->y) out->y = ceilf(in->y);
  1538. else out->y = floorf(in->y);
  1539. }
  1540. // degenerate cases may not give desired results. GIGO.
  1541. void vRoundToward2p(const Vector2* in, const Vector2* center, Vector2i* out) {
  1542. if(in->x > center->x) out->x = floorf(in->x);
  1543. else out->x = ceilf(in->x);
  1544. if(in->y > center->y) out->y = floorf(in->y);
  1545. else out->y = ceilf(in->y);
  1546. }
  1547. // plane-vector operations
  1548. // distance from point to plane
  1549. float pvDist3p(Plane* p, Vector3* v) {
  1550. return vDot3p(v, &p->n) + p->d;
  1551. }
  1552. // matrix-vector operations
  1553. Vector3 vMatrixMulProjectedMagic3(Vector3 in, Matrix* m) {
  1554. Vector4 v;
  1555. v.x = in.x * m->m[0+0] + in.y * m->m[4+0] + in.z * m->m[8+0] + 1.0 * m->m[12+0];
  1556. v.y = in.x * m->m[0+1] + in.y * m->m[4+1] + in.z * m->m[8+1] + 1.0 * m->m[12+1];
  1557. v.z = in.x * m->m[0+2] + in.y * m->m[4+2] + in.z * m->m[8+2] + 1.0 * m->m[12+2];
  1558. v.w = in.x * m->m[0+3] + in.y * m->m[4+3] + in.z * m->m[8+3] + 1.0 * m->m[12+3];
  1559. if(v.w == 0) return (Vector3){0,0,0};
  1560. if(v.w < 0) v.w = -v.w;
  1561. return (Vector3){.x = v.x / v.w, .y = v.y / v.w, .z = v.z / v.w};
  1562. }
  1563. Vector3 vMatrixMul3(Vector3 in, Matrix* m) {
  1564. Vector4 v;
  1565. v.x = in.x * m->m[0+0] + in.y * m->m[4+0] + in.z * m->m[8+0] + 1.0 * m->m[12+0];
  1566. v.y = in.x * m->m[0+1] + in.y * m->m[4+1] + in.z * m->m[8+1] + 1.0 * m->m[12+1];
  1567. v.z = in.x * m->m[0+2] + in.y * m->m[4+2] + in.z * m->m[8+2] + 1.0 * m->m[12+2];
  1568. v.w = in.x * m->m[0+3] + in.y * m->m[4+3] + in.z * m->m[8+3] + 1.0 * m->m[12+3];
  1569. if(v.w == 0) return (Vector3){0,0,0};
  1570. return (Vector3){.x = v.x / v.w, .y = v.y / v.w, .z = v.z / v.w};
  1571. }
  1572. Vector4 vMatrixMul4(Vector4 in, Matrix* m) {
  1573. Vector4 v;
  1574. v.x = in.x * m->m[0+0] + in.y * m->m[4+0] + in.z * m->m[8+0] + in.w * m->m[12+0];
  1575. v.y = in.x * m->m[0+1] + in.y * m->m[4+1] + in.z * m->m[8+1] + in.w * m->m[12+1];
  1576. v.z = in.x * m->m[0+2] + in.y * m->m[4+2] + in.z * m->m[8+2] + in.w * m->m[12+2];
  1577. v.w = in.x * m->m[0+3] + in.y * m->m[4+3] + in.z * m->m[8+3] + in.w * m->m[12+3];
  1578. return v;
  1579. }
  1580. // multiply a vector by a matrix
  1581. void vMatrixMul3p(Vector3* restrict in, Matrix* restrict m, Vector3* restrict out) {
  1582. vMatrixMulf3p(in->x, in->y, in->z, m, out);
  1583. }
  1584. void vMatrixMulf3p(float x, float y, float z, Matrix* restrict m, Vector3* restrict out) {
  1585. Vector4 v;
  1586. v.x = x * m->m[0+0] + y * m->m[4+0] + z * m->m[8+0] + 1 * m->m[12+0];
  1587. v.y = x * m->m[0+1] + y * m->m[4+1] + z * m->m[8+1] + 1 * m->m[12+1];
  1588. v.z = x * m->m[0+2] + y * m->m[4+2] + z * m->m[8+2] + 1 * m->m[12+2];
  1589. v.w = x * m->m[0+3] + y * m->m[4+3] + z * m->m[8+3] + 1 * m->m[12+3];
  1590. out->x = v.x / v.w;
  1591. out->y = v.y / v.w;
  1592. out->z = v.z / v.w;
  1593. }
  1594. void evalBezier3p(Vector3* e1, Vector3* e2, Vector3* c1, Vector3* c2, float t, Vector3* out) {
  1595. out->x = evalBezier1D(e1->x, e2->x, c1->x, c2->x, t);
  1596. out->y = evalBezier1D(e1->y, e2->y, c1->y, c2->y, t);
  1597. out->z = evalBezier1D(e1->z, e2->z, c1->z, c2->z, t);
  1598. }
  1599. void evalBezier2D(Vector2* e1, Vector2* e2, Vector2* c1, Vector2* c2, float t, Vector2* out) {
  1600. out->x = evalBezier1D(e1->x, e2->x, c1->x, c2->x, t);
  1601. out->y = evalBezier1D(e1->y, e2->y, c1->y, c2->y, t);
  1602. }
  1603. float evalBezier1D(float e1, float e2, float c1, float c2, float t) {
  1604. float mt, mt2, t2;
  1605. mt = 1 - t;
  1606. mt2 = mt * mt;
  1607. t2 = t * t;
  1608. return (mt2 * mt * e1) + (3 * mt2 * t * c1) + (3 * t2 * mt * c2) + (t2 * t * e2);
  1609. }
  1610. void evalBezierTangent3p(Vector3* e1, Vector3* e2, Vector3* c1, Vector3* c2, float t, Vector3* out) {
  1611. out->x = evalBezier1D_dt(e1->x, e2->x, c1->x, c2->x, t);
  1612. out->y = evalBezier1D_dt(e1->y, e2->y, c1->y, c2->y, t);
  1613. out->z = evalBezier1D_dt(e1->z, e2->z, c1->z, c2->z, t);
  1614. }
  1615. float evalBezier1D_dt(float e1, float e2, float c1, float c2, float t) {
  1616. float mt, mt2, t2;
  1617. mt = 1 - t;
  1618. mt2 = mt * mt;
  1619. t2 = t * t;
  1620. return (3 * mt2 * (c1 - e1)) + (6 * mt * t * (c2 - c1)) + (3 * t2 * (e2 - c2));
  1621. }
  1622. float evalBezier1D_ddt(float e1, float e2, float c1, float c2, float t) {
  1623. return (6 * (1 - t) * (c2 - c1 - c1 + e1)) + (6 * t * (e2 - c2 - c2 - c1));
  1624. }
  1625. void evalBezierNorm3p(Vector3* e1, Vector3* e2, Vector3* c1, Vector3* c2, float t, Vector3* out) {
  1626. out->x = evalBezier1D_ddt(e1->x, e2->x, c1->x, c2->x, t);
  1627. out->y = evalBezier1D_ddt(e1->y, e2->y, c1->y, c2->y, t);
  1628. out->z = evalBezier1D_ddt(e1->z, e2->z, c1->z, c2->z, t);
  1629. }
  1630. // Quadratic bezier functions
  1631. float evalQBezier1D(float e1, float e2, float c1, float t) {
  1632. float mt, mt2;
  1633. mt = 1 - t;
  1634. mt2 = mt * mt;
  1635. return (mt2 * e1) + (2 * mt * t * c1) + (t * t * e2);
  1636. }
  1637. void evalQBezier2D3p(Vector2* e1, Vector2* e2, Vector2* c1, float t, Vector2* out) {
  1638. out->x = evalQBezier1D(e1->x, e2->x, c1->x, t);
  1639. out->y = evalQBezier1D(e1->y, e2->y, c1->y, t);
  1640. }
  1641. void evalQBezier3p(Vector3* e1, Vector3* e2, Vector3* c1, float t, Vector3* out) {
  1642. out->x = evalQBezier1D(e1->x, e2->x, c1->x, t);
  1643. out->y = evalQBezier1D(e1->y, e2->y, c1->y, t);
  1644. out->z = evalQBezier1D(e1->z, e2->z, c1->z, t);
  1645. }
  1646. ///// bounding box functions
  1647. // 3D versions
  1648. int boxDisjoint3p(const AABB3* a, const AABB3* b) {
  1649. return a->max.x < b->min.x || b->max.x < a->min.x
  1650. || a->max.y < b->min.y || b->max.y < a->min.y
  1651. || a->max.z < b->min.z || b->max.z < a->min.z;
  1652. }
  1653. int boxOverlaps3p(const AABB3* a, const AABB3* b) {
  1654. return !boxDisjoint3p(a, b);
  1655. }
  1656. int boxContainsPoint3p(const AABB3* b, const Vector3* p) {
  1657. return b->min.x <= p->x && b->max.x >= p->x
  1658. && b->min.y <= p->y && b->max.y >= p->y
  1659. && b->min.z <= p->z && b->max.z >= p->z;
  1660. }
  1661. void boxCenter3p(const AABB3* b, Vector3* out) {
  1662. out->x = (b->max.x + b->min.x) * .5f;
  1663. out->y = (b->max.y + b->min.y) * .5f;
  1664. out->z = (b->max.z + b->min.z) * .5f;
  1665. }
  1666. Vector3 boxCenter3(const AABB3 b) {
  1667. return (Vector3) {
  1668. (b.max.x + b.min.x) * .5f,
  1669. (b.max.y + b.min.y) * .5f,
  1670. (b.max.z + b.min.z) * .5f
  1671. };
  1672. }
  1673. void boxSize3p(const AABB3* b, Vector3* out) {
  1674. out->x = b->max.x - b->min.x;
  1675. out->y = b->max.y - b->min.y;
  1676. out->z = b->max.z - b->min.z;
  1677. }
  1678. Vector3 boxSize3(const AABB3 b) {
  1679. return (Vector3){
  1680. b.max.x - b.min.x,
  1681. b.max.y - b.min.y,
  1682. b.max.z - b.min.z
  1683. };
  1684. }
  1685. void boxExpandTo3p(AABB3* b, Vector3* p) {
  1686. b->min.x = fminf(b->min.x, p->x);
  1687. b->min.y = fminf(b->min.y, p->y);
  1688. b->min.z = fminf(b->min.z, p->z);
  1689. b->max.x = fmaxf(b->max.x, p->x);
  1690. b->max.y = fmaxf(b->max.y, p->y);
  1691. b->max.z = fmaxf(b->max.z, p->z);
  1692. }
  1693. void boxExpandTo3(AABB3* b, Vector3 p) {
  1694. boxExpandTo3p(b, &p);
  1695. }
  1696. // 2D versions
  1697. int boxDisjoint2p(const AABB2* a, const AABB2* b) {
  1698. return a->max.x < b->min.x || b->max.x < a->min.x
  1699. || a->max.y < b->min.y || b->max.y < a->min.y;
  1700. }
  1701. int boxOverlaps2p(const AABB2* a, const AABB2* b) {
  1702. return !boxDisjoint2p(a, b);
  1703. }
  1704. int boxContainsPoint2p(const AABB2* b, const Vector2* p) {
  1705. return b->min.x <= p->x && b->max.x >= p->x
  1706. && b->min.y <= p->y && b->max.y >= p->y;
  1707. }
  1708. void boxCenter2p(const AABB2* b, Vector2* out) {
  1709. out->x = (b->max.x + b->min.x) / 2.0;
  1710. out->y = (b->max.y + b->min.y) / 2.0;
  1711. }
  1712. Vector2 boxSize2(const AABB2 b) {
  1713. return (Vector2){
  1714. b.max.x - b.min.x,
  1715. b.max.y - b.min.y
  1716. };
  1717. }
  1718. void boxSize2p(const AABB2* b, Vector2* out) {
  1719. out->x = b->max.x - b->min.x;
  1720. out->y = b->max.y - b->min.y;
  1721. }
  1722. void boxQuadrant2p(const AABB2* in, char ix, char iy, AABB2* out) {
  1723. Vector2 sz, c;
  1724. boxCenter2p(in, &c);
  1725. boxSize2p(in, &sz);
  1726. sz.x *= .5;
  1727. sz.y *= .5;
  1728. out->min.x = c.x - (ix ? 0.0f : sz.x);
  1729. out->min.y = c.y - (iy ? 0.0f : sz.y);
  1730. out->max.x = c.x + (ix ? sz.x : 0.0f);
  1731. out->max.y = c.y + (iy ? sz.y : 0.0f);
  1732. }
  1733. // 2D integer versions
  1734. int boxDisjoint2ip(const AABB2i* a, const AABB2i* b) {
  1735. return a->max.x < b->min.x || b->max.x < a->min.x
  1736. || a->max.y < b->min.y || b->max.y < a->min.y;
  1737. }
  1738. int boxOverlaps2ip(const AABB2i* a, const AABB2i* b) {
  1739. return !boxDisjoint2ip(a, b);
  1740. }
  1741. int boxContainsPoint2ip(const AABB2i* b, const Vector2i* p) {
  1742. return b->min.x <= p->x && b->max.x >= p->x
  1743. && b->min.y <= p->y && b->max.y >= p->y;
  1744. }
  1745. void boxCenter2ip(const AABB2i* b, Vector2* out) {
  1746. out->x = (b->max.x + b->min.x) / 2.0f;
  1747. out->y = (b->max.y + b->min.y) / 2.0f;
  1748. }
  1749. void boxSize2ip(const AABB2i* b, Vector2* out) {
  1750. out->x = b->max.x - b->min.x;
  1751. out->y = b->max.y - b->min.y;
  1752. }
  1753. // BUG: needs some fancy math work to keep everything tight. integers don't split nicely
  1754. void boxQuadrant2ip(const AABB2i* in, char ix, char iy, AABB2i* out) {
  1755. Vector2 sz, c;
  1756. C3DLAS_errprintf("fix me: %s:%d: %s", __FILE__, __LINE__, __func__);
  1757. return;
  1758. // assert(0);
  1759. boxCenter2ip(in, &c);
  1760. boxSize2ip(in, &sz);
  1761. sz.x *= .5;
  1762. sz.y *= .5;
  1763. out->min.x = c.x - (ix ? 0.0f : sz.x);
  1764. out->min.y = c.y - (iy ? 0.0f : sz.y);
  1765. out->max.x = c.x + (ix ? sz.x : 0.0f);
  1766. out->max.y = c.y + (iy ? sz.y : 0.0f);
  1767. }
  1768. // find the center of a quad
  1769. void quadCenter2p(const Quad2* q, Vector2* out) {
  1770. Vector2 c = {0};
  1771. int i;
  1772. for(i = 0; i < 4; i++) {
  1773. c.x += q->v[i].x;
  1774. c.y += q->v[i].y;
  1775. }
  1776. out->x = c.x / 4;
  1777. out->y = c.y / 4;
  1778. }
  1779. void quadRoundOutward2p(const Quad2* in, Quad2i* out) {
  1780. Vector2 c;
  1781. int i;
  1782. quadCenter2p(in, &c);
  1783. for(i = 0; i < 4; i++)
  1784. vRoundAway2p(&in->v[i], &c, &out->v[i]);
  1785. }
  1786. void quadRoundInward2p(const Quad2* in, Quad2i* out) {
  1787. Vector2 c;
  1788. int i;
  1789. quadCenter2p(in, &c);
  1790. for(i = 0; i < 4; i++)
  1791. vRoundToward2p(&in->v[i], &c, &out->v[i]);
  1792. }
  1793. int quadIsPoint2i(const Quad2i* q) {
  1794. return (
  1795. (q->v[0].x == q->v[1].x) && (q->v[1].x == q->v[2].x) && (q->v[2].x == q->v[3].x) &&
  1796. (q->v[0].y == q->v[1].y) && (q->v[1].y == q->v[2].y) && (q->v[2].y == q->v[3].y)
  1797. );
  1798. }
  1799. int quadIsAARect2i(const Quad2i* q) {
  1800. return (
  1801. q->v[0].x == q->v[3].x && q->v[1].x == q->v[2].x &&
  1802. q->v[0].y == q->v[1].y && q->v[2].y == q->v[3].y);
  1803. }
  1804. // ray stuff
  1805. void makeRay3p(Vector3* origin, Vector3* direction, Ray3* out) {
  1806. out->o.x = origin->x;
  1807. out->o.y = origin->y;
  1808. out->o.z = origin->z;
  1809. vNorm3p(direction, &out->d);
  1810. }
  1811. // ray stuff
  1812. void makeRay2(Vector2* origin, Vector2* direction, Ray2* out) {
  1813. out->o.x = origin->x;
  1814. out->o.y = origin->y;
  1815. vNorm2p(direction, &out->d);
  1816. }
  1817. // returns a local t value for the segment the normalized value falls into
  1818. static float bsNormalToLocalT2(BezierSpline2* bs, float normalT, int* segNum) {
  1819. float segT = 1.0 / (bs->length - (!bs->isLoop));
  1820. if(segNum) *segNum = (int)(normalT / segT);
  1821. return fmod(normalT, segT) / segT;
  1822. }
  1823. // returns which segment a normalized t falls in
  1824. static int bsSegNum2(BezierSpline2* bs, float normalT) {
  1825. float segT = 1.0 / (bs->length - (!bs->isLoop));
  1826. return (int)(normalT / segT);
  1827. }
  1828. // returns a full set of control points for the segment t falls into
  1829. // out's order is e1, c1, c2, e2
  1830. static void bsSegmentForT2(BezierSpline2* bs, float normalT, Vector2* out) {
  1831. BezierSplineSegment2* p, *n;
  1832. int segN, i;
  1833. segN = i = bsSegNum2(bs, normalT);
  1834. p = bs->segments;
  1835. while(i--) p = p->next;
  1836. // a loop wraps around at the end
  1837. n = (bs->isLoop && (segN == (bs->length - 1))) ? bs->segments : p->next;
  1838. // end 1
  1839. out[0].x = p->e.x;
  1840. out[0].y = p->e.y;
  1841. // control 1
  1842. out[1].x = p->c.x;
  1843. out[1].y = p->c.y;
  1844. // control 2 - this one is reflected across e2
  1845. vReflectAcross2p(&n->c, &n->e, &out[2]);
  1846. // end 2
  1847. out[3].x = n->e.x;
  1848. out[3].y = n->e.y;
  1849. }
  1850. // BUG: this function is probably horribly broken
  1851. // this function evaluates a spline with a [0,1] normalized value of t across the whole spline
  1852. void bsEvalPoint2(BezierSpline2* bs, float normalT, Vector2* out) {
  1853. int segN;
  1854. float localT;
  1855. // find which spline segment the t is in
  1856. localT = bsNormalToLocalT2(bs, normalT, &segN);
  1857. // find the local value of t
  1858. Vector2 cp[4];
  1859. bsSegmentForT2(bs, normalT, cp);
  1860. evalBezier2D(&cp[0], &cp[3], &cp[1], &cp[2], localT, out);
  1861. }
  1862. // subdivide a spline into a set of line segments. linePoints must be allocated externally.
  1863. // this function is faster than more accurate ones.
  1864. void bsEvenLines(BezierSpline2* bs, int lineCount, Vector2* linePoints) {
  1865. /*
  1866. float tIncrement;
  1867. tIncrement = (float)(bs->length - (!bs->isLoop)) / (float)lineCount;
  1868. */
  1869. }
  1870. // Catmull-Rom Spline
  1871. float evalCatmullRom1D(float t, float a, float b, float c, float d) {
  1872. float t2 = t * t;
  1873. float t3 = t2 * t;
  1874. return 0.5f * (
  1875. (2.f * b) +
  1876. (-a + c) * t +
  1877. (2.f * a - 5.f * b + 4.f * c - d) * t2 +
  1878. (-a + 3.f * b - 3.f * c + d) * t3
  1879. );
  1880. }
  1881. Vector2 evalCatmullRom2D(float t, Vector2 a, Vector2 b, Vector2 c, Vector2 d) {
  1882. float t2 = t * t;
  1883. float t3 = t2 * t;
  1884. float q0 = -t3 + 2.f * t2 - t;
  1885. float q1 = 3.f * t3 - 5.f * t2 + 2.f;
  1886. float q2 = -3.f * t3 + 4.f * t2 + t;
  1887. float q3 = t3 - t2;
  1888. return (Vector2){
  1889. .x = 0.5f * (a.x * q0 + b.x * q1 + c.x * q2 + d.x * q3),
  1890. .y = 0.5f * (a.y * q0 + b.y * q1 + c.y * q2 + d.y * q3)
  1891. };
  1892. }
  1893. Vector3 evalCatmullRom3D(float t, Vector3 a, Vector3 b, Vector3 c, Vector3 d) {
  1894. float t2 = t * t;
  1895. float t3 = t2 * t;
  1896. float q0 = -t3 + 2.f * t2 - t;
  1897. float q1 = 3.f * t3 - 5.f * t2 + 2.f;
  1898. float q2 = -3.f * t3 + 4.f * t2 + t;
  1899. float q3 = t3 - t2;
  1900. return (Vector3){
  1901. .x = 0.5f * (a.x * q0 + b.x * q1 + c.x * q2 + d.x * q3),
  1902. .y = 0.5f * (a.y * q0 + b.y * q1 + c.y * q2 + d.y * q3),
  1903. .z = 0.5f * (a.z * q0 + b.z * q1 + c.z * q2 + d.z * q3)
  1904. };
  1905. }
  1906. float evalCatmullRom1D_dt(float t, float a, float b, float c, float d) {
  1907. float t2 = t * t;
  1908. float q0 = -3.f * t2 + 4.f * t - 1.f;
  1909. float q1 = 9.f * t2 - 10.f * t;
  1910. float q2 = -9.f * t2 + 8.f * t + 1.f;
  1911. float q3 = 3.f * t2 - 2.f * t;
  1912. return 0.5f * (a * q0 + b * q1 + c * q2 + d * q3);
  1913. }
  1914. Vector2 evalCatmullRom2D_dt(float t, Vector2 a, Vector2 b, Vector2 c, Vector2 d) {
  1915. float t2 = t * t;
  1916. float q0 = -3.f * t2 + 4.f * t - 1.f;
  1917. float q1 = 9.f * t2 - 10.f * t;
  1918. float q2 = -9.f * t2 + 8.f * t + 1.f;
  1919. float q3 = 3.f * t2 - 2.f * t;
  1920. return (Vector2){
  1921. .x = 0.5f * (a.x * q0 + b.x * q1 + c.x * q2 + d.x * q3),
  1922. .y = 0.5f * (a.y * q0 + b.y * q1 + c.y * q2 + d.y * q3)
  1923. };
  1924. }
  1925. Vector3 evalCatmullRom3D_dt(float t, Vector3 a, Vector3 b, Vector3 c, Vector3 d) {
  1926. float t2 = t * t;
  1927. float q0 = -3.f * t2 + 4.f * t - 1.f;
  1928. float q1 = 9.f * t2 - 10.f * t;
  1929. float q2 = -9.f * t2 + 8.f * t + 1.f;
  1930. float q3 = 3.f * t2 - 2.f * t;
  1931. return (Vector3){
  1932. .x = 0.5f * (a.x * q0 + b.x * q1 + c.x * q2 + d.x * q3),
  1933. .y = 0.5f * (a.y * q0 + b.y * q1 + c.y * q2 + d.y * q3),
  1934. .z = 0.5f * (a.z * q0 + b.z * q1 + c.z * q2 + d.z * q3)
  1935. };
  1936. }
  1937. float evalCatmullRom1D_both(float t, float a, float b, float c, float d, float* dt) {
  1938. float t2 = t * t;
  1939. float t3 = t2 * t;
  1940. float q0 = -t3 + 2.f * t2 - t;
  1941. float q1 = 3.f * t3 - 5.f * t2 + 2.f;
  1942. float q2 = -3.f * t3 + 4.f * t2 + t;
  1943. float q3 = t3 - t2;
  1944. float dq0 = -3.f * t2 + 4.f * t - 1.f;
  1945. float dq1 = 9.f * t2 - 10.f * t;
  1946. float dq2 = -9.f * t2 + 8.f * t + 1.f;
  1947. float dq3 = 3.f * t2 - 2.f * t;
  1948. *dt = 0.5f * (a * dq0 + b * dq1 + c * dq2 + d * dq3);
  1949. return 0.5f * (a * q0 + b * q1 + c * q2 + d * q3);
  1950. }
  1951. Vector2 evalCatmullRom2D_both(float t, Vector2 a, Vector2 b, Vector2 c, Vector2 d, Vector2* dt) {
  1952. float t2 = t * t;
  1953. float t3 = t2 * t;
  1954. float q0 = -t3 + 2.f * t2 - t;
  1955. float q1 = 3.f * t3 - 5.f * t2 + 2.f;
  1956. float q2 = -3.f * t3 + 4.f * t2 + t;
  1957. float q3 = t3 - t2;
  1958. float dq0 = -3.f * t2 + 4.f * t - 1.f;
  1959. float dq1 = 9.f * t2 - 10.f * t;
  1960. float dq2 = -9.f * t2 + 8.f * t + 1.f;
  1961. float dq3 = 3.f * t2 - 2.f * t;
  1962. *dt = (Vector2){
  1963. .x = 0.5f * (a.x * dq0 + b.x * dq1 + c.x * dq2 + d.x * dq3),
  1964. .y = 0.5f * (a.y * dq0 + b.y * dq1 + c.y * dq2 + d.y * dq3)
  1965. };
  1966. return (Vector2){
  1967. .x = 0.5f * (a.x * q0 + b.x * q1 + c.x * q2 + d.x * q3),
  1968. .y = 0.5f * (a.y * q0 + b.y * q1 + c.y * q2 + d.y * q3)
  1969. };
  1970. }
  1971. Vector3 evalCatmullRom3D_both(float t, Vector3 a, Vector3 b, Vector3 c, Vector3 d, Vector3* dt) {
  1972. float t2 = t * t;
  1973. float t3 = t2 * t;
  1974. float q0 = -t3 + 2.f * t2 - t;
  1975. float q1 = 3.f * t3 - 5.f * t2 + 2.f;
  1976. float q2 = -3.f * t3 + 4.f * t2 + t;
  1977. float q3 = t3 - t2;
  1978. float dq0 = -3.f * t2 + 4.f * t - 1.f;
  1979. float dq1 = 9.f * t2 - 10.f * t;
  1980. float dq2 = -9.f * t2 + 8.f * t + 1.f;
  1981. float dq3 = 3.f * t2 - 2.f * t;
  1982. *dt = (Vector3){
  1983. .x = 0.5f * (a.x * dq0 + b.x * dq1 + c.x * dq2 + d.x * dq3),
  1984. .y = 0.5f * (a.y * dq0 + b.y * dq1 + c.y * dq2 + d.y * dq3),
  1985. .z = 0.5f * (a.z * dq0 + b.z * dq1 + c.z * dq2 + d.z * dq3)
  1986. };
  1987. return (Vector3){
  1988. .x = 0.5f * (a.x * q0 + b.x * q1 + c.x * q2 + d.x * q3),
  1989. .y = 0.5f * (a.y * q0 + b.y * q1 + c.y * q2 + d.y * q3),
  1990. .z = 0.5f * (a.z * q0 + b.z * q1 + c.z * q2 + d.z * q3)
  1991. };
  1992. }
  1993. // Cubic Hermite Splines
  1994. float evalCubicHermite1D(float t, float p0, float p1, float m0, float m1) {
  1995. const float t2 = t * t;
  1996. const float t3 = t2 * t;
  1997. return (1 + t3 + t3 - t2 - t2 - t2) * p0 +
  1998. (t3 - t2 - t2 + t) * m0 +
  1999. (t2 + t2 + t2 - t3 - t3) * p1 +
  2000. (t3 - t2) * m1;
  2001. }
  2002. Vector2 evalCubicHermite2D(float t, Vector2 p0, Vector2 p1, Vector2 m0, Vector2 m1) {
  2003. return (Vector2){
  2004. .x = evalCubicHermite1D(t, p0.x, p1.x, m0.x, m1.x),
  2005. .y = evalCubicHermite1D(t, p0.y, p1.y, m0.y, m1.y)
  2006. };
  2007. }
  2008. Vector3 evalCubicHermite3D(float t, Vector3 p0, Vector3 p1, Vector3 m0, Vector3 m1) {
  2009. #ifdef C3DLAS_USE_SIMD
  2010. __m128 p0_ = _mm_loadu_ps((float*)&p0);
  2011. __m128 p1_ = _mm_loadu_ps((float*)&p1);
  2012. __m128 m0_ = _mm_loadu_ps((float*)&m0);
  2013. __m128 m1_ = _mm_loadu_ps((float*)&m1);
  2014. // __m128 t_ = _mm_load1_ps(&t);
  2015. // __m128 one = _mm_set_ps1(1.0f);
  2016. float t2 = t * t;
  2017. float t3 = t2 * t;
  2018. float t3_2 = t3 + t3;
  2019. float t2_2 = t2 + t2;
  2020. float t2_3 = t2_2 + t2;
  2021. // __m128 t3_2 = _mm_add_ps(t3, t3);
  2022. // __m128 t2_2 = _mm_add_ps(t2, t2);
  2023. // __m128 t2_3 = _mm_add_ps(t2_2, t2);
  2024. __m128 a = _mm_set_ps1(1.0f + t3_2 - t2_3);
  2025. __m128 o1 = _mm_mul_ps(a, p0_);
  2026. __m128 d = _mm_set_ps1(t3 + t - t2_2);
  2027. __m128 o2 = _mm_mul_ps(d, m0_);
  2028. __m128 e = _mm_set_ps1(t2_3 - t3_2);
  2029. __m128 o3 = _mm_mul_ps(e, p1_);
  2030. __m128 f = _mm_set_ps1(t3 + t2);
  2031. __m128 o4 = _mm_mul_ps(f, m1_);
  2032. __m128 o = _mm_add_ps(_mm_add_ps(o1, o2), _mm_add_ps(o3, o4));
  2033. union {
  2034. Vector4 v4;
  2035. Vector3 v3;
  2036. } u;
  2037. _mm_storeu_ps(&u.v4, o);
  2038. return u.v3;
  2039. #else
  2040. return (Vector3){
  2041. .x = evalCubicHermite1D(t, p0.x, p1.x, m0.x, m1.x),
  2042. .y = evalCubicHermite1D(t, p0.y, p1.y, m0.y, m1.y),
  2043. .z = evalCubicHermite1D(t, p0.z, p1.z, m0.z, m1.z)
  2044. };
  2045. #endif
  2046. }
  2047. #include "matrix3.c"
  2048. #include "matrix4.c"
  2049. #include "quaternion.c"
  2050. #include "quad.c"
  2051. #include "line.c"
  2052. #include "intersect/plane.c"
  2053. #include "intersect/box.c"
  2054. #include "intersect/line.c"
  2055. #include "intersect/triangle.c"