12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364(* Claude Code
*
* Copyright (C) 2026 Yoann Padioleau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* (LGPL) as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*)(* See Transform.mli *)(* a 3 x 3 matrix, row by row *)typem3=floatarray(* p -> m p + o, and its inverse p -> inv_m p + inv_o *)typet={m:m3;o:Vec3.t;inv_m:m3;inv_o:Vec3.t}letid3:m3=[|1.;0.;0.;0.;1.;0.;0.;0.;1.|]letapply(m:m3)((x,y,z):Vec3.t):Vec3.t=((m.(0)*.x)+.(m.(1)*.y)+.(m.(2)*.z),(m.(3)*.x)+.(m.(4)*.y)+.(m.(5)*.z),(m.(6)*.x)+.(m.(7)*.y)+.(m.(8)*.z))(* the transpose applied: m^T v *)letapply_transposed(m:m3)((x,y,z):Vec3.t):Vec3.t=((m.(0)*.x)+.(m.(3)*.y)+.(m.(6)*.z),(m.(1)*.x)+.(m.(4)*.y)+.(m.(7)*.z),(m.(2)*.x)+.(m.(5)*.y)+.(m.(8)*.z))letmul(a:m3)(b:m3):m3=Array.init9(funk->leti=k/3andj=kmod3in(a.((3*i)+0)*.b.(j))+.(a.((3*i)+1)*.b.(3+j))+.(a.((3*i)+2)*.b.(6+j)))letidentity={m=id3;o=(0.,0.,0.);inv_m=id3;inv_o=(0.,0.,0.)}lettranslate(v:Vec3.t):t={identitywitho=v;inv_o=Vec3.scale(-1.)v}letscale((x,y,z):Vec3.t):t=ifx=0.||y=0.||z=0.theninvalid_arg"Transform.scale: a zero flattens the solid";{identitywithm=[|x;0.;0.;0.;y;0.;0.;0.;z|];inv_m=[|1./.x;0.;0.;0.;1./.y;0.;0.;0.;1./.z|]}letrotate(axis:int)(degrees:float):t=letra=letc=cosaands=sinainmatchaxiswith|0->[|1.;0.;0.;0.;c;-.s;0.;s;c|]|1->[|c;0.;s;0.;1.;0.;-.s;0.;c|]|_->[|c;-.s;0.;s;c;0.;0.;0.;1.|]inleta=degrees*.Float.pi/.180.in{identitywithm=ra;inv_m=r(-.a)}(* b first, then a: p -> ma (mb p + ob) + oa; undone by b's inverse
* after a's *)letcompose(a:t)(b:t):t={m=mula.mb.m;o=Vec3.add(applya.mb.o)a.o;inv_m=mulb.inv_ma.inv_m;inv_o=Vec3.add(applyb.inv_ma.inv_o)b.inv_o}letpoint(t:t)(p:Vec3.t):Vec3.t=Vec3.add(applyt.mp)t.oletdirection(t:t)(d:Vec3.t):Vec3.t=applyt.mdletinverse_point(t:t)(p:Vec3.t):Vec3.t=Vec3.add(applyt.inv_mp)t.inv_oletinverse_direction(t:t)(d:Vec3.t):Vec3.t=applyt.inv_mdletnormal(t:t)(n:Vec3.t):Vec3.t=Vec3.normalize(apply_transposedt.inv_mn)letis_translation(t:t):bool=t.m=id3