Bend limbs along a single axis with a Bézier spine
- core: Bezier (any degree, De Casteljau), LimbBend (cubic spine through the rigid upper/joint/lower shape, one ring per texture row spaced by arc length, rigid rings so pieces share vertices) and QuadSplitter (cuts faces at the rings, interpolating UVs). - fabric: ModelPartMixin draws parts that have a bend with BentCubeRenderer, which deforms vanilla's own cubes. Overlays and armor use the limb's spine so they stay attached. Bends are reset every setupAnim because models are shared between entities. - testmod: flap and squat animations, and a client gametest that screenshots each animation from the front and side (runClientGameTest). The tester runs with the full Fabric API because single modules don't bring their version-specific dependencies. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -10,7 +10,9 @@ A player emote library for Saturn Client, with limb bending.
|
||||
version with [Stonecutter](https://stonecutter.kikugie.dev/) and published as
|
||||
`org.saturnclient:emotes-fabric:<version>+<mc>`, with `core` bundled inside the jar.
|
||||
- `src/testmod/`: a dev-only tester mod that is never published. It adds `/emotes play <name>`,
|
||||
`/emotes stop` and `/emotes info`. Press F5 to see yourself.
|
||||
`/emotes stop` and `/emotes info`. Press F5 to see yourself. It also has a Fabric client gametest
|
||||
that creates a world and screenshots each animation from the front and side, into
|
||||
`versions/<mc>/build/run/clientGameTest/screenshots/`.
|
||||
|
||||
Supported versions: 1.21.4 to 1.21.11, the same range as Saturn Client. Each version's Fabric API
|
||||
version is set in `stonecutter.properties.toml`. The code uses Mojang mappings.
|
||||
@@ -22,22 +24,41 @@ version is set in `stonecutter.properties.toml`. The code uses Mojang mappings.
|
||||
and the armor layers both go through this method, so armor follows the pose.
|
||||
|
||||
Both hook points exist unchanged in every supported version. Version-specific code goes behind
|
||||
Stonecutter comments:
|
||||
Stonecutter comments, like the vertex accessors in `BentCubeRenderer`:
|
||||
|
||||
```java
|
||||
//? if >=1.21.9 {
|
||||
import net.minecraft.client.renderer.entity.state.AvatarRenderState;
|
||||
return new float[] { vertex.x(), vertex.y(), vertex.z(), vertex.u(), vertex.v() };
|
||||
//?} else
|
||||
/*import net.minecraft.client.renderer.entity.state.PlayerRenderState;*/
|
||||
/*return new float[] { vertex.pos().x(), vertex.pos().y(), vertex.pos().z(), vertex.u(), vertex.v() };*/
|
||||
```
|
||||
|
||||
Bending (`BoneTransform.bend` / `bendAxis`) is part of the model but isn't rendered yet.
|
||||
## Bending
|
||||
|
||||
Each limb bends along a single axis (`BoneTransform.bend`, `bendAxis`). It works like the cloak
|
||||
renderer: build a spine, put a ring of shared vertices along it, and draw the faces between the rings.
|
||||
|
||||
- `LimbBend` (core) runs the spine along a cubic Bézier (`Bezier`). The control points are the rigid
|
||||
"upper half, joint, lower half" shape, and `sharpness` goes from a round curve (0) to a tight joint
|
||||
(1). The spine is cut into one ring per texture row (12 per limb), spaced evenly by arc length, so
|
||||
the limb keeps its length. Each ring moves its cross-section rigidly, so neighbouring pieces share
|
||||
vertices and the mesh stays closed.
|
||||
- `QuadSplitter` (core) cuts each vanilla face into strips at the rings and splits its UVs to match.
|
||||
The texture is unchanged apart from the cuts.
|
||||
- `ModelPartMixin` swaps in `BentCubeRenderer` for any part with a bend. That renderer deforms
|
||||
vanilla's own cubes, so slim arms, sleeves, pants and armor all work. Overlays and armor use the
|
||||
limb's spine, not their own inflated box, so they stay attached.
|
||||
|
||||
Axis 0 folds towards the front (-Z) and PI/2 towards +X, in the limb's own space. Knees fold back,
|
||||
so they use axis PI. The body bends too, but the head and arms don't follow its upper half yet.
|
||||
Held items still attach to the unbent arm.
|
||||
|
||||
## Commands
|
||||
|
||||
```sh
|
||||
./gradlew :core:test # core unit tests
|
||||
./gradlew :1.21.11:runTestmodClient # launch the game with the tester (run dir: ./run)
|
||||
./gradlew :1.21.11:runClientGameTest # screenshot each test animation, then quit
|
||||
./gradlew :1.21.4:compileTestmodJava # quick compile check for one version
|
||||
./gradlew buildAll # every version's jar → build/libs/<version>/
|
||||
GITEA_TOKEN=... ./gradlew publish # publish core + every version to Gitea
|
||||
|
||||
Reference in New Issue
Block a user