Files
VR-Mess/research/godot-box3d-6dof.md
T
FoxyzandClaude Opus 5.5 3a990c6dbe Body rebuild step 0: Generic6DOFJoint3D on Box3D (fork patch 2) — ball w/ cone/twist + torque-capped muscle motor, weld, drive
- addons/godot-box3d/bin/libgodot-box3d.so rebuilt from fork branch generic-6dof-joint
  (weld patch + 6DOF); .vendor/box3d-generic-6dof.patch exported
- SixDofSpike: type, ball pivot/swing, cone+twist limits, muscle holds 2.94 N·m lever at 10 N·m
  cap and fails at 1.5, tracks moving target, drive follows + push-off reaction, weld rigid,
  live flag toggles — PASS x3; all existing spikes PASS x3 on the new binary
- research/godot-box3d-6dof.md (mapping, units, C# muscle recipe); HANDOFF/AGENTS pointers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 05:10:45 +03:00

49 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Addon patch 2: Generic6DOFJoint3D on Box3D (2026-10-02)
Second local patch to the godot-box3d fork (after the ConeTwist→weld patch, `godot-box3d-weld.md`). Purpose:
the joint primitives for the Project-TX-style muscle ragdoll (`nimso-project-tx.md`, `vr-physics-rig-hexabody.md` §4).
- Fork branch `generic-6dof-joint` (on top of `rigid-weld-joint`) in `.vendor/godot-box3d`, commit "Expose Box3D
joints through Godot's Generic6DOFJoint3D"; patch file `.vendor/box3d-generic-6dof.patch`. NOT pushed to
`github.com/Foxyz1302/godot-box3d` yet (owner decision). Linux binary only (same rebuild recipe as the weld
patch: `cmake --build build --parallel 12` in `.vendor/godot-box3d`, copy `bin/libgodot-box3d.so` to
`addons/godot-box3d/bin/`; stock binaries stay in `addons/godot-box3d/bin-stock/`).
- Files: `src/joints/box3d_generic_6dof_joint_impl_3d.{hpp,cpp}` (new), `src/servers/box3d_physics_server_3d.cpp`
(`_joint_make_generic_6dof` + param/flag get/set dispatch; was a hard error).
## Mapping (configuration-based — Box3D has no general 6-DOF constraint)
| Godot configuration | Box3D joint | Notes |
|---|---|---|
| all 3 linear axes locked (limit on, lower ≥ upper, no linear spring/motor), angular not fully locked or angular motor/spring on | `b3SphericalJoint` = **BALL** | joint **X = twist axis** (angular X limits = twist range); swing cone symmetric, half-angle = largest \|limit\| of angular Y/Z (warned if Y/Z differ); angular spring → rotation spring to the angular equilibrium (Euler, Godot default YXZ); angular **motor = torque-capped velocity motor** |
| everything locked, no angular motor/spring (the Godot default) | `b3WeldJoint` = **WELD** | rigid at the creation pose |
| any linear axis free/springy/motored | `b3MotorJoint` = **DRIVE** | springs pull frame B onto frame A shifted by the equilibrium points (linear + Euler); force/torque caps = Linear/Angular **MotorForceLimit** (0 = uncapped); motor target velocities add a velocity drive; linear limits NOT enforced (warned) |
- **Units differ from Godot/Jolt**: spring STIFFNESS = frequency in **Hz**, DAMPING = **damping ratio** (Box3D
soft constraints are mass-independent). Choose ~5–15 Hz, ratio ~1.
- Motor target velocities are per joint axis in **joint frame A**; the impl converts to Box3D's world-space relative
angular/linear velocity at set time using body A's current rotation → set them EVERY TICK (they are a PD output).
- Flags and limits **rebuild** the Box3D joint (warm start lost — set them once); motor velocities, force limits,
springs and equilibrium points apply **live**. Configure before `AddChild` (as with every joint here).
- Bullet-era params (limit softness/restitution/damping, ERP, angular force limit) are ignored.
## Muscle recipe (C#, used by `scripts/SixDofSpike.cs`)
```csharp
// BALL joint: angular limits as the anatomical range, EnableMotor on X/Y/Z, AngularMotorForceLimit = strength (N·m)
Quaternion rel = frameAWorld.Inverse() * frameBWorld; // current joint rotation, frame-A coordinates
Vector3 err = BodyMath.RotationError(targetRel, rel); // axis*angle in frame-A coordinates
Vector3 w = (err * Kp).LimitLength(maxSpin); // PD velocity
joint.SetParamX(Generic6DofJoint3D.Param.AngularMotorTargetVelocity, w.X); // …Y, …Z
```
The solver applies at most `AngularMotorForceLimit` torque per step — strength is a real cap, leverage emerges.
## Proof — `scenes/sixdof_spike.tscn` ("6DOF: overall PASS", 3× identical)
server type `Type6Dof`; BALL pivot holds (≤ 0.7 mm) while swinging 100°; cone 30° / twist 10° hold under hard torque
(31.3° / 11.6° peak — Box3D soft-limit overshoot); muscle PD holds a 1 kg × 0.6 m lever (2.94 N·m gravity load)
horizontal with a 10 N·m cap (0.0°) and FAILS with 1.5 N·m (drops 107°); tracks a 60° raise to 0.0°; DRIVE follows a
moving target to 0.000 m; a hand driven into a wall never penetrates it and pushes the 10 kg anchor body AWAY
(−0.82 m — push-off reaction; pulling toward a fixed point is the climbing case); all-locked = rigid (0.13°); 90
live flag toggles stay finite. All existing spikes (weld, physics, grab, body, collapse, arm) PASS 3× on the new binary.