ifire's picture
Initial mirror of localai-org/motion-bricks.cpp@6fdb75e
d456972 verified
|
Raw
History Blame Contribute Delete
5.37 kB

Go and Three.js demo

The initial demo is a local Go application that calls libmotionbricks through the PureGo binding and serves an embedded Three.js viewer. It renders the released 34-joint G1 hierarchy directly from MotionBricks root translations and local XYZW joint rotations; it does not require MuJoCo or a skinned mesh. Solid cyan cylinders and round joints identify the generated character. An orange diamond-jointed ghost skeleton identifies a selected placed style-pose constraint supplied to the planner; all four constraints can be overlaid for inspection.

Build and run

First build the native project and create the model/style assets described in the main README. Then build the Go application:

cmake --build --preset debug
cd demo
CGO_ENABLED=0 go build -o ../build/debug/bin/motionbricks-demo .
cd ..

The demo and reusable Go binding call the native shared library through PureGo. They contain no cgo bridge and do not require a C compiler during the Go build, so cgo can be disabled. This does not remove the separate C++/CMake build that produces libmotionbricks.

Run it from the repository root:

./build/debug/bin/motionbricks-demo \
  -listen 127.0.0.1:8080 \
  -library ./build/debug/libmotionbricks.so \
  -model ./generated/g1-f32 \
  -styles ./generated/styles \
  -device cpu

Open http://127.0.0.1:8080/. Hold physical W/A/S/D keys to move, or tap an on-screen direction to latch it; tap the active pad direction again to stop. Space or Escape also stops movement. Left/right arrow keys rotate the facing direction without changing the current travel vector. The selector switches among all .mbstyle files found in the style directory, including the 15 converted upstream styles. Drag over the viewport to orbit, use the wheel to zoom, and use Reset camera to restore the automatically framed view. The camera follows only the animated skeleton, so target placement never pulls the view away from the character. The T0–T3 slider selects one fully visible target pose. Overlay all four consecutive poses reveals the complete constraint window. These are adjacent 30 FPS constraint frames rather than four distant waypoints, so their exact world positions are intentionally close together.

-device accepts cpu, vulkan, or auto. The server deliberately binds to localhost by default. Model inference is serialized while sessions keep independent agent/context state.

Runtime shape

The browser creates a session, receives a 30 FPS animation chunk, and asks for a replacement chunk when controls change or playback approaches the end. Each request contains movement, facing, style, seed, and the number of frames already consumed. The Go server advances that session's native agent and returns owned animation data and target constraints as JSON:

  • root translations: [frames, 3];
  • local joint rotations: [frames, 34, 4], XYZW;
  • placed target roots: [4, 3];
  • placed target local rotations: [4, 34, 4], XYZW;
  • G1 joint names, parent indices, and neutral positions from the loaded model.

The native target data is captured after style-frame sampling, spring-based world placement, and heading correction. The ghosts therefore visualize the actual planner inputs. The viewer does not force them in front: forward travel normally places them ahead, while stops and turns can make them overlap the character or move sideways.

The browser builds THREE.Bone objects from the returned hierarchy and draws solid cylinders/spheres for the generated skeleton and translucent cylinders/diamonds for target poses. It also draws generated and target root paths on the floor. Animation chunks are immutable in JavaScript; a later version can replace JSON with a binary streaming protocol without changing the native API.

Three.js r180 is vendored under demo/web/vendor so the demo has no runtime CDN dependency.

Tests

With the generated assets present, CTest registers motionbricks-go-demo when Go and Chromium are available. The test starts an in-process HTTP server, loads the real native model, plans an initial walk chunk, then uses headless Chromium to select walk_zombie, turn right, plan another chunk, render the 34-joint generated hierarchy plus the target inspector, and capture initial, forward-motion, and style-and-turn screenshots. It uses real Chrome click and keyboard events and asserts forward-pad movement, pad stop, keyboard movement, keyboard stop, animated-skeleton camera anchoring, individual target selection, and the four-pose overlay before the visual self-test.

The Go tests can also be run directly:

cd demo
MOTIONBRICKS_LIB=../build/debug/libmotionbricks.so \
MOTIONBRICKS_MODEL=../generated/g1-f32 \
MOTIONBRICKS_STYLES=../generated/styles \
MOTIONBRICKS_CHROME="$(command -v chromium)" \
CGO_ENABLED=0 go test -v ./...

Without the native asset environment variables, the parser test still runs and the native/browser integration cases are skipped.

Initial limitations

  • G1 is the only skeleton supported by the released model.
  • The viewer intentionally shows a bone skeleton, not a skinned avatar.
  • HTTP JSON carries whole planned chunks; binary streaming and client-side overlap blending are future work.
  • Sessions are in-memory and intended for a trusted local demo, not an internet-facing multi-user service.