package tiny_libs
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_libs.physics_3d/Integrate3d.ml.html
Source file Integrate3d.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101(* 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 Integrate3d.mli *) type method_ = Explicit_euler | Semi_implicit_euler | Verlet | Rk4 type spin_law = Momentum | Spin_gyroscopic | Spin_naive type turn = First_order | Exact type force = Vec3.t -> Vec3.t -> Vec3.t let methods = [ Explicit_euler; Semi_implicit_euler; Verlet; Rk4 ] let name = function | Explicit_euler -> "explicit Euler" | Semi_implicit_euler -> "semi-implicit Euler" | Verlet -> "Verlet" | Rk4 -> "RK4" let no_force _ _ = (0., 0., 0.) (*****************************************************************************) (* The linear half: physics/2d/Integrate, with a z *) (*****************************************************************************) let explicit_euler ~force ~dt (b : Body3d.t) = let a = force b.pos b.vel in { b with pos = Vec3.add b.pos (Vec3.scale dt b.vel); vel = Vec3.add b.vel (Vec3.scale dt a) } let semi_implicit_euler ~force ~dt (b : Body3d.t) = let a = force b.pos b.vel in let vel = Vec3.add b.vel (Vec3.scale dt a) in { b with vel; pos = Vec3.add b.pos (Vec3.scale dt vel) } let verlet ~force ~dt (b : Body3d.t) = let a = force b.pos b.vel in let pos = Vec3.add (Vec3.add b.pos (Vec3.scale dt b.vel)) (Vec3.scale (0.5 *. dt *. dt) a) in (* claude: a velocity-dependent force (drag) has no new velocity yet: * predict it, as physics/2d/Integrate.verlet does, and say so *) let predicted = Vec3.add b.vel (Vec3.scale dt a) in let a' = force pos predicted in { b with pos; vel = Vec3.add b.vel (Vec3.scale (0.5 *. dt) (Vec3.add a a')) } let rk4 ~force ~dt (b : Body3d.t) = let deriv (pos, vel) = (vel, force pos vel) in let advance (p, v) s (dp, dv) = (Vec3.add p (Vec3.scale s dp), Vec3.add v (Vec3.scale s dv)) in let y = (b.pos, b.vel) in let k1 = deriv y in let k2 = deriv (advance y (dt /. 2.) k1) in let k3 = deriv (advance y (dt /. 2.) k2) in let k4 = deriv (advance y dt k3) in (* the four slopes, weighted 1, 2, 2, 1 *) let sixth x1 x2 x3 x4 = Vec3.scale (1. /. 6.) (Vec3.add (Vec3.add x1 (Vec3.scale 2. x2)) (Vec3.add (Vec3.scale 2. x3) x4)) in let dpos = sixth (fst k1) (fst k2) (fst k3) (fst k4) in let dvel = sixth (snd k1) (snd k2) (snd k3) (snd k4) in { b with pos = Vec3.add b.pos (Vec3.scale dt dpos); vel = Vec3.add b.vel (Vec3.scale dt dvel) } let linear = function | Explicit_euler -> explicit_euler | Semi_implicit_euler -> semi_implicit_euler | Verlet -> verlet | Rk4 -> rk4 (*****************************************************************************) (* The rotational half: what 3D adds *) (*****************************************************************************) let turn_by ~turn ~spin ~dt (q : Quat.t) = match turn with First_order -> Quat.integrate ~spin ~dt q | Exact -> Quat.turned_by ~spin ~dt q let spin_step ?(law = Momentum) ?(turn = Exact) ~torque ~dt (b : Body3d.t) = if b.Body3d.inv_inertia = Mat3.zero then (* a body no torque can spin. It may still have been given a spin * (a flipper the player drives), and that spin still turns it. *) { b with orientation = turn_by ~turn ~spin:b.Body3d.spin ~dt b.Body3d.orientation } else match law with | Momentum -> (* dL/dt = torque, and that is the whole of it: with no torque L * does not move at all. The wobble and the flip come out of the * *other* line, w = I_world^-1 L, because I_world turns with the * body. Nothing here needs the gyroscopic term: it is what you * get when you insist on stepping w instead. *) let l = Vec3.add (Mat3.mul_vec (Body3d.inertia_world b) b.Body3d.spin) (Vec3.scale dt torque) in let b = { b with Body3d.orientation = turn_by ~turn ~spin:b.Body3d.spin ~dt b.Body3d.orientation } in { b with Body3d.spin = Mat3.mul_vec (Body3d.inv_inertia_world b) l } | Spin_gyroscopic | Spin_naive -> let i_world = Body3d.inertia_world b in let gyro = if law = Spin_gyroscopic then Vec3.cross b.Body3d.spin (Mat3.mul_vec i_world b.Body3d.spin) else (0., 0., 0.) in let alpha = Mat3.mul_vec (Body3d.inv_inertia_world b) (Vec3.sub torque gyro) in let spin = Vec3.add b.Body3d.spin (Vec3.scale dt alpha) in { b with Body3d.spin; orientation = turn_by ~turn ~spin ~dt b.Body3d.orientation } let step m ?law ?turn ?(torque = (0., 0., 0.)) ~force ~dt b = spin_step ?law ?turn ~torque ~dt (linear m ~force ~dt b)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>