123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706 |
- package linalg
- import "core:math"
- F16_EPSILON :: 1e-3;
- F32_EPSILON :: 1e-7;
- F64_EPSILON :: 1e-15;
- Vector2f16 :: distinct [2]f16;
- Vector3f16 :: distinct [3]f16;
- Vector4f16 :: distinct [4]f16;
- Matrix1x1f16 :: distinct [1][1]f16;
- Matrix1x2f16 :: distinct [1][2]f16;
- Matrix1x3f16 :: distinct [1][3]f16;
- Matrix1x4f16 :: distinct [1][4]f16;
- Matrix2x1f16 :: distinct [2][1]f16;
- Matrix2x2f16 :: distinct [2][2]f16;
- Matrix2x3f16 :: distinct [2][3]f16;
- Matrix2x4f16 :: distinct [2][4]f16;
- Matrix3x1f16 :: distinct [3][1]f16;
- Matrix3x2f16 :: distinct [3][2]f16;
- Matrix3x3f16 :: distinct [3][3]f16;
- Matrix3x4f16 :: distinct [3][4]f16;
- Matrix4x1f16 :: distinct [4][1]f16;
- Matrix4x2f16 :: distinct [4][2]f16;
- Matrix4x3f16 :: distinct [4][3]f16;
- Matrix4x4f16 :: distinct [4][4]f16;
- Matrix1f16 :: Matrix1x1f16;
- Matrix2f16 :: Matrix2x2f16;
- Matrix3f16 :: Matrix3x3f16;
- Matrix4f16 :: Matrix4x4f16;
- Vector2f32 :: distinct [2]f32;
- Vector3f32 :: distinct [3]f32;
- Vector4f32 :: distinct [4]f32;
- Matrix1x1f32 :: distinct [1][1]f32;
- Matrix1x2f32 :: distinct [1][2]f32;
- Matrix1x3f32 :: distinct [1][3]f32;
- Matrix1x4f32 :: distinct [1][4]f32;
- Matrix2x1f32 :: distinct [2][1]f32;
- Matrix2x2f32 :: distinct [2][2]f32;
- Matrix2x3f32 :: distinct [2][3]f32;
- Matrix2x4f32 :: distinct [2][4]f32;
- Matrix3x1f32 :: distinct [3][1]f32;
- Matrix3x2f32 :: distinct [3][2]f32;
- Matrix3x3f32 :: distinct [3][3]f32;
- Matrix3x4f32 :: distinct [3][4]f32;
- Matrix4x1f32 :: distinct [4][1]f32;
- Matrix4x2f32 :: distinct [4][2]f32;
- Matrix4x3f32 :: distinct [4][3]f32;
- Matrix4x4f32 :: distinct [4][4]f32;
- Matrix1f32 :: Matrix1x1f32;
- Matrix2f32 :: Matrix2x2f32;
- Matrix3f32 :: Matrix3x3f32;
- Matrix4f32 :: Matrix4x4f32;
- Vector2f64 :: distinct [2]f64;
- Vector3f64 :: distinct [3]f64;
- Vector4f64 :: distinct [4]f64;
- Matrix1x1f64 :: distinct [1][1]f64;
- Matrix1x2f64 :: distinct [1][2]f64;
- Matrix1x3f64 :: distinct [1][3]f64;
- Matrix1x4f64 :: distinct [1][4]f64;
- Matrix2x1f64 :: distinct [2][1]f64;
- Matrix2x2f64 :: distinct [2][2]f64;
- Matrix2x3f64 :: distinct [2][3]f64;
- Matrix2x4f64 :: distinct [2][4]f64;
- Matrix3x1f64 :: distinct [3][1]f64;
- Matrix3x2f64 :: distinct [3][2]f64;
- Matrix3x3f64 :: distinct [3][3]f64;
- Matrix3x4f64 :: distinct [3][4]f64;
- Matrix4x1f64 :: distinct [4][1]f64;
- Matrix4x2f64 :: distinct [4][2]f64;
- Matrix4x3f64 :: distinct [4][3]f64;
- Matrix4x4f64 :: distinct [4][4]f64;
- Matrix1f64 :: Matrix1x1f64;
- Matrix2f64 :: Matrix2x2f64;
- Matrix3f64 :: Matrix3x3f64;
- Matrix4f64 :: Matrix4x4f64;
- Quaternionf16 :: distinct quaternion64;
- Quaternionf32 :: distinct quaternion128;
- Quaternionf64 :: distinct quaternion256;
- MATRIX1F16_IDENTITY :: Matrix1f16{{1}};
- MATRIX2F16_IDENTITY :: Matrix2f16{{1, 0}, {0, 1}};
- MATRIX3F16_IDENTITY :: Matrix3f16{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
- MATRIX4F16_IDENTITY :: Matrix4f16{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
- MATRIX1F32_IDENTITY :: Matrix1f32{{1}};
- MATRIX2F32_IDENTITY :: Matrix2f32{{1, 0}, {0, 1}};
- MATRIX3F32_IDENTITY :: Matrix3f32{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
- MATRIX4F32_IDENTITY :: Matrix4f32{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
- MATRIX1F64_IDENTITY :: Matrix1f64{{1}};
- MATRIX2F64_IDENTITY :: Matrix2f64{{1, 0}, {0, 1}};
- MATRIX3F64_IDENTITY :: Matrix3f64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
- MATRIX4F64_IDENTITY :: Matrix4f64{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
- QUATERNIONF16_IDENTITY :: Quaternionf16(1);
- QUATERNIONF32_IDENTITY :: Quaternionf32(1);
- QUATERNIONF64_IDENTITY :: Quaternionf64(1);
- VECTOR3F16_X_AXIS :: Vector3f16{1, 0, 0};
- VECTOR3F16_Y_AXIS :: Vector3f16{0, 1, 0};
- VECTOR3F16_Z_AXIS :: Vector3f16{0, 0, 1};
- VECTOR3F32_X_AXIS :: Vector3f32{1, 0, 0};
- VECTOR3F32_Y_AXIS :: Vector3f32{0, 1, 0};
- VECTOR3F32_Z_AXIS :: Vector3f32{0, 0, 1};
- VECTOR3F64_X_AXIS :: Vector3f64{1, 0, 0};
- VECTOR3F64_Y_AXIS :: Vector3f64{0, 1, 0};
- VECTOR3F64_Z_AXIS :: Vector3f64{0, 0, 1};
- vector2_orthogonal :: proc(v: $V/[2]$E) -> V where !IS_ARRAY(E), IS_FLOAT(E) {
- return {-v.y, v.x};
- }
- vector3_orthogonal :: proc(v: $V/[3]$E) -> V where !IS_ARRAY(E), IS_FLOAT(E) {
- x := abs(v.x);
- y := abs(v.y);
- z := abs(v.z);
- other: V;
- if x < y {
- if x < z {
- other = {1, 0, 0};
- } else {
- other = {0, 0, 1};
- }
- } else {
- if y < z {
- other = {0, 1, 0};
- } else {
- other = {0, 0, 1};
- }
- }
- return normalize(cross(v, other));
- }
- orthogonal :: proc{vector2_orthogonal, vector3_orthogonal};
- vector4_srgb_to_linear_f16 :: proc(col: Vector4f16) -> Vector4f16 {
- r := math.pow(col.x, 2.2);
- g := math.pow(col.y, 2.2);
- b := math.pow(col.z, 2.2);
- a := col.w;
- return {r, g, b, a};
- }
- vector4_srgb_to_linear_f32 :: proc(col: Vector4f32) -> Vector4f32 {
- r := math.pow(col.x, 2.2);
- g := math.pow(col.y, 2.2);
- b := math.pow(col.z, 2.2);
- a := col.w;
- return {r, g, b, a};
- }
- vector4_srgb_to_linear_f64 :: proc(col: Vector4f64) -> Vector4f64 {
- r := math.pow(col.x, 2.2);
- g := math.pow(col.y, 2.2);
- b := math.pow(col.z, 2.2);
- a := col.w;
- return {r, g, b, a};
- }
- vector4_srgb_to_linear :: proc{
- vector4_srgb_to_linear_f16,
- vector4_srgb_to_linear_f32,
- vector4_srgb_to_linear_f64,
- };
- vector4_linear_to_srgb_f16 :: proc(col: Vector4f16) -> Vector4f16 {
- a :: 2.51;
- b :: 0.03;
- c :: 2.43;
- d :: 0.59;
- e :: 0.14;
- x := col.x;
- y := col.y;
- z := col.z;
- x = (x * (a * x + b)) / (x * (c * x + d) + e);
- y = (y * (a * y + b)) / (y * (c * y + d) + e);
- z = (z * (a * z + b)) / (z * (c * z + d) + e);
- x = math.pow(clamp(x, 0, 1), 1.0 / 2.2);
- y = math.pow(clamp(y, 0, 1), 1.0 / 2.2);
- z = math.pow(clamp(z, 0, 1), 1.0 / 2.2);
- return {x, y, z, col.w};
- }
- vector4_linear_to_srgb_f32 :: proc(col: Vector4f32) -> Vector4f32 {
- a :: 2.51;
- b :: 0.03;
- c :: 2.43;
- d :: 0.59;
- e :: 0.14;
- x := col.x;
- y := col.y;
- z := col.z;
- x = (x * (a * x + b)) / (x * (c * x + d) + e);
- y = (y * (a * y + b)) / (y * (c * y + d) + e);
- z = (z * (a * z + b)) / (z * (c * z + d) + e);
- x = math.pow(clamp(x, 0, 1), 1.0 / 2.2);
- y = math.pow(clamp(y, 0, 1), 1.0 / 2.2);
- z = math.pow(clamp(z, 0, 1), 1.0 / 2.2);
- return {x, y, z, col.w};
- }
- vector4_linear_to_srgb_f64 :: proc(col: Vector4f64) -> Vector4f64 {
- a :: 2.51;
- b :: 0.03;
- c :: 2.43;
- d :: 0.59;
- e :: 0.14;
- x := col.x;
- y := col.y;
- z := col.z;
- x = (x * (a * x + b)) / (x * (c * x + d) + e);
- y = (y * (a * y + b)) / (y * (c * y + d) + e);
- z = (z * (a * z + b)) / (z * (c * z + d) + e);
- x = math.pow(clamp(x, 0, 1), 1.0 / 2.2);
- y = math.pow(clamp(y, 0, 1), 1.0 / 2.2);
- z = math.pow(clamp(z, 0, 1), 1.0 / 2.2);
- return {x, y, z, col.w};
- }
- vector4_linear_to_srgb :: proc{
- vector4_linear_to_srgb_f16,
- vector4_linear_to_srgb_f32,
- vector4_linear_to_srgb_f64,
- };
- vector4_hsl_to_rgb_f16 :: proc(h, s, l: f16, a: f16 = 1) -> Vector4f16 {
- hue_to_rgb :: proc(p, q, t: f16) -> f16 {
- t := t;
- if t < 0 { t += 1; }
- if t > 1 { t -= 1; }
- switch {
- case t < 1.0/6.0: return p + (q - p) * 6.0 * t;
- case t < 1.0/2.0: return q;
- case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t);
- }
- return p;
- }
- r, g, b: f16;
- if s == 0 {
- r = l;
- g = l;
- b = l;
- } else {
- q := l * (1+s) if l < 0.5 else l+s - l*s;
- p := 2*l - q;
- r = hue_to_rgb(p, q, h + 1.0/3.0);
- g = hue_to_rgb(p, q, h);
- b = hue_to_rgb(p, q, h - 1.0/3.0);
- }
- return {r, g, b, a};
- }
- vector4_hsl_to_rgb_f32 :: proc(h, s, l: f32, a: f32 = 1) -> Vector4f32 {
- hue_to_rgb :: proc(p, q, t: f32) -> f32 {
- t := t;
- if t < 0 { t += 1; }
- if t > 1 { t -= 1; }
- switch {
- case t < 1.0/6.0: return p + (q - p) * 6.0 * t;
- case t < 1.0/2.0: return q;
- case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t);
- }
- return p;
- }
- r, g, b: f32;
- if s == 0 {
- r = l;
- g = l;
- b = l;
- } else {
- q := l * (1+s) if l < 0.5 else l+s - l*s;
- p := 2*l - q;
- r = hue_to_rgb(p, q, h + 1.0/3.0);
- g = hue_to_rgb(p, q, h);
- b = hue_to_rgb(p, q, h - 1.0/3.0);
- }
- return {r, g, b, a};
- }
- vector4_hsl_to_rgb_f64 :: proc(h, s, l: f64, a: f64 = 1) -> Vector4f64 {
- hue_to_rgb :: proc(p, q, t: f64) -> f64 {
- t := t;
- if t < 0 { t += 1; }
- if t > 1 { t -= 1; }
- switch {
- case t < 1.0/6.0: return p + (q - p) * 6.0 * t;
- case t < 1.0/2.0: return q;
- case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t);
- }
- return p;
- }
- r, g, b: f64;
- if s == 0 {
- r = l;
- g = l;
- b = l;
- } else {
- q := l * (1+s) if l < 0.5 else l+s - l*s;
- p := 2*l - q;
- r = hue_to_rgb(p, q, h + 1.0/3.0);
- g = hue_to_rgb(p, q, h);
- b = hue_to_rgb(p, q, h - 1.0/3.0);
- }
- return {r, g, b, a};
- }
- vector4_hsl_to_rgb :: proc{
- vector4_hsl_to_rgb_f16,
- vector4_hsl_to_rgb_f32,
- vector4_hsl_to_rgb_f64,
- };
- vector4_rgb_to_hsl_f16 :: proc(col: Vector4f16) -> Vector4f16 {
- r := col.x;
- g := col.y;
- b := col.z;
- a := col.w;
- v_min := min(r, g, b);
- v_max := max(r, g, b);
- h, s, l: f16;
- h = 0.0;
- s = 0.0;
- l = (v_min + v_max) * 0.5;
- if v_max != v_min {
- d: = v_max - v_min;
- s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min);
- switch {
- case v_max == r:
- h = (g - b) / d + (6.0 if g < b else 0.0);
- case v_max == g:
- h = (b - r) / d + 2.0;
- case v_max == b:
- h = (r - g) / d + 4.0;
- }
- h *= 1.0/6.0;
- }
- return {h, s, l, a};
- }
- vector4_rgb_to_hsl_f32 :: proc(col: Vector4f32) -> Vector4f32 {
- r := col.x;
- g := col.y;
- b := col.z;
- a := col.w;
- v_min := min(r, g, b);
- v_max := max(r, g, b);
- h, s, l: f32;
- h = 0.0;
- s = 0.0;
- l = (v_min + v_max) * 0.5;
- if v_max != v_min {
- d: = v_max - v_min;
- s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min);
- switch {
- case v_max == r:
- h = (g - b) / d + (6.0 if g < b else 0.0);
- case v_max == g:
- h = (b - r) / d + 2.0;
- case v_max == b:
- h = (r - g) / d + 4.0;
- }
- h *= 1.0/6.0;
- }
- return {h, s, l, a};
- }
- vector4_rgb_to_hsl_f64 :: proc(col: Vector4f64) -> Vector4f64 {
- r := col.x;
- g := col.y;
- b := col.z;
- a := col.w;
- v_min := min(r, g, b);
- v_max := max(r, g, b);
- h, s, l: f64;
- h = 0.0;
- s = 0.0;
- l = (v_min + v_max) * 0.5;
- if v_max != v_min {
- d: = v_max - v_min;
- s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min);
- switch {
- case v_max == r:
- h = (g - b) / d + (6.0 if g < b else 0.0);
- case v_max == g:
- h = (b - r) / d + 2.0;
- case v_max == b:
- h = (r - g) / d + 4.0;
- }
- h *= 1.0/6.0;
- }
- return {h, s, l, a};
- }
- vector4_rgb_to_hsl :: proc{
- vector4_rgb_to_hsl_f16,
- vector4_rgb_to_hsl_f32,
- vector4_rgb_to_hsl_f64,
- };
- quaternion_angle_axis_f16 :: proc(angle_radians: f16, axis: Vector3f16) -> (q: Quaternionf16) {
- t := angle_radians*0.5;
- v := normalize(axis) * math.sin(t);
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- q.w = math.cos(t);
- return;
- }
- quaternion_angle_axis_f32 :: proc(angle_radians: f32, axis: Vector3f32) -> (q: Quaternionf32) {
- t := angle_radians*0.5;
- v := normalize(axis) * math.sin(t);
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- q.w = math.cos(t);
- return;
- }
- quaternion_angle_axis_f64 :: proc(angle_radians: f64, axis: Vector3f64) -> (q: Quaternionf64) {
- t := angle_radians*0.5;
- v := normalize(axis) * math.sin(t);
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- q.w = math.cos(t);
- return;
- }
- quaternion_angle_axis :: proc{
- quaternion_angle_axis_f16,
- quaternion_angle_axis_f32,
- quaternion_angle_axis_f64,
- };
- angle_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
- if abs(q.w) > math.SQRT_THREE*0.5 {
- return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2;
- }
- return math.cos(q.x) * 2;
- }
- angle_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
- if abs(q.w) > math.SQRT_THREE*0.5 {
- return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2;
- }
- return math.cos(q.x) * 2;
- }
- angle_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
- if abs(q.w) > math.SQRT_THREE*0.5 {
- return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2;
- }
- return math.cos(q.x) * 2;
- }
- angle_from_quaternion :: proc{
- angle_from_quaternion_f16,
- angle_from_quaternion_f32,
- angle_from_quaternion_f64,
- };
- axis_from_quaternion_f16 :: proc(q: Quaternionf16) -> Vector3f16 {
- t1 := 1 - q.w*q.w;
- if t1 < 0 {
- return {0, 0, 1};
- }
- t2 := 1.0 / math.sqrt(t1);
- return {q.x*t2, q.y*t2, q.z*t2};
- }
- axis_from_quaternion_f32 :: proc(q: Quaternionf32) -> Vector3f32 {
- t1 := 1 - q.w*q.w;
- if t1 < 0 {
- return {0, 0, 1};
- }
- t2 := 1.0 / math.sqrt(t1);
- return {q.x*t2, q.y*t2, q.z*t2};
- }
- axis_from_quaternion_f64 :: proc(q: Quaternionf64) -> Vector3f64 {
- t1 := 1 - q.w*q.w;
- if t1 < 0 {
- return {0, 0, 1};
- }
- t2 := 1.0 / math.sqrt(t1);
- return {q.x*t2, q.y*t2, q.z*t2};
- }
- axis_from_quaternion :: proc{
- axis_from_quaternion_f16,
- axis_from_quaternion_f32,
- axis_from_quaternion_f64,
- };
- angle_axis_from_quaternion_f16 :: proc(q: Quaternionf16) -> (angle: f16, axis: Vector3f16) {
- angle = angle_from_quaternion(q);
- axis = axis_from_quaternion(q);
- return;
- }
- angle_axis_from_quaternion_f32 :: proc(q: Quaternionf32) -> (angle: f32, axis: Vector3f32) {
- angle = angle_from_quaternion(q);
- axis = axis_from_quaternion(q);
- return;
- }
- angle_axis_from_quaternion_f64 :: proc(q: Quaternionf64) -> (angle: f64, axis: Vector3f64) {
- angle = angle_from_quaternion(q);
- axis = axis_from_quaternion(q);
- return;
- }
- angle_axis_from_quaternion :: proc {
- angle_axis_from_quaternion_f16,
- angle_axis_from_quaternion_f32,
- angle_axis_from_quaternion_f64,
- };
- quaternion_from_forward_and_up_f16 :: proc(forward, up: Vector3f16) -> Quaternionf16 {
- f := normalize(forward);
- s := normalize(cross(f, up));
- u := cross(s, f);
- m := Matrix3f16{
- {+s.x, +u.x, -f.x},
- {+s.y, +u.y, -f.y},
- {+s.z, +u.z, -f.z},
- };
- tr := trace(m);
- q: Quaternionf16;
- switch {
- case tr > 0:
- S := 2 * math.sqrt(1 + tr);
- q.w = 0.25 * S;
- q.x = (m[2][1] - m[1][2]) / S;
- q.y = (m[0][2] - m[2][0]) / S;
- q.z = (m[1][0] - m[0][1]) / S;
- case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]):
- S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]);
- q.w = (m[2][1] - m[1][2]) / S;
- q.x = 0.25 * S;
- q.y = (m[0][1] + m[1][0]) / S;
- q.z = (m[0][2] + m[2][0]) / S;
- case m[1][1] > m[2][2]:
- S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]);
- q.w = (m[0][2] - m[2][0]) / S;
- q.x = (m[0][1] + m[1][0]) / S;
- q.y = 0.25 * S;
- q.z = (m[1][2] + m[2][1]) / S;
- case:
- S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]);
- q.w = (m[1][0] - m[0][1]) / S;
- q.x = (m[0][2] - m[2][0]) / S;
- q.y = (m[1][2] + m[2][1]) / S;
- q.z = 0.25 * S;
- }
- return normalize(q);
- }
- quaternion_from_forward_and_up_f32 :: proc(forward, up: Vector3f32) -> Quaternionf32 {
- f := normalize(forward);
- s := normalize(cross(f, up));
- u := cross(s, f);
- m := Matrix3f32{
- {+s.x, +u.x, -f.x},
- {+s.y, +u.y, -f.y},
- {+s.z, +u.z, -f.z},
- };
- tr := trace(m);
- q: Quaternionf32;
- switch {
- case tr > 0:
- S := 2 * math.sqrt(1 + tr);
- q.w = 0.25 * S;
- q.x = (m[2][1] - m[1][2]) / S;
- q.y = (m[0][2] - m[2][0]) / S;
- q.z = (m[1][0] - m[0][1]) / S;
- case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]):
- S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]);
- q.w = (m[2][1] - m[1][2]) / S;
- q.x = 0.25 * S;
- q.y = (m[0][1] + m[1][0]) / S;
- q.z = (m[0][2] + m[2][0]) / S;
- case m[1][1] > m[2][2]:
- S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]);
- q.w = (m[0][2] - m[2][0]) / S;
- q.x = (m[0][1] + m[1][0]) / S;
- q.y = 0.25 * S;
- q.z = (m[1][2] + m[2][1]) / S;
- case:
- S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]);
- q.w = (m[1][0] - m[0][1]) / S;
- q.x = (m[0][2] - m[2][0]) / S;
- q.y = (m[1][2] + m[2][1]) / S;
- q.z = 0.25 * S;
- }
- return normalize(q);
- }
- quaternion_from_forward_and_up_f64 :: proc(forward, up: Vector3f64) -> Quaternionf64 {
- f := normalize(forward);
- s := normalize(cross(f, up));
- u := cross(s, f);
- m := Matrix3f64{
- {+s.x, +u.x, -f.x},
- {+s.y, +u.y, -f.y},
- {+s.z, +u.z, -f.z},
- };
- tr := trace(m);
- q: Quaternionf64;
- switch {
- case tr > 0:
- S := 2 * math.sqrt(1 + tr);
- q.w = 0.25 * S;
- q.x = (m[2][1] - m[1][2]) / S;
- q.y = (m[0][2] - m[2][0]) / S;
- q.z = (m[1][0] - m[0][1]) / S;
- case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]):
- S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]);
- q.w = (m[2][1] - m[1][2]) / S;
- q.x = 0.25 * S;
- q.y = (m[0][1] + m[1][0]) / S;
- q.z = (m[0][2] + m[2][0]) / S;
- case m[1][1] > m[2][2]:
- S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]);
- q.w = (m[0][2] - m[2][0]) / S;
- q.x = (m[0][1] + m[1][0]) / S;
- q.y = 0.25 * S;
- q.z = (m[1][2] + m[2][1]) / S;
- case:
- S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]);
- q.w = (m[1][0] - m[0][1]) / S;
- q.x = (m[0][2] - m[2][0]) / S;
- q.y = (m[1][2] + m[2][1]) / S;
- q.z = 0.25 * S;
- }
- return normalize(q);
- }
- quaternion_from_forward_and_up :: proc{
- quaternion_from_forward_and_up_f16,
- quaternion_from_forward_and_up_f32,
- quaternion_from_forward_and_up_f64,
- };
- quaternion_look_at_f16 :: proc(eye, centre: Vector3f16, up: Vector3f16) -> Quaternionf16 {
- return quaternion_from_matrix3(matrix3_look_at(eye, centre, up));
- }
- quaternion_look_at_f32 :: proc(eye, centre: Vector3f32, up: Vector3f32) -> Quaternionf32 {
- return quaternion_from_matrix3(matrix3_look_at(eye, centre, up));
- }
- quaternion_look_at_f64 :: proc(eye, centre: Vector3f64, up: Vector3f64) -> Quaternionf64 {
- return quaternion_from_matrix3(matrix3_look_at(eye, centre, up));
- }
- quaternion_look_at :: proc{
- quaternion_look_at_f16,
- quaternion_look_at_f32,
- quaternion_look_at_f64,
- };
- quaternion_nlerp_f16 :: proc(a, b: Quaternionf16, t: f16) -> (c: Quaternionf16) {
- c.x = a.x + (b.x-a.x)*t;
- c.y = a.y + (b.y-a.y)*t;
- c.z = a.z + (b.z-a.z)*t;
- c.w = a.w + (b.w-a.w)*t;
- return normalize(c);
- }
- quaternion_nlerp_f32 :: proc(a, b: Quaternionf32, t: f32) -> (c: Quaternionf32) {
- c.x = a.x + (b.x-a.x)*t;
- c.y = a.y + (b.y-a.y)*t;
- c.z = a.z + (b.z-a.z)*t;
- c.w = a.w + (b.w-a.w)*t;
- return normalize(c);
- }
- quaternion_nlerp_f64 :: proc(a, b: Quaternionf64, t: f64) -> (c: Quaternionf64) {
- c.x = a.x + (b.x-a.x)*t;
- c.y = a.y + (b.y-a.y)*t;
- c.z = a.z + (b.z-a.z)*t;
- c.w = a.w + (b.w-a.w)*t;
- return normalize(c);
- }
- quaternion_nlerp :: proc{
- quaternion_nlerp_f16,
- quaternion_nlerp_f32,
- quaternion_nlerp_f64,
- };
- quaternion_slerp_f16 :: proc(x, y: Quaternionf16, t: f16) -> (q: Quaternionf16) {
- a, b := x, y;
- cos_angle := dot(a, b);
- if cos_angle < 0 {
- b = -b;
- cos_angle = -cos_angle;
- }
- if cos_angle > 1 - F32_EPSILON {
- q.x = a.x + (b.x-a.x)*t;
- q.y = a.y + (b.y-a.y)*t;
- q.z = a.z + (b.z-a.z)*t;
- q.w = a.w + (b.w-a.w)*t;
- return;
- }
- angle := math.acos(cos_angle);
- sin_angle := math.sin(angle);
- factor_a := math.sin((1-t) * angle) / sin_angle;
- factor_b := math.sin(t * angle) / sin_angle;
- q.x = factor_a * a.x + factor_b * b.x;
- q.y = factor_a * a.y + factor_b * b.y;
- q.z = factor_a * a.z + factor_b * b.z;
- q.w = factor_a * a.w + factor_b * b.w;
- return;
- }
- quaternion_slerp_f32 :: proc(x, y: Quaternionf32, t: f32) -> (q: Quaternionf32) {
- a, b := x, y;
- cos_angle := dot(a, b);
- if cos_angle < 0 {
- b = -b;
- cos_angle = -cos_angle;
- }
- if cos_angle > 1 - F32_EPSILON {
- q.x = a.x + (b.x-a.x)*t;
- q.y = a.y + (b.y-a.y)*t;
- q.z = a.z + (b.z-a.z)*t;
- q.w = a.w + (b.w-a.w)*t;
- return;
- }
- angle := math.acos(cos_angle);
- sin_angle := math.sin(angle);
- factor_a := math.sin((1-t) * angle) / sin_angle;
- factor_b := math.sin(t * angle) / sin_angle;
- q.x = factor_a * a.x + factor_b * b.x;
- q.y = factor_a * a.y + factor_b * b.y;
- q.z = factor_a * a.z + factor_b * b.z;
- q.w = factor_a * a.w + factor_b * b.w;
- return;
- }
- quaternion_slerp_f64 :: proc(x, y: Quaternionf64, t: f64) -> (q: Quaternionf64) {
- a, b := x, y;
- cos_angle := dot(a, b);
- if cos_angle < 0 {
- b = -b;
- cos_angle = -cos_angle;
- }
- if cos_angle > 1 - F64_EPSILON {
- q.x = a.x + (b.x-a.x)*t;
- q.y = a.y + (b.y-a.y)*t;
- q.z = a.z + (b.z-a.z)*t;
- q.w = a.w + (b.w-a.w)*t;
- return;
- }
- angle := math.acos(cos_angle);
- sin_angle := math.sin(angle);
- factor_a := math.sin((1-t) * angle) / sin_angle;
- factor_b := math.sin(t * angle) / sin_angle;
- q.x = factor_a * a.x + factor_b * b.x;
- q.y = factor_a * a.y + factor_b * b.y;
- q.z = factor_a * a.z + factor_b * b.z;
- q.w = factor_a * a.w + factor_b * b.w;
- return;
- }
- quaternion_slerp :: proc{
- quaternion_slerp_f16,
- quaternion_slerp_f32,
- quaternion_slerp_f64,
- };
- quaternion_squad_f16 :: proc(q1, q2, s1, s2: Quaternionf16, h: f16) -> Quaternionf16 {
- slerp :: quaternion_slerp;
- return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h);
- }
- quaternion_squad_f32 :: proc(q1, q2, s1, s2: Quaternionf32, h: f32) -> Quaternionf32 {
- slerp :: quaternion_slerp;
- return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h);
- }
- quaternion_squad_f64 :: proc(q1, q2, s1, s2: Quaternionf64, h: f64) -> Quaternionf64 {
- slerp :: quaternion_slerp;
- return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h);
- }
- quaternion_squad :: proc{
- quaternion_squad_f16,
- quaternion_squad_f32,
- quaternion_squad_f64,
- };
- quaternion_from_matrix4_f16 :: proc(m: Matrix4f16) -> (q: Quaternionf16) {
- m3: Matrix3f16 = ---;
- m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2];
- m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2];
- m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2];
- return quaternion_from_matrix3(m3);
- }
- quaternion_from_matrix4_f32 :: proc(m: Matrix4f32) -> (q: Quaternionf32) {
- m3: Matrix3f32 = ---;
- m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2];
- m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2];
- m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2];
- return quaternion_from_matrix3(m3);
- }
- quaternion_from_matrix4_f64 :: proc(m: Matrix4f64) -> (q: Quaternionf64) {
- m3: Matrix3f64 = ---;
- m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2];
- m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2];
- m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2];
- return quaternion_from_matrix3(m3);
- }
- quaternion_from_matrix4 :: proc{
- quaternion_from_matrix4_f16,
- quaternion_from_matrix4_f32,
- quaternion_from_matrix4_f64,
- };
- quaternion_from_matrix3_f16 :: proc(m: Matrix3f16) -> (q: Quaternionf16) {
- four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2];
- four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2];
- four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1];
- four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2];
- biggest_index := 0;
- four_biggest_squared_minus_1 := four_w_squared_minus_1;
- if four_x_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_x_squared_minus_1;
- biggest_index = 1;
- }
- if four_y_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_y_squared_minus_1;
- biggest_index = 2;
- }
- if four_z_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_z_squared_minus_1;
- biggest_index = 3;
- }
- biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5;
- mult := 0.25 / biggest_val;
- q = 1;
- switch biggest_index {
- case 0:
- q.w = biggest_val;
- q.x = (m[1][2] - m[2][1]) * mult;
- q.y = (m[2][0] - m[0][2]) * mult;
- q.z = (m[0][1] - m[1][0]) * mult;
- case 1:
- q.w = (m[1][2] - m[2][1]) * mult;
- q.x = biggest_val;
- q.y = (m[0][1] + m[1][0]) * mult;
- q.z = (m[2][0] + m[0][2]) * mult;
- case 2:
- q.w = (m[2][0] - m[0][2]) * mult;
- q.x = (m[0][1] + m[1][0]) * mult;
- q.y = biggest_val;
- q.z = (m[1][2] + m[2][1]) * mult;
- case 3:
- q.w = (m[0][1] - m[1][0]) * mult;
- q.x = (m[2][0] + m[0][2]) * mult;
- q.y = (m[1][2] + m[2][1]) * mult;
- q.z = biggest_val;
- }
- return;
- }
- quaternion_from_matrix3_f32 :: proc(m: Matrix3f32) -> (q: Quaternionf32) {
- four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2];
- four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2];
- four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1];
- four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2];
- biggest_index := 0;
- four_biggest_squared_minus_1 := four_w_squared_minus_1;
- if four_x_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_x_squared_minus_1;
- biggest_index = 1;
- }
- if four_y_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_y_squared_minus_1;
- biggest_index = 2;
- }
- if four_z_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_z_squared_minus_1;
- biggest_index = 3;
- }
- biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5;
- mult := 0.25 / biggest_val;
- q = 1;
- switch biggest_index {
- case 0:
- q.w = biggest_val;
- q.x = (m[1][2] - m[2][1]) * mult;
- q.y = (m[2][0] - m[0][2]) * mult;
- q.z = (m[0][1] - m[1][0]) * mult;
- case 1:
- q.w = (m[1][2] - m[2][1]) * mult;
- q.x = biggest_val;
- q.y = (m[0][1] + m[1][0]) * mult;
- q.z = (m[2][0] + m[0][2]) * mult;
- case 2:
- q.w = (m[2][0] - m[0][2]) * mult;
- q.x = (m[0][1] + m[1][0]) * mult;
- q.y = biggest_val;
- q.z = (m[1][2] + m[2][1]) * mult;
- case 3:
- q.w = (m[0][1] - m[1][0]) * mult;
- q.x = (m[2][0] + m[0][2]) * mult;
- q.y = (m[1][2] + m[2][1]) * mult;
- q.z = biggest_val;
- }
- return;
- }
- quaternion_from_matrix3_f64 :: proc(m: Matrix3f64) -> (q: Quaternionf64) {
- four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2];
- four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2];
- four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1];
- four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2];
- biggest_index := 0;
- four_biggest_squared_minus_1 := four_w_squared_minus_1;
- if four_x_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_x_squared_minus_1;
- biggest_index = 1;
- }
- if four_y_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_y_squared_minus_1;
- biggest_index = 2;
- }
- if four_z_squared_minus_1 > four_biggest_squared_minus_1 {
- four_biggest_squared_minus_1 = four_z_squared_minus_1;
- biggest_index = 3;
- }
- biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5;
- mult := 0.25 / biggest_val;
- q = 1;
- switch biggest_index {
- case 0:
- q.w = biggest_val;
- q.x = (m[1][2] - m[2][1]) * mult;
- q.y = (m[2][0] - m[0][2]) * mult;
- q.z = (m[0][1] - m[1][0]) * mult;
- case 1:
- q.w = (m[1][2] - m[2][1]) * mult;
- q.x = biggest_val;
- q.y = (m[0][1] + m[1][0]) * mult;
- q.z = (m[2][0] + m[0][2]) * mult;
- case 2:
- q.w = (m[2][0] - m[0][2]) * mult;
- q.x = (m[0][1] + m[1][0]) * mult;
- q.y = biggest_val;
- q.z = (m[1][2] + m[2][1]) * mult;
- case 3:
- q.w = (m[0][1] - m[1][0]) * mult;
- q.x = (m[2][0] + m[0][2]) * mult;
- q.y = (m[1][2] + m[2][1]) * mult;
- q.z = biggest_val;
- }
- return;
- }
- quaternion_from_matrix3 :: proc{
- quaternion_from_matrix3_f16,
- quaternion_from_matrix3_f32,
- quaternion_from_matrix3_f64,
- };
- quaternion_between_two_vector3_f16 :: proc(from, to: Vector3f16) -> (q: Quaternionf16) {
- x := normalize(from);
- y := normalize(to);
- cos_theta := dot(x, y);
- if abs(cos_theta + 1) < 2*F32_EPSILON {
- v := vector3_orthogonal(x);
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- q.w = 0;
- return;
- }
- v := cross(x, y);
- w := cos_theta + 1;
- q.w = w;
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- return normalize(q);
- }
- quaternion_between_two_vector3_f32 :: proc(from, to: Vector3f32) -> (q: Quaternionf32) {
- x := normalize(from);
- y := normalize(to);
- cos_theta := dot(x, y);
- if abs(cos_theta + 1) < 2*F32_EPSILON {
- v := vector3_orthogonal(x);
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- q.w = 0;
- return;
- }
- v := cross(x, y);
- w := cos_theta + 1;
- q.w = w;
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- return normalize(q);
- }
- quaternion_between_two_vector3_f64 :: proc(from, to: Vector3f64) -> (q: Quaternionf64) {
- x := normalize(from);
- y := normalize(to);
- cos_theta := dot(x, y);
- if abs(cos_theta + 1) < 2*F64_EPSILON {
- v := vector3_orthogonal(x);
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- q.w = 0;
- return;
- }
- v := cross(x, y);
- w := cos_theta + 1;
- q.w = w;
- q.x = v.x;
- q.y = v.y;
- q.z = v.z;
- return normalize(q);
- }
- quaternion_between_two_vector3 :: proc{
- quaternion_between_two_vector3_f16,
- quaternion_between_two_vector3_f32,
- quaternion_between_two_vector3_f64,
- };
- matrix2_inverse_transpose_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) {
- d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
- id := 1.0/d;
- c[0][0] = +m[1][1] * id;
- c[0][1] = -m[0][1] * id;
- c[1][0] = -m[1][0] * id;
- c[1][1] = +m[0][0] * id;
- return c;
- }
- matrix2_inverse_transpose_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) {
- d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
- id := 1.0/d;
- c[0][0] = +m[1][1] * id;
- c[0][1] = -m[0][1] * id;
- c[1][0] = -m[1][0] * id;
- c[1][1] = +m[0][0] * id;
- return c;
- }
- matrix2_inverse_transpose_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) {
- d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
- id := 1.0/d;
- c[0][0] = +m[1][1] * id;
- c[0][1] = -m[0][1] * id;
- c[1][0] = -m[1][0] * id;
- c[1][1] = +m[0][0] * id;
- return c;
- }
- matrix2_inverse_transpose :: proc{
- matrix2_inverse_transpose_f16,
- matrix2_inverse_transpose_f32,
- matrix2_inverse_transpose_f64,
- };
- matrix2_determinant_f16 :: proc(m: Matrix2f16) -> f16 {
- return m[0][0]*m[1][1] - m[1][0]*m[0][1];
- }
- matrix2_determinant_f32 :: proc(m: Matrix2f32) -> f32 {
- return m[0][0]*m[1][1] - m[1][0]*m[0][1];
- }
- matrix2_determinant_f64 :: proc(m: Matrix2f64) -> f64 {
- return m[0][0]*m[1][1] - m[1][0]*m[0][1];
- }
- matrix2_determinant :: proc{
- matrix2_determinant_f16,
- matrix2_determinant_f32,
- matrix2_determinant_f64,
- };
- matrix2_inverse_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) {
- d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
- id := 1.0/d;
- c[0][0] = +m[1][1] * id;
- c[1][0] = -m[0][1] * id;
- c[0][1] = -m[1][0] * id;
- c[1][1] = +m[0][0] * id;
- return c;
- }
- matrix2_inverse_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) {
- d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
- id := 1.0/d;
- c[0][0] = +m[1][1] * id;
- c[1][0] = -m[0][1] * id;
- c[0][1] = -m[1][0] * id;
- c[1][1] = +m[0][0] * id;
- return c;
- }
- matrix2_inverse_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) {
- d := m[0][0]*m[1][1] - m[1][0]*m[0][1];
- id := 1.0/d;
- c[0][0] = +m[1][1] * id;
- c[1][0] = -m[0][1] * id;
- c[0][1] = -m[1][0] * id;
- c[1][1] = +m[0][0] * id;
- return c;
- }
- matrix2_inverse :: proc{
- matrix2_inverse_f16,
- matrix2_inverse_f32,
- matrix2_inverse_f64,
- };
- matrix2_adjoint_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) {
- c[0][0] = +m[1][1];
- c[0][1] = -m[1][0];
- c[1][0] = -m[0][1];
- c[1][1] = +m[0][0];
- return c;
- }
- matrix2_adjoint_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) {
- c[0][0] = +m[1][1];
- c[0][1] = -m[1][0];
- c[1][0] = -m[0][1];
- c[1][1] = +m[0][0];
- return c;
- }
- matrix2_adjoint_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) {
- c[0][0] = +m[1][1];
- c[0][1] = -m[1][0];
- c[1][0] = -m[0][1];
- c[1][1] = +m[0][0];
- return c;
- }
- matrix2_adjoint :: proc{
- matrix2_adjoint_f16,
- matrix2_adjoint_f32,
- matrix2_adjoint_f64,
- };
- matrix3_from_quaternion_f16 :: proc(q: Quaternionf16) -> (m: Matrix3f16) {
- qxx := q.x * q.x;
- qyy := q.y * q.y;
- qzz := q.z * q.z;
- qxz := q.x * q.z;
- qxy := q.x * q.y;
- qyz := q.y * q.z;
- qwx := q.w * q.x;
- qwy := q.w * q.y;
- qwz := q.w * q.z;
- m[0][0] = 1 - 2 * (qyy + qzz);
- m[0][1] = 2 * (qxy + qwz);
- m[0][2] = 2 * (qxz - qwy);
- m[1][0] = 2 * (qxy - qwz);
- m[1][1] = 1 - 2 * (qxx + qzz);
- m[1][2] = 2 * (qyz + qwx);
- m[2][0] = 2 * (qxz + qwy);
- m[2][1] = 2 * (qyz - qwx);
- m[2][2] = 1 - 2 * (qxx + qyy);
- return m;
- }
- matrix3_from_quaternion_f32 :: proc(q: Quaternionf32) -> (m: Matrix3f32) {
- qxx := q.x * q.x;
- qyy := q.y * q.y;
- qzz := q.z * q.z;
- qxz := q.x * q.z;
- qxy := q.x * q.y;
- qyz := q.y * q.z;
- qwx := q.w * q.x;
- qwy := q.w * q.y;
- qwz := q.w * q.z;
- m[0][0] = 1 - 2 * (qyy + qzz);
- m[0][1] = 2 * (qxy + qwz);
- m[0][2] = 2 * (qxz - qwy);
- m[1][0] = 2 * (qxy - qwz);
- m[1][1] = 1 - 2 * (qxx + qzz);
- m[1][2] = 2 * (qyz + qwx);
- m[2][0] = 2 * (qxz + qwy);
- m[2][1] = 2 * (qyz - qwx);
- m[2][2] = 1 - 2 * (qxx + qyy);
- return m;
- }
- matrix3_from_quaternion_f64 :: proc(q: Quaternionf64) -> (m: Matrix3f64) {
- qxx := q.x * q.x;
- qyy := q.y * q.y;
- qzz := q.z * q.z;
- qxz := q.x * q.z;
- qxy := q.x * q.y;
- qyz := q.y * q.z;
- qwx := q.w * q.x;
- qwy := q.w * q.y;
- qwz := q.w * q.z;
- m[0][0] = 1 - 2 * (qyy + qzz);
- m[0][1] = 2 * (qxy + qwz);
- m[0][2] = 2 * (qxz - qwy);
- m[1][0] = 2 * (qxy - qwz);
- m[1][1] = 1 - 2 * (qxx + qzz);
- m[1][2] = 2 * (qyz + qwx);
- m[2][0] = 2 * (qxz + qwy);
- m[2][1] = 2 * (qyz - qwx);
- m[2][2] = 1 - 2 * (qxx + qyy);
- return m;
- }
- matrix3_from_quaternion :: proc{
- matrix3_from_quaternion_f16,
- matrix3_from_quaternion_f32,
- matrix3_from_quaternion_f64,
- };
- matrix3_inverse_f16 :: proc(m: Matrix3f16) -> Matrix3f16 {
- return transpose(matrix3_inverse_transpose(m));
- }
- matrix3_inverse_f32 :: proc(m: Matrix3f32) -> Matrix3f32 {
- return transpose(matrix3_inverse_transpose(m));
- }
- matrix3_inverse_f64 :: proc(m: Matrix3f64) -> Matrix3f64 {
- return transpose(matrix3_inverse_transpose(m));
- }
- matrix3_inverse :: proc{
- matrix3_inverse_f16,
- matrix3_inverse_f32,
- matrix3_inverse_f64,
- };
- matrix3_determinant_f16 :: proc(m: Matrix3f16) -> f16 {
- a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
- b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
- c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
- return a + b + c;
- }
- matrix3_determinant_f32 :: proc(m: Matrix3f32) -> f32 {
- a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
- b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
- c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
- return a + b + c;
- }
- matrix3_determinant_f64 :: proc(m: Matrix3f64) -> f64 {
- a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
- b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
- c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
- return a + b + c;
- }
- matrix3_determinant :: proc{
- matrix3_determinant_f16,
- matrix3_determinant_f32,
- matrix3_determinant_f64,
- };
- matrix3_adjoint_f16 :: proc(m: Matrix3f16) -> (adjoint: Matrix3f16) {
- adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]);
- adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
- adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]);
- adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
- adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]);
- adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
- adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]);
- adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
- adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]);
- return adjoint;
- }
- matrix3_adjoint_f32 :: proc(m: Matrix3f32) -> (adjoint: Matrix3f32) {
- adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]);
- adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
- adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]);
- adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
- adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]);
- adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
- adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]);
- adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
- adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]);
- return adjoint;
- }
- matrix3_adjoint_f64 :: proc(m: Matrix3f64) -> (adjoint: Matrix3f64) {
- adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]);
- adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
- adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]);
- adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
- adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]);
- adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
- adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]);
- adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
- adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]);
- return adjoint;
- }
- matrix3_adjoint :: proc{
- matrix3_adjoint_f16,
- matrix3_adjoint_f32,
- matrix3_adjoint_f64,
- };
- matrix3_inverse_transpose_f16 :: proc(m: Matrix3f16) -> (inverse_transpose: Matrix3f16) {
- adjoint := matrix3_adjoint(m);
- determinant := matrix3_determinant(m);
- inv_determinant := 1.0 / determinant;
- for i in 0..<3 {
- for j in 0..<3 {
- inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
- }
- }
- return;
- }
- matrix3_inverse_transpose_f32 :: proc(m: Matrix3f32) -> (inverse_transpose: Matrix3f32) {
- adjoint := matrix3_adjoint(m);
- determinant := matrix3_determinant(m);
- inv_determinant := 1.0 / determinant;
- for i in 0..<3 {
- for j in 0..<3 {
- inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
- }
- }
- return;
- }
- matrix3_inverse_transpose_f64 :: proc(m: Matrix3f64) -> (inverse_transpose: Matrix3f64) {
- adjoint := matrix3_adjoint(m);
- determinant := matrix3_determinant(m);
- inv_determinant := 1.0 / determinant;
- for i in 0..<3 {
- for j in 0..<3 {
- inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
- }
- }
- return;
- }
- matrix3_inverse_transpose :: proc{
- matrix3_inverse_transpose_f16,
- matrix3_inverse_transpose_f32,
- matrix3_inverse_transpose_f64,
- };
- matrix3_scale_f16 :: proc(s: Vector3f16) -> (m: Matrix3f16) {
- m[0][0] = s[0];
- m[1][1] = s[1];
- m[2][2] = s[2];
- return m;
- }
- matrix3_scale_f32 :: proc(s: Vector3f32) -> (m: Matrix3f32) {
- m[0][0] = s[0];
- m[1][1] = s[1];
- m[2][2] = s[2];
- return m;
- }
- matrix3_scale_f64 :: proc(s: Vector3f64) -> (m: Matrix3f64) {
- m[0][0] = s[0];
- m[1][1] = s[1];
- m[2][2] = s[2];
- return m;
- }
- matrix3_scale :: proc{
- matrix3_scale_f16,
- matrix3_scale_f32,
- matrix3_scale_f64,
- };
- matrix3_rotate_f16 :: proc(angle_radians: f16, v: Vector3f16) -> (rot: Matrix3f16) {
- c := math.cos(angle_radians);
- s := math.sin(angle_radians);
- a := normalize(v);
- t := a * (1-c);
- rot[0][0] = c + t[0]*a[0];
- rot[0][1] = 0 + t[0]*a[1] + s*a[2];
- rot[0][2] = 0 + t[0]*a[2] - s*a[1];
- rot[1][0] = 0 + t[1]*a[0] - s*a[2];
- rot[1][1] = c + t[1]*a[1];
- rot[1][2] = 0 + t[1]*a[2] + s*a[0];
- rot[2][0] = 0 + t[2]*a[0] + s*a[1];
- rot[2][1] = 0 + t[2]*a[1] - s*a[0];
- rot[2][2] = c + t[2]*a[2];
- return rot;
- }
- matrix3_rotate_f32 :: proc(angle_radians: f32, v: Vector3f32) -> (rot: Matrix3f32) {
- c := math.cos(angle_radians);
- s := math.sin(angle_radians);
- a := normalize(v);
- t := a * (1-c);
- rot[0][0] = c + t[0]*a[0];
- rot[0][1] = 0 + t[0]*a[1] + s*a[2];
- rot[0][2] = 0 + t[0]*a[2] - s*a[1];
- rot[1][0] = 0 + t[1]*a[0] - s*a[2];
- rot[1][1] = c + t[1]*a[1];
- rot[1][2] = 0 + t[1]*a[2] + s*a[0];
- rot[2][0] = 0 + t[2]*a[0] + s*a[1];
- rot[2][1] = 0 + t[2]*a[1] - s*a[0];
- rot[2][2] = c + t[2]*a[2];
- return rot;
- }
- matrix3_rotate_f64 :: proc(angle_radians: f64, v: Vector3f64) -> (rot: Matrix3f64) {
- c := math.cos(angle_radians);
- s := math.sin(angle_radians);
- a := normalize(v);
- t := a * (1-c);
- rot[0][0] = c + t[0]*a[0];
- rot[0][1] = 0 + t[0]*a[1] + s*a[2];
- rot[0][2] = 0 + t[0]*a[2] - s*a[1];
- rot[1][0] = 0 + t[1]*a[0] - s*a[2];
- rot[1][1] = c + t[1]*a[1];
- rot[1][2] = 0 + t[1]*a[2] + s*a[0];
- rot[2][0] = 0 + t[2]*a[0] + s*a[1];
- rot[2][1] = 0 + t[2]*a[1] - s*a[0];
- rot[2][2] = c + t[2]*a[2];
- return rot;
- }
- matrix3_rotate :: proc{
- matrix3_rotate_f16,
- matrix3_rotate_f32,
- matrix3_rotate_f64,
- };
- matrix3_look_at_f16 :: proc(eye, centre, up: Vector3f16) -> Matrix3f16 {
- f := normalize(centre - eye);
- s := normalize(cross(f, up));
- u := cross(s, f);
- return Matrix3f16{
- {+s.x, +u.x, -f.x},
- {+s.y, +u.y, -f.y},
- {+s.z, +u.z, -f.z},
- };
- }
- matrix3_look_at_f32 :: proc(eye, centre, up: Vector3f32) -> Matrix3f32 {
- f := normalize(centre - eye);
- s := normalize(cross(f, up));
- u := cross(s, f);
- return Matrix3f32{
- {+s.x, +u.x, -f.x},
- {+s.y, +u.y, -f.y},
- {+s.z, +u.z, -f.z},
- };
- }
- matrix3_look_at_f64 :: proc(eye, centre, up: Vector3f64) -> Matrix3f64 {
- f := normalize(centre - eye);
- s := normalize(cross(f, up));
- u := cross(s, f);
- return Matrix3f64{
- {+s.x, +u.x, -f.x},
- {+s.y, +u.y, -f.y},
- {+s.z, +u.z, -f.z},
- };
- }
- matrix3_look_at :: proc{
- matrix3_look_at_f16,
- matrix3_look_at_f32,
- matrix3_look_at_f64,
- };
- matrix4_from_quaternion_f16 :: proc(q: Quaternionf16) -> (m: Matrix4f16) {
- qxx := q.x * q.x;
- qyy := q.y * q.y;
- qzz := q.z * q.z;
- qxz := q.x * q.z;
- qxy := q.x * q.y;
- qyz := q.y * q.z;
- qwx := q.w * q.x;
- qwy := q.w * q.y;
- qwz := q.w * q.z;
- m[0][0] = 1 - 2 * (qyy + qzz);
- m[0][1] = 2 * (qxy + qwz);
- m[0][2] = 2 * (qxz - qwy);
- m[1][0] = 2 * (qxy - qwz);
- m[1][1] = 1 - 2 * (qxx + qzz);
- m[1][2] = 2 * (qyz + qwx);
- m[2][0] = 2 * (qxz + qwy);
- m[2][1] = 2 * (qyz - qwx);
- m[2][2] = 1 - 2 * (qxx + qyy);
- m[3][3] = 1;
- return m;
- }
- matrix4_from_quaternion_f32 :: proc(q: Quaternionf32) -> (m: Matrix4f32) {
- qxx := q.x * q.x;
- qyy := q.y * q.y;
- qzz := q.z * q.z;
- qxz := q.x * q.z;
- qxy := q.x * q.y;
- qyz := q.y * q.z;
- qwx := q.w * q.x;
- qwy := q.w * q.y;
- qwz := q.w * q.z;
- m[0][0] = 1 - 2 * (qyy + qzz);
- m[0][1] = 2 * (qxy + qwz);
- m[0][2] = 2 * (qxz - qwy);
- m[1][0] = 2 * (qxy - qwz);
- m[1][1] = 1 - 2 * (qxx + qzz);
- m[1][2] = 2 * (qyz + qwx);
- m[2][0] = 2 * (qxz + qwy);
- m[2][1] = 2 * (qyz - qwx);
- m[2][2] = 1 - 2 * (qxx + qyy);
- m[3][3] = 1;
- return m;
- }
- matrix4_from_quaternion_f64 :: proc(q: Quaternionf64) -> (m: Matrix4f64) {
- qxx := q.x * q.x;
- qyy := q.y * q.y;
- qzz := q.z * q.z;
- qxz := q.x * q.z;
- qxy := q.x * q.y;
- qyz := q.y * q.z;
- qwx := q.w * q.x;
- qwy := q.w * q.y;
- qwz := q.w * q.z;
- m[0][0] = 1 - 2 * (qyy + qzz);
- m[0][1] = 2 * (qxy + qwz);
- m[0][2] = 2 * (qxz - qwy);
- m[1][0] = 2 * (qxy - qwz);
- m[1][1] = 1 - 2 * (qxx + qzz);
- m[1][2] = 2 * (qyz + qwx);
- m[2][0] = 2 * (qxz + qwy);
- m[2][1] = 2 * (qyz - qwx);
- m[2][2] = 1 - 2 * (qxx + qyy);
- m[3][3] = 1;
- return m;
- }
- matrix4_from_quaternion :: proc{
- matrix4_from_quaternion_f16,
- matrix4_from_quaternion_f32,
- matrix4_from_quaternion_f64,
- };
- matrix4_from_trs_f16 :: proc(t: Vector3f16, r: Quaternionf16, s: Vector3f16) -> Matrix4f16 {
- translation := matrix4_translate(t);
- rotation := matrix4_from_quaternion(r);
- scale := matrix4_scale(s);
- return mul(translation, mul(rotation, scale));
- }
- matrix4_from_trs_f32 :: proc(t: Vector3f32, r: Quaternionf32, s: Vector3f32) -> Matrix4f32 {
- translation := matrix4_translate(t);
- rotation := matrix4_from_quaternion(r);
- scale := matrix4_scale(s);
- return mul(translation, mul(rotation, scale));
- }
- matrix4_from_trs_f64 :: proc(t: Vector3f64, r: Quaternionf64, s: Vector3f64) -> Matrix4f64 {
- translation := matrix4_translate(t);
- rotation := matrix4_from_quaternion(r);
- scale := matrix4_scale(s);
- return mul(translation, mul(rotation, scale));
- }
- matrix4_from_trs :: proc{
- matrix4_from_trs_f16,
- matrix4_from_trs_f32,
- matrix4_from_trs_f64,
- };
- matrix4_inverse_f16 :: proc(m: Matrix4f16) -> Matrix4f16 {
- return transpose(matrix4_inverse_transpose(m));
- }
- matrix4_inverse_f32 :: proc(m: Matrix4f32) -> Matrix4f32 {
- return transpose(matrix4_inverse_transpose(m));
- }
- matrix4_inverse_f64 :: proc(m: Matrix4f64) -> Matrix4f64 {
- return transpose(matrix4_inverse_transpose(m));
- }
- matrix4_inverse :: proc{
- matrix4_inverse_f16,
- matrix4_inverse_f32,
- matrix4_inverse_f64,
- };
- matrix4_minor_f16 :: proc(m: Matrix4f16, c, r: int) -> f16 {
- cut_down: Matrix3f16;
- for i in 0..<3 {
- col := i if i < c else i+1;
- for j in 0..<3 {
- row := j if j < r else j+1;
- cut_down[i][j] = m[col][row];
- }
- }
- return matrix3_determinant(cut_down);
- }
- matrix4_minor_f32 :: proc(m: Matrix4f32, c, r: int) -> f32 {
- cut_down: Matrix3f32;
- for i in 0..<3 {
- col := i if i < c else i+1;
- for j in 0..<3 {
- row := j if j < r else j+1;
- cut_down[i][j] = m[col][row];
- }
- }
- return matrix3_determinant(cut_down);
- }
- matrix4_minor_f64 :: proc(m: Matrix4f64, c, r: int) -> f64 {
- cut_down: Matrix3f64;
- for i in 0..<3 {
- col := i if i < c else i+1;
- for j in 0..<3 {
- row := j if j < r else j+1;
- cut_down[i][j] = m[col][row];
- }
- }
- return matrix3_determinant(cut_down);
- }
- matrix4_minor :: proc{
- matrix4_minor_f16,
- matrix4_minor_f32,
- matrix4_minor_f64,
- };
- matrix4_cofactor_f16 :: proc(m: Matrix4f16, c, r: int) -> f16 {
- sign, minor: f16;
- sign = 1 if (c + r) % 2 == 0 else -1;
- minor = matrix4_minor(m, c, r);
- return sign * minor;
- }
- matrix4_cofactor_f32 :: proc(m: Matrix4f32, c, r: int) -> f32 {
- sign, minor: f32;
- sign = 1 if (c + r) % 2 == 0 else -1;
- minor = matrix4_minor(m, c, r);
- return sign * minor;
- }
- matrix4_cofactor_f64 :: proc(m: Matrix4f64, c, r: int) -> f64 {
- sign, minor: f64;
- sign = 1 if (c + r) % 2 == 0 else -1;
- minor = matrix4_minor(m, c, r);
- return sign * minor;
- }
- matrix4_cofactor :: proc{
- matrix4_cofactor_f16,
- matrix4_cofactor_f32,
- matrix4_cofactor_f64,
- };
- matrix4_adjoint_f16 :: proc(m: Matrix4f16) -> (adjoint: Matrix4f16) {
- for i in 0..<4 {
- for j in 0..<4 {
- adjoint[i][j] = matrix4_cofactor(m, i, j);
- }
- }
- return;
- }
- matrix4_adjoint_f32 :: proc(m: Matrix4f32) -> (adjoint: Matrix4f32) {
- for i in 0..<4 {
- for j in 0..<4 {
- adjoint[i][j] = matrix4_cofactor(m, i, j);
- }
- }
- return;
- }
- matrix4_adjoint_f64 :: proc(m: Matrix4f64) -> (adjoint: Matrix4f64) {
- for i in 0..<4 {
- for j in 0..<4 {
- adjoint[i][j] = matrix4_cofactor(m, i, j);
- }
- }
- return;
- }
- matrix4_adjoint :: proc{
- matrix4_adjoint_f16,
- matrix4_adjoint_f32,
- matrix4_adjoint_f64,
- };
- matrix4_determinant_f16 :: proc(m: Matrix4f16) -> (determinant: f16) {
- adjoint := matrix4_adjoint(m);
- for i in 0..<4 {
- determinant += m[i][0] * adjoint[i][0];
- }
- return;
- }
- matrix4_determinant_f32 :: proc(m: Matrix4f32) -> (determinant: f32) {
- adjoint := matrix4_adjoint(m);
- for i in 0..<4 {
- determinant += m[i][0] * adjoint[i][0];
- }
- return;
- }
- matrix4_determinant_f64 :: proc(m: Matrix4f64) -> (determinant: f64) {
- adjoint := matrix4_adjoint(m);
- for i in 0..<4 {
- determinant += m[i][0] * adjoint[i][0];
- }
- return;
- }
- matrix4_determinant :: proc{
- matrix4_determinant_f16,
- matrix4_determinant_f32,
- matrix4_determinant_f64,
- };
- matrix4_inverse_transpose_f16 :: proc(m: Matrix4f16) -> (inverse_transpose: Matrix4f16) {
- adjoint := matrix4_adjoint(m);
- determinant: f16 = 0;
- for i in 0..<4 {
- determinant += m[i][0] * adjoint[i][0];
- }
- inv_determinant := 1.0 / determinant;
- for i in 0..<4 {
- for j in 0..<4 {
- inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
- }
- }
- return;
- }
- matrix4_inverse_transpose_f32 :: proc(m: Matrix4f32) -> (inverse_transpose: Matrix4f32) {
- adjoint := matrix4_adjoint(m);
- determinant: f32 = 0;
- for i in 0..<4 {
- determinant += m[i][0] * adjoint[i][0];
- }
- inv_determinant := 1.0 / determinant;
- for i in 0..<4 {
- for j in 0..<4 {
- inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
- }
- }
- return;
- }
- matrix4_inverse_transpose_f64 :: proc(m: Matrix4f64) -> (inverse_transpose: Matrix4f64) {
- adjoint := matrix4_adjoint(m);
- determinant: f64 = 0;
- for i in 0..<4 {
- determinant += m[i][0] * adjoint[i][0];
- }
- inv_determinant := 1.0 / determinant;
- for i in 0..<4 {
- for j in 0..<4 {
- inverse_transpose[i][j] = adjoint[i][j] * inv_determinant;
- }
- }
- return;
- }
- matrix4_inverse_transpose :: proc{
- matrix4_inverse_transpose_f16,
- matrix4_inverse_transpose_f32,
- matrix4_inverse_transpose_f64,
- };
- matrix4_translate_f16 :: proc(v: Vector3f16) -> Matrix4f16 {
- m := MATRIX4F16_IDENTITY;
- m[3][0] = v[0];
- m[3][1] = v[1];
- m[3][2] = v[2];
- return m;
- }
- matrix4_translate_f32 :: proc(v: Vector3f32) -> Matrix4f32 {
- m := MATRIX4F32_IDENTITY;
- m[3][0] = v[0];
- m[3][1] = v[1];
- m[3][2] = v[2];
- return m;
- }
- matrix4_translate_f64 :: proc(v: Vector3f64) -> Matrix4f64 {
- m := MATRIX4F64_IDENTITY;
- m[3][0] = v[0];
- m[3][1] = v[1];
- m[3][2] = v[2];
- return m;
- }
- matrix4_translate :: proc{
- matrix4_translate_f16,
- matrix4_translate_f32,
- matrix4_translate_f64,
- };
- matrix4_rotate_f16 :: proc(angle_radians: f16, v: Vector3f16) -> Matrix4f16 {
- c := math.cos(angle_radians);
- s := math.sin(angle_radians);
- a := normalize(v);
- t := a * (1-c);
- rot := MATRIX4F16_IDENTITY;
- rot[0][0] = c + t[0]*a[0];
- rot[0][1] = 0 + t[0]*a[1] + s*a[2];
- rot[0][2] = 0 + t[0]*a[2] - s*a[1];
- rot[0][3] = 0;
- rot[1][0] = 0 + t[1]*a[0] - s*a[2];
- rot[1][1] = c + t[1]*a[1];
- rot[1][2] = 0 + t[1]*a[2] + s*a[0];
- rot[1][3] = 0;
- rot[2][0] = 0 + t[2]*a[0] + s*a[1];
- rot[2][1] = 0 + t[2]*a[1] - s*a[0];
- rot[2][2] = c + t[2]*a[2];
- rot[2][3] = 0;
- return rot;
- }
- matrix4_rotate_f32 :: proc(angle_radians: f32, v: Vector3f32) -> Matrix4f32 {
- c := math.cos(angle_radians);
- s := math.sin(angle_radians);
- a := normalize(v);
- t := a * (1-c);
- rot := MATRIX4F32_IDENTITY;
- rot[0][0] = c + t[0]*a[0];
- rot[0][1] = 0 + t[0]*a[1] + s*a[2];
- rot[0][2] = 0 + t[0]*a[2] - s*a[1];
- rot[0][3] = 0;
- rot[1][0] = 0 + t[1]*a[0] - s*a[2];
- rot[1][1] = c + t[1]*a[1];
- rot[1][2] = 0 + t[1]*a[2] + s*a[0];
- rot[1][3] = 0;
- rot[2][0] = 0 + t[2]*a[0] + s*a[1];
- rot[2][1] = 0 + t[2]*a[1] - s*a[0];
- rot[2][2] = c + t[2]*a[2];
- rot[2][3] = 0;
- return rot;
- }
- matrix4_rotate_f64 :: proc(angle_radians: f64, v: Vector3f64) -> Matrix4f64 {
- c := math.cos(angle_radians);
- s := math.sin(angle_radians);
- a := normalize(v);
- t := a * (1-c);
- rot := MATRIX4F64_IDENTITY;
- rot[0][0] = c + t[0]*a[0];
- rot[0][1] = 0 + t[0]*a[1] + s*a[2];
- rot[0][2] = 0 + t[0]*a[2] - s*a[1];
- rot[0][3] = 0;
- rot[1][0] = 0 + t[1]*a[0] - s*a[2];
- rot[1][1] = c + t[1]*a[1];
- rot[1][2] = 0 + t[1]*a[2] + s*a[0];
- rot[1][3] = 0;
- rot[2][0] = 0 + t[2]*a[0] + s*a[1];
- rot[2][1] = 0 + t[2]*a[1] - s*a[0];
- rot[2][2] = c + t[2]*a[2];
- rot[2][3] = 0;
- return rot;
- }
- matrix4_rotate :: proc{
- matrix4_rotate_f16,
- matrix4_rotate_f32,
- matrix4_rotate_f64,
- };
- matrix4_scale_f16 :: proc(v: Vector3f16) -> (m: Matrix4f16) {
- m[0][0] = v[0];
- m[1][1] = v[1];
- m[2][2] = v[2];
- m[3][3] = 1;
- return;
- }
- matrix4_scale_f32 :: proc(v: Vector3f32) -> (m: Matrix4f32) {
- m[0][0] = v[0];
- m[1][1] = v[1];
- m[2][2] = v[2];
- m[3][3] = 1;
- return;
- }
- matrix4_scale_f64 :: proc(v: Vector3f64) -> (m: Matrix4f64) {
- m[0][0] = v[0];
- m[1][1] = v[1];
- m[2][2] = v[2];
- m[3][3] = 1;
- return;
- }
- matrix4_scale :: proc{
- matrix4_scale_f16,
- matrix4_scale_f32,
- matrix4_scale_f64,
- };
- matrix4_look_at_f16 :: proc(eye, centre, up: Vector3f16, flip_z_axis := true) -> (m: Matrix4f16) {
- f := normalize(centre - eye);
- s := normalize(cross(f, up));
- u := cross(s, f);
- fe := dot(f, eye);
- return {
- {+s.x, +u.x, -f.x, 0},
- {+s.y, +u.y, -f.y, 0},
- {+s.z, +u.z, -f.z, 0},
- {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1},
- };
- }
- matrix4_look_at_f32 :: proc(eye, centre, up: Vector3f32, flip_z_axis := true) -> (m: Matrix4f32) {
- f := normalize(centre - eye);
- s := normalize(cross(f, up));
- u := cross(s, f);
- fe := dot(f, eye);
- return {
- {+s.x, +u.x, -f.x, 0},
- {+s.y, +u.y, -f.y, 0},
- {+s.z, +u.z, -f.z, 0},
- {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1},
- };
- }
- matrix4_look_at_f64 :: proc(eye, centre, up: Vector3f64, flip_z_axis := true) -> (m: Matrix4f64) {
- f := normalize(centre - eye);
- s := normalize(cross(f, up));
- u := cross(s, f);
- fe := dot(f, eye);
- return {
- {+s.x, +u.x, -f.x, 0},
- {+s.y, +u.y, -f.y, 0},
- {+s.z, +u.z, -f.z, 0},
- {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1},
- };
- }
- matrix4_look_at :: proc{
- matrix4_look_at_f16,
- matrix4_look_at_f32,
- matrix4_look_at_f64,
- };
- matrix4_perspective_f16 :: proc(fovy, aspect, near, far: f16, flip_z_axis := true) -> (m: Matrix4f16) {
- tan_half_fovy := math.tan(0.5 * fovy);
- m[0][0] = 1 / (aspect*tan_half_fovy);
- m[1][1] = 1 / (tan_half_fovy);
- m[2][2] = +(far + near) / (far - near);
- m[2][3] = +1;
- m[3][2] = -2*far*near / (far - near);
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix4_perspective_f32 :: proc(fovy, aspect, near, far: f32, flip_z_axis := true) -> (m: Matrix4f32) {
- tan_half_fovy := math.tan(0.5 * fovy);
- m[0][0] = 1 / (aspect*tan_half_fovy);
- m[1][1] = 1 / (tan_half_fovy);
- m[2][2] = +(far + near) / (far - near);
- m[2][3] = +1;
- m[3][2] = -2*far*near / (far - near);
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix4_perspective_f64 :: proc(fovy, aspect, near, far: f64, flip_z_axis := true) -> (m: Matrix4f64) {
- tan_half_fovy := math.tan(0.5 * fovy);
- m[0][0] = 1 / (aspect*tan_half_fovy);
- m[1][1] = 1 / (tan_half_fovy);
- m[2][2] = +(far + near) / (far - near);
- m[2][3] = +1;
- m[3][2] = -2*far*near / (far - near);
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix4_perspective :: proc{
- matrix4_perspective_f16,
- matrix4_perspective_f32,
- matrix4_perspective_f64,
- };
- matrix_ortho3d_f16 :: proc(left, right, bottom, top, near, far: f16, flip_z_axis := true) -> (m: Matrix4f16) {
- m[0][0] = +2 / (right - left);
- m[1][1] = +2 / (top - bottom);
- m[2][2] = +2 / (far - near);
- m[3][0] = -(right + left) / (right - left);
- m[3][1] = -(top + bottom) / (top - bottom);
- m[3][2] = -(far + near) / (far- near);
- m[3][3] = 1;
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix_ortho3d_f32 :: proc(left, right, bottom, top, near, far: f32, flip_z_axis := true) -> (m: Matrix4f32) {
- m[0][0] = +2 / (right - left);
- m[1][1] = +2 / (top - bottom);
- m[2][2] = +2 / (far - near);
- m[3][0] = -(right + left) / (right - left);
- m[3][1] = -(top + bottom) / (top - bottom);
- m[3][2] = -(far + near) / (far- near);
- m[3][3] = 1;
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix_ortho3d_f64 :: proc(left, right, bottom, top, near, far: f64, flip_z_axis := true) -> (m: Matrix4f64) {
- m[0][0] = +2 / (right - left);
- m[1][1] = +2 / (top - bottom);
- m[2][2] = +2 / (far - near);
- m[3][0] = -(right + left) / (right - left);
- m[3][1] = -(top + bottom) / (top - bottom);
- m[3][2] = -(far + near) / (far- near);
- m[3][3] = 1;
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix_ortho3d :: proc{
- matrix_ortho3d_f16,
- matrix_ortho3d_f32,
- matrix_ortho3d_f64,
- };
- matrix4_infinite_perspective_f16 :: proc(fovy, aspect, near: f16, flip_z_axis := true) -> (m: Matrix4f16) {
- tan_half_fovy := math.tan(0.5 * fovy);
- m[0][0] = 1 / (aspect*tan_half_fovy);
- m[1][1] = 1 / (tan_half_fovy);
- m[2][2] = +1;
- m[2][3] = +1;
- m[3][2] = -2*near;
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix4_infinite_perspective_f32 :: proc(fovy, aspect, near: f32, flip_z_axis := true) -> (m: Matrix4f32) {
- tan_half_fovy := math.tan(0.5 * fovy);
- m[0][0] = 1 / (aspect*tan_half_fovy);
- m[1][1] = 1 / (tan_half_fovy);
- m[2][2] = +1;
- m[2][3] = +1;
- m[3][2] = -2*near;
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix4_infinite_perspective_f64 :: proc(fovy, aspect, near: f64, flip_z_axis := true) -> (m: Matrix4f64) {
- tan_half_fovy := math.tan(0.5 * fovy);
- m[0][0] = 1 / (aspect*tan_half_fovy);
- m[1][1] = 1 / (tan_half_fovy);
- m[2][2] = +1;
- m[2][3] = +1;
- m[3][2] = -2*near;
- if flip_z_axis {
- m[2] = -m[2];
- }
- return;
- }
- matrix4_infinite_perspective :: proc{
- matrix4_infinite_perspective_f16,
- matrix4_infinite_perspective_f32,
- matrix4_infinite_perspective_f64,
- };
- matrix2_from_scalar_f16 :: proc(f: f16) -> (m: Matrix2f16) {
- m[0][0], m[0][1] = f, 0;
- m[1][0], m[1][1] = 0, f;
- return;
- }
- matrix2_from_scalar_f32 :: proc(f: f32) -> (m: Matrix2f32) {
- m[0][0], m[0][1] = f, 0;
- m[1][0], m[1][1] = 0, f;
- return;
- }
- matrix2_from_scalar_f64 :: proc(f: f64) -> (m: Matrix2f64) {
- m[0][0], m[0][1] = f, 0;
- m[1][0], m[1][1] = 0, f;
- return;
- }
- matrix2_from_scalar :: proc{
- matrix2_from_scalar_f16,
- matrix2_from_scalar_f32,
- matrix2_from_scalar_f64,
- };
- matrix3_from_scalar_f16 :: proc(f: f16) -> (m: Matrix3f16) {
- m[0][0], m[0][1], m[0][2] = f, 0, 0;
- m[1][0], m[1][1], m[1][2] = 0, f, 0;
- m[2][0], m[2][1], m[2][2] = 0, 0, f;
- return;
- }
- matrix3_from_scalar_f32 :: proc(f: f32) -> (m: Matrix3f32) {
- m[0][0], m[0][1], m[0][2] = f, 0, 0;
- m[1][0], m[1][1], m[1][2] = 0, f, 0;
- m[2][0], m[2][1], m[2][2] = 0, 0, f;
- return;
- }
- matrix3_from_scalar_f64 :: proc(f: f64) -> (m: Matrix3f64) {
- m[0][0], m[0][1], m[0][2] = f, 0, 0;
- m[1][0], m[1][1], m[1][2] = 0, f, 0;
- m[2][0], m[2][1], m[2][2] = 0, 0, f;
- return;
- }
- matrix3_from_scalar :: proc{
- matrix3_from_scalar_f16,
- matrix3_from_scalar_f32,
- matrix3_from_scalar_f64,
- };
- matrix4_from_scalar_f16 :: proc(f: f16) -> (m: Matrix4f16) {
- m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0;
- m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0;
- m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0;
- m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f;
- return;
- }
- matrix4_from_scalar_f32 :: proc(f: f32) -> (m: Matrix4f32) {
- m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0;
- m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0;
- m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0;
- m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f;
- return;
- }
- matrix4_from_scalar_f64 :: proc(f: f64) -> (m: Matrix4f64) {
- m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0;
- m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0;
- m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0;
- m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f;
- return;
- }
- matrix4_from_scalar :: proc{
- matrix4_from_scalar_f16,
- matrix4_from_scalar_f32,
- matrix4_from_scalar_f64,
- };
- matrix2_from_matrix3_f16 :: proc(m: Matrix3f16) -> (r: Matrix2f16) {
- r[0][0], r[0][1] = m[0][0], m[0][1];
- r[1][0], r[1][1] = m[1][0], m[1][1];
- return;
- }
- matrix2_from_matrix3_f32 :: proc(m: Matrix3f32) -> (r: Matrix2f32) {
- r[0][0], r[0][1] = m[0][0], m[0][1];
- r[1][0], r[1][1] = m[1][0], m[1][1];
- return;
- }
- matrix2_from_matrix3_f64 :: proc(m: Matrix3f64) -> (r: Matrix2f64) {
- r[0][0], r[0][1] = m[0][0], m[0][1];
- r[1][0], r[1][1] = m[1][0], m[1][1];
- return;
- }
- matrix2_from_matrix3 :: proc{
- matrix2_from_matrix3_f16,
- matrix2_from_matrix3_f32,
- matrix2_from_matrix3_f64,
- };
- matrix2_from_matrix4_f16 :: proc(m: Matrix4f16) -> (r: Matrix2f16) {
- r[0][0], r[0][1] = m[0][0], m[0][1];
- r[1][0], r[1][1] = m[1][0], m[1][1];
- return;
- }
- matrix2_from_matrix4_f32 :: proc(m: Matrix4f32) -> (r: Matrix2f32) {
- r[0][0], r[0][1] = m[0][0], m[0][1];
- r[1][0], r[1][1] = m[1][0], m[1][1];
- return;
- }
- matrix2_from_matrix4_f64 :: proc(m: Matrix4f64) -> (r: Matrix2f64) {
- r[0][0], r[0][1] = m[0][0], m[0][1];
- r[1][0], r[1][1] = m[1][0], m[1][1];
- return;
- }
- matrix2_from_matrix4 :: proc{
- matrix2_from_matrix4_f16,
- matrix2_from_matrix4_f32,
- matrix2_from_matrix4_f64,
- };
- matrix3_from_matrix2_f16 :: proc(m: Matrix2f16) -> (r: Matrix3f16) {
- r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0;
- r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0;
- r[2][0], r[2][1], r[2][2] = 0, 0, 1;
- return;
- }
- matrix3_from_matrix2_f32 :: proc(m: Matrix2f32) -> (r: Matrix3f32) {
- r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0;
- r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0;
- r[2][0], r[2][1], r[2][2] = 0, 0, 1;
- return;
- }
- matrix3_from_matrix2_f64 :: proc(m: Matrix2f64) -> (r: Matrix3f64) {
- r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0;
- r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0;
- r[2][0], r[2][1], r[2][2] = 0, 0, 1;
- return;
- }
- matrix3_from_matrix2 :: proc{
- matrix3_from_matrix2_f16,
- matrix3_from_matrix2_f32,
- matrix3_from_matrix2_f64,
- };
- matrix3_from_matrix4_f16 :: proc(m: Matrix4f16) -> (r: Matrix3f16) {
- r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2];
- r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2];
- r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2];
- return;
- }
- matrix3_from_matrix4_f32 :: proc(m: Matrix4f32) -> (r: Matrix3f32) {
- r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2];
- r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2];
- r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2];
- return;
- }
- matrix3_from_matrix4_f64 :: proc(m: Matrix4f64) -> (r: Matrix3f64) {
- r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2];
- r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2];
- r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2];
- return;
- }
- matrix3_from_matrix4 :: proc{
- matrix3_from_matrix4_f16,
- matrix3_from_matrix4_f32,
- matrix3_from_matrix4_f64,
- };
- matrix4_from_matrix2_f16 :: proc(m: Matrix2f16) -> (r: Matrix4f16) {
- r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0;
- r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0;
- r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0;
- r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
- return;
- }
- matrix4_from_matrix2_f32 :: proc(m: Matrix2f32) -> (r: Matrix4f32) {
- r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0;
- r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0;
- r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0;
- r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
- return;
- }
- matrix4_from_matrix2_f64 :: proc(m: Matrix2f64) -> (r: Matrix4f64) {
- r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0;
- r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0;
- r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0;
- r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
- return;
- }
- matrix4_from_matrix2 :: proc{
- matrix4_from_matrix2_f16,
- matrix4_from_matrix2_f32,
- matrix4_from_matrix2_f64,
- };
- matrix4_from_matrix3_f16 :: proc(m: Matrix3f16) -> (r: Matrix4f16) {
- r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0;
- r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0;
- r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0;
- r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
- return;
- }
- matrix4_from_matrix3_f32 :: proc(m: Matrix3f32) -> (r: Matrix4f32) {
- r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0;
- r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0;
- r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0;
- r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
- return;
- }
- matrix4_from_matrix3_f64 :: proc(m: Matrix3f64) -> (r: Matrix4f64) {
- r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0;
- r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0;
- r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0;
- r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1;
- return;
- }
- matrix4_from_matrix3 :: proc{
- matrix4_from_matrix3_f16,
- matrix4_from_matrix3_f32,
- matrix4_from_matrix3_f64,
- };
- quaternion_from_scalar_f16 :: proc(f: f16) -> (q: Quaternionf16) {
- q.w = f;
- return;
- }
- quaternion_from_scalar_f32 :: proc(f: f32) -> (q: Quaternionf32) {
- q.w = f;
- return;
- }
- quaternion_from_scalar_f64 :: proc(f: f64) -> (q: Quaternionf64) {
- q.w = f;
- return;
- }
- quaternion_from_scalar :: proc{
- quaternion_from_scalar_f16,
- quaternion_from_scalar_f32,
- quaternion_from_scalar_f64,
- };
- to_matrix2f16 :: proc{matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16};
- to_matrix3f16 :: proc{matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16};
- to_matrix4f16 :: proc{matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16};
- to_quaternionf16 :: proc{quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16};
- to_matrix2f32 :: proc{matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32};
- to_matrix3f32 :: proc{matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32};
- to_matrix4f32 :: proc{matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32};
- to_quaternionf32 :: proc{quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32};
- to_matrix2f64 :: proc{matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64};
- to_matrix3f64 :: proc{matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64};
- to_matrix4f64 :: proc{matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64};
- to_quaternionf64 :: proc{quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64};
- to_matrix2f :: proc{
- matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16,
- matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32,
- matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64,
- };
- to_matrix3 :: proc{
- matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16,
- matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32,
- matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64,
- };
- to_matrix4 :: proc{
- matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16,
- matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32,
- matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64,
- };
- to_quaternion :: proc{
- quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16,
- quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32,
- quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64,
- };
- matrix2_orthonormalize_f16 :: proc(m: Matrix2f16) -> (r: Matrix2f16) {
- r[0] = normalize(m[0]);
- d0 := dot(r[0], r[1]);
- r[1] -= r[0] * d0;
- r[1] = normalize(r[1]);
- return;
- }
- matrix2_orthonormalize_f32 :: proc(m: Matrix2f32) -> (r: Matrix2f32) {
- r[0] = normalize(m[0]);
- d0 := dot(r[0], r[1]);
- r[1] -= r[0] * d0;
- r[1] = normalize(r[1]);
- return;
- }
- matrix2_orthonormalize_f64 :: proc(m: Matrix2f64) -> (r: Matrix2f64) {
- r[0] = normalize(m[0]);
- d0 := dot(r[0], r[1]);
- r[1] -= r[0] * d0;
- r[1] = normalize(r[1]);
- return;
- }
- matrix2_orthonormalize :: proc{
- matrix2_orthonormalize_f16,
- matrix2_orthonormalize_f32,
- matrix2_orthonormalize_f64,
- };
- matrix3_orthonormalize_f16 :: proc(m: Matrix3f16) -> (r: Matrix3f16) {
- r[0] = normalize(m[0]);
- d0 := dot(r[0], r[1]);
- r[1] -= r[0] * d0;
- r[1] = normalize(r[1]);
- d1 := dot(r[1], r[2]);
- d0 = dot(r[0], r[2]);
- r[2] -= r[0]*d0 + r[1]*d1;
- r[2] = normalize(r[2]);
- return;
- }
- matrix3_orthonormalize_f32 :: proc(m: Matrix3f32) -> (r: Matrix3f32) {
- r[0] = normalize(m[0]);
- d0 := dot(r[0], r[1]);
- r[1] -= r[0] * d0;
- r[1] = normalize(r[1]);
- d1 := dot(r[1], r[2]);
- d0 = dot(r[0], r[2]);
- r[2] -= r[0]*d0 + r[1]*d1;
- r[2] = normalize(r[2]);
- return;
- }
- matrix3_orthonormalize_f64 :: proc(m: Matrix3f64) -> (r: Matrix3f64) {
- r[0] = normalize(m[0]);
- d0 := dot(r[0], r[1]);
- r[1] -= r[0] * d0;
- r[1] = normalize(r[1]);
- d1 := dot(r[1], r[2]);
- d0 = dot(r[0], r[2]);
- r[2] -= r[0]*d0 + r[1]*d1;
- r[2] = normalize(r[2]);
- return;
- }
- matrix3_orthonormalize :: proc{
- matrix3_orthonormalize_f16,
- matrix3_orthonormalize_f32,
- matrix3_orthonormalize_f64,
- };
- vector3_orthonormalize_f16 :: proc(x, y: Vector3f16) -> (z: Vector3f16) {
- return normalize(x - y * dot(y, x));
- }
- vector3_orthonormalize_f32 :: proc(x, y: Vector3f32) -> (z: Vector3f32) {
- return normalize(x - y * dot(y, x));
- }
- vector3_orthonormalize_f64 :: proc(x, y: Vector3f64) -> (z: Vector3f64) {
- return normalize(x - y * dot(y, x));
- }
- vector3_orthonormalize :: proc{
- vector3_orthonormalize_f16,
- vector3_orthonormalize_f32,
- vector3_orthonormalize_f64,
- };
- orthonormalize :: proc{
- matrix2_orthonormalize_f16, matrix3_orthonormalize_f16, vector3_orthonormalize_f16,
- matrix2_orthonormalize_f32, matrix3_orthonormalize_f32, vector3_orthonormalize_f32,
- matrix2_orthonormalize_f64, matrix3_orthonormalize_f64, vector3_orthonormalize_f64,
- };
- matrix4_orientation_f16 :: proc(normal, up: Vector3f16) -> Matrix4f16 {
- if all(equal(normal, up)) {
- return MATRIX4F16_IDENTITY;
- }
- rotation_axis := cross(up, normal);
- angle := math.acos(dot(normal, up));
- return matrix4_rotate(angle, rotation_axis);
- }
- matrix4_orientation_f32 :: proc(normal, up: Vector3f32) -> Matrix4f32 {
- if all(equal(normal, up)) {
- return MATRIX4F32_IDENTITY;
- }
- rotation_axis := cross(up, normal);
- angle := math.acos(dot(normal, up));
- return matrix4_rotate(angle, rotation_axis);
- }
- matrix4_orientation_f64 :: proc(normal, up: Vector3f64) -> Matrix4f64 {
- if all(equal(normal, up)) {
- return MATRIX4F64_IDENTITY;
- }
- rotation_axis := cross(up, normal);
- angle := math.acos(dot(normal, up));
- return matrix4_rotate(angle, rotation_axis);
- }
- matrix4_orientation :: proc{
- matrix4_orientation_f16,
- matrix4_orientation_f32,
- matrix4_orientation_f64,
- };
- euclidean_from_polar_f16 :: proc(polar: Vector2f16) -> Vector3f16 {
- latitude, longitude := polar.x, polar.y;
- cx, sx := math.cos(latitude), math.sin(latitude);
- cy, sy := math.cos(longitude), math.sin(longitude);
- return {
- cx*sy,
- sx,
- cx*cy,
- };
- }
- euclidean_from_polar_f32 :: proc(polar: Vector2f32) -> Vector3f32 {
- latitude, longitude := polar.x, polar.y;
- cx, sx := math.cos(latitude), math.sin(latitude);
- cy, sy := math.cos(longitude), math.sin(longitude);
- return {
- cx*sy,
- sx,
- cx*cy,
- };
- }
- euclidean_from_polar_f64 :: proc(polar: Vector2f64) -> Vector3f64 {
- latitude, longitude := polar.x, polar.y;
- cx, sx := math.cos(latitude), math.sin(latitude);
- cy, sy := math.cos(longitude), math.sin(longitude);
- return {
- cx*sy,
- sx,
- cx*cy,
- };
- }
- euclidean_from_polar :: proc{
- euclidean_from_polar_f16,
- euclidean_from_polar_f32,
- euclidean_from_polar_f64,
- };
- polar_from_euclidean_f16 :: proc(euclidean: Vector3f16) -> Vector3f16 {
- n := length(euclidean);
- tmp := euclidean / n;
- xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z);
- return {
- math.asin(tmp.y),
- math.atan2(tmp.x, tmp.z),
- xz_dist,
- };
- }
- polar_from_euclidean_f32 :: proc(euclidean: Vector3f32) -> Vector3f32 {
- n := length(euclidean);
- tmp := euclidean / n;
- xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z);
- return {
- math.asin(tmp.y),
- math.atan2(tmp.x, tmp.z),
- xz_dist,
- };
- }
- polar_from_euclidean_f64 :: proc(euclidean: Vector3f64) -> Vector3f64 {
- n := length(euclidean);
- tmp := euclidean / n;
- xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z);
- return {
- math.asin(tmp.y),
- math.atan2(tmp.x, tmp.z),
- xz_dist,
- };
- }
- polar_from_euclidean :: proc{
- polar_from_euclidean_f16,
- polar_from_euclidean_f32,
- polar_from_euclidean_f64,
- };
|