specific.odin 75 KB

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