123456789101112131415161718192021222324252627282930313233(* 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 Energy3d.mli *)(* claude: an immovable body (an infinite mass) or one that never turns
* (an infinite tensor) is always still about that axis, and infinity
* times a zero speed is a nan rather than the 0 it should be: hence the
* guards *)letstill(v:Vec3.t)=v=(0.,0.,0.)letlinear_kinetic(b:Body3d.t)=ifstillb.velthen0.else0.5*.b.mass*.Vec3.dotb.velb.velletrotational_kinetic(b:Body3d.t)=ifstillb.spinthen0.else0.5*.Vec3.dotb.spin(Mat3.mul_vec(Body3d.inertia_worldb)b.spin)letkineticb=linear_kineticb+.rotational_kineticbletmomentum(b:Body3d.t)=ifstillb.velthen(0.,0.,0.)elseVec3.scaleb.massb.velletangular(b:Body3d.t)=ifstillb.spinthen(0.,0.,0.)elseMat3.mul_vec(Body3d.inertia_worldb)b.spinletangular_momentum~around(b:Body3d.t)=Vec3.add(Vec3.cross(Vec3.subb.posaround)(momentumb))(angularb)letgravity~g(b:Body3d.t)=let_,y,_=b.posinb.mass*.g*.y