specific.odin 78 KB

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