specific.odin 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706
  1. package linalg
  2. import "core:math"
  3. F16_EPSILON :: 1e-3;
  4. F32_EPSILON :: 1e-7;
  5. F64_EPSILON :: 1e-15;
  6. Vector2f16 :: distinct [2]f16;
  7. Vector3f16 :: distinct [3]f16;
  8. Vector4f16 :: distinct [4]f16;
  9. Matrix1x1f16 :: distinct [1][1]f16;
  10. Matrix1x2f16 :: distinct [1][2]f16;
  11. Matrix1x3f16 :: distinct [1][3]f16;
  12. Matrix1x4f16 :: distinct [1][4]f16;
  13. Matrix2x1f16 :: distinct [2][1]f16;
  14. Matrix2x2f16 :: distinct [2][2]f16;
  15. Matrix2x3f16 :: distinct [2][3]f16;
  16. Matrix2x4f16 :: distinct [2][4]f16;
  17. Matrix3x1f16 :: distinct [3][1]f16;
  18. Matrix3x2f16 :: distinct [3][2]f16;
  19. Matrix3x3f16 :: distinct [3][3]f16;
  20. Matrix3x4f16 :: distinct [3][4]f16;
  21. Matrix4x1f16 :: distinct [4][1]f16;
  22. Matrix4x2f16 :: distinct [4][2]f16;
  23. Matrix4x3f16 :: distinct [4][3]f16;
  24. Matrix4x4f16 :: distinct [4][4]f16;
  25. Matrix1f16 :: Matrix1x1f16;
  26. Matrix2f16 :: Matrix2x2f16;
  27. Matrix3f16 :: Matrix3x3f16;
  28. Matrix4f16 :: Matrix4x4f16;
  29. Vector2f32 :: distinct [2]f32;
  30. Vector3f32 :: distinct [3]f32;
  31. Vector4f32 :: distinct [4]f32;
  32. Matrix1x1f32 :: distinct [1][1]f32;
  33. Matrix1x2f32 :: distinct [1][2]f32;
  34. Matrix1x3f32 :: distinct [1][3]f32;
  35. Matrix1x4f32 :: distinct [1][4]f32;
  36. Matrix2x1f32 :: distinct [2][1]f32;
  37. Matrix2x2f32 :: distinct [2][2]f32;
  38. Matrix2x3f32 :: distinct [2][3]f32;
  39. Matrix2x4f32 :: distinct [2][4]f32;
  40. Matrix3x1f32 :: distinct [3][1]f32;
  41. Matrix3x2f32 :: distinct [3][2]f32;
  42. Matrix3x3f32 :: distinct [3][3]f32;
  43. Matrix3x4f32 :: distinct [3][4]f32;
  44. Matrix4x1f32 :: distinct [4][1]f32;
  45. Matrix4x2f32 :: distinct [4][2]f32;
  46. Matrix4x3f32 :: distinct [4][3]f32;
  47. Matrix4x4f32 :: distinct [4][4]f32;
  48. Matrix1f32 :: Matrix1x1f32;
  49. Matrix2f32 :: Matrix2x2f32;
  50. Matrix3f32 :: Matrix3x3f32;
  51. Matrix4f32 :: Matrix4x4f32;
  52. Vector2f64 :: distinct [2]f64;
  53. Vector3f64 :: distinct [3]f64;
  54. Vector4f64 :: distinct [4]f64;
  55. Matrix1x1f64 :: distinct [1][1]f64;
  56. Matrix1x2f64 :: distinct [1][2]f64;
  57. Matrix1x3f64 :: distinct [1][3]f64;
  58. Matrix1x4f64 :: distinct [1][4]f64;
  59. Matrix2x1f64 :: distinct [2][1]f64;
  60. Matrix2x2f64 :: distinct [2][2]f64;
  61. Matrix2x3f64 :: distinct [2][3]f64;
  62. Matrix2x4f64 :: distinct [2][4]f64;
  63. Matrix3x1f64 :: distinct [3][1]f64;
  64. Matrix3x2f64 :: distinct [3][2]f64;
  65. Matrix3x3f64 :: distinct [3][3]f64;
  66. Matrix3x4f64 :: distinct [3][4]f64;
  67. Matrix4x1f64 :: distinct [4][1]f64;
  68. Matrix4x2f64 :: distinct [4][2]f64;
  69. Matrix4x3f64 :: distinct [4][3]f64;
  70. Matrix4x4f64 :: distinct [4][4]f64;
  71. Matrix1f64 :: Matrix1x1f64;
  72. Matrix2f64 :: Matrix2x2f64;
  73. Matrix3f64 :: Matrix3x3f64;
  74. Matrix4f64 :: Matrix4x4f64;
  75. Quaternionf16 :: distinct quaternion64;
  76. Quaternionf32 :: distinct quaternion128;
  77. Quaternionf64 :: distinct quaternion256;
  78. MATRIX1F16_IDENTITY :: Matrix1f16{{1}};
  79. MATRIX2F16_IDENTITY :: Matrix2f16{{1, 0}, {0, 1}};
  80. MATRIX3F16_IDENTITY :: Matrix3f16{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
  81. MATRIX4F16_IDENTITY :: Matrix4f16{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
  82. MATRIX1F32_IDENTITY :: Matrix1f32{{1}};
  83. MATRIX2F32_IDENTITY :: Matrix2f32{{1, 0}, {0, 1}};
  84. MATRIX3F32_IDENTITY :: Matrix3f32{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
  85. MATRIX4F32_IDENTITY :: Matrix4f32{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
  86. MATRIX1F64_IDENTITY :: Matrix1f64{{1}};
  87. MATRIX2F64_IDENTITY :: Matrix2f64{{1, 0}, {0, 1}};
  88. MATRIX3F64_IDENTITY :: Matrix3f64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
  89. MATRIX4F64_IDENTITY :: Matrix4f64{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
  90. QUATERNIONF16_IDENTITY :: Quaternionf16(1);
  91. QUATERNIONF32_IDENTITY :: Quaternionf32(1);
  92. QUATERNIONF64_IDENTITY :: Quaternionf64(1);
  93. VECTOR3F16_X_AXIS :: Vector3f16{1, 0, 0};
  94. VECTOR3F16_Y_AXIS :: Vector3f16{0, 1, 0};
  95. VECTOR3F16_Z_AXIS :: Vector3f16{0, 0, 1};
  96. VECTOR3F32_X_AXIS :: Vector3f32{1, 0, 0};
  97. VECTOR3F32_Y_AXIS :: Vector3f32{0, 1, 0};
  98. VECTOR3F32_Z_AXIS :: Vector3f32{0, 0, 1};
  99. VECTOR3F64_X_AXIS :: Vector3f64{1, 0, 0};
  100. VECTOR3F64_Y_AXIS :: Vector3f64{0, 1, 0};
  101. VECTOR3F64_Z_AXIS :: Vector3f64{0, 0, 1};
  102. vector2_orthogonal :: proc(v: $V/[2]$E) -> V where !IS_ARRAY(E), IS_FLOAT(E) {
  103. return {-v.y, v.x};
  104. }
  105. vector3_orthogonal :: proc(v: $V/[3]$E) -> V where !IS_ARRAY(E), IS_FLOAT(E) {
  106. x := abs(v.x);
  107. y := abs(v.y);
  108. z := abs(v.z);
  109. other: V;
  110. if x < y {
  111. if x < z {
  112. other = {1, 0, 0};
  113. } else {
  114. other = {0, 0, 1};
  115. }
  116. } else {
  117. if y < z {
  118. other = {0, 1, 0};
  119. } else {
  120. other = {0, 0, 1};
  121. }
  122. }
  123. return normalize(cross(v, other));
  124. }
  125. orthogonal :: proc{vector2_orthogonal, vector3_orthogonal};
  126. vector4_srgb_to_linear_f16 :: proc(col: Vector4f16) -> Vector4f16 {
  127. r := math.pow(col.x, 2.2);
  128. g := math.pow(col.y, 2.2);
  129. b := math.pow(col.z, 2.2);
  130. a := col.w;
  131. return {r, g, b, a};
  132. }
  133. vector4_srgb_to_linear_f32 :: proc(col: Vector4f32) -> Vector4f32 {
  134. r := math.pow(col.x, 2.2);
  135. g := math.pow(col.y, 2.2);
  136. b := math.pow(col.z, 2.2);
  137. a := col.w;
  138. return {r, g, b, a};
  139. }
  140. vector4_srgb_to_linear_f64 :: proc(col: Vector4f64) -> Vector4f64 {
  141. r := math.pow(col.x, 2.2);
  142. g := math.pow(col.y, 2.2);
  143. b := math.pow(col.z, 2.2);
  144. a := col.w;
  145. return {r, g, b, a};
  146. }
  147. vector4_srgb_to_linear :: proc{
  148. vector4_srgb_to_linear_f16,
  149. vector4_srgb_to_linear_f32,
  150. vector4_srgb_to_linear_f64,
  151. };
  152. vector4_linear_to_srgb_f16 :: proc(col: Vector4f16) -> Vector4f16 {
  153. a :: 2.51;
  154. b :: 0.03;
  155. c :: 2.43;
  156. d :: 0.59;
  157. e :: 0.14;
  158. x := col.x;
  159. y := col.y;
  160. z := col.z;
  161. x = (x * (a * x + b)) / (x * (c * x + d) + e);
  162. y = (y * (a * y + b)) / (y * (c * y + d) + e);
  163. z = (z * (a * z + b)) / (z * (c * z + d) + e);
  164. x = math.pow(clamp(x, 0, 1), 1.0 / 2.2);
  165. y = math.pow(clamp(y, 0, 1), 1.0 / 2.2);
  166. z = math.pow(clamp(z, 0, 1), 1.0 / 2.2);
  167. return {x, y, z, col.w};
  168. }
  169. vector4_linear_to_srgb_f32 :: proc(col: Vector4f32) -> Vector4f32 {
  170. a :: 2.51;
  171. b :: 0.03;
  172. c :: 2.43;
  173. d :: 0.59;
  174. e :: 0.14;
  175. x := col.x;
  176. y := col.y;
  177. z := col.z;
  178. x = (x * (a * x + b)) / (x * (c * x + d) + e);
  179. y = (y * (a * y + b)) / (y * (c * y + d) + e);
  180. z = (z * (a * z + b)) / (z * (c * z + d) + e);
  181. x = math.pow(clamp(x, 0, 1), 1.0 / 2.2);
  182. y = math.pow(clamp(y, 0, 1), 1.0 / 2.2);
  183. z = math.pow(clamp(z, 0, 1), 1.0 / 2.2);
  184. return {x, y, z, col.w};
  185. }
  186. vector4_linear_to_srgb_f64 :: proc(col: Vector4f64) -> Vector4f64 {
  187. a :: 2.51;
  188. b :: 0.03;
  189. c :: 2.43;
  190. d :: 0.59;
  191. e :: 0.14;
  192. x := col.x;
  193. y := col.y;
  194. z := col.z;
  195. x = (x * (a * x + b)) / (x * (c * x + d) + e);
  196. y = (y * (a * y + b)) / (y * (c * y + d) + e);
  197. z = (z * (a * z + b)) / (z * (c * z + d) + e);
  198. x = math.pow(clamp(x, 0, 1), 1.0 / 2.2);
  199. y = math.pow(clamp(y, 0, 1), 1.0 / 2.2);
  200. z = math.pow(clamp(z, 0, 1), 1.0 / 2.2);
  201. return {x, y, z, col.w};
  202. }
  203. vector4_linear_to_srgb :: proc{
  204. vector4_linear_to_srgb_f16,
  205. vector4_linear_to_srgb_f32,
  206. vector4_linear_to_srgb_f64,
  207. };
  208. vector4_hsl_to_rgb_f16 :: proc(h, s, l: f16, a: f16 = 1) -> Vector4f16 {
  209. hue_to_rgb :: proc(p, q, t: f16) -> f16 {
  210. t := t;
  211. if t < 0 { t += 1; }
  212. if t > 1 { t -= 1; }
  213. switch {
  214. case t < 1.0/6.0: return p + (q - p) * 6.0 * t;
  215. case t < 1.0/2.0: return q;
  216. case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t);
  217. }
  218. return p;
  219. }
  220. r, g, b: f16;
  221. if s == 0 {
  222. r = l;
  223. g = l;
  224. b = l;
  225. } else {
  226. q := l * (1+s) if l < 0.5 else l+s - l*s;
  227. p := 2*l - q;
  228. r = hue_to_rgb(p, q, h + 1.0/3.0);
  229. g = hue_to_rgb(p, q, h);
  230. b = hue_to_rgb(p, q, h - 1.0/3.0);
  231. }
  232. return {r, g, b, a};
  233. }
  234. vector4_hsl_to_rgb_f32 :: proc(h, s, l: f32, a: f32 = 1) -> Vector4f32 {
  235. hue_to_rgb :: proc(p, q, t: f32) -> f32 {
  236. t := t;
  237. if t < 0 { t += 1; }
  238. if t > 1 { t -= 1; }
  239. switch {
  240. case t < 1.0/6.0: return p + (q - p) * 6.0 * t;
  241. case t < 1.0/2.0: return q;
  242. case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t);
  243. }
  244. return p;
  245. }
  246. r, g, b: f32;
  247. if s == 0 {
  248. r = l;
  249. g = l;
  250. b = l;
  251. } else {
  252. q := l * (1+s) if l < 0.5 else l+s - l*s;
  253. p := 2*l - q;
  254. r = hue_to_rgb(p, q, h + 1.0/3.0);
  255. g = hue_to_rgb(p, q, h);
  256. b = hue_to_rgb(p, q, h - 1.0/3.0);
  257. }
  258. return {r, g, b, a};
  259. }
  260. vector4_hsl_to_rgb_f64 :: proc(h, s, l: f64, a: f64 = 1) -> Vector4f64 {
  261. hue_to_rgb :: proc(p, q, t: f64) -> f64 {
  262. t := t;
  263. if t < 0 { t += 1; }
  264. if t > 1 { t -= 1; }
  265. switch {
  266. case t < 1.0/6.0: return p + (q - p) * 6.0 * t;
  267. case t < 1.0/2.0: return q;
  268. case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t);
  269. }
  270. return p;
  271. }
  272. r, g, b: f64;
  273. if s == 0 {
  274. r = l;
  275. g = l;
  276. b = l;
  277. } else {
  278. q := l * (1+s) if l < 0.5 else l+s - l*s;
  279. p := 2*l - q;
  280. r = hue_to_rgb(p, q, h + 1.0/3.0);
  281. g = hue_to_rgb(p, q, h);
  282. b = hue_to_rgb(p, q, h - 1.0/3.0);
  283. }
  284. return {r, g, b, a};
  285. }
  286. vector4_hsl_to_rgb :: proc{
  287. vector4_hsl_to_rgb_f16,
  288. vector4_hsl_to_rgb_f32,
  289. vector4_hsl_to_rgb_f64,
  290. };
  291. vector4_rgb_to_hsl_f16 :: proc(col: Vector4f16) -> Vector4f16 {
  292. r := col.x;
  293. g := col.y;
  294. b := col.z;
  295. a := col.w;
  296. v_min := min(r, g, b);
  297. v_max := max(r, g, b);
  298. h, s, l: f16;
  299. h = 0.0;
  300. s = 0.0;
  301. l = (v_min + v_max) * 0.5;
  302. if v_max != v_min {
  303. d: = v_max - v_min;
  304. s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min);
  305. switch {
  306. case v_max == r:
  307. h = (g - b) / d + (6.0 if g < b else 0.0);
  308. case v_max == g:
  309. h = (b - r) / d + 2.0;
  310. case v_max == b:
  311. h = (r - g) / d + 4.0;
  312. }
  313. h *= 1.0/6.0;
  314. }
  315. return {h, s, l, a};
  316. }
  317. vector4_rgb_to_hsl_f32 :: proc(col: Vector4f32) -> Vector4f32 {
  318. r := col.x;
  319. g := col.y;
  320. b := col.z;
  321. a := col.w;
  322. v_min := min(r, g, b);
  323. v_max := max(r, g, b);
  324. h, s, l: f32;
  325. h = 0.0;
  326. s = 0.0;
  327. l = (v_min + v_max) * 0.5;
  328. if v_max != v_min {
  329. d: = v_max - v_min;
  330. s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min);
  331. switch {
  332. case v_max == r:
  333. h = (g - b) / d + (6.0 if g < b else 0.0);
  334. case v_max == g:
  335. h = (b - r) / d + 2.0;
  336. case v_max == b:
  337. h = (r - g) / d + 4.0;
  338. }
  339. h *= 1.0/6.0;
  340. }
  341. return {h, s, l, a};
  342. }
  343. vector4_rgb_to_hsl_f64 :: proc(col: Vector4f64) -> Vector4f64 {
  344. r := col.x;
  345. g := col.y;
  346. b := col.z;
  347. a := col.w;
  348. v_min := min(r, g, b);
  349. v_max := max(r, g, b);
  350. h, s, l: f64;
  351. h = 0.0;
  352. s = 0.0;
  353. l = (v_min + v_max) * 0.5;
  354. if v_max != v_min {
  355. d: = v_max - v_min;
  356. s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min);
  357. switch {
  358. case v_max == r:
  359. h = (g - b) / d + (6.0 if g < b else 0.0);
  360. case v_max == g:
  361. h = (b - r) / d + 2.0;
  362. case v_max == b:
  363. h = (r - g) / d + 4.0;
  364. }
  365. h *= 1.0/6.0;
  366. }
  367. return {h, s, l, a};
  368. }
  369. vector4_rgb_to_hsl :: proc{
  370. vector4_rgb_to_hsl_f16,
  371. vector4_rgb_to_hsl_f32,
  372. vector4_rgb_to_hsl_f64,
  373. };
  374. quaternion_angle_axis_f16 :: proc(angle_radians: f16, axis: Vector3f16) -> (q: Quaternionf16) {
  375. t := angle_radians*0.5;
  376. v := normalize(axis) * math.sin(t);
  377. q.x = v.x;
  378. q.y = v.y;
  379. q.z = v.z;
  380. q.w = math.cos(t);
  381. return;
  382. }
  383. quaternion_angle_axis_f32 :: proc(angle_radians: f32, axis: Vector3f32) -> (q: Quaternionf32) {
  384. t := angle_radians*0.5;
  385. v := normalize(axis) * math.sin(t);
  386. q.x = v.x;
  387. q.y = v.y;
  388. q.z = v.z;
  389. q.w = math.cos(t);
  390. return;
  391. }
  392. quaternion_angle_axis_f64 :: proc(angle_radians: f64, axis: Vector3f64) -> (q: Quaternionf64) {
  393. t := angle_radians*0.5;
  394. v := normalize(axis) * math.sin(t);
  395. q.x = v.x;
  396. q.y = v.y;
  397. q.z = v.z;
  398. q.w = math.cos(t);
  399. return;
  400. }
  401. quaternion_angle_axis :: proc{
  402. quaternion_angle_axis_f16,
  403. quaternion_angle_axis_f32,
  404. quaternion_angle_axis_f64,
  405. };
  406. angle_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
  407. if abs(q.w) > math.SQRT_THREE*0.5 {
  408. return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2;
  409. }
  410. return math.cos(q.x) * 2;
  411. }
  412. angle_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
  413. if abs(q.w) > math.SQRT_THREE*0.5 {
  414. return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2;
  415. }
  416. return math.cos(q.x) * 2;
  417. }
  418. angle_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
  419. if abs(q.w) > math.SQRT_THREE*0.5 {
  420. return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2;
  421. }
  422. return math.cos(q.x) * 2;
  423. }
  424. angle_from_quaternion :: proc{
  425. angle_from_quaternion_f16,
  426. angle_from_quaternion_f32,
  427. angle_from_quaternion_f64,
  428. };
  429. axis_from_quaternion_f16 :: proc(q: Quaternionf16) -> Vector3f16 {
  430. t1 := 1 - q.w*q.w;
  431. if t1 < 0 {
  432. return {0, 0, 1};
  433. }
  434. t2 := 1.0 / math.sqrt(t1);
  435. return {q.x*t2, q.y*t2, q.z*t2};
  436. }
  437. axis_from_quaternion_f32 :: proc(q: Quaternionf32) -> Vector3f32 {
  438. t1 := 1 - q.w*q.w;
  439. if t1 < 0 {
  440. return {0, 0, 1};
  441. }
  442. t2 := 1.0 / math.sqrt(t1);
  443. return {q.x*t2, q.y*t2, q.z*t2};
  444. }
  445. axis_from_quaternion_f64 :: proc(q: Quaternionf64) -> Vector3f64 {
  446. t1 := 1 - q.w*q.w;
  447. if t1 < 0 {
  448. return {0, 0, 1};
  449. }
  450. t2 := 1.0 / math.sqrt(t1);
  451. return {q.x*t2, q.y*t2, q.z*t2};
  452. }
  453. axis_from_quaternion :: proc{
  454. axis_from_quaternion_f16,
  455. axis_from_quaternion_f32,
  456. axis_from_quaternion_f64,
  457. };
  458. angle_axis_from_quaternion_f16 :: proc(q: Quaternionf16) -> (angle: f16, axis: Vector3f16) {
  459. angle = angle_from_quaternion(q);
  460. axis = axis_from_quaternion(q);
  461. return;
  462. }
  463. angle_axis_from_quaternion_f32 :: proc(q: Quaternionf32) -> (angle: f32, axis: Vector3f32) {
  464. angle = angle_from_quaternion(q);
  465. axis = axis_from_quaternion(q);
  466. return;
  467. }
  468. angle_axis_from_quaternion_f64 :: proc(q: Quaternionf64) -> (angle: f64, axis: Vector3f64) {
  469. angle = angle_from_quaternion(q);
  470. axis = axis_from_quaternion(q);
  471. return;
  472. }
  473. angle_axis_from_quaternion :: proc {
  474. angle_axis_from_quaternion_f16,
  475. angle_axis_from_quaternion_f32,
  476. angle_axis_from_quaternion_f64,
  477. };
  478. quaternion_from_forward_and_up_f16 :: proc(forward, up: Vector3f16) -> Quaternionf16 {
  479. f := normalize(forward);
  480. s := normalize(cross(f, up));
  481. u := cross(s, f);
  482. m := Matrix3f16{
  483. {+s.x, +u.x, -f.x},
  484. {+s.y, +u.y, -f.y},
  485. {+s.z, +u.z, -f.z},
  486. };
  487. tr := trace(m);
  488. q: Quaternionf16;
  489. switch {
  490. case tr > 0:
  491. S := 2 * math.sqrt(1 + tr);
  492. q.w = 0.25 * S;
  493. q.x = (m[2][1] - m[1][2]) / S;
  494. q.y = (m[0][2] - m[2][0]) / S;
  495. q.z = (m[1][0] - m[0][1]) / S;
  496. case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]):
  497. S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]);
  498. q.w = (m[2][1] - m[1][2]) / S;
  499. q.x = 0.25 * S;
  500. q.y = (m[0][1] + m[1][0]) / S;
  501. q.z = (m[0][2] + m[2][0]) / S;
  502. case m[1][1] > m[2][2]:
  503. S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]);
  504. q.w = (m[0][2] - m[2][0]) / S;
  505. q.x = (m[0][1] + m[1][0]) / S;
  506. q.y = 0.25 * S;
  507. q.z = (m[1][2] + m[2][1]) / S;
  508. case:
  509. S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]);
  510. q.w = (m[1][0] - m[0][1]) / S;
  511. q.x = (m[0][2] - m[2][0]) / S;
  512. q.y = (m[1][2] + m[2][1]) / S;
  513. q.z = 0.25 * S;
  514. }
  515. return normalize(q);
  516. }
  517. quaternion_from_forward_and_up_f32 :: proc(forward, up: Vector3f32) -> Quaternionf32 {
  518. f := normalize(forward);
  519. s := normalize(cross(f, up));
  520. u := cross(s, f);
  521. m := Matrix3f32{
  522. {+s.x, +u.x, -f.x},
  523. {+s.y, +u.y, -f.y},
  524. {+s.z, +u.z, -f.z},
  525. };
  526. tr := trace(m);
  527. q: Quaternionf32;
  528. switch {
  529. case tr > 0:
  530. S := 2 * math.sqrt(1 + tr);
  531. q.w = 0.25 * S;
  532. q.x = (m[2][1] - m[1][2]) / S;
  533. q.y = (m[0][2] - m[2][0]) / S;
  534. q.z = (m[1][0] - m[0][1]) / S;
  535. case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]):
  536. S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]);
  537. q.w = (m[2][1] - m[1][2]) / S;
  538. q.x = 0.25 * S;
  539. q.y = (m[0][1] + m[1][0]) / S;
  540. q.z = (m[0][2] + m[2][0]) / S;
  541. case m[1][1] > m[2][2]:
  542. S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]);
  543. q.w = (m[0][2] - m[2][0]) / S;
  544. q.x = (m[0][1] + m[1][0]) / S;
  545. q.y = 0.25 * S;
  546. q.z = (m[1][2] + m[2][1]) / S;
  547. case:
  548. S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]);
  549. q.w = (m[1][0] - m[0][1]) / S;
  550. q.x = (m[0][2] - m[2][0]) / S;
  551. q.y = (m[1][2] + m[2][1]) / S;
  552. q.z = 0.25 * S;
  553. }
  554. return normalize(q);
  555. }
  556. quaternion_from_forward_and_up_f64 :: proc(forward, up: Vector3f64) -> Quaternionf64 {
  557. f := normalize(forward);
  558. s := normalize(cross(f, up));
  559. u := cross(s, f);
  560. m := Matrix3f64{
  561. {+s.x, +u.x, -f.x},
  562. {+s.y, +u.y, -f.y},
  563. {+s.z, +u.z, -f.z},
  564. };
  565. tr := trace(m);
  566. q: Quaternionf64;
  567. switch {
  568. case tr > 0:
  569. S := 2 * math.sqrt(1 + tr);
  570. q.w = 0.25 * S;
  571. q.x = (m[2][1] - m[1][2]) / S;
  572. q.y = (m[0][2] - m[2][0]) / S;
  573. q.z = (m[1][0] - m[0][1]) / S;
  574. case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]):
  575. S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]);
  576. q.w = (m[2][1] - m[1][2]) / S;
  577. q.x = 0.25 * S;
  578. q.y = (m[0][1] + m[1][0]) / S;
  579. q.z = (m[0][2] + m[2][0]) / S;
  580. case m[1][1] > m[2][2]:
  581. S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]);
  582. q.w = (m[0][2] - m[2][0]) / S;
  583. q.x = (m[0][1] + m[1][0]) / S;
  584. q.y = 0.25 * S;
  585. q.z = (m[1][2] + m[2][1]) / S;
  586. case:
  587. S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]);
  588. q.w = (m[1][0] - m[0][1]) / S;
  589. q.x = (m[0][2] - m[2][0]) / S;
  590. q.y = (m[1][2] + m[2][1]) / S;
  591. q.z = 0.25 * S;
  592. }
  593. return normalize(q);
  594. }
  595. quaternion_from_forward_and_up :: proc{
  596. quaternion_from_forward_and_up_f16,
  597. quaternion_from_forward_and_up_f32,
  598. quaternion_from_forward_and_up_f64,
  599. };
  600. quaternion_look_at_f16 :: proc(eye, centre: Vector3f16, up: Vector3f16) -> Quaternionf16 {
  601. return quaternion_from_matrix3(matrix3_look_at(eye, centre, up));
  602. }
  603. quaternion_look_at_f32 :: proc(eye, centre: Vector3f32, up: Vector3f32) -> Quaternionf32 {
  604. return quaternion_from_matrix3(matrix3_look_at(eye, centre, up));
  605. }
  606. quaternion_look_at_f64 :: proc(eye, centre: Vector3f64, up: Vector3f64) -> Quaternionf64 {
  607. return quaternion_from_matrix3(matrix3_look_at(eye, centre, up));
  608. }
  609. quaternion_look_at :: proc{
  610. quaternion_look_at_f16,
  611. quaternion_look_at_f32,
  612. quaternion_look_at_f64,
  613. };
  614. quaternion_nlerp_f16 :: proc(a, b: Quaternionf16, t: f16) -> (c: Quaternionf16) {
  615. c.x = a.x + (b.x-a.x)*t;
  616. c.y = a.y + (b.y-a.y)*t;
  617. c.z = a.z + (b.z-a.z)*t;
  618. c.w = a.w + (b.w-a.w)*t;
  619. return normalize(c);
  620. }
  621. quaternion_nlerp_f32 :: proc(a, b: Quaternionf32, t: f32) -> (c: Quaternionf32) {
  622. c.x = a.x + (b.x-a.x)*t;
  623. c.y = a.y + (b.y-a.y)*t;
  624. c.z = a.z + (b.z-a.z)*t;
  625. c.w = a.w + (b.w-a.w)*t;
  626. return normalize(c);
  627. }
  628. quaternion_nlerp_f64 :: proc(a, b: Quaternionf64, t: f64) -> (c: Quaternionf64) {
  629. c.x = a.x + (b.x-a.x)*t;
  630. c.y = a.y + (b.y-a.y)*t;
  631. c.z = a.z + (b.z-a.z)*t;
  632. c.w = a.w + (b.w-a.w)*t;
  633. return normalize(c);
  634. }
  635. quaternion_nlerp :: proc{
  636. quaternion_nlerp_f16,
  637. quaternion_nlerp_f32,
  638. quaternion_nlerp_f64,
  639. };
  640. quaternion_slerp_f16 :: proc(x, y: Quaternionf16, t: f16) -> (q: Quaternionf16) {
  641. a, b := x, y;
  642. cos_angle := dot(a, b);
  643. if cos_angle < 0 {
  644. b = -b;
  645. cos_angle = -cos_angle;
  646. }
  647. if cos_angle > 1 - F32_EPSILON {
  648. q.x = a.x + (b.x-a.x)*t;
  649. q.y = a.y + (b.y-a.y)*t;
  650. q.z = a.z + (b.z-a.z)*t;
  651. q.w = a.w + (b.w-a.w)*t;
  652. return;
  653. }
  654. angle := math.acos(cos_angle);
  655. sin_angle := math.sin(angle);
  656. factor_a := math.sin((1-t) * angle) / sin_angle;
  657. factor_b := math.sin(t * angle) / sin_angle;
  658. q.x = factor_a * a.x + factor_b * b.x;
  659. q.y = factor_a * a.y + factor_b * b.y;
  660. q.z = factor_a * a.z + factor_b * b.z;
  661. q.w = factor_a * a.w + factor_b * b.w;
  662. return;
  663. }
  664. quaternion_slerp_f32 :: proc(x, y: Quaternionf32, t: f32) -> (q: Quaternionf32) {
  665. a, b := x, y;
  666. cos_angle := dot(a, b);
  667. if cos_angle < 0 {
  668. b = -b;
  669. cos_angle = -cos_angle;
  670. }
  671. if cos_angle > 1 - F32_EPSILON {
  672. q.x = a.x + (b.x-a.x)*t;
  673. q.y = a.y + (b.y-a.y)*t;
  674. q.z = a.z + (b.z-a.z)*t;
  675. q.w = a.w + (b.w-a.w)*t;
  676. return;
  677. }
  678. angle := math.acos(cos_angle);
  679. sin_angle := math.sin(angle);
  680. factor_a := math.sin((1-t) * angle) / sin_angle;
  681. factor_b := math.sin(t * angle) / sin_angle;
  682. q.x = factor_a * a.x + factor_b * b.x;
  683. q.y = factor_a * a.y + factor_b * b.y;
  684. q.z = factor_a * a.z + factor_b * b.z;
  685. q.w = factor_a * a.w + factor_b * b.w;
  686. return;
  687. }
  688. quaternion_slerp_f64 :: proc(x, y: Quaternionf64, t: f64) -> (q: Quaternionf64) {
  689. a, b := x, y;
  690. cos_angle := dot(a, b);
  691. if cos_angle < 0 {
  692. b = -b;
  693. cos_angle = -cos_angle;
  694. }
  695. if cos_angle > 1 - F64_EPSILON {
  696. q.x = a.x + (b.x-a.x)*t;
  697. q.y = a.y + (b.y-a.y)*t;
  698. q.z = a.z + (b.z-a.z)*t;
  699. q.w = a.w + (b.w-a.w)*t;
  700. return;
  701. }
  702. angle := math.acos(cos_angle);
  703. sin_angle := math.sin(angle);
  704. factor_a := math.sin((1-t) * angle) / sin_angle;
  705. factor_b := math.sin(t * angle) / sin_angle;
  706. q.x = factor_a * a.x + factor_b * b.x;
  707. q.y = factor_a * a.y + factor_b * b.y;
  708. q.z = factor_a * a.z + factor_b * b.z;
  709. q.w = factor_a * a.w + factor_b * b.w;
  710. return;
  711. }
  712. quaternion_slerp :: proc{
  713. quaternion_slerp_f16,
  714. quaternion_slerp_f32,
  715. quaternion_slerp_f64,
  716. };
  717. quaternion_squad_f16 :: proc(q1, q2, s1, s2: Quaternionf16, h: f16) -> Quaternionf16 {
  718. slerp :: quaternion_slerp;
  719. return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h);
  720. }
  721. quaternion_squad_f32 :: proc(q1, q2, s1, s2: Quaternionf32, h: f32) -> Quaternionf32 {
  722. slerp :: quaternion_slerp;
  723. return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h);
  724. }
  725. quaternion_squad_f64 :: proc(q1, q2, s1, s2: Quaternionf64, h: f64) -> Quaternionf64 {
  726. slerp :: quaternion_slerp;
  727. return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h);
  728. }
  729. quaternion_squad :: proc{
  730. quaternion_squad_f16,
  731. quaternion_squad_f32,
  732. quaternion_squad_f64,
  733. };
  734. quaternion_from_matrix4_f16 :: proc(m: Matrix4f16) -> (q: Quaternionf16) {
  735. m3: Matrix3f16 = ---;
  736. m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2];
  737. m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2];
  738. m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2];
  739. return quaternion_from_matrix3(m3);
  740. }
  741. quaternion_from_matrix4_f32 :: proc(m: Matrix4f32) -> (q: Quaternionf32) {
  742. m3: Matrix3f32 = ---;
  743. m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2];
  744. m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2];
  745. m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2];
  746. return quaternion_from_matrix3(m3);
  747. }
  748. quaternion_from_matrix4_f64 :: proc(m: Matrix4f64) -> (q: Quaternionf64) {
  749. m3: Matrix3f64 = ---;
  750. m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2];
  751. m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2];
  752. m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2];
  753. return quaternion_from_matrix3(m3);
  754. }
  755. quaternion_from_matrix4 :: proc{
  756. quaternion_from_matrix4_f16,
  757. quaternion_from_matrix4_f32,
  758. quaternion_from_matrix4_f64,
  759. };
  760. quaternion_from_matrix3_f16 :: proc(m: Matrix3f16) -> (q: Quaternionf16) {
  761. four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2];
  762. four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2];
  763. four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1];
  764. four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2];
  765. biggest_index := 0;
  766. four_biggest_squared_minus_1 := four_w_squared_minus_1;
  767. if four_x_squared_minus_1 > four_biggest_squared_minus_1 {
  768. four_biggest_squared_minus_1 = four_x_squared_minus_1;
  769. biggest_index = 1;
  770. }
  771. if four_y_squared_minus_1 > four_biggest_squared_minus_1 {
  772. four_biggest_squared_minus_1 = four_y_squared_minus_1;
  773. biggest_index = 2;
  774. }
  775. if four_z_squared_minus_1 > four_biggest_squared_minus_1 {
  776. four_biggest_squared_minus_1 = four_z_squared_minus_1;
  777. biggest_index = 3;
  778. }
  779. biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5;
  780. mult := 0.25 / biggest_val;
  781. q = 1;
  782. switch biggest_index {
  783. case 0:
  784. q.w = biggest_val;
  785. q.x = (m[1][2] - m[2][1]) * mult;
  786. q.y = (m[2][0] - m[0][2]) * mult;
  787. q.z = (m[0][1] - m[1][0]) * mult;
  788. case 1:
  789. q.w = (m[1][2] - m[2][1]) * mult;
  790. q.x = biggest_val;
  791. q.y = (m[0][1] + m[1][0]) * mult;
  792. q.z = (m[2][0] + m[0][2]) * mult;
  793. case 2:
  794. q.w = (m[2][0] - m[0][2]) * mult;
  795. q.x = (m[0][1] + m[1][0]) * mult;
  796. q.y = biggest_val;
  797. q.z = (m[1][2] + m[2][1]) * mult;
  798. case 3:
  799. q.w = (m[0][1] - m[1][0]) * mult;
  800. q.x = (m[2][0] + m[0][2]) * mult;
  801. q.y = (m[1][2] + m[2][1]) * mult;
  802. q.z = biggest_val;
  803. }
  804. return;
  805. }
  806. quaternion_from_matrix3_f32 :: proc(m: Matrix3f32) -> (q: Quaternionf32) {
  807. four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2];
  808. four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2];
  809. four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1];
  810. four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2];
  811. biggest_index := 0;
  812. four_biggest_squared_minus_1 := four_w_squared_minus_1;
  813. if four_x_squared_minus_1 > four_biggest_squared_minus_1 {
  814. four_biggest_squared_minus_1 = four_x_squared_minus_1;
  815. biggest_index = 1;
  816. }
  817. if four_y_squared_minus_1 > four_biggest_squared_minus_1 {
  818. four_biggest_squared_minus_1 = four_y_squared_minus_1;
  819. biggest_index = 2;
  820. }
  821. if four_z_squared_minus_1 > four_biggest_squared_minus_1 {
  822. four_biggest_squared_minus_1 = four_z_squared_minus_1;
  823. biggest_index = 3;
  824. }
  825. biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5;
  826. mult := 0.25 / biggest_val;
  827. q = 1;
  828. switch biggest_index {
  829. case 0:
  830. q.w = biggest_val;
  831. q.x = (m[1][2] - m[2][1]) * mult;
  832. q.y = (m[2][0] - m[0][2]) * mult;
  833. q.z = (m[0][1] - m[1][0]) * mult;
  834. case 1:
  835. q.w = (m[1][2] - m[2][1]) * mult;
  836. q.x = biggest_val;
  837. q.y = (m[0][1] + m[1][0]) * mult;
  838. q.z = (m[2][0] + m[0][2]) * mult;
  839. case 2:
  840. q.w = (m[2][0] - m[0][2]) * mult;
  841. q.x = (m[0][1] + m[1][0]) * mult;
  842. q.y = biggest_val;
  843. q.z = (m[1][2] + m[2][1]) * mult;
  844. case 3:
  845. q.w = (m[0][1] - m[1][0]) * mult;
  846. q.x = (m[2][0] + m[0][2]) * mult;
  847. q.y = (m[1][2] + m[2][1]) * mult;
  848. q.z = biggest_val;
  849. }
  850. return;
  851. }
  852. quaternion_from_matrix3_f64 :: proc(m: Matrix3f64) -> (q: Quaternionf64) {
  853. four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2];
  854. four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2];
  855. four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1];
  856. four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2];
  857. biggest_index := 0;
  858. four_biggest_squared_minus_1 := four_w_squared_minus_1;
  859. if four_x_squared_minus_1 > four_biggest_squared_minus_1 {
  860. four_biggest_squared_minus_1 = four_x_squared_minus_1;
  861. biggest_index = 1;
  862. }
  863. if four_y_squared_minus_1 > four_biggest_squared_minus_1 {
  864. four_biggest_squared_minus_1 = four_y_squared_minus_1;
  865. biggest_index = 2;
  866. }
  867. if four_z_squared_minus_1 > four_biggest_squared_minus_1 {
  868. four_biggest_squared_minus_1 = four_z_squared_minus_1;
  869. biggest_index = 3;
  870. }
  871. biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5;
  872. mult := 0.25 / biggest_val;
  873. q = 1;
  874. switch biggest_index {
  875. case 0:
  876. q.w = biggest_val;
  877. q.x = (m[1][2] - m[2][1]) * mult;
  878. q.y = (m[2][0] - m[0][2]) * mult;
  879. q.z = (m[0][1] - m[1][0]) * mult;
  880. case 1:
  881. q.w = (m[1][2] - m[2][1]) * mult;
  882. q.x = biggest_val;
  883. q.y = (m[0][1] + m[1][0]) * mult;
  884. q.z = (m[2][0] + m[0][2]) * mult;
  885. case 2:
  886. q.w = (m[2][0] - m[0][2]) * mult;
  887. q.x = (m[0][1] + m[1][0]) * mult;
  888. q.y = biggest_val;
  889. q.z = (m[1][2] + m[2][1]) * mult;
  890. case 3:
  891. q.w = (m[0][1] - m[1][0]) * mult;
  892. q.x = (m[2][0] + m[0][2]) * mult;
  893. q.y = (m[1][2] + m[2][1]) * mult;
  894. q.z = biggest_val;
  895. }
  896. return;
  897. }
  898. quaternion_from_matrix3 :: proc{
  899. quaternion_from_matrix3_f16,
  900. quaternion_from_matrix3_f32,
  901. quaternion_from_matrix3_f64,
  902. };
  903. quaternion_between_two_vector3_f16 :: proc(from, to: Vector3f16) -> (q: Quaternionf16) {
  904. x := normalize(from);
  905. y := normalize(to);
  906. cos_theta := dot(x, y);
  907. if abs(cos_theta + 1) < 2*F32_EPSILON {
  908. v := vector3_orthogonal(x);
  909. q.x = v.x;
  910. q.y = v.y;
  911. q.z = v.z;
  912. q.w = 0;
  913. return;
  914. }
  915. v := cross(x, y);
  916. w := cos_theta + 1;
  917. q.w = w;
  918. q.x = v.x;
  919. q.y = v.y;
  920. q.z = v.z;
  921. return normalize(q);
  922. }
  923. quaternion_between_two_vector3_f32 :: proc(from, to: Vector3f32) -> (q: Quaternionf32) {
  924. x := normalize(from);
  925. y := normalize(to);
  926. cos_theta := dot(x, y);
  927. if abs(cos_theta + 1) < 2*F32_EPSILON {
  928. v := vector3_orthogonal(x);
  929. q.x = v.x;
  930. q.y = v.y;
  931. q.z = v.z;
  932. q.w = 0;
  933. return;
  934. }
  935. v := cross(x, y);
  936. w := cos_theta + 1;
  937. q.w = w;
  938. q.x = v.x;
  939. q.y = v.y;
  940. q.z = v.z;
  941. return normalize(q);
  942. }
  943. quaternion_between_two_vector3_f64 :: proc(from, to: Vector3f64) -> (q: Quaternionf64) {
  944. x := normalize(from);
  945. y := normalize(to);
  946. cos_theta := dot(x, y);
  947. if abs(cos_theta + 1) < 2*F64_EPSILON {
  948. v := vector3_orthogonal(x);
  949. q.x = v.x;
  950. q.y = v.y;
  951. q.z = v.z;
  952. q.w = 0;
  953. return;
  954. }
  955. v := cross(x, y);
  956. w := cos_theta + 1;
  957. q.w = w;
  958. q.x = v.x;
  959. q.y = v.y;
  960. q.z = v.z;
  961. return normalize(q);
  962. }
  963. quaternion_between_two_vector3 :: proc{
  964. quaternion_between_two_vector3_f16,
  965. quaternion_between_two_vector3_f32,
  966. quaternion_between_two_vector3_f64,
  967. };
  968. matrix2_inverse_transpose_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) {
  969. d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
  970. id := 1.0/d;
  971. c[0][0] = +m[1][1] * id;
  972. c[0][1] = -m[0][1] * id;
  973. c[1][0] = -m[1][0] * id;
  974. c[1][1] = +m[0][0] * id;
  975. return c;
  976. }
  977. matrix2_inverse_transpose_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) {
  978. d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
  979. id := 1.0/d;
  980. c[0][0] = +m[1][1] * id;
  981. c[0][1] = -m[0][1] * id;
  982. c[1][0] = -m[1][0] * id;
  983. c[1][1] = +m[0][0] * id;
  984. return c;
  985. }
  986. matrix2_inverse_transpose_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) {
  987. d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
  988. id := 1.0/d;
  989. c[0][0] = +m[1][1] * id;
  990. c[0][1] = -m[0][1] * id;
  991. c[1][0] = -m[1][0] * id;
  992. c[1][1] = +m[0][0] * id;
  993. return c;
  994. }
  995. matrix2_inverse_transpose :: proc{
  996. matrix2_inverse_transpose_f16,
  997. matrix2_inverse_transpose_f32,
  998. matrix2_inverse_transpose_f64,
  999. };
  1000. matrix2_determinant_f16 :: proc(m: Matrix2f16) -> f16 {
  1001. return m[0][0]*m[1][1] - m[1][0]*m[0][1];
  1002. }
  1003. matrix2_determinant_f32 :: proc(m: Matrix2f32) -> f32 {
  1004. return m[0][0]*m[1][1] - m[1][0]*m[0][1];
  1005. }
  1006. matrix2_determinant_f64 :: proc(m: Matrix2f64) -> f64 {
  1007. return m[0][0]*m[1][1] - m[1][0]*m[0][1];
  1008. }
  1009. matrix2_determinant :: proc{
  1010. matrix2_determinant_f16,
  1011. matrix2_determinant_f32,
  1012. matrix2_determinant_f64,
  1013. };
  1014. matrix2_inverse_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) {
  1015. d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
  1016. id := 1.0/d;
  1017. c[0][0] = +m[1][1] * id;
  1018. c[1][0] = -m[0][1] * id;
  1019. c[0][1] = -m[1][0] * id;
  1020. c[1][1] = +m[0][0] * id;
  1021. return c;
  1022. }
  1023. matrix2_inverse_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) {
  1024. d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
  1025. id := 1.0/d;
  1026. c[0][0] = +m[1][1] * id;
  1027. c[1][0] = -m[0][1] * id;
  1028. c[0][1] = -m[1][0] * id;
  1029. c[1][1] = +m[0][0] * id;
  1030. return c;
  1031. }
  1032. matrix2_inverse_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) {
  1033. d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
  1034. id := 1.0/d;
  1035. c[0][0] = +m[1][1] * id;
  1036. c[1][0] = -m[0][1] * id;
  1037. c[0][1] = -m[1][0] * id;
  1038. c[1][1] = +m[0][0] * id;
  1039. return c;
  1040. }
  1041. matrix2_inverse :: proc{
  1042. matrix2_inverse_f16,
  1043. matrix2_inverse_f32,
  1044. matrix2_inverse_f64,
  1045. };
  1046. matrix2_adjoint_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) {
  1047. c[0][0] = +m[1][1];
  1048. c[0][1] = -m[1][0];
  1049. c[1][0] = -m[0][1];
  1050. c[1][1] = +m[0][0];
  1051. return c;
  1052. }
  1053. matrix2_adjoint_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) {
  1054. c[0][0] = +m[1][1];
  1055. c[0][1] = -m[1][0];
  1056. c[1][0] = -m[0][1];
  1057. c[1][1] = +m[0][0];
  1058. return c;
  1059. }
  1060. matrix2_adjoint_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) {
  1061. c[0][0] = +m[1][1];
  1062. c[0][1] = -m[1][0];
  1063. c[1][0] = -m[0][1];
  1064. c[1][1] = +m[0][0];
  1065. return c;
  1066. }
  1067. matrix2_adjoint :: proc{
  1068. matrix2_adjoint_f16,
  1069. matrix2_adjoint_f32,
  1070. matrix2_adjoint_f64,
  1071. };
  1072. matrix3_from_quaternion_f16 :: proc(q: Quaternionf16) -> (m: Matrix3f16) {
  1073. qxx := q.x * q.x;
  1074. qyy := q.y * q.y;
  1075. qzz := q.z * q.z;
  1076. qxz := q.x * q.z;
  1077. qxy := q.x * q.y;
  1078. qyz := q.y * q.z;
  1079. qwx := q.w * q.x;
  1080. qwy := q.w * q.y;
  1081. qwz := q.w * q.z;
  1082. m[0][0] = 1 - 2 * (qyy + qzz);
  1083. m[0][1] = 2 * (qxy + qwz);
  1084. m[0][2] = 2 * (qxz - qwy);
  1085. m[1][0] = 2 * (qxy - qwz);
  1086. m[1][1] = 1 - 2 * (qxx + qzz);
  1087. m[1][2] = 2 * (qyz + qwx);
  1088. m[2][0] = 2 * (qxz + qwy);
  1089. m[2][1] = 2 * (qyz - qwx);
  1090. m[2][2] = 1 - 2 * (qxx + qyy);
  1091. return m;
  1092. }
  1093. matrix3_from_quaternion_f32 :: proc(q: Quaternionf32) -> (m: Matrix3f32) {
  1094. qxx := q.x * q.x;
  1095. qyy := q.y * q.y;
  1096. qzz := q.z * q.z;
  1097. qxz := q.x * q.z;
  1098. qxy := q.x * q.y;
  1099. qyz := q.y * q.z;
  1100. qwx := q.w * q.x;
  1101. qwy := q.w * q.y;
  1102. qwz := q.w * q.z;
  1103. m[0][0] = 1 - 2 * (qyy + qzz);
  1104. m[0][1] = 2 * (qxy + qwz);
  1105. m[0][2] = 2 * (qxz - qwy);
  1106. m[1][0] = 2 * (qxy - qwz);
  1107. m[1][1] = 1 - 2 * (qxx + qzz);
  1108. m[1][2] = 2 * (qyz + qwx);
  1109. m[2][0] = 2 * (qxz + qwy);
  1110. m[2][1] = 2 * (qyz - qwx);
  1111. m[2][2] = 1 - 2 * (qxx + qyy);
  1112. return m;
  1113. }
  1114. matrix3_from_quaternion_f64 :: proc(q: Quaternionf64) -> (m: Matrix3f64) {
  1115. qxx := q.x * q.x;
  1116. qyy := q.y * q.y;
  1117. qzz := q.z * q.z;
  1118. qxz := q.x * q.z;
  1119. qxy := q.x * q.y;
  1120. qyz := q.y * q.z;
  1121. qwx := q.w * q.x;
  1122. qwy := q.w * q.y;
  1123. qwz := q.w * q.z;
  1124. m[0][0] = 1 - 2 * (qyy + qzz);
  1125. m[0][1] = 2 * (qxy + qwz);
  1126. m[0][2] = 2 * (qxz - qwy);
  1127. m[1][0] = 2 * (qxy - qwz);
  1128. m[1][1] = 1 - 2 * (qxx + qzz);
  1129. m[1][2] = 2 * (qyz + qwx);
  1130. m[2][0] = 2 * (qxz + qwy);
  1131. m[2][1] = 2 * (qyz - qwx);
  1132. m[2][2] = 1 - 2 * (qxx + qyy);
  1133. return m;
  1134. }
  1135. matrix3_from_quaternion :: proc{
  1136. matrix3_from_quaternion_f16,
  1137. matrix3_from_quaternion_f32,
  1138. matrix3_from_quaternion_f64,
  1139. };
  1140. matrix3_inverse_f16 :: proc(m: Matrix3f16) -> Matrix3f16 {
  1141. return transpose(matrix3_inverse_transpose(m));
  1142. }
  1143. matrix3_inverse_f32 :: proc(m: Matrix3f32) -> Matrix3f32 {
  1144. return transpose(matrix3_inverse_transpose(m));
  1145. }
  1146. matrix3_inverse_f64 :: proc(m: Matrix3f64) -> Matrix3f64 {
  1147. return transpose(matrix3_inverse_transpose(m));
  1148. }
  1149. matrix3_inverse :: proc{
  1150. matrix3_inverse_f16,
  1151. matrix3_inverse_f32,
  1152. matrix3_inverse_f64,
  1153. };
  1154. matrix3_determinant_f16 :: proc(m: Matrix3f16) -> f16 {
  1155. a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
  1156. b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
  1157. c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
  1158. return a + b + c;
  1159. }
  1160. matrix3_determinant_f32 :: proc(m: Matrix3f32) -> f32 {
  1161. a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
  1162. b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
  1163. c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
  1164. return a + b + c;
  1165. }
  1166. matrix3_determinant_f64 :: proc(m: Matrix3f64) -> f64 {
  1167. a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
  1168. b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
  1169. c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
  1170. return a + b + c;
  1171. }
  1172. matrix3_determinant :: proc{
  1173. matrix3_determinant_f16,
  1174. matrix3_determinant_f32,
  1175. matrix3_determinant_f64,
  1176. };
  1177. matrix3_adjoint_f16 :: proc(m: Matrix3f16) -> (adjoint: Matrix3f16) {
  1178. adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]);
  1179. adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
  1180. adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]);
  1181. adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
  1182. adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]);
  1183. adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
  1184. adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]);
  1185. adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
  1186. adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]);
  1187. return adjoint;
  1188. }
  1189. matrix3_adjoint_f32 :: proc(m: Matrix3f32) -> (adjoint: Matrix3f32) {
  1190. adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]);
  1191. adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
  1192. adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]);
  1193. adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
  1194. adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]);
  1195. adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
  1196. adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]);
  1197. adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
  1198. adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]);
  1199. return adjoint;
  1200. }
  1201. matrix3_adjoint_f64 :: proc(m: Matrix3f64) -> (adjoint: Matrix3f64) {
  1202. adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]);
  1203. adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
  1204. adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]);
  1205. adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
  1206. adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]);
  1207. adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
  1208. adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]);
  1209. adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
  1210. adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]);
  1211. return adjoint;
  1212. }
  1213. matrix3_adjoint :: proc{
  1214. matrix3_adjoint_f16,
  1215. matrix3_adjoint_f32,
  1216. matrix3_adjoint_f64,
  1217. };
  1218. matrix3_inverse_transpose_f16 :: proc(m: Matrix3f16) -> (inverse_transpose: Matrix3f16) {
  1219. adjoint := matrix3_adjoint(m);
  1220. determinant := matrix3_determinant(m);
  1221. inv_determinant := 1.0 / determinant;
  1222. for i in 0..<3 {
  1223. for j in 0..<3 {
  1224. inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
  1225. }
  1226. }
  1227. return;
  1228. }
  1229. matrix3_inverse_transpose_f32 :: proc(m: Matrix3f32) -> (inverse_transpose: Matrix3f32) {
  1230. adjoint := matrix3_adjoint(m);
  1231. determinant := matrix3_determinant(m);
  1232. inv_determinant := 1.0 / determinant;
  1233. for i in 0..<3 {
  1234. for j in 0..<3 {
  1235. inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
  1236. }
  1237. }
  1238. return;
  1239. }
  1240. matrix3_inverse_transpose_f64 :: proc(m: Matrix3f64) -> (inverse_transpose: Matrix3f64) {
  1241. adjoint := matrix3_adjoint(m);
  1242. determinant := matrix3_determinant(m);
  1243. inv_determinant := 1.0 / determinant;
  1244. for i in 0..<3 {
  1245. for j in 0..<3 {
  1246. inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
  1247. }
  1248. }
  1249. return;
  1250. }
  1251. matrix3_inverse_transpose :: proc{
  1252. matrix3_inverse_transpose_f16,
  1253. matrix3_inverse_transpose_f32,
  1254. matrix3_inverse_transpose_f64,
  1255. };
  1256. matrix3_scale_f16 :: proc(s: Vector3f16) -> (m: Matrix3f16) {
  1257. m[0][0] = s[0];
  1258. m[1][1] = s[1];
  1259. m[2][2] = s[2];
  1260. return m;
  1261. }
  1262. matrix3_scale_f32 :: proc(s: Vector3f32) -> (m: Matrix3f32) {
  1263. m[0][0] = s[0];
  1264. m[1][1] = s[1];
  1265. m[2][2] = s[2];
  1266. return m;
  1267. }
  1268. matrix3_scale_f64 :: proc(s: Vector3f64) -> (m: Matrix3f64) {
  1269. m[0][0] = s[0];
  1270. m[1][1] = s[1];
  1271. m[2][2] = s[2];
  1272. return m;
  1273. }
  1274. matrix3_scale :: proc{
  1275. matrix3_scale_f16,
  1276. matrix3_scale_f32,
  1277. matrix3_scale_f64,
  1278. };
  1279. matrix3_rotate_f16 :: proc(angle_radians: f16, v: Vector3f16) -> (rot: Matrix3f16) {
  1280. c := math.cos(angle_radians);
  1281. s := math.sin(angle_radians);
  1282. a := normalize(v);
  1283. t := a * (1-c);
  1284. rot[0][0] = c + t[0]*a[0];
  1285. rot[0][1] = 0 + t[0]*a[1] + s*a[2];
  1286. rot[0][2] = 0 + t[0]*a[2] - s*a[1];
  1287. rot[1][0] = 0 + t[1]*a[0] - s*a[2];
  1288. rot[1][1] = c + t[1]*a[1];
  1289. rot[1][2] = 0 + t[1]*a[2] + s*a[0];
  1290. rot[2][0] = 0 + t[2]*a[0] + s*a[1];
  1291. rot[2][1] = 0 + t[2]*a[1] - s*a[0];
  1292. rot[2][2] = c + t[2]*a[2];
  1293. return rot;
  1294. }
  1295. matrix3_rotate_f32 :: proc(angle_radians: f32, v: Vector3f32) -> (rot: Matrix3f32) {
  1296. c := math.cos(angle_radians);
  1297. s := math.sin(angle_radians);
  1298. a := normalize(v);
  1299. t := a * (1-c);
  1300. rot[0][0] = c + t[0]*a[0];
  1301. rot[0][1] = 0 + t[0]*a[1] + s*a[2];
  1302. rot[0][2] = 0 + t[0]*a[2] - s*a[1];
  1303. rot[1][0] = 0 + t[1]*a[0] - s*a[2];
  1304. rot[1][1] = c + t[1]*a[1];
  1305. rot[1][2] = 0 + t[1]*a[2] + s*a[0];
  1306. rot[2][0] = 0 + t[2]*a[0] + s*a[1];
  1307. rot[2][1] = 0 + t[2]*a[1] - s*a[0];
  1308. rot[2][2] = c + t[2]*a[2];
  1309. return rot;
  1310. }
  1311. matrix3_rotate_f64 :: proc(angle_radians: f64, v: Vector3f64) -> (rot: Matrix3f64) {
  1312. c := math.cos(angle_radians);
  1313. s := math.sin(angle_radians);
  1314. a := normalize(v);
  1315. t := a * (1-c);
  1316. rot[0][0] = c + t[0]*a[0];
  1317. rot[0][1] = 0 + t[0]*a[1] + s*a[2];
  1318. rot[0][2] = 0 + t[0]*a[2] - s*a[1];
  1319. rot[1][0] = 0 + t[1]*a[0] - s*a[2];
  1320. rot[1][1] = c + t[1]*a[1];
  1321. rot[1][2] = 0 + t[1]*a[2] + s*a[0];
  1322. rot[2][0] = 0 + t[2]*a[0] + s*a[1];
  1323. rot[2][1] = 0 + t[2]*a[1] - s*a[0];
  1324. rot[2][2] = c + t[2]*a[2];
  1325. return rot;
  1326. }
  1327. matrix3_rotate :: proc{
  1328. matrix3_rotate_f16,
  1329. matrix3_rotate_f32,
  1330. matrix3_rotate_f64,
  1331. };
  1332. matrix3_look_at_f16 :: proc(eye, centre, up: Vector3f16) -> Matrix3f16 {
  1333. f := normalize(centre - eye);
  1334. s := normalize(cross(f, up));
  1335. u := cross(s, f);
  1336. return Matrix3f16{
  1337. {+s.x, +u.x, -f.x},
  1338. {+s.y, +u.y, -f.y},
  1339. {+s.z, +u.z, -f.z},
  1340. };
  1341. }
  1342. matrix3_look_at_f32 :: proc(eye, centre, up: Vector3f32) -> Matrix3f32 {
  1343. f := normalize(centre - eye);
  1344. s := normalize(cross(f, up));
  1345. u := cross(s, f);
  1346. return Matrix3f32{
  1347. {+s.x, +u.x, -f.x},
  1348. {+s.y, +u.y, -f.y},
  1349. {+s.z, +u.z, -f.z},
  1350. };
  1351. }
  1352. matrix3_look_at_f64 :: proc(eye, centre, up: Vector3f64) -> Matrix3f64 {
  1353. f := normalize(centre - eye);
  1354. s := normalize(cross(f, up));
  1355. u := cross(s, f);
  1356. return Matrix3f64{
  1357. {+s.x, +u.x, -f.x},
  1358. {+s.y, +u.y, -f.y},
  1359. {+s.z, +u.z, -f.z},
  1360. };
  1361. }
  1362. matrix3_look_at :: proc{
  1363. matrix3_look_at_f16,
  1364. matrix3_look_at_f32,
  1365. matrix3_look_at_f64,
  1366. };
  1367. matrix4_from_quaternion_f16 :: proc(q: Quaternionf16) -> (m: Matrix4f16) {
  1368. qxx := q.x * q.x;
  1369. qyy := q.y * q.y;
  1370. qzz := q.z * q.z;
  1371. qxz := q.x * q.z;
  1372. qxy := q.x * q.y;
  1373. qyz := q.y * q.z;
  1374. qwx := q.w * q.x;
  1375. qwy := q.w * q.y;
  1376. qwz := q.w * q.z;
  1377. m[0][0] = 1 - 2 * (qyy + qzz);
  1378. m[0][1] = 2 * (qxy + qwz);
  1379. m[0][2] = 2 * (qxz - qwy);
  1380. m[1][0] = 2 * (qxy - qwz);
  1381. m[1][1] = 1 - 2 * (qxx + qzz);
  1382. m[1][2] = 2 * (qyz + qwx);
  1383. m[2][0] = 2 * (qxz + qwy);
  1384. m[2][1] = 2 * (qyz - qwx);
  1385. m[2][2] = 1 - 2 * (qxx + qyy);
  1386. m[3][3] = 1;
  1387. return m;
  1388. }
  1389. matrix4_from_quaternion_f32 :: proc(q: Quaternionf32) -> (m: Matrix4f32) {
  1390. qxx := q.x * q.x;
  1391. qyy := q.y * q.y;
  1392. qzz := q.z * q.z;
  1393. qxz := q.x * q.z;
  1394. qxy := q.x * q.y;
  1395. qyz := q.y * q.z;
  1396. qwx := q.w * q.x;
  1397. qwy := q.w * q.y;
  1398. qwz := q.w * q.z;
  1399. m[0][0] = 1 - 2 * (qyy + qzz);
  1400. m[0][1] = 2 * (qxy + qwz);
  1401. m[0][2] = 2 * (qxz - qwy);
  1402. m[1][0] = 2 * (qxy - qwz);
  1403. m[1][1] = 1 - 2 * (qxx + qzz);
  1404. m[1][2] = 2 * (qyz + qwx);
  1405. m[2][0] = 2 * (qxz + qwy);
  1406. m[2][1] = 2 * (qyz - qwx);
  1407. m[2][2] = 1 - 2 * (qxx + qyy);
  1408. m[3][3] = 1;
  1409. return m;
  1410. }
  1411. matrix4_from_quaternion_f64 :: proc(q: Quaternionf64) -> (m: Matrix4f64) {
  1412. qxx := q.x * q.x;
  1413. qyy := q.y * q.y;
  1414. qzz := q.z * q.z;
  1415. qxz := q.x * q.z;
  1416. qxy := q.x * q.y;
  1417. qyz := q.y * q.z;
  1418. qwx := q.w * q.x;
  1419. qwy := q.w * q.y;
  1420. qwz := q.w * q.z;
  1421. m[0][0] = 1 - 2 * (qyy + qzz);
  1422. m[0][1] = 2 * (qxy + qwz);
  1423. m[0][2] = 2 * (qxz - qwy);
  1424. m[1][0] = 2 * (qxy - qwz);
  1425. m[1][1] = 1 - 2 * (qxx + qzz);
  1426. m[1][2] = 2 * (qyz + qwx);
  1427. m[2][0] = 2 * (qxz + qwy);
  1428. m[2][1] = 2 * (qyz - qwx);
  1429. m[2][2] = 1 - 2 * (qxx + qyy);
  1430. m[3][3] = 1;
  1431. return m;
  1432. }
  1433. matrix4_from_quaternion :: proc{
  1434. matrix4_from_quaternion_f16,
  1435. matrix4_from_quaternion_f32,
  1436. matrix4_from_quaternion_f64,
  1437. };
  1438. matrix4_from_trs_f16 :: proc(t: Vector3f16, r: Quaternionf16, s: Vector3f16) -> Matrix4f16 {
  1439. translation := matrix4_translate(t);
  1440. rotation := matrix4_from_quaternion(r);
  1441. scale := matrix4_scale(s);
  1442. return mul(translation, mul(rotation, scale));
  1443. }
  1444. matrix4_from_trs_f32 :: proc(t: Vector3f32, r: Quaternionf32, s: Vector3f32) -> Matrix4f32 {
  1445. translation := matrix4_translate(t);
  1446. rotation := matrix4_from_quaternion(r);
  1447. scale := matrix4_scale(s);
  1448. return mul(translation, mul(rotation, scale));
  1449. }
  1450. matrix4_from_trs_f64 :: proc(t: Vector3f64, r: Quaternionf64, s: Vector3f64) -> Matrix4f64 {
  1451. translation := matrix4_translate(t);
  1452. rotation := matrix4_from_quaternion(r);
  1453. scale := matrix4_scale(s);
  1454. return mul(translation, mul(rotation, scale));
  1455. }
  1456. matrix4_from_trs :: proc{
  1457. matrix4_from_trs_f16,
  1458. matrix4_from_trs_f32,
  1459. matrix4_from_trs_f64,
  1460. };
  1461. matrix4_inverse_f16 :: proc(m: Matrix4f16) -> Matrix4f16 {
  1462. return transpose(matrix4_inverse_transpose(m));
  1463. }
  1464. matrix4_inverse_f32 :: proc(m: Matrix4f32) -> Matrix4f32 {
  1465. return transpose(matrix4_inverse_transpose(m));
  1466. }
  1467. matrix4_inverse_f64 :: proc(m: Matrix4f64) -> Matrix4f64 {
  1468. return transpose(matrix4_inverse_transpose(m));
  1469. }
  1470. matrix4_inverse :: proc{
  1471. matrix4_inverse_f16,
  1472. matrix4_inverse_f32,
  1473. matrix4_inverse_f64,
  1474. };
  1475. matrix4_minor_f16 :: proc(m: Matrix4f16, c, r: int) -> f16 {
  1476. cut_down: Matrix3f16;
  1477. for i in 0..<3 {
  1478. col := i if i < c else i+1;
  1479. for j in 0..<3 {
  1480. row := j if j < r else j+1;
  1481. cut_down[i][j] = m[col][row];
  1482. }
  1483. }
  1484. return matrix3_determinant(cut_down);
  1485. }
  1486. matrix4_minor_f32 :: proc(m: Matrix4f32, c, r: int) -> f32 {
  1487. cut_down: Matrix3f32;
  1488. for i in 0..<3 {
  1489. col := i if i < c else i+1;
  1490. for j in 0..<3 {
  1491. row := j if j < r else j+1;
  1492. cut_down[i][j] = m[col][row];
  1493. }
  1494. }
  1495. return matrix3_determinant(cut_down);
  1496. }
  1497. matrix4_minor_f64 :: proc(m: Matrix4f64, c, r: int) -> f64 {
  1498. cut_down: Matrix3f64;
  1499. for i in 0..<3 {
  1500. col := i if i < c else i+1;
  1501. for j in 0..<3 {
  1502. row := j if j < r else j+1;
  1503. cut_down[i][j] = m[col][row];
  1504. }
  1505. }
  1506. return matrix3_determinant(cut_down);
  1507. }
  1508. matrix4_minor :: proc{
  1509. matrix4_minor_f16,
  1510. matrix4_minor_f32,
  1511. matrix4_minor_f64,
  1512. };
  1513. matrix4_cofactor_f16 :: proc(m: Matrix4f16, c, r: int) -> f16 {
  1514. sign, minor: f16;
  1515. sign = 1 if (c + r) % 2 == 0 else -1;
  1516. minor = matrix4_minor(m, c, r);
  1517. return sign * minor;
  1518. }
  1519. matrix4_cofactor_f32 :: proc(m: Matrix4f32, c, r: int) -> f32 {
  1520. sign, minor: f32;
  1521. sign = 1 if (c + r) % 2 == 0 else -1;
  1522. minor = matrix4_minor(m, c, r);
  1523. return sign * minor;
  1524. }
  1525. matrix4_cofactor_f64 :: proc(m: Matrix4f64, c, r: int) -> f64 {
  1526. sign, minor: f64;
  1527. sign = 1 if (c + r) % 2 == 0 else -1;
  1528. minor = matrix4_minor(m, c, r);
  1529. return sign * minor;
  1530. }
  1531. matrix4_cofactor :: proc{
  1532. matrix4_cofactor_f16,
  1533. matrix4_cofactor_f32,
  1534. matrix4_cofactor_f64,
  1535. };
  1536. matrix4_adjoint_f16 :: proc(m: Matrix4f16) -> (adjoint: Matrix4f16) {
  1537. for i in 0..<4 {
  1538. for j in 0..<4 {
  1539. adjoint[i][j] = matrix4_cofactor(m, i, j);
  1540. }
  1541. }
  1542. return;
  1543. }
  1544. matrix4_adjoint_f32 :: proc(m: Matrix4f32) -> (adjoint: Matrix4f32) {
  1545. for i in 0..<4 {
  1546. for j in 0..<4 {
  1547. adjoint[i][j] = matrix4_cofactor(m, i, j);
  1548. }
  1549. }
  1550. return;
  1551. }
  1552. matrix4_adjoint_f64 :: proc(m: Matrix4f64) -> (adjoint: Matrix4f64) {
  1553. for i in 0..<4 {
  1554. for j in 0..<4 {
  1555. adjoint[i][j] = matrix4_cofactor(m, i, j);
  1556. }
  1557. }
  1558. return;
  1559. }
  1560. matrix4_adjoint :: proc{
  1561. matrix4_adjoint_f16,
  1562. matrix4_adjoint_f32,
  1563. matrix4_adjoint_f64,
  1564. };
  1565. matrix4_determinant_f16 :: proc(m: Matrix4f16) -> (determinant: f16) {
  1566. adjoint := matrix4_adjoint(m);
  1567. for i in 0..<4 {
  1568. determinant += m[i][0] * adjoint[i][0];
  1569. }
  1570. return;
  1571. }
  1572. matrix4_determinant_f32 :: proc(m: Matrix4f32) -> (determinant: f32) {
  1573. adjoint := matrix4_adjoint(m);
  1574. for i in 0..<4 {
  1575. determinant += m[i][0] * adjoint[i][0];
  1576. }
  1577. return;
  1578. }
  1579. matrix4_determinant_f64 :: proc(m: Matrix4f64) -> (determinant: f64) {
  1580. adjoint := matrix4_adjoint(m);
  1581. for i in 0..<4 {
  1582. determinant += m[i][0] * adjoint[i][0];
  1583. }
  1584. return;
  1585. }
  1586. matrix4_determinant :: proc{
  1587. matrix4_determinant_f16,
  1588. matrix4_determinant_f32,
  1589. matrix4_determinant_f64,
  1590. };
  1591. matrix4_inverse_transpose_f16 :: proc(m: Matrix4f16) -> (inverse_transpose: Matrix4f16) {
  1592. adjoint := matrix4_adjoint(m);
  1593. determinant: f16 = 0;
  1594. for i in 0..<4 {
  1595. determinant += m[i][0] * adjoint[i][0];
  1596. }
  1597. inv_determinant := 1.0 / determinant;
  1598. for i in 0..<4 {
  1599. for j in 0..<4 {
  1600. inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
  1601. }
  1602. }
  1603. return;
  1604. }
  1605. matrix4_inverse_transpose_f32 :: proc(m: Matrix4f32) -> (inverse_transpose: Matrix4f32) {
  1606. adjoint := matrix4_adjoint(m);
  1607. determinant: f32 = 0;
  1608. for i in 0..<4 {
  1609. determinant += m[i][0] * adjoint[i][0];
  1610. }
  1611. inv_determinant := 1.0 / determinant;
  1612. for i in 0..<4 {
  1613. for j in 0..<4 {
  1614. inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
  1615. }
  1616. }
  1617. return;
  1618. }
  1619. matrix4_inverse_transpose_f64 :: proc(m: Matrix4f64) -> (inverse_transpose: Matrix4f64) {
  1620. adjoint := matrix4_adjoint(m);
  1621. determinant: f64 = 0;
  1622. for i in 0..<4 {
  1623. determinant += m[i][0] * adjoint[i][0];
  1624. }
  1625. inv_determinant := 1.0 / determinant;
  1626. for i in 0..<4 {
  1627. for j in 0..<4 {
  1628. inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
  1629. }
  1630. }
  1631. return;
  1632. }
  1633. matrix4_inverse_transpose :: proc{
  1634. matrix4_inverse_transpose_f16,
  1635. matrix4_inverse_transpose_f32,
  1636. matrix4_inverse_transpose_f64,
  1637. };
  1638. matrix4_translate_f16 :: proc(v: Vector3f16) -> Matrix4f16 {
  1639. m := MATRIX4F16_IDENTITY;
  1640. m[3][0] = v[0];
  1641. m[3][1] = v[1];
  1642. m[3][2] = v[2];
  1643. return m;
  1644. }
  1645. matrix4_translate_f32 :: proc(v: Vector3f32) -> Matrix4f32 {
  1646. m := MATRIX4F32_IDENTITY;
  1647. m[3][0] = v[0];
  1648. m[3][1] = v[1];
  1649. m[3][2] = v[2];
  1650. return m;
  1651. }
  1652. matrix4_translate_f64 :: proc(v: Vector3f64) -> Matrix4f64 {
  1653. m := MATRIX4F64_IDENTITY;
  1654. m[3][0] = v[0];
  1655. m[3][1] = v[1];
  1656. m[3][2] = v[2];
  1657. return m;
  1658. }
  1659. matrix4_translate :: proc{
  1660. matrix4_translate_f16,
  1661. matrix4_translate_f32,
  1662. matrix4_translate_f64,
  1663. };
  1664. matrix4_rotate_f16 :: proc(angle_radians: f16, v: Vector3f16) -> Matrix4f16 {
  1665. c := math.cos(angle_radians);
  1666. s := math.sin(angle_radians);
  1667. a := normalize(v);
  1668. t := a * (1-c);
  1669. rot := MATRIX4F16_IDENTITY;
  1670. rot[0][0] = c + t[0]*a[0];
  1671. rot[0][1] = 0 + t[0]*a[1] + s*a[2];
  1672. rot[0][2] = 0 + t[0]*a[2] - s*a[1];
  1673. rot[0][3] = 0;
  1674. rot[1][0] = 0 + t[1]*a[0] - s*a[2];
  1675. rot[1][1] = c + t[1]*a[1];
  1676. rot[1][2] = 0 + t[1]*a[2] + s*a[0];
  1677. rot[1][3] = 0;
  1678. rot[2][0] = 0 + t[2]*a[0] + s*a[1];
  1679. rot[2][1] = 0 + t[2]*a[1] - s*a[0];
  1680. rot[2][2] = c + t[2]*a[2];
  1681. rot[2][3] = 0;
  1682. return rot;
  1683. }
  1684. matrix4_rotate_f32 :: proc(angle_radians: f32, v: Vector3f32) -> Matrix4f32 {
  1685. c := math.cos(angle_radians);
  1686. s := math.sin(angle_radians);
  1687. a := normalize(v);
  1688. t := a * (1-c);
  1689. rot := MATRIX4F32_IDENTITY;
  1690. rot[0][0] = c + t[0]*a[0];
  1691. rot[0][1] = 0 + t[0]*a[1] + s*a[2];
  1692. rot[0][2] = 0 + t[0]*a[2] - s*a[1];
  1693. rot[0][3] = 0;
  1694. rot[1][0] = 0 + t[1]*a[0] - s*a[2];
  1695. rot[1][1] = c + t[1]*a[1];
  1696. rot[1][2] = 0 + t[1]*a[2] + s*a[0];
  1697. rot[1][3] = 0;
  1698. rot[2][0] = 0 + t[2]*a[0] + s*a[1];
  1699. rot[2][1] = 0 + t[2]*a[1] - s*a[0];
  1700. rot[2][2] = c + t[2]*a[2];
  1701. rot[2][3] = 0;
  1702. return rot;
  1703. }
  1704. matrix4_rotate_f64 :: proc(angle_radians: f64, v: Vector3f64) -> Matrix4f64 {
  1705. c := math.cos(angle_radians);
  1706. s := math.sin(angle_radians);
  1707. a := normalize(v);
  1708. t := a * (1-c);
  1709. rot := MATRIX4F64_IDENTITY;
  1710. rot[0][0] = c + t[0]*a[0];
  1711. rot[0][1] = 0 + t[0]*a[1] + s*a[2];
  1712. rot[0][2] = 0 + t[0]*a[2] - s*a[1];
  1713. rot[0][3] = 0;
  1714. rot[1][0] = 0 + t[1]*a[0] - s*a[2];
  1715. rot[1][1] = c + t[1]*a[1];
  1716. rot[1][2] = 0 + t[1]*a[2] + s*a[0];
  1717. rot[1][3] = 0;
  1718. rot[2][0] = 0 + t[2]*a[0] + s*a[1];
  1719. rot[2][1] = 0 + t[2]*a[1] - s*a[0];
  1720. rot[2][2] = c + t[2]*a[2];
  1721. rot[2][3] = 0;
  1722. return rot;
  1723. }
  1724. matrix4_rotate :: proc{
  1725. matrix4_rotate_f16,
  1726. matrix4_rotate_f32,
  1727. matrix4_rotate_f64,
  1728. };
  1729. matrix4_scale_f16 :: proc(v: Vector3f16) -> (m: Matrix4f16) {
  1730. m[0][0] = v[0];
  1731. m[1][1] = v[1];
  1732. m[2][2] = v[2];
  1733. m[3][3] = 1;
  1734. return;
  1735. }
  1736. matrix4_scale_f32 :: proc(v: Vector3f32) -> (m: Matrix4f32) {
  1737. m[0][0] = v[0];
  1738. m[1][1] = v[1];
  1739. m[2][2] = v[2];
  1740. m[3][3] = 1;
  1741. return;
  1742. }
  1743. matrix4_scale_f64 :: proc(v: Vector3f64) -> (m: Matrix4f64) {
  1744. m[0][0] = v[0];
  1745. m[1][1] = v[1];
  1746. m[2][2] = v[2];
  1747. m[3][3] = 1;
  1748. return;
  1749. }
  1750. matrix4_scale :: proc{
  1751. matrix4_scale_f16,
  1752. matrix4_scale_f32,
  1753. matrix4_scale_f64,
  1754. };
  1755. matrix4_look_at_f16 :: proc(eye, centre, up: Vector3f16, flip_z_axis := true) -> (m: Matrix4f16) {
  1756. f := normalize(centre - eye);
  1757. s := normalize(cross(f, up));
  1758. u := cross(s, f);
  1759. fe := dot(f, eye);
  1760. return {
  1761. {+s.x, +u.x, -f.x, 0},
  1762. {+s.y, +u.y, -f.y, 0},
  1763. {+s.z, +u.z, -f.z, 0},
  1764. {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1},
  1765. };
  1766. }
  1767. matrix4_look_at_f32 :: proc(eye, centre, up: Vector3f32, flip_z_axis := true) -> (m: Matrix4f32) {
  1768. f := normalize(centre - eye);
  1769. s := normalize(cross(f, up));
  1770. u := cross(s, f);
  1771. fe := dot(f, eye);
  1772. return {
  1773. {+s.x, +u.x, -f.x, 0},
  1774. {+s.y, +u.y, -f.y, 0},
  1775. {+s.z, +u.z, -f.z, 0},
  1776. {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1},
  1777. };
  1778. }
  1779. matrix4_look_at_f64 :: proc(eye, centre, up: Vector3f64, flip_z_axis := true) -> (m: Matrix4f64) {
  1780. f := normalize(centre - eye);
  1781. s := normalize(cross(f, up));
  1782. u := cross(s, f);
  1783. fe := dot(f, eye);
  1784. return {
  1785. {+s.x, +u.x, -f.x, 0},
  1786. {+s.y, +u.y, -f.y, 0},
  1787. {+s.z, +u.z, -f.z, 0},
  1788. {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1},
  1789. };
  1790. }
  1791. matrix4_look_at :: proc{
  1792. matrix4_look_at_f16,
  1793. matrix4_look_at_f32,
  1794. matrix4_look_at_f64,
  1795. };
  1796. matrix4_perspective_f16 :: proc(fovy, aspect, near, far: f16, flip_z_axis := true) -> (m: Matrix4f16) {
  1797. tan_half_fovy := math.tan(0.5 * fovy);
  1798. m[0][0] = 1 / (aspect*tan_half_fovy);
  1799. m[1][1] = 1 / (tan_half_fovy);
  1800. m[2][2] = +(far + near) / (far - near);
  1801. m[2][3] = +1;
  1802. m[3][2] = -2*far*near / (far - near);
  1803. if flip_z_axis {
  1804. m[2] = -m[2];
  1805. }
  1806. return;
  1807. }
  1808. matrix4_perspective_f32 :: proc(fovy, aspect, near, far: f32, flip_z_axis := true) -> (m: Matrix4f32) {
  1809. tan_half_fovy := math.tan(0.5 * fovy);
  1810. m[0][0] = 1 / (aspect*tan_half_fovy);
  1811. m[1][1] = 1 / (tan_half_fovy);
  1812. m[2][2] = +(far + near) / (far - near);
  1813. m[2][3] = +1;
  1814. m[3][2] = -2*far*near / (far - near);
  1815. if flip_z_axis {
  1816. m[2] = -m[2];
  1817. }
  1818. return;
  1819. }
  1820. matrix4_perspective_f64 :: proc(fovy, aspect, near, far: f64, flip_z_axis := true) -> (m: Matrix4f64) {
  1821. tan_half_fovy := math.tan(0.5 * fovy);
  1822. m[0][0] = 1 / (aspect*tan_half_fovy);
  1823. m[1][1] = 1 / (tan_half_fovy);
  1824. m[2][2] = +(far + near) / (far - near);
  1825. m[2][3] = +1;
  1826. m[3][2] = -2*far*near / (far - near);
  1827. if flip_z_axis {
  1828. m[2] = -m[2];
  1829. }
  1830. return;
  1831. }
  1832. matrix4_perspective :: proc{
  1833. matrix4_perspective_f16,
  1834. matrix4_perspective_f32,
  1835. matrix4_perspective_f64,
  1836. };
  1837. matrix_ortho3d_f16 :: proc(left, right, bottom, top, near, far: f16, flip_z_axis := true) -> (m: Matrix4f16) {
  1838. m[0][0] = +2 / (right - left);
  1839. m[1][1] = +2 / (top - bottom);
  1840. m[2][2] = +2 / (far - near);
  1841. m[3][0] = -(right + left) / (right - left);
  1842. m[3][1] = -(top + bottom) / (top - bottom);
  1843. m[3][2] = -(far + near) / (far- near);
  1844. m[3][3] = 1;
  1845. if flip_z_axis {
  1846. m[2] = -m[2];
  1847. }
  1848. return;
  1849. }
  1850. matrix_ortho3d_f32 :: proc(left, right, bottom, top, near, far: f32, flip_z_axis := true) -> (m: Matrix4f32) {
  1851. m[0][0] = +2 / (right - left);
  1852. m[1][1] = +2 / (top - bottom);
  1853. m[2][2] = +2 / (far - near);
  1854. m[3][0] = -(right + left) / (right - left);
  1855. m[3][1] = -(top + bottom) / (top - bottom);
  1856. m[3][2] = -(far + near) / (far- near);
  1857. m[3][3] = 1;
  1858. if flip_z_axis {
  1859. m[2] = -m[2];
  1860. }
  1861. return;
  1862. }
  1863. matrix_ortho3d_f64 :: proc(left, right, bottom, top, near, far: f64, flip_z_axis := true) -> (m: Matrix4f64) {
  1864. m[0][0] = +2 / (right - left);
  1865. m[1][1] = +2 / (top - bottom);
  1866. m[2][2] = +2 / (far - near);
  1867. m[3][0] = -(right + left) / (right - left);
  1868. m[3][1] = -(top + bottom) / (top - bottom);
  1869. m[3][2] = -(far + near) / (far- near);
  1870. m[3][3] = 1;
  1871. if flip_z_axis {
  1872. m[2] = -m[2];
  1873. }
  1874. return;
  1875. }
  1876. matrix_ortho3d :: proc{
  1877. matrix_ortho3d_f16,
  1878. matrix_ortho3d_f32,
  1879. matrix_ortho3d_f64,
  1880. };
  1881. matrix4_infinite_perspective_f16 :: proc(fovy, aspect, near: f16, flip_z_axis := true) -> (m: Matrix4f16) {
  1882. tan_half_fovy := math.tan(0.5 * fovy);
  1883. m[0][0] = 1 / (aspect*tan_half_fovy);
  1884. m[1][1] = 1 / (tan_half_fovy);
  1885. m[2][2] = +1;
  1886. m[2][3] = +1;
  1887. m[3][2] = -2*near;
  1888. if flip_z_axis {
  1889. m[2] = -m[2];
  1890. }
  1891. return;
  1892. }
  1893. matrix4_infinite_perspective_f32 :: proc(fovy, aspect, near: f32, flip_z_axis := true) -> (m: Matrix4f32) {
  1894. tan_half_fovy := math.tan(0.5 * fovy);
  1895. m[0][0] = 1 / (aspect*tan_half_fovy);
  1896. m[1][1] = 1 / (tan_half_fovy);
  1897. m[2][2] = +1;
  1898. m[2][3] = +1;
  1899. m[3][2] = -2*near;
  1900. if flip_z_axis {
  1901. m[2] = -m[2];
  1902. }
  1903. return;
  1904. }
  1905. matrix4_infinite_perspective_f64 :: proc(fovy, aspect, near: f64, flip_z_axis := true) -> (m: Matrix4f64) {
  1906. tan_half_fovy := math.tan(0.5 * fovy);
  1907. m[0][0] = 1 / (aspect*tan_half_fovy);
  1908. m[1][1] = 1 / (tan_half_fovy);
  1909. m[2][2] = +1;
  1910. m[2][3] = +1;
  1911. m[3][2] = -2*near;
  1912. if flip_z_axis {
  1913. m[2] = -m[2];
  1914. }
  1915. return;
  1916. }
  1917. matrix4_infinite_perspective :: proc{
  1918. matrix4_infinite_perspective_f16,
  1919. matrix4_infinite_perspective_f32,
  1920. matrix4_infinite_perspective_f64,
  1921. };
  1922. matrix2_from_scalar_f16 :: proc(f: f16) -> (m: Matrix2f16) {
  1923. m[0][0], m[0][1] = f, 0;
  1924. m[1][0], m[1][1] = 0, f;
  1925. return;
  1926. }
  1927. matrix2_from_scalar_f32 :: proc(f: f32) -> (m: Matrix2f32) {
  1928. m[0][0], m[0][1] = f, 0;
  1929. m[1][0], m[1][1] = 0, f;
  1930. return;
  1931. }
  1932. matrix2_from_scalar_f64 :: proc(f: f64) -> (m: Matrix2f64) {
  1933. m[0][0], m[0][1] = f, 0;
  1934. m[1][0], m[1][1] = 0, f;
  1935. return;
  1936. }
  1937. matrix2_from_scalar :: proc{
  1938. matrix2_from_scalar_f16,
  1939. matrix2_from_scalar_f32,
  1940. matrix2_from_scalar_f64,
  1941. };
  1942. matrix3_from_scalar_f16 :: proc(f: f16) -> (m: Matrix3f16) {
  1943. m[0][0], m[0][1], m[0][2] = f, 0, 0;
  1944. m[1][0], m[1][1], m[1][2] = 0, f, 0;
  1945. m[2][0], m[2][1], m[2][2] = 0, 0, f;
  1946. return;
  1947. }
  1948. matrix3_from_scalar_f32 :: proc(f: f32) -> (m: Matrix3f32) {
  1949. m[0][0], m[0][1], m[0][2] = f, 0, 0;
  1950. m[1][0], m[1][1], m[1][2] = 0, f, 0;
  1951. m[2][0], m[2][1], m[2][2] = 0, 0, f;
  1952. return;
  1953. }
  1954. matrix3_from_scalar_f64 :: proc(f: f64) -> (m: Matrix3f64) {
  1955. m[0][0], m[0][1], m[0][2] = f, 0, 0;
  1956. m[1][0], m[1][1], m[1][2] = 0, f, 0;
  1957. m[2][0], m[2][1], m[2][2] = 0, 0, f;
  1958. return;
  1959. }
  1960. matrix3_from_scalar :: proc{
  1961. matrix3_from_scalar_f16,
  1962. matrix3_from_scalar_f32,
  1963. matrix3_from_scalar_f64,
  1964. };
  1965. matrix4_from_scalar_f16 :: proc(f: f16) -> (m: Matrix4f16) {
  1966. m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0;
  1967. m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0;
  1968. m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0;
  1969. m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f;
  1970. return;
  1971. }
  1972. matrix4_from_scalar_f32 :: proc(f: f32) -> (m: Matrix4f32) {
  1973. m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0;
  1974. m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0;
  1975. m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0;
  1976. m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f;
  1977. return;
  1978. }
  1979. matrix4_from_scalar_f64 :: proc(f: f64) -> (m: Matrix4f64) {
  1980. m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0;
  1981. m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0;
  1982. m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0;
  1983. m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f;
  1984. return;
  1985. }
  1986. matrix4_from_scalar :: proc{
  1987. matrix4_from_scalar_f16,
  1988. matrix4_from_scalar_f32,
  1989. matrix4_from_scalar_f64,
  1990. };
  1991. matrix2_from_matrix3_f16 :: proc(m: Matrix3f16) -> (r: Matrix2f16) {
  1992. r[0][0], r[0][1] = m[0][0], m[0][1];
  1993. r[1][0], r[1][1] = m[1][0], m[1][1];
  1994. return;
  1995. }
  1996. matrix2_from_matrix3_f32 :: proc(m: Matrix3f32) -> (r: Matrix2f32) {
  1997. r[0][0], r[0][1] = m[0][0], m[0][1];
  1998. r[1][0], r[1][1] = m[1][0], m[1][1];
  1999. return;
  2000. }
  2001. matrix2_from_matrix3_f64 :: proc(m: Matrix3f64) -> (r: Matrix2f64) {
  2002. r[0][0], r[0][1] = m[0][0], m[0][1];
  2003. r[1][0], r[1][1] = m[1][0], m[1][1];
  2004. return;
  2005. }
  2006. matrix2_from_matrix3 :: proc{
  2007. matrix2_from_matrix3_f16,
  2008. matrix2_from_matrix3_f32,
  2009. matrix2_from_matrix3_f64,
  2010. };
  2011. matrix2_from_matrix4_f16 :: proc(m: Matrix4f16) -> (r: Matrix2f16) {
  2012. r[0][0], r[0][1] = m[0][0], m[0][1];
  2013. r[1][0], r[1][1] = m[1][0], m[1][1];
  2014. return;
  2015. }
  2016. matrix2_from_matrix4_f32 :: proc(m: Matrix4f32) -> (r: Matrix2f32) {
  2017. r[0][0], r[0][1] = m[0][0], m[0][1];
  2018. r[1][0], r[1][1] = m[1][0], m[1][1];
  2019. return;
  2020. }
  2021. matrix2_from_matrix4_f64 :: proc(m: Matrix4f64) -> (r: Matrix2f64) {
  2022. r[0][0], r[0][1] = m[0][0], m[0][1];
  2023. r[1][0], r[1][1] = m[1][0], m[1][1];
  2024. return;
  2025. }
  2026. matrix2_from_matrix4 :: proc{
  2027. matrix2_from_matrix4_f16,
  2028. matrix2_from_matrix4_f32,
  2029. matrix2_from_matrix4_f64,
  2030. };
  2031. matrix3_from_matrix2_f16 :: proc(m: Matrix2f16) -> (r: Matrix3f16) {
  2032. r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0;
  2033. r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0;
  2034. r[2][0], r[2][1], r[2][2] = 0, 0, 1;
  2035. return;
  2036. }
  2037. matrix3_from_matrix2_f32 :: proc(m: Matrix2f32) -> (r: Matrix3f32) {
  2038. r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0;
  2039. r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0;
  2040. r[2][0], r[2][1], r[2][2] = 0, 0, 1;
  2041. return;
  2042. }
  2043. matrix3_from_matrix2_f64 :: proc(m: Matrix2f64) -> (r: Matrix3f64) {
  2044. r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0;
  2045. r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0;
  2046. r[2][0], r[2][1], r[2][2] = 0, 0, 1;
  2047. return;
  2048. }
  2049. matrix3_from_matrix2 :: proc{
  2050. matrix3_from_matrix2_f16,
  2051. matrix3_from_matrix2_f32,
  2052. matrix3_from_matrix2_f64,
  2053. };
  2054. matrix3_from_matrix4_f16 :: proc(m: Matrix4f16) -> (r: Matrix3f16) {
  2055. r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2];
  2056. r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2];
  2057. r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2];
  2058. return;
  2059. }
  2060. matrix3_from_matrix4_f32 :: proc(m: Matrix4f32) -> (r: Matrix3f32) {
  2061. r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2];
  2062. r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2];
  2063. r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2];
  2064. return;
  2065. }
  2066. matrix3_from_matrix4_f64 :: proc(m: Matrix4f64) -> (r: Matrix3f64) {
  2067. r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2];
  2068. r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2];
  2069. r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2];
  2070. return;
  2071. }
  2072. matrix3_from_matrix4 :: proc{
  2073. matrix3_from_matrix4_f16,
  2074. matrix3_from_matrix4_f32,
  2075. matrix3_from_matrix4_f64,
  2076. };
  2077. matrix4_from_matrix2_f16 :: proc(m: Matrix2f16) -> (r: Matrix4f16) {
  2078. r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0;
  2079. r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0;
  2080. r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0;
  2081. r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
  2082. return;
  2083. }
  2084. matrix4_from_matrix2_f32 :: proc(m: Matrix2f32) -> (r: Matrix4f32) {
  2085. r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0;
  2086. r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0;
  2087. r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0;
  2088. r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
  2089. return;
  2090. }
  2091. matrix4_from_matrix2_f64 :: proc(m: Matrix2f64) -> (r: Matrix4f64) {
  2092. r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0;
  2093. r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0;
  2094. r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0;
  2095. r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
  2096. return;
  2097. }
  2098. matrix4_from_matrix2 :: proc{
  2099. matrix4_from_matrix2_f16,
  2100. matrix4_from_matrix2_f32,
  2101. matrix4_from_matrix2_f64,
  2102. };
  2103. matrix4_from_matrix3_f16 :: proc(m: Matrix3f16) -> (r: Matrix4f16) {
  2104. r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0;
  2105. r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0;
  2106. r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0;
  2107. r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
  2108. return;
  2109. }
  2110. matrix4_from_matrix3_f32 :: proc(m: Matrix3f32) -> (r: Matrix4f32) {
  2111. r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0;
  2112. r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0;
  2113. r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0;
  2114. r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
  2115. return;
  2116. }
  2117. matrix4_from_matrix3_f64 :: proc(m: Matrix3f64) -> (r: Matrix4f64) {
  2118. r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0;
  2119. r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0;
  2120. r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0;
  2121. r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
  2122. return;
  2123. }
  2124. matrix4_from_matrix3 :: proc{
  2125. matrix4_from_matrix3_f16,
  2126. matrix4_from_matrix3_f32,
  2127. matrix4_from_matrix3_f64,
  2128. };
  2129. quaternion_from_scalar_f16 :: proc(f: f16) -> (q: Quaternionf16) {
  2130. q.w = f;
  2131. return;
  2132. }
  2133. quaternion_from_scalar_f32 :: proc(f: f32) -> (q: Quaternionf32) {
  2134. q.w = f;
  2135. return;
  2136. }
  2137. quaternion_from_scalar_f64 :: proc(f: f64) -> (q: Quaternionf64) {
  2138. q.w = f;
  2139. return;
  2140. }
  2141. quaternion_from_scalar :: proc{
  2142. quaternion_from_scalar_f16,
  2143. quaternion_from_scalar_f32,
  2144. quaternion_from_scalar_f64,
  2145. };
  2146. to_matrix2f16 :: proc{matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16};
  2147. to_matrix3f16 :: proc{matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16};
  2148. to_matrix4f16 :: proc{matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16};
  2149. to_quaternionf16 :: proc{quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16};
  2150. to_matrix2f32 :: proc{matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32};
  2151. to_matrix3f32 :: proc{matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32};
  2152. to_matrix4f32 :: proc{matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32};
  2153. to_quaternionf32 :: proc{quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32};
  2154. to_matrix2f64 :: proc{matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64};
  2155. to_matrix3f64 :: proc{matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64};
  2156. to_matrix4f64 :: proc{matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64};
  2157. to_quaternionf64 :: proc{quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64};
  2158. to_matrix2f :: proc{
  2159. matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16,
  2160. matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32,
  2161. matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64,
  2162. };
  2163. to_matrix3 :: proc{
  2164. matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16,
  2165. matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32,
  2166. matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64,
  2167. };
  2168. to_matrix4 :: proc{
  2169. matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16,
  2170. matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32,
  2171. matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64,
  2172. };
  2173. to_quaternion :: proc{
  2174. quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16,
  2175. quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32,
  2176. quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64,
  2177. };
  2178. matrix2_orthonormalize_f16 :: proc(m: Matrix2f16) -> (r: Matrix2f16) {
  2179. r[0] = normalize(m[0]);
  2180. d0 := dot(r[0], r[1]);
  2181. r[1] -= r[0] * d0;
  2182. r[1] = normalize(r[1]);
  2183. return;
  2184. }
  2185. matrix2_orthonormalize_f32 :: proc(m: Matrix2f32) -> (r: Matrix2f32) {
  2186. r[0] = normalize(m[0]);
  2187. d0 := dot(r[0], r[1]);
  2188. r[1] -= r[0] * d0;
  2189. r[1] = normalize(r[1]);
  2190. return;
  2191. }
  2192. matrix2_orthonormalize_f64 :: proc(m: Matrix2f64) -> (r: Matrix2f64) {
  2193. r[0] = normalize(m[0]);
  2194. d0 := dot(r[0], r[1]);
  2195. r[1] -= r[0] * d0;
  2196. r[1] = normalize(r[1]);
  2197. return;
  2198. }
  2199. matrix2_orthonormalize :: proc{
  2200. matrix2_orthonormalize_f16,
  2201. matrix2_orthonormalize_f32,
  2202. matrix2_orthonormalize_f64,
  2203. };
  2204. matrix3_orthonormalize_f16 :: proc(m: Matrix3f16) -> (r: Matrix3f16) {
  2205. r[0] = normalize(m[0]);
  2206. d0 := dot(r[0], r[1]);
  2207. r[1] -= r[0] * d0;
  2208. r[1] = normalize(r[1]);
  2209. d1 := dot(r[1], r[2]);
  2210. d0 = dot(r[0], r[2]);
  2211. r[2] -= r[0]*d0 + r[1]*d1;
  2212. r[2] = normalize(r[2]);
  2213. return;
  2214. }
  2215. matrix3_orthonormalize_f32 :: proc(m: Matrix3f32) -> (r: Matrix3f32) {
  2216. r[0] = normalize(m[0]);
  2217. d0 := dot(r[0], r[1]);
  2218. r[1] -= r[0] * d0;
  2219. r[1] = normalize(r[1]);
  2220. d1 := dot(r[1], r[2]);
  2221. d0 = dot(r[0], r[2]);
  2222. r[2] -= r[0]*d0 + r[1]*d1;
  2223. r[2] = normalize(r[2]);
  2224. return;
  2225. }
  2226. matrix3_orthonormalize_f64 :: proc(m: Matrix3f64) -> (r: Matrix3f64) {
  2227. r[0] = normalize(m[0]);
  2228. d0 := dot(r[0], r[1]);
  2229. r[1] -= r[0] * d0;
  2230. r[1] = normalize(r[1]);
  2231. d1 := dot(r[1], r[2]);
  2232. d0 = dot(r[0], r[2]);
  2233. r[2] -= r[0]*d0 + r[1]*d1;
  2234. r[2] = normalize(r[2]);
  2235. return;
  2236. }
  2237. matrix3_orthonormalize :: proc{
  2238. matrix3_orthonormalize_f16,
  2239. matrix3_orthonormalize_f32,
  2240. matrix3_orthonormalize_f64,
  2241. };
  2242. vector3_orthonormalize_f16 :: proc(x, y: Vector3f16) -> (z: Vector3f16) {
  2243. return normalize(x - y * dot(y, x));
  2244. }
  2245. vector3_orthonormalize_f32 :: proc(x, y: Vector3f32) -> (z: Vector3f32) {
  2246. return normalize(x - y * dot(y, x));
  2247. }
  2248. vector3_orthonormalize_f64 :: proc(x, y: Vector3f64) -> (z: Vector3f64) {
  2249. return normalize(x - y * dot(y, x));
  2250. }
  2251. vector3_orthonormalize :: proc{
  2252. vector3_orthonormalize_f16,
  2253. vector3_orthonormalize_f32,
  2254. vector3_orthonormalize_f64,
  2255. };
  2256. orthonormalize :: proc{
  2257. matrix2_orthonormalize_f16, matrix3_orthonormalize_f16, vector3_orthonormalize_f16,
  2258. matrix2_orthonormalize_f32, matrix3_orthonormalize_f32, vector3_orthonormalize_f32,
  2259. matrix2_orthonormalize_f64, matrix3_orthonormalize_f64, vector3_orthonormalize_f64,
  2260. };
  2261. matrix4_orientation_f16 :: proc(normal, up: Vector3f16) -> Matrix4f16 {
  2262. if all(equal(normal, up)) {
  2263. return MATRIX4F16_IDENTITY;
  2264. }
  2265. rotation_axis := cross(up, normal);
  2266. angle := math.acos(dot(normal, up));
  2267. return matrix4_rotate(angle, rotation_axis);
  2268. }
  2269. matrix4_orientation_f32 :: proc(normal, up: Vector3f32) -> Matrix4f32 {
  2270. if all(equal(normal, up)) {
  2271. return MATRIX4F32_IDENTITY;
  2272. }
  2273. rotation_axis := cross(up, normal);
  2274. angle := math.acos(dot(normal, up));
  2275. return matrix4_rotate(angle, rotation_axis);
  2276. }
  2277. matrix4_orientation_f64 :: proc(normal, up: Vector3f64) -> Matrix4f64 {
  2278. if all(equal(normal, up)) {
  2279. return MATRIX4F64_IDENTITY;
  2280. }
  2281. rotation_axis := cross(up, normal);
  2282. angle := math.acos(dot(normal, up));
  2283. return matrix4_rotate(angle, rotation_axis);
  2284. }
  2285. matrix4_orientation :: proc{
  2286. matrix4_orientation_f16,
  2287. matrix4_orientation_f32,
  2288. matrix4_orientation_f64,
  2289. };
  2290. euclidean_from_polar_f16 :: proc(polar: Vector2f16) -> Vector3f16 {
  2291. latitude, longitude := polar.x, polar.y;
  2292. cx, sx := math.cos(latitude), math.sin(latitude);
  2293. cy, sy := math.cos(longitude), math.sin(longitude);
  2294. return {
  2295. cx*sy,
  2296. sx,
  2297. cx*cy,
  2298. };
  2299. }
  2300. euclidean_from_polar_f32 :: proc(polar: Vector2f32) -> Vector3f32 {
  2301. latitude, longitude := polar.x, polar.y;
  2302. cx, sx := math.cos(latitude), math.sin(latitude);
  2303. cy, sy := math.cos(longitude), math.sin(longitude);
  2304. return {
  2305. cx*sy,
  2306. sx,
  2307. cx*cy,
  2308. };
  2309. }
  2310. euclidean_from_polar_f64 :: proc(polar: Vector2f64) -> Vector3f64 {
  2311. latitude, longitude := polar.x, polar.y;
  2312. cx, sx := math.cos(latitude), math.sin(latitude);
  2313. cy, sy := math.cos(longitude), math.sin(longitude);
  2314. return {
  2315. cx*sy,
  2316. sx,
  2317. cx*cy,
  2318. };
  2319. }
  2320. euclidean_from_polar :: proc{
  2321. euclidean_from_polar_f16,
  2322. euclidean_from_polar_f32,
  2323. euclidean_from_polar_f64,
  2324. };
  2325. polar_from_euclidean_f16 :: proc(euclidean: Vector3f16) -> Vector3f16 {
  2326. n := length(euclidean);
  2327. tmp := euclidean / n;
  2328. xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z);
  2329. return {
  2330. math.asin(tmp.y),
  2331. math.atan2(tmp.x, tmp.z),
  2332. xz_dist,
  2333. };
  2334. }
  2335. polar_from_euclidean_f32 :: proc(euclidean: Vector3f32) -> Vector3f32 {
  2336. n := length(euclidean);
  2337. tmp := euclidean / n;
  2338. xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z);
  2339. return {
  2340. math.asin(tmp.y),
  2341. math.atan2(tmp.x, tmp.z),
  2342. xz_dist,
  2343. };
  2344. }
  2345. polar_from_euclidean_f64 :: proc(euclidean: Vector3f64) -> Vector3f64 {
  2346. n := length(euclidean);
  2347. tmp := euclidean / n;
  2348. xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z);
  2349. return {
  2350. math.asin(tmp.y),
  2351. math.atan2(tmp.x, tmp.z),
  2352. xz_dist,
  2353. };
  2354. }
  2355. polar_from_euclidean :: proc{
  2356. polar_from_euclidean_f16,
  2357. polar_from_euclidean_f32,
  2358. polar_from_euclidean_f64,
  2359. };