Validation
Every number on this page comes from the engine's own test suite, run on the code that is published, and is checked against an exact result: a formula, a conservation law or a hand calculation. The page is built from the tests' output; if any of these tests failed, the page could not be built.
The tests run the engine as the studio's Research mode does: 60 pixels per metre, a time step of 1/240 s with 5 substeps, 8 solver iterations. "Error" is the relative difference between the engine and the exact result, or, for things that must stay put, how far they moved.
Note. These are the engine's numbers in the cases tested. A scene of your own can differ: a coarser step, many contacts, or a model the accuracy claim does not cover (below).
42 benchmarks shown, from a run of all 178 engine tests on 2026-10-17 (commit 6860d57): every one passed.
Motion under gravity and constant forces
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| Free fall for 1 s | ½ g t² | 4.9086 m | 4.905 m | 0.074 % | passes |
| Constant force on a free block | x = F t² / 2m | 3.7754 m | 3.7734 m | 0.055 % | passes |
| Circular orbit under the bodies' own gravitation | T = 2π √(r³ / G M) | 2.4 s | 2.3992 s | 0.035 % | passes |
Oscillations
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| Mass on a spring | T = 2π √(m/k) | 0.99584 s | 0.99346 s | 0.24 % | passes |
| Pendulum, small angle | T = 2π √(L/g) | 2.0083 s | 2.0061 s | 0.11 % | passes |
| Torsional pendulum, k = 4 N·m/rad | T = 2π √(I/k) | 0.94247 s | 0.94248 s | < 0.001 % | passes |
| Forced, damped oscillator near resonance (ω = 6 rad/s) | X = F₀ / √((k − mω²)² + (cω)²) | 0.2776 m | 0.27778 m | 0.065 % | passes |
| Base excitation (a shaken wall), ω = 3 rad/s | transmissibility X/Y = √(k² + (cω)²) / √((k − mω²)² + (cω)²) | 0.02656 m | 0.026565 m | 0.017 % | passes |
Friction and rolling
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| Block sliding down a 30° incline, μ = 0.3 (μk = 0.24) | ½ g (sin θ − μk cos θ) t² | 1.4312 m | 1.433 m | 0.12 % | passes |
| Block on a 20° incline, μ = 0.5 > tan θ | stays at rest | — | — | 2 µm slid | passes |
| Solid disk rolling down 15° | g (sin θ − c_rr cos θ) / 1.5 | 0.79969 m | 0.79896 m | 0.091 % | passes |
| Disk rolling on flat ground at 3 m/s, c_rr = 0.02 | deceleration c_rr g / 1.5 | — | — | 0.040 % | passes |
| Cart with a heavy load on 10 g wheels, coasting | c_rr g M / (M + Σ I/r²) | 0.1963 m/s² | 0.19617 m/s² | 0.071 % | passes |
| Frictionless cart pushed under a rolling disk | (F − 2 c_rr m g / 3) / (M + m/3) | 2.5197 m/s² | 2.5154 m/s² | 0.17 % | passes |
Collisions
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| Elastic collision of equal masses | the velocities swap: 0 and 2 m/s | 2 m/s | 2 m/s | 0 % | passes |
| Newton's cradle, five balls, e = 1, struck at 2 m/s | the last ball leaves at 2 m/s, the others stay | 1.9971 m/s | 2 m/s | 0.15 % | passes |
Pulleys, cables and chains
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| Atwood machine, ideal pulley | a = (m₁ − m₂) g / (m₁ + m₂) | 0.40943 m | 0.40875 m | 0.17 % | passes |
| Atwood machine, the cable's tension | T = 2 m₁ m₂ g / (m₁ + m₂) | 13.08 N | 13.08 N | < 0.001 % | passes |
| Atwood machine with a heavy pulley | a = (m₁ − m₂) g / (m₁ + m₂ + I/r²) | 0.30707 m | 0.30656 m | 0.17 % | passes |
| Movable pulley, 2 : 1 | exact kinematics and forces | 0.30707 m | 0.30656 m | 0.17 % | passes |
| Cable over a rough drum, μ = 0.3 (capstan) | T₁/T₂ = e^(μπ) | 0.095376 m | 0.095536 m | 0.17 % | passes |
| Mass on an elastic cable at rest | sag m g L / EA | 1.0392 m | 1.0392 m | < 0.001 % | passes |
| Atwood machine with a heavy cable (0.5 kg/m) | (m₁ + m₂ + ρL) ẍ = g (m₁ − m₂ + ρ(h₁ − h₂) + 2ρx) | 0.37106 m | 0.37068 m | 0.10 % | passes |
| Chain over a smooth peg | ẍ = g (h₁ − h₂ + 2x) / L | 0.27145 m | 0.27091 m | 0.20 % | passes |
| Chain pulling a block off a smooth table | (m₁ + m₂ + ρL) ÿ = (m₂ + ρy) g | 0.46319 m | 0.4625 m | 0.15 % | passes |
| 2 : 1 tackle with a heavy rope | Lagrange's equation, integrated | 0.65819 m | 0.65726 m | 0.14 % | passes |
Gears, belts and motors
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| Gear pair 16 : 40 over 19 turns | ω_B = −ω_A r_A / r_B | 4.8 rad/s | 4.8 rad/s | 0 % | passes |
| Ring gear 40 with a 12-tooth pinion | ω_ring / ω_pinion = 12/40 | 0.3 | 0.3 | 0 % | passes |
| Rack and pinion | v = ω r | 1.6 m/s | 1.6 m/s | 0 % | passes |
| Planetary set with a fixed ring | Willis: ω_C = ω_S Z_S / (Z_S + Z_R) | -0.99999 rad/s | -1 rad/s | < 0.001 % | passes |
| Torque-limited motor driving a gear | τ / (I_A + I_B (r_A/r_B)²) | 0.35587 rad/s | 0.35587 rad/s | < 0.001 % | passes |
| Belt 2 : 1 driving a conveyor | ω_B = 2 ω_A | 2 | 2 | 0 % | passes |
Statics and forces (free-body diagrams)
The forces the studio draws in a free-body diagram, against the hand calculation.
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| Block at rest on an incline: normal force | N = m g cos θ | 26.673 N | 26.673 N | < 0.001 % | passes |
| Atwood machine: tension on m₁ | T = 2 m₁ m₂ g / (m₁ + m₂) | 23.544 N | 23.544 N | < 0.001 % | passes |
| Beam on two pins with a load: left reaction | moments about the right pin | 65.399 N | 65.4 N | < 0.001 % | passes |
| Pin angle stop holding a bar | stop torque = the weight's moment | -4.0483 N·m | -4.0483 N·m | < 0.001 % | passes |
Air resistance
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| Ball falling with linear drag b = 0.8 kg/s | v = (m g / b)(1 − e^(−bt/m)) | — | — | 0.015 % | passes |
| Sphere falling in sea-level air | v_t tanh(g t / v_t), v_t = √(2mg / ρ C_d A) | — | — | 0.0075 % | passes |
Robustness of the solver
Not comparisons with a formula: stacks and structures that must stay at rest, and results that must not depend on the units or on sleeping bodies.
| Benchmark | Exact result | Engine | Exact | Error | Test |
|---|---|---|---|---|---|
| 900 kg and 3000 kg on a 1 kg box | at rest | — | — | 0 m sway | passes |
| Ten-box tower under the Sun's gravity (274 m/s²) | at rest | — | — | 0 m drift | passes |
| The same scene in pixels, metres and millimetres | the same motion | — | — | 55 µm (largest difference) | passes |
| 1000 kg bob on three 0.1 kg bars, swinging | the pins hold | — | — | 7 µm pin gap | passes |
The whole run
Every test's own output (178 lines)
PASS [spring_mass_period] T_meas=0.995843 T_exp=0.993459 rel_err=0.002400
PASS [convex_decomposition] L: 2 pieces, area 4.000000 (4.000000); L clockwise: 2 pieces, area 4.000000 (4.000000); U: 3 pieces, area 5.000000 (5.000000); star: 5 pieces, area 1.175570 (1.175570); a crossing outline: none; a square: itself
PASS [user_material_incline] μs 0.5, μk 0.4: at 0.9 atan μs it holds (a 0.000000 m/s²); at 1.15 atan μs a = 1.600239 m/s² (g(sinθ − μk cosθ) = 1.606997: 0.420512 %)
PASS [user_material_mixing] μs: user–user 0.316228 (√(0.5·0.2) = 0.3162), user–steel 0.591608 (√(0.5·0.7) = 0.5916), with a measured entry 0.310000 (0.31); rolling 0.020000 (0.02); redefined: yes, removed: yes
PASS [user_material_density_and_file] mass from 2 kg/m² on 0.25 m²: 0.500000 kg; after a scene file the body has the material and keeps its mass 3.000000 kg
PASS [geometric_mean_vs_presets] static μ of the 15 preset pairs from the geometric mean of the materials' own: mean error 36.315441 %, worst 107.019661 % (Steel–Ice)
PASS [compound_mass_properties] 2 pieces, centre (0.750000, 1.250000), I 4.166667 kg m^2 (4.166667)
PASS [compound_cup_holds_ball] ball at y 3.700707 (inner floor 3.700000, rim 2.700000), x 1.500000 (1.500000)
PASS [compound_bodies_rest_on_ground] deepest point 1.668453 mm into the floor, speed 0.000000 m/s
PASS [resting_stack_settles] speed=0.000000 spin=0.000000
PASS [pendulum_small_angle] T_meas=2.008338 T_exp=2.006067 rel_err=0.001132
PASS [prismatic_no_lateral_drift] y=0.000000 vy=0.000000
PASS [rope_atwood_geometry] L=2.628318 expected=2.628319
PASS [rope_atwood_ideal_acceleration] drop=0.409431 expected=0.408750 rel_err=0.001666
PASS [rope_atwood_ideal_tension] T=13.080063N expected=13.080001N rel_err=0.000005
PASS [rope_atwood_massive_pulley_acceleration] drop=0.307075 expected=0.306563 rel_err=0.001672
PASS [rope_rolling_pulley_spin] omega=6.131263 expected=6.131250 rel_err=0.000002
PASS [rope_slack_free_fall] drop=0.110976 expected=0.110363 tension=0.000000
PASS [rope_movable_pulley_geometry] length_err=0.000000
PASS [rope_movable_pulley_equilibrium] wheel_rise=0.000000 counter_drop=0.000000
PASS [rope_movable_pulley_2to1] counter_drop=0.307074 expected=0.306563 wheel_rise=0.153537 rel_err=0.001670
PASS [rope_wraps_circle] auto_nodes=1 x=-0.099936 y=0.989882
PASS [rope_unwraps] auto_nodes=0
PASS [rope_wraps_polygon_corner] auto_nodes=1 x=0.000080 y=1.200056
PASS [rope_ball_rests_in_cable_v] flips=0 sway=0.005978m tension=118.653824..120.419609N
PASS [rope_disabled_cable] wrapped_nodes=3 disabled_nodes=2 y=2.223147
PASS [rope_save_load_roundtrip] ropes=1
PASS [rope_removal_cascade] after_wheel_nodes=1 ropes_left=0
PASS [revolute_motor_torque_limit] omega=1.599999 expected=1.600000 rel_err=0.000001
PASS [pinned_body_motor] omega=1.599999 expected=1.600000 rel_err=0.000001
PASS [collision_mask_passthrough] y=1.728291
PASS [validation_free_fall] drop=4.908612 expected=4.905000 rel_err=0.000736
PASS [validation_elastic_collision] va=0.000000 vb=2.000000 (expected 0, 2)
PASS [validation_rolling_disk] dist=0.799691 expected=0.798960 rel_err=0.000915 slip=0.000059m/s
PASS [custom_moment_of_inertia] hoop_dist=0.599758 expected=0.599220 rel_err=0.000899 kept_after_mass_change=1 scene_file=1.000000 shape_again=1
PASS [ring_body_rolls] mass_ok=1 dist=0.649374 expected=0.648779 rel_err=0.000917 scene_hole=1.000000 scene_MoI=1.000000 clamped=1 solid_again=1
PASS [ring_body_holds_bodies] inside_err_m=0.000167 on_top_err_m=0.000167 roller_max_dist=0.801238 (limit 0.800000) small_ring_err_m=0.000168 asleep=1
PASS [gravitation_orbits] planet: radius_err=0.109507% period=2.400006s expected=2.399157s; pair: separation_err=0.066471% centre_moved=0.000000mm
PASS [magnus_ball_curves_on_its_circle] R 57.130501 m: worst radius error 0.025086 %, 1.316098 cm from the start after one period
PASS [spin_drag_ball_and_plate] ball ω after 5 s 57.623444 (57.623474, 0.000053 %); plate ω after 3 s -4.928036 (-4.928043, 0.000133 %)
PASS [liquid_box_floats_at_its_draft] draft 9.997896 cm (10.000000), speed 0.000000 m/s
PASS [liquid_ball_floats_half_under] cap 9.998078 cm (10.000000)
PASS [liquid_ball_floats_quarter_density] cap 6.527765 cm (6.527040)
PASS [liquid_raft_rights_itself] tilt after 20 s 0.051055° (from 30°)
PASS [liquid_added_mass_light_ball] rises at 11.470946 m/s² (11.485658; without added mass 41.555042)
PASS [liquid_light_ball_settles] fastest after 3 s 0.000000 m/s, highest bounce 0.532542 m above the surface (centre)
PASS [liquid_and_spin_saved_in_scene_files] liquid 1024.999756 kg/m³
PASS [liquid_and_spin_saved_in_scene_files_metres] liquid 1025.000000 kg/m³
PASS [liquid_ball_sinks_at_terminal_speed] speed 1.823578 m/s (1.827450), at 1.800561 m
PASS [friction_incline_static_holds] slid=0.000002m speed=0.000000
PASS [friction_incline_kinetic] slid=1.431245 expected=1.433015 rel_err=0.001235
PASS [gear_mesh_ratio_many_turns] turns=19.099743 wB=4.800000 expected=4.800000 worst_rel_err=0.000000
PASS [gear_mesh_apart_disengaged] enabled=0 wB=0.000000
PASS [belt_ratio_and_conveyor] wB/wA=2.000000 box_vx=1.196620 belt=1.200000
PASS [motor_drives_geared_load] omega=0.355874 expected=0.355872 rel_err=0.000006
PASS [gear_pressure_angle_radial_force] tangential 1.500000 N (1.500000), radial 0.545955 N (0.545955), B's pin plus the tooth force 0.000000 N (0)
PASS [gear_without_pressure_angle_is_tangential] tangential 1.500000 N (1.500000), radial 0.000000 N (0.000000), B's pin plus the tooth force 0.000000 N (0)
PASS [welded_bar_triangle_rests] finite, fastest in the last 2 s 0.010494 m/s
PASS [pinned_bar_triangle_rests] finite, fastest in the last 2 s 0.016452 m/s
PASS [welded_frame_with_restitution_rests] finite, fastest in the 10th second 0.000000 m/s (< 0.01)
PASS [welded_frame_with_restitution_rests_5_substeps] finite, fastest in the 10th second 0.000000 m/s (< 0.01)
PASS [weathervane_dart_points_along_its_flight] worst angle to its path after 0.5 s 7.085037° (< 10: it trails the curving path most at the top, where it is slowest; let go 45° off it), saved 1.000000
PASS [weathervane_does_nothing_in_a_vacuum] angle 0.000000 rad
PASS [prismatic_end_stop_plastic] rebound=0.000000m/s overshoot=0.000000m
PASS [prismatic_end_stop_momentum] v_rail=0.500000 v_slider=0.500000 (expected 0.5, 0.5)
PASS [prismatic_rests_on_inclined_stop] gap=0.000000m drift=0.000000m
PASS [pair_friction_cart_carries_disk] a_cart=2.519713 expected=2.515372 rel_err=0.001726 a_disk=0.970560 slip=0.000079m/s
PASS [pair_friction_body_override_still_mixes] a_disk=0.000000 (a per-body 0 makes every pair frictionless: the disk stays put)
PASS [pair_friction_bookkeeping] stored=1 forgotten=1
PASS [coupled_loaded_cart_rests] band=0.000000m speed=0.000000m/s drift=0.000000m sink=0.000020m
PASS [coupled_pendulum_on_wall_rests] rod_err=0.000000m wall_gap=-0.000003m speed=0.000000m/s
PASS [rounded_mass_properties] capsule_I_rel_err=0.000218 outline_moved=0.000046px
PASS [rounded_bodies_rest] capsule_y=-0.099833 stack_top_y=-1.049932 ball_y=-0.499790 max_speed=0.000000
PASS [rounded_bodies_slide_and_roll] slide_rel_err=0.001242 roll_rel_err=0.001238 I/(mR^2)=0.500273
PASS [rope_wraps_rounded_corner] corner_wheels=2 x=-0.000068 y=1.219383 expected_y=1.219198
PASS [gear_ring_internal_ratio] wRing/wPinion=0.300000 expected=0.300000
PASS [gear_rack_and_pinion] v_rack=1.600000m/s expected=1.600000 released_at_end=1
PASS [gear_planetary_willis] w_carrier=-0.999995 expected=-1.000000 w_planet=3.000000 expected=3.000014
PASS [gear_pinion_rolls_on_rack] v/(w r)=1.000000 L_rel_change=0.000000
PASS [rope_capstan_drum] held=0.000000m slid=0.095376 expected=0.095536 rel_err=0.001670 T1/T2=2.566333 k=2.566333
PASS [rope_capstan_eyelets] slid=0.094118 expected=0.095536 rel_err=0.014842 mu0_drop=0.409431
PASS [rope_body_stays_in_cable_v] 8/8 stayed above the eyelet
PASS [rope_elastic_cable] lowest=1.077663 expected=1.078480 rest=1.039234 expected=1.039240 T=19.616844N impact_peak=318.236603N
PASS [cable_mass_atwood_fixed_pulley] drop=0.371063 expected=0.370683 rel_err=0.001025 T1=9.772166N expected=9.770832N energy_drift=0.001519 of the kinetic energy
PASS [cable_mass_atwood_gripping_pulley] drop=0.270964 expected=0.270696 rel_err=0.000991 T1=10.500913N expected=10.500269N energy_drift=0.001452 of the kinetic energy
PASS [cable_mass_atwood_mounted_pulley] drop=0.371064 expected=0.370683 rel_err=0.001026 T1=9.772172N expected=9.770832N energy_drift=0.001522 of the kinetic energy
PASS [cable_mass_chain_over_peg] drop=0.271447 expected=0.270910 (massless ends 0.273882) rel_err=0.001979 end_tension=0.055710N peak_tension=8.247075N
PASS [cable_mass_chain_off_table] fell=0.463186 expected=0.462499 rel_err=0.001485 block_slid=0.463185 block_y=-0.099991
PASS [cable_mass_capstan] held=0.000000m T1/T2=2.333333 (expected 2.333333) slid=0.098048 expected=0.098219 rel_err=0.001746 40_substeps_rel_err=0.000260 slipping T1/T2=2.574949 expected=2.574959 (e^(mu pi)=2.566333)
PASS [cable_mass_moving_pulley] counter_drop=0.658195 expected=0.657257 rel_err=0.001427 (without the turn's momentum 0.662537) pulley_rise=0.329098 energy_drift=0.000664 of the kinetic energy
PASS [cable_mass_slack_and_swing] slack_drop=0.110976 expected=0.110363 end_tensions=0.000000,0.000000 swing_energy_drift=0.013663 (massless cable 0.011156, 20 substeps 0.003474)
PASS [rope_with_mass_inextensible] hanging_stretch=0.007606% jitter=0.004069mm tied_between_boxes_worst=0.784183%
PASS [rope_load_rests_over_pulley] at_1/60: mass_speed=0.000012m/s pulley=0.000082rad/s height=0.976626m; at_1/240: mass_speed=0.000002m/s pulley=0.000000rad/s height=0.976624m
PASS [rope_waves_die_out] wiggle_energy_left_after_3s=0.007556 (undamped 0.875380) swing_energy_left_after_10s=0.626187 (undamped 0.646571) hanging_chain_at_rest_moves=0.002362mm_in_10s
PASS [rope_keeps_energy_while_turning] spinning_rope_energy_after_5s: 20rad/s_at_1/240=0.999983 20rad/s_at_1/60=1.000244 60rad/s_at_1/60=0.999984 rope_pendulum_swing_energy_after_10s=0.917003
PASS [ropes_in_series_between_rings_land] fastest=9.1133m/s (landing about 9) last_second_fastest=0m/s outer_ring_height=2.99987m (radius 3)
PASS [stiff_rope_cantilever_deflection] tip 82.719696 mm, Euler-Bernoulli 83.395218 mm (0.810025 %), fastest link 0.000012 m/s
PASS [stiff_rope_holds_its_curve] ends 1.004138 m apart (1), middle 0.498601 m from the chord (0.5)
PASS [stiff_rope_vibrates_without_gaining_energy] no friction: peak 0.938244, after 5 s 0.000025; default friction: peak 0.935368, after 5 s 0.000019
PASS [rope_snaps_past_its_break_tension] 1 links broken, mass at 6.001923 m
PASS [rope_holds_below_its_break_tension] 0 links broken, mass at 1.100021 m
PASS [rope_tied_to_rope_rests] fastest 0.548540 m/s, last second 0.003178 m/s, ball 0.000000 m off centre, pins carry 21.159119 N of 20.797199 N
PASS [taut_rope_between_pins_sags_elastically_1_60] fastest ever 0.851929 m/s, now 0.000005 m/s; sag 3.605913 cm (3.611077), tension 216.167450 N (217.331299)
PASS [taut_rope_between_pins_sags_elastically_1_240] fastest ever 0.858121 m/s, now 0.000015 m/s; sag 3.611839 cm (3.611077), tension 216.894348 N (217.331299)
PASS [scale_invariance_px_m_mm] max_difference=0.000055 (m or m/s)
PASS [articulated_heavy_cart_rests] band_500kg=0.000000m pin_gap=0.000000m sink_1t_on_1g_wheels=0.000020m
PASS [articulated_heavy_bob_chain] pin_gap=0.000007m energy_drift=0.147070% of the kinetic energy
PASS [articulated_welds_and_overlaps] drop_max_speed=4.144901m/s joint_gap=0.000026m cantilever_sag=0.000000m
PASS [articulated_loops] four_bar_pin_gap=0.000004m crank_w=6.000002 parallelogram_energy_drift=0.025070J late_swing=0.203318m
PASS [truss_heavy_load_light_nodes] 60.000000kg_on_0.300000kg@1/240: load_moves=0.000000mm F_B1B2_err=0.000000% 60.000000kg_on_0.300000kg@1/60: load_moves=0.000000mm F_B1B2_err=0.000000% 1000.000000kg_on_0.050000kg@1/240: load_moves=0.000000mm F_B1B2_err=0.000000%
PASS [articulated_motors_and_stops] geared_motor_rel_err=0.000003 heavy_trolley_rod_err=0.000014m stop_overshoot=0.000000m
PASS [articulation_fallbacks] long_chain_articulations=0 long_chain_gap=0.000000m gauss_seidel_rod_err=0.000000m
PASS [welded_wheel_many_parts] bodies=43 articulations=1 speed_err=0.000000rad/s shape_err=0.000001m turn_err=0.000000rad turns_1s_to_10s=0.749955 (0.75) free_hub: fall_speed_err=0.000108m/s shape_err=0.000000m
PASS [joints_on_fixed_axle_swing] pin_gauss_seidel=5.801212/5.801444rad/s pin_exact=5.801220/5.801444rad/s weld_gauss_seidel=5.516916/5.516972rad/s weld_exact=5.516912/5.516972rad/s
PASS [rolling_on_flat_ground] disk_3mps_rel_err=0.000398 rubber_ground_first=0.000043 rubber_disk_first=0.000043 loaded_cart_rel_err=0.000191
PASS [air_resistance] linear_rel_err=0.000154 sphere_rel_err=0.000075 terminal_speed_err=0.000000 k_model_err=0.000075 vacuum_err=0.000001 leaf_in_wind_err=0.000000 plank_area_ratio=19.999983 plank_flat_err=0.000297 plank_edge_err=0.000019
PASS [strong_gravity_rest] worst_drift_in_4s=0.000000m
PASS [slice_capsule] pieces=2 round_ends=1 mass_sum=3.000000 share_vs_area_err=0.000348 velocity_err=0.000000m/s
PASS [newtons_cradle] v_impact=2.459146m/s first_out=0.899253 first_others_max=0.058514m/s second_out=0.815961 second_others_max=0.109300m/s
PASS [newtons_cradle_reversed_order] v_impact=2.459146m/s first_out=0.899253 first_others_max=0.058514m/s second_out=0.815961 second_others_max=0.109300m/s
PASS [newtons_cradle_elastic_row] last=1.997066m/s (expected 2) others_max=0.000000m/s
PASS [cable_unwinds_from_disk] L=2.568847m max_path=2.569100m max_tie_to_load=2.569100m wound_back=1 lifted_again=0.187911m
PASS [cable_leaves_pulley] L=5.928319m max_path=5.929422m right_pulley_left=1
PASS [gear_loose_in_ring] gear_centre_distance=0.958559m expected=0.960000 in_mesh=1 ball_inside_gap=0.010002px ball_outside_gap=-0.010002px
PASS [rolling_resistance_light_wheels] a=0.196304 expected=0.196166 rel_err=0.000707
PASS [heavy_on_light_stacks] worst_sway=0.000000m worst_sink=0.001719m worst_tilt=0.000000rad (900:1, 3000:1, 500/1/50 kg; Sandbox and Research steps) sun_tower_sway=0.000000m sun_tower_top_drop=0.001719m
PASS [islands_with_articulations_stack_on_cart] heavy_sink=0.000461m small_sink=0.000242m sway=0.000000m speed=0.000000m/s (900 kg and 100 kg on 1 kg on a 2 kg cart; Gauss-Seidel sank 0.859937m)
PASS [island_fixed_row_stays_quiet] wheel speed=0.000000m/s y=-0.200000m (a wheel pinned at its centre, resting on the ground and under a 50 kg box)
PASS [sleep_pile_sleeps_and_keeps_its_forces] awake at 0.3 s: 1, asleep after 4 s: 10/10 moved while asleep=0.000000 px, bottom box carries 2.643592 kg (>= its own 1 kg)
PASS [sleep_wakes_on_touch_and_sleeps_again] slept=1 woke when hit=1 fewest asleep=0.000000 asleep again=7/7
PASS [sleep_wakes_on_every_kind_of_edit] ground_removed:slept=1,fell=1 moved:woke=1 gravity:slid=1 friction:slept=1,slid=1 joint:woke=1 velocity:woke=1,again=1 load:woke=1
PASS [sleep_lets_mechanisms_sleep_and_holds_driven_bodies] free box 1, box on a spring 1, pendulum bob 1 (Stage 7.4: these sleep); loaded box 0, wheel on a motor 0, box with a thruster 0 (these never)
PASS [sleeping_mechanisms_wake_as_one] all asleep 1; the dropped ball woke the chain 1 and nothing else 1; asleep again 1 with its rods off by 0.000064 mm; the spring's new stiffness woke its box 1; a pull woke the whole Rope 1
PASS [sleep_does_not_change_the_result] largest difference of any body after 9 s, with and without sleeping, at 1/60 and 1/240 s: 0.000177 m
PASS [sleep_follows_a_moving_or_dragged_ground] slept=1 woke on the platform=1 carried 0.784652 m (platform 0.8 m) asleep again=1 fell when the ground was dragged away=1
PASS [sleep_saves_time] a settled pyramid of 78 boxes: 0.199490 ms per step asleep, 99.630280 ms awake (this test build uses AddressSanitizer)
PASS [sleeping_mechanisms_save_time] 40 pendulums and a pile of 36 boxes: 76 of 76 asleep, 0.284268 ms per step asleep, 34.663879 ms awake; the quiet grid rebuilt 0 times in 120 steps (this test build uses AddressSanitizer)
PASS [large_contact_islands] slab_on_columns/sandbox: sway 0.000000 mm sink 3.045909 mm tilt 0.000000 slab_on_columns/research: sway 0.000000 mm sink 0.143178 mm tilt 0.000000 block_on_pyramid/sandbox: sway 0.000000 mm sink 2.014160 mm tilt 0.000000 block_on_pyramid/research: sway 0.000000 mm sink 0.102234 mm tilt 0.000000 | Gauss-Seidel slab/sandbox: sway 12076.004883 mm sink 1545.064941 mm
PASS [scene_json_round_trip] 10469 bytes; saved again: same fields, numbers within 0.000000 (relative)
PASS [scene_json_every_kind] bodies 22, gear kinds mesh/belt/internal/rack 1111
PASS [scene_json_same_motion] 2 s, every body: max deviation 0.000000 mm
PASS [scene_json_sim_time] simTime 2.000000
PASS [scene_json_cable_mass] massPerMeter 0.400000, a chain solved with mass: 1
PASS [scene_json_units] metres world: g = 9.810000 m/s²; saved again: same file, numbers within 0.000000
PASS [scene_json_units_motion] 1 s in pixels vs metres: max deviation 0.158183 mm
PASS [scene_json_keeps_studio_data] names, annotations, camera, chains, unknown fields kept; settings read
PASS [scene_json_errors] bad files refused and the world left as it was; an empty scene loads
PASS [broad_phase_huge_bodies] a 1e8-px box, a body at 1e30 and one at NaN in the scene: the ball still lands and rests on the floor (y = -0.199833 m)
PASS [broad_phase_giant_body] a radius-1e30 body: ten steps finish (they ran out of memory before)
PASS [studio_scene_files] 22/22 studio scenes follow the studio's motion; worst 0.006935 mm (fig-ref-cart-pendulum)
PASS [applied_force_constant] x=3.775437 expected=3.773365 v_err=0.000018
PASS [applied_torque_disk] omega=11.851649 expected=11.851851
PASS [applied_load_ignored_by_static] a static body does not move under a load
PASS [forced_oscillator_amplitude_w3] amplitude=0.073370 m expected=0.073424 m rel_err=0.000738
PASS [forced_oscillator_amplitude_w6] amplitude=0.277597 m expected=0.277778 m rel_err=0.000652
PASS [forced_oscillator_amplitude_w9] amplitude=0.043211 m expected=0.043217 m rel_err=0.000137
PASS [base_excitation_transmissibility_w3] X=0.026560 m expected=0.026565 m rel_err=0.000168 wall_drift=0.000000 m
PASS [base_excitation_transmissibility_w6] X=0.101943 m expected=0.101980 m rel_err=0.000362 wall_drift=0.000000 m
PASS [base_excitation_transmissibility_w9] X=0.016240 m expected=0.016243 m rel_err=0.000200 wall_drift=0.000000 m
PASS [kinematic_lift_carries_box] gap change=0.000004 m, speed difference=0.000000 m/s, lift y=-2.000045
PASS [kinematic_platform_drags_box] box speed=1.000000 m/s (platform 1 m/s)
PASS [kinematic_platform_rotates] turned 0.399992 rad (0.4 expected)
PASS [torsional_pendulum_period_k4] T=0.942469 s, 2π√(I/k)=0.942478 s
PASS [torsional_pendulum_period_k40] T=0.298036 s, 2π√(I/k)=0.298038 s
PASS [torsional_damper_decay_rate] decay 0.277784 1/s, c/2I=0.277778 1/s
PASS [pin_friction_slows_and_stops] ω(1 s)=4.444260 rad/s (4.444445), ω(2.5 s)=0.000000
PASS [pin_friction_holds_bar] turned 0.000000 rad
PASS [pin_friction_lets_bar_fall] turned 1.060743 rad
PASS [pin_limit_plastic_stop] angle 0.600000 rad (limit 0.6), ω 0.000000
PASS [pin_limit_holds_weight_moment] stop torque -4.048272 N·m (-4.048271)
PASS [pin_breaks_under_its_load] broken, reaction 19.619839 N, y 5.384116 m
PASS [pin_holds_below_break_force] holding, reaction 19.619839 N, y 0.500000 m
PASS [pin_extras_scene_file] round trip of the spring, friction, limits and break forces
PASS [pin_extras_scene_file_metres] round trip of the spring, friction, limits and break forces
PASS [torsion_pendulum_energy_articulated] worst energy change 0.199645 % of -3.323500 J
PASS [fbd_atwood_cable_forces] T on m1 = 23.544067 N (2m1m2g/(m1+m2) = 23.544001), on the pulley 47.088135 N down
PASS [fbd_beam_pin_reactions] R_left 65.399452 N (65.400002), R_right 81.749321 N (81.750008), sum 147.148773 of 147.150009
PASS [fbd_block_on_incline] N 26.672640 N (mg cos θ 26.672638), F 12.437658 N (mg sin θ 12.437655)What the accuracy claim covers
Research results are checked for circles, boxes and polygons (rounded too); distance, spring, pin, slider and weld joints with their motors, limits and torsional springs; grounds and walls at any angle; static, kinetic and rolling friction; ideal cables over pulleys and drums, with or without mass along them; gears, racks, ring gears, planetary sets and belts; applied forces and motion as functions of time; air resistance; gravitation between bodies.
Approximations, labelled as such in the studio:
- The Rope is a chain of small rigid links with mass: it sags, swings and drapes realistically, but its tensions are a model. Use the Cable for exact tensions; a cable with mass carries its weight along its length but does not sag sideways.
- Air resistance from the shape uses a drag coefficient (adjustable); the k v² and b v models are exact.
- Very large mass ratios resting on each other through contacts alone (no joints) settle by a fraction of a millimetre; joints between such bodies are solved exactly.
- Liquids are still pools: buoyancy (ρ g V of the part under, at its centre) is exact for that model; the liquid does not flow or make waves, and the Wave damping that calms floating bodies is a model.
- The Magnus lift uses C_L = k × the spin ratio (at most 0.6) and a ball's spin drag a skin-friction coefficient: both adjustable models; a polygon's spin drag comes from the pressure on its faces.
Reproduce it
The tests are in the source: PhysicsEngineCore/Codes/regression_tests.cpp.
cmake -S PhysicsEngineCore -B build && cmake --build build --target PhysicsEngineTests
./build/PhysicsEngineTests
Each line PASS [name] … gives the measured and the expected values; the table above shows them for the benchmarks a reader is most likely to check.