Implement ragdoll rendering via GPU skinning #52

Open
kit wants to merge 2 commits from feature/29-ragdoll-rendering into dev
Owner

Summary

  • Server streams per-bone world-space transforms (position + quaternion) for prop_ragdoll entities in the snapshot protocol
  • Client model loader creates SkinnedMesh + Skeleton with GPU skinning via a custom vertex shader (#ifdef USE_SKINNING)
  • Scene manager applies streamed bone data each frame, converting Source→Three.js coordinates and computing entity-relative skin matrices
  • Non-ragdoll entities are unaffected — GPU skinning is identity at rest pose

Files changed

Layer File Changes
C++ snapshot.h/cpp BoneTransform struct, variable-length entity serialization
C++ main.cpp ClearBones/SetEntityBones Lua API, bone copy in capture_snapshot
Lua sv_webstream.lua WebStream_BoneCollect Think hook — extracts bone matrices via GetField()
JS protocol.js Variable-length entity parsing with boneCount + bone data
JS loader.js SkinnedMesh, Skeleton, sourceMatrixToThree(), skin attributes from VVD
JS material.js Vertex shader skinning behind USE_SKINNING define
JS scene.js _updateEntityBones, lazy independent skeleton creation, cleanup

Test plan

  • Non-ragdoll entities render correctly (no visual change)
  • Ragdoll poses match in-game after bone data arrives
  • Move/drop a ragdoll in-game, verify web client updates in real-time
  • Check performance with multiple ragdolls

Closes #29

## Summary - Server streams per-bone world-space transforms (position + quaternion) for `prop_ragdoll` entities in the snapshot protocol - Client model loader creates `SkinnedMesh` + `Skeleton` with GPU skinning via a custom vertex shader (`#ifdef USE_SKINNING`) - Scene manager applies streamed bone data each frame, converting Source→Three.js coordinates and computing entity-relative skin matrices - Non-ragdoll entities are unaffected — GPU skinning is identity at rest pose ## Files changed | Layer | File | Changes | |-------|------|---------| | C++ | `snapshot.h/cpp` | `BoneTransform` struct, variable-length entity serialization | | C++ | `main.cpp` | `ClearBones`/`SetEntityBones` Lua API, bone copy in `capture_snapshot` | | Lua | `sv_webstream.lua` | `WebStream_BoneCollect` Think hook — extracts bone matrices via `GetField()` | | JS | `protocol.js` | Variable-length entity parsing with `boneCount` + bone data | | JS | `loader.js` | `SkinnedMesh`, `Skeleton`, `sourceMatrixToThree()`, skin attributes from VVD | | JS | `material.js` | Vertex shader skinning behind `USE_SKINNING` define | | JS | `scene.js` | `_updateEntityBones`, lazy independent skeleton creation, cleanup | ## Test plan - [x] Non-ragdoll entities render correctly (no visual change) - [x] Ragdoll poses match in-game after bone data arrives - [ ] Move/drop a ragdoll in-game, verify web client updates in real-time - [ ] Check performance with multiple ragdolls Closes #29
Server collects per-bone world-space transforms from prop_ragdoll entities
each frame via GetBoneMatrix(), extracts position + quaternion, and streams
them in the entity snapshot protocol. Client model loader creates
SkinnedMesh + Skeleton with rest-pose bone inverses, and the scene manager
applies streamed bone data by computing skin matrices (boneWorld * posToBone),
converting from Source to Three.js coordinates, and updating skeleton bones
relative to the mesh's world matrix.

Closes #29

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three.js computes bounding spheres differently for SkinnedMesh,
which causes incorrect culling with our rest-pose bone setup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feature/29-ragdoll-rendering:feature/29-ragdoll-rendering
git switch feature/29-ragdoll-rendering

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch dev
git merge --no-ff feature/29-ragdoll-rendering
git switch feature/29-ragdoll-rendering
git rebase dev
git switch dev
git merge --ff-only feature/29-ragdoll-rendering
git switch feature/29-ragdoll-rendering
git rebase dev
git switch dev
git merge --no-ff feature/29-ragdoll-rendering
git switch dev
git merge --squash feature/29-ragdoll-rendering
git switch dev
git merge --ff-only feature/29-ragdoll-rendering
git switch dev
git merge feature/29-ragdoll-rendering
git push origin dev
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kit/gmod-web-stream!52
No description provided.