Files
VR-Mess/research/vr-body-physics-godot.md
T

70 lines
4.7 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.
# Research: body physics on Godot 4.7 + Box3D — verified capabilities
Companion to `vr-body-physics-hugs.md` (prior art + recommendation). This file grounds that
recommendation in what the LOCAL stack actually supports. Everything [S] was verified by the
orchestrator directly against `.vendor/godot-box3d/` source and the pinned docs at
`/home/foxyz/Projects/Games/.shared/godot-docs-4.7/`. Researched 2026-10-01.
## 1. Joint inventory on Box3D (v0.2.6, verified in source)
- [S] Implemented joint types (`src/joints/`, dispatch in
`src/servers/box3d_physics_server_3d.cpp`): **pin** (`_joint_make_pin`, line 942),
**hinge** (`_joint_make_hinge`, line 1003), **slider** (line 1068), **cone-twist**
(line 1100 — LOCALLY PATCHED to b3WeldJoint, see `godot-box3d-weld.md`).
- [S] **Generic6DOFJoint3D is NOT supported** — `_joint_make_generic_6dof` (line 1126) is a
hard `ERR_FAIL_MSG("Box3D: Generic6DOFJoint3D is not supported; use PinJoint3D, HingeJoint3D,
or SliderJoint3D instead.")`. Any design must not rely on 6DOF drives.
- [S] **Hinge motors WORK** (`src/joints/box3d_hinge_joint_impl_3d.cpp`): `HINGE_JOINT_FLAG_ENABLE_MOTOR`
→ `b3RevoluteJoint_EnableMotor`; params `HINGE_JOINT_MOTOR_TARGET_VELOCITY` +
`HINGE_JOINT_MOTOR_MAX_IMPULSE` → `b3RevoluteJoint_SetMotorSpeed/SetMaxMotorTorque` (lines 22–24,
128–131). It is a VELOCITY motor with a torque clamp — position control = per-tick PD:
`targetVelocity = (targetAngle − angle) × gain`, clamped, with `maxImpulse` as the force budget.
This is the Box3D primitive for active-ragdoll limb drives (phase 2 of the hugs design).
- [S] Body modes exist (`_body_set_mode`, line 448); constant forces/torques work
(`_body_add_constant_torque` line 749) — already proven in production by PhysicsHands'
90 N chase (RigidBody3D, mass 0.4, gravity off, CCD, `ApplyTorque` verified earlier).
## 2. Godot 4.7 skeleton/modifier APIs (pinned docs, `classes/*.rst`)
- [S] Available and current: `SkeletonModifier3D` (base, `_process_modification_with_delta`),
`IKModifier3D`, `LookAtModifier3D`, `CopyTransformModifier3D`, `ConvertTransformModifier3D`,
`ModifierBoneTarget3D`, `LimitAngularVelocityModifier3D`, `RetargetModifier3D`,
`BoneAttachment3D`, `PhysicalBone3D` + `PhysicalBoneSimulator3D`, `SkeletonProfileHumanoid`.
- [S] `SkeletonIK3D` remains deprecated (known trap, HANDOFF §2). `XRBodyModifier3D` and
`XRFaceModifier3D` exist (OpenXR body/face tracking — future spike material).
- [I] For the placeholder rig (no Skeleton3D), none of these apply yet — the plan keeps the
procedural `BodyRig` boxes and adds physics BODIES that the boxes follow (CopyTransform-style
reads in `_Process`), then re-home the same chase bodies onto a real skeleton later via
`BoneAttachment3D`/`SkeletonModifier3D`. Migration path stays intact.
## 3. Drive patterns that work on this stack
- [S] **PD-driven rigid follow is PROVEN on Box3D at 90 Hz** — PhysicsHands is exactly that
(desired velocity `(target−pos)/dt`, force-clamped to 90 N). A heavier torso body is the same
pattern with a larger mass and larger budget; the 0.4 kg hands' stability across grab v5's
saga is the empirical evidence the pattern holds.
- [S] Kinematic drive + physical reaction alternative: `AnimatableBody3D` pushes dynamics in
Godot; but a kinematic chest is INFINITE mass — it would shove NPC bodies without ever being
resisted, breaking the mutual-force requirement from `vr-body-physics-hugs.md` §4. [I] Rejected
for the chest; fine for the WorldPanel.
- [I] No built-in "spring to target pose" body/joint in Godot or Box3D — confirmed absence;
every drive is hand-rolled PD (hands already do it; hinge motor is the solver-native version).
## 4. Collision strategy
- [S] Layers/masks live on `CollisionObject3D` (standing trap). Current use: 1 = world, 2 = UI;
hands layer 1/mask 1. Proposal: 3 = player body (torso + future arm segments), torso mask = 1|3
(world + itself-if-needed), hands mask 1|3 so palms can rest on the own chest; exclude
torso↔own-forearm pairs later via joint `ExcludeNodesFromCollision` equivalents — Box3D has no
pair-exclusion API [I, verify when needed]; simplest is disjoint masks per limb until proven
otherwise.
## 5. Recommendation for VR Messs
Follow `vr-body-physics-hugs.md` §5. Verifications add two facts to it:
- Phase 2 limb drives are buildable TODAY on the patched addon: hinge velocity motors + per-tick
PD toward the analytic IK angles (no Generic6DOF, no 6DOF drives — design accordingly).
- Phase 1 needs NO new addon work: torso = RigidBody3D chase-driven (hands pattern, bigger mass),
arms stay analytic IK, palms + torso give mutual contact. Sickness guard: camera stays
kinematic; torso chases the HMD, never welds to it; cap tug coupling below the chase budget.