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.