← Hashito System Home 日本語 Tools Blog Posters
Load
Samples Save Save Save Save Save Save Save Save
ViewNothing loaded yet
Drop JSON or images here Add them in order: polygons → texture → skeleton → motion → camera.
The file type is detected from its contents. Drag to rotate, wheel to zoom.
0.00 / 0.00 s
Scene contents
Nothing loaded yet
After loading, the counts of vertices, faces, bones, tracks and camera keys appear here, along with any bone names that could not be matched.
Load a polygon JSON to begin. Files never leave this browser.
How to use: load a polygon JSON → add a texture image → add a skeleton JSON to create joints → add a motion JSON with per-bone angles over time → add a camera JSON for the shot → press “Export video”. A scene JSON bundles any number of characters, props and movement paths in one file. The type is detected from the contents, so any button works (vertices = polygons, bones = skeleton, tracks = motion, keys = camera, actors = scene). Files are never uploaded.

JSON format

Right-handed coordinates, Y up, units roughly metres (1.7 = 170 cm tall). Angles in degrees. Time t in seconds.

1. Polygons (vertices / faces)

{
  "name": "hero",
  "vertices": [[x, y, z], ...],
  "faces": [[0, 1, 2], [4, 5, 7, 6], ...],       // triangles or quads; indices counter-clockwise seen from outside
  "uvs": [[u, v], ...],                          // per-vertex UV (optional)
  "faceUvs": [[[u,v],[u,v],[u,v],[u,v]], ...],   // per-face UV (wins over uvs; for cutting regions out of one atlas)
  "color": [r, g, b],                            // 0-1, colour used when there is no texture (optional)
  "faceColors": [[r, g, b], ...],                // per-face colour (optional)
  "repeat": true,                                // repeat the image when UV exceeds 0-1 (floors, walls)
  "doubleSided": false
}

2. Skeleton (bones / weights)

{
  "bones": [
    {"name": "hips",  "parent": null,   "head": [0, 0.95, 0]},
    {"name": "spine", "parent": "hips", "head": [0, 1.10, 0]},
    ...
  ],
  "weights": [                     // in vertex order, up to 4 bones per vertex
    [["thigh_l", 1]],
    [["chest", 0.7], ["spine", 0.3]],
    {"head": 1},                   // object form also accepted
    ...
  ]                                // omit to bind each vertex to the 2 nearest bones automatically
}

3. Motion (tracks)

{
  "duration": 1.2, "loop": true, "ease": "smooth",     // ease is smooth or linear
  "tracks": {
    "thigh_l": [{"t": 0, "rot": [-32, 0, 0]}, {"t": 0.6, "rot": [32, 0, 0]}, {"t": 1.2, "rot": [-32, 0, 0]}],
    "hips":    [{"t": 0, "pos": [0, 0, 0]}, {"t": 0.3, "pos": [0, -0.03, 0]}, ...]   // pos offsets the bone position
  }
}

4. Camera (keys)

{
  "fov": 50, "size": [640, 480],                       // size is the exported video size
  "style": {"resolution": [320, 240], "nearest": true, "vertexSnap": true,
            "background": "#07080c", "fog": ["#07080c", 3, 9]},
  "keys": [
    {"t": 0, "pos": [2.2, 2.6, 3.0], "look": [0, 0.9, 0]},
    {"t": 4, "pos": [-2.6, 1.3, 2.6], "look": "head", "fov": 32}   // look may also name a bone or an actor
  ]
}

Scene (actors / props / camera)

{
  "world": {"background": "#07080c", "ambient": 0.55, "sun": [0.3, 1, 0.4], "fog": ["#07080c", 3.5, 10]},
  "camera": { ...same as 4... },
  "actors": [
    {"name": "hero", "model": {...1...}, "skeleton": {...2...}, "animation": {...3...},
     "texture": "data:image/png;base64,...",          // Data URL to embed; a file name means load the image separately
     "position": [0, 0, 0], "rotation": [0, 180, 0], "scale": 1,
     "path": [{"t": 0, "pos": [0, 0, 2.8], "rotY": 180}, {"t": 5, "pos": [0, 0, -3], "rotY": 180}]}   // movement path
  ],
  "props": [{"name": "floor", "model": {...1...}, "texture": "data:..."}],   // static objects without bones
  "duration": 5
}
To view or measure STL / OBJ / GLB shapes, try the 3D Model Viewer; to animate a single photo, try Movo Blocks. Our free study posters explain data and web concepts visually.

FAQ

What files do I need to get something moving?

The minimum is one polygon JSON: vertex coordinates plus faces (lists of vertex indices) are enough to display a model. To move joints, add a skeleton JSON (bone hierarchy, positions and per-vertex weights) and a motion JSON (per-bone angle keyframes). The camera JSON holds keyframes of position, look-at point and field of view; without it you orbit freely with the mouse. Textures are plain PNG or JPEG image files. A scene JSON that bundles all four lets you keep several characters and props in a single file.

What happens if I do not write vertex weights?

When the skeleton JSON has no weights, each vertex is bound automatically to the nearest bone (the segment from a bone to its children). The two nearest bones are blended by distance, so vertices near a joint are pulled a little by both. For box-built low-poly models this is usually enough; write weights when you need a joint to bend exactly as intended.

Can I get a PS1-style look (low resolution, jittering vertices)?

Yes. In the style block of the camera or scene JSON set resolution (the internal render size, e.g. 320x240), nearest (do not blur textures when scaled up) and vertexSnap (round vertex positions to the screen grid so they jitter like early 3D games). The checkboxes on the page toggle the same options. Affine texture warping is not reproduced.

Which video format is used, and are length and frame count exact?

Video is saved as WebM (VP9 or VP8). Instead of real-time recording, each frame is rendered and committed one at a time, so frames are never dropped on slow devices and the file matches the requested frame rate and length exactly. The size comes from size in the camera JSON (e.g. 640x480), or the viewport size if absent. Browsers without frame-by-frame capture fall back to real-time recording.

Are models or images uploaded to a server?

No. Loading, rendering and video export all happen inside your browser. Only the three.js library is fetched from its CDN (jsDelivr). Exported videos are saved straight to your device.