Physics system - #3
Open
sstarosz wants to merge 18 commits into
Open
Conversation
- Phase 3: remove guide transforms and write-back constraints; node writes solved joint-local poses directly into joints, deriving parent inverse from parent body's Bullet transform - Phase 4: hash config inputs (FNV-1a); rebuild Bullet world in-place when bodies/joints/gravity/fps change, keeping chains glued to current skeleton pose - Kinematic anchors now feed from joints' world matrices with baked body<->bone offsets - Rewrite physics discovery to trace node connections instead of guide transforms - Skeleton reset rewinds solver by toggling fps to force config rebuild - Update behavioral tests to swing root bone and verify cycle fix, no rewind teleport, and config edits take effect - Import speedup: scalar body children via OpenMaya plug API, joints still on cmds.setAttr - Add btTransformToRowMatrix and rowMatrixMultiply helpers with unit tests - Update docs/changelog for Phase 3/4 changes
…es and derive kinematic from physics mode
…im collision masks
- Extract Bullet engine, math, and shared value types into mmd/core static library - Decouple physics_node as a Maya adapter over mmd::core::Simulation - Rename mmdPhysicsNode -> pmxPhysicsNode (node, commands, files, docs, tests) - Move physics_node and rigid body commands under pmx prefix to match PMX naming - Add unit tests for math and simulation engine (Maya-free) - Add integration tests for pmxRigidBody / pmxRigidBodyConstraint commands - Document the core/adaptor split and the new node name across all docs
sstarosz
added a commit
that referenced
this pull request
Aug 9, 2026
- cmake/FindMaya.cmake: prefer the cached SDK matching MAYA_VERSION before scanning the other cached SDKs (newest-first) as a fallback, so a Maya-2027 build never resolves the 2026 SDK just because it was cached earlier. - CMakePresets.json: drop the unused ci preset (configure + build) and the redundant BUILD_NATIVE_MODULE=ON override (the option already defaults to ON), and add explicit Debug/Release configuration to the build presets. - docs/CPPDevelopment.md: replace the removed ci-preset instructions with the maya2026-release -DBUILD_TESTS=ON flow. - CHANGELOG.md: note the SDK-resolution fix and the preset cleanup. Extracted from feature/physics-system (PR #3) so the build-system fixes can be reviewed independently of the physics feature.
sstarosz
added a commit
that referenced
this pull request
Aug 9, 2026
- vcpkg.json: add Bullet 3.25 (float precision) as the first C/C++ dependency. - CMakeLists.txt: fail with clear instructions when no CMake toolchain is configured, then resolve Bullet via find_package(Bullet CONFIG REQUIRED). - CMakePresets.json: add the hidden with-vcpkg preset that activates the vcpkg toolchain from \, and make all maya* presets inherit it. - .github/workflows: set up vcpkg (lukka/run-vcpkg) in pr-checks and release. - .gitignore: ignore third_party/ and vcpkg_installed/. - docs/CPPDevelopment.md: document vcpkg setup + troubleshooting. - README.md: list vcpkg as a prerequisite and note auto-install of deps. - CHANGELOG.md: note vcpkg dependency management under [Unreleased]. - tests/CMakeLists.txt: drop the stale 'Re-enable the CI preset (ci)' comment (the ci preset was removed in PR #4). Part of the feature/physics-system (PR #3) split — stacked on PR #4 (fix/cmake-build-fixes).
sstarosz
added a commit
that referenced
this pull request
Aug 9, 2026
- vcpkg.json: add Bullet 3.25 (float precision) as the first C/C++ dependency. - CMakeLists.txt: fail with clear instructions when no CMake toolchain is configured, then resolve Bullet via find_package(Bullet CONFIG REQUIRED). - CMakePresets.json: add the hidden with-vcpkg preset that activates the vcpkg toolchain from \, and make all maya* presets inherit it. - .github/workflows: set up vcpkg (lukka/run-vcpkg) in pr-checks and release. - .gitignore: ignore third_party/ and vcpkg_installed/. - docs/CPPDevelopment.md: document vcpkg setup + troubleshooting. - README.md: list vcpkg as a prerequisite and note auto-install of deps. - CHANGELOG.md: note vcpkg dependency management under [Unreleased]. - tests/CMakeLists.txt: drop the stale 'Re-enable the CI preset (ci)' comment (the ci preset was removed in PR #4). Part of the feature/physics-system (PR #3) split — stacked on PR #4 (fix/cmake-build-fixes).
sstarosz
added a commit
that referenced
this pull request
Aug 10, 2026
* Cmd: add native pmxRigidBody command (create mode, data + kinematic anchors) Native C++ pmxRigidBody command — the single body-modification path for pmxPhysicsNode. Create mode only, SIMULATION IS DISABLED: writes the full body DATA (PMX shape_size verbatim into bodyShapeSize, group/mask, physics mode via the core Simulation::PhysicsMode enum) and binds FOLLOW_BONE bodies to their related joint through the kinematic-anchor input. Dynamic bodies are data-only (no write-back, no stepping) — edit/query/remove and the rigid-body-constraint command are later PRs. Adapted from the PR #3 draft to the merged node schema: - bodyShapeSize (single float3) instead of bodyRadius/bodyExtents/bodyLength - core Simulation::PhysicsMode (no node-side enum) - single groupInverseWorldMatrix instead of per-anchor anchorParentInverseMatrix Registration in MayaMMD.cpp + CMake source list + integration tests wired into the 'cmd' suite (11 new tests). * Cmd: apply clang-format reflow to rigid_body_cmd.cpp * Cmd: refactor pmxRigidBody to pure interface + populate bodies at import Design cleanup of the pmxRigidBody command (per review): - Rename rigid_body_cmd.h -> rigid_body_cmd.hpp and make it a PURE interface: all private static helpers (resolveSolver, doCreate, matrixFromTR, worldMatrix, connectOrReplace, jointPmxBoneIndex, resolveBone) moved into the .cpp's anonymous namespace. The header now exposes only kName/creator/syntaxCreator/doIt/isUndoable. - Add shared plug utilities to maya_utils.hpp (setPlugMatrixValue, setPlugDouble3, connectOrReplace) so the constraint command reuses them in the next PR instead of duplicating. - const/constexpr pass: use physics_math deg2rad/rad2deg (constexpr), constexpr clamp01, const locals, 3-arg findPlug (non-deprecated). - Bring back rigid-body population in rigid_body_builder.py: every PMX rigid body is now added to the node via pmxRigidBody at import (data + kinematic anchors for FOLLOW_BONE). Simulation still disabled (no joints/write-back/time). Dict lookups keyed by enum VALUE so a duplicate enum class (mayapy double-load of mmd.core) cannot break the mapping. - Import test now asserts bodies mirror the PMX rigid bodies (count + first body data). - Expand cmd integration tests: write-back K offset baked, wiring-field defaults, per-collider shape_size verbatim, MMD->Maya rest-pose conversion, kinematic anchor ordering with multiple bodies. Verified: node/cmd/import suites pass, C++ unit tests 31/31, clang-tidy clean, ruff/clang-format clean. * style: format cmd suite registration in TEST_SUITES * Fix: reload rigid_body_builder in plugin init so bodies appear after plugin reload mmd.maya.pmx.rigid_body_builder was missing from plugin.py's _MMD_MODULES reload list. In a live Maya session the module stays cached in sys.modules with the OLD (empty-node) create_physics_from_pmx_data, so recompiling the .mll and reloading the plugin kept importing the stale builder and bodies never appeared on the node. Add it to the list, BEFORE pmx_scene_builder (which imports create_physics_from_pmx_data from it) so the fresh module is picked up when pmx_scene_builder is reloaded. * Review: make connectOrReplace truly idempotent + add 4 more cmd tests - connectOrReplace now returns early when dst is already driven by the SAME source, instead of queuing a duplicate connect that fails. This makes the repeated groupInverseWorldMatrix re-connect (one per kinematic body create) a real no-op instead of a swallowed kFailure. - Add cmd integration tests: numeric -bone <pmxBoneIdx> resolution, query/edit rejection, invalid-target rejection, missing-solver-argument rejection. * Review: fix anchor offset group-scale round-trip, clamp -group to 0..15 - rigid_body_cmd.cpp: anchor offsets (joint-anchored AND static-collider) now build the world matrix directly from world-space T/R via matrixFromTR(worldT, worldR) instead of the group-space round-trip matrixFromTR(localT, localR) * groupWorld, which dropped scale from the offset (the exact bug the K-offset write-back comment documents). - rigid_body_cmd.cpp: clamp -group to the PMX 0..15 range with plain ifs (replaces a nested ternary that tripped clang-tidy). - rigid_body_cmd.hpp: document -group range in the header. - test_pmx_rigid_body_cmd_integration.py: add test_group_clamped (-group=-5 -> 0, -group=99 -> 15); format. * Docs: add pmxRigidBody command entries to CHANGELOG
sstarosz
added a commit
that referenced
this pull request
Aug 11, 2026
* Sim: wire the physics simulation (time-driven + Phase-3 write-back) Makes the imported pmxPhysicsNode simulation actually RUN — ported from the PR #3 draft's wiring and adapted to the current builder: - _create_physics_solver: connect time1.outTime -> node.time (the node declares itself non-cacheable, so the evaluation manager steps the Bullet world every frame; an empty world is a valid no-op). - _wire_dynamic_write_back (called after every body and joint exists): * group.worldMatrix[0] -> groupWorldMatrix (DG-fallback write-back); * bodies[i].bodyParentBodyIndex = the parent bone's rigid body, so the node derives M_parent = K[parentBodyIndex] from the parent BODY's solved transform (no DG feedback cycle); * joint.parentInverseMatrix -> bodyParentInverseMatrix DG fallback ONLY when the parent bone has no rigid body; * bodies[i].bodyResetAnchorIndex = nearest kinematic ancestor (scrub-back rewind); * outTranslate/outRotate -> joint.translate/rotate LAST (PHYSICS_BONE is rotation-only). Maya auto-inserts the standard unitConversion between the float3 outputs and the joint angle attrs. - _compute_reset_anchor_map, step_physics, write_back_physics helpers. - Physics-mode comparisons keyed by .value (duplicate-enum safe). Tests (import suite, real model): - Physics Wiring: time + groupWorldMatrix connected; 285 dynamic joints driven (262 with translate); 281 parent-body refs; 4 DG fallbacks; 285 reset anchors; no DG parentInverse when the parent has a body. - Simulation Steps: BEHAVIOURAL — 248/285 dynamic joints move when the root bone swings (sim is alive). - Write-back Moves Bone: BEHAVIOURAL — the solver drives a skirt joint ~40 deg in 30 frames (mesh-binding signal). - 11 passed (8 prior + 3 new); cmd + node suites green. * Review: unit-typed write-back outputs (no unitConversion), enable caching, drop unused helper Addresses review feedback on PR #10: 1. UNIT-TYPED OUTPUTS — the pmxPhysicsNode outTranslate/outRotate children were unitless k3Double, so connecting them to joint.translate/rotate forced Maya to auto-insert a unitConversion per body. The children are now MFnUnitAttribute kDistance (outTranslateX/Y/Z) / kAngle (outRotateX/Y/Z), exactly like transform.translate/rotate, and the builder connects the compounds DIRECTLY — no conversion nodes. Values are identical (verified behaviourally: dR=40.684 both before and after). Angles are written in degrees explicitly: MAngle's default constructor unit is RADIANS, which silently inflated every angle by 180/pi (caught by the write-back test: dR 2331 vs 40.7). 2. CACHING — the explicit setAttr(node.caching, 0) is gone: the node's getCacheSetup() already declares the STATEFUL solver non-cacheable via setUnsafeNode (caching its outputs would freeze the sim — the mayaBullet bug this node was built to fix), so the attribute stays at its default. 3. write_back_physics removed (unused); step_physics kept and now used by the import behavioural tests (replacing a local copy). Tests: wiring test now asserts each outTranslate/outRotate destination is the JOINT directly (never a unitConversion — the 84 unitConversions from the bone builder's IK controls are unrelated). cmd/import/node all green. * Refactor: drop anchorOffset + groupInverseWorldMatrix inputs (derive, don't store) Big simplification of the pmxPhysicsNode schema (breaking — re-import required). Two matrix inputs were redundant: 1. anchorOffset — the kinematic body<->joint rest offset (bodyRestWorld * jointRestWorld^-1) is the EXACT INVERSE of bodyWriteBackOffset (K = jointRestWorld * bodyRestWorld^-1), which is already baked per body for the write-back. The node now derives each kinematic anchor's offset as K[bodyIndex]^-1 (the anchor loop already knows the body index); identity for joint-less static colliders, exactly as before. 2. groupInverseWorldMatrix — the exact inverse of groupWorldMatrix (a single input the builder already connects for every model). The node derives the inverse internally. Removed: the two attributes + their registration/affects/signature entries, the pmxRigidBody command's anchorOffset writes and group-inverse connectOrReplace, and the node's anchorOffset/groupInverse reads. The command now only writes anchorWorldMatrix (joint world or pinned rest). Verified data-equivalent: 248/285 joints move, write-back dR=40.684 — identical before/after. cmd/import/node suites green; clang-tidy clean. * Refactor: drop bodyParentInverseMatrix DG fallback (derive parent, don't store) * Refactor: drop configVersion hashing (compare definitions, don't hash bytes) * Refactor: run the Bullet world in world space (drop the groupWorldMatrix input) * Refactor: evaluate the write-back chain directly on btTransforms (drop the MMatrix round-trip) * Refactor: drop legacy rigid-body visual-guide path (obsolete since native solver) * Docs: mark rigid body/joint simulation as implemented, drop legacy "not supported" validation entries * Refactor: store bodyParentBodyIndex as long, read as int (drop short truncation) * Style: wrap long print statement for consistent formatting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.