← ハシトシステム トップ English ツール ブログ ポスター
読み込む
サンプル 保存 保存 保存 保存 保存 保存 保存 保存
ビューまだ何も読み込んでいません
JSON や画像をここにドロップ ポリゴン → テクスチャ → 骨格 → 動き → カメラ の順に足していけます。
中身を見て種類を自動で判別します。ドラッグで回転、ホイールで拡大縮小。
0.00 / 0.00 秒
場面の中身
まだ読み込んでいません
読み込むと、頂点・面・骨・トラック・カメラのキーの数と、紐づかなかった骨の名前を表示します。
ポリゴンの JSON を読み込むと使えます。ファイルはこのブラウザの中だけで扱います。
使い方:ポリゴン JSON を読み込む → テクスチャ画像を足す → 骨格 JSON で関節を作る → 動き JSON で骨ごとの角度を時間で指定 → カメラ JSON で撮り方を決める → 「動画を書き出す」。 場面 JSONにまとめると、人物を何人でも・小道具も・移動の経路も1ファイルで持てます。 種類は中身で判別するので、どのボタンから読んでも構いません(vertices があればポリゴン、bones があれば骨格、tracks があれば動き、keys があればカメラ、actors があれば場面)。 ファイルはサーバーへ送られません。

JSON の書き方

座標は右手系・Y が上・単位はメートル相当(1.7 なら身長 170cm)。角度は度。時刻 t は秒。

1. ポリゴン(vertices / faces)

{
  "name": "hero",
  "vertices": [[x, y, z], ...],
  "faces": [[0, 1, 2], [4, 5, 7, 6], ...],       // 三角形でも四角形でも。頂点番号を外から見て反時計回りに
  "uvs": [[u, v], ...],                          // 頂点ごとの UV(省略可)
  "faceUvs": [[[u,v],[u,v],[u,v],[u,v]], ...],   // 面ごとの UV(uvs より優先。1枚の画像から区画を切って貼るとき)
  "color": [r, g, b],                            // 0〜1。テクスチャが無いときの色(省略可)
  "faceColors": [[r, g, b], ...],                // 面ごとの色(省略可)
  "repeat": true,                                // UV が 0〜1 を超えたら画像を繰り返す(床・壁)
  "doubleSided": false
}

2. 骨格(bones / weights)

{
  "bones": [
    {"name": "hips",  "parent": null,   "head": [0, 0.95, 0]},
    {"name": "spine", "parent": "hips", "head": [0, 1.10, 0]},
    ...
  ],
  "weights": [                     // 頂点番号の順。1頂点につき最大4本
    [["thigh_l", 1]],
    [["chest", 0.7], ["spine", 0.3]],
    {"head": 1},                   // この書き方でも可
    ...
  ]                                // 省略すると、一番近い骨2本に距離で自動で紐づける
}

3. 動き(tracks)

{
  "duration": 1.2, "loop": true, "ease": "smooth",     // ease は smooth か 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 は骨の位置のずらし
  }
}

4. カメラ(keys)

{
  "fov": 50, "size": [640, 480],                       // 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 に骨や人物の名前も書ける
  ]
}

場面(actors / props / camera)

{
  "world": {"background": "#07080c", "ambient": 0.55, "sun": [0.3, 1, 0.4], "fog": ["#07080c", 3.5, 10]},
  "camera": { ...4 と同じ... },
  "actors": [
    {"name": "hero", "model": {...1...}, "skeleton": {...2...}, "animation": {...3...},
     "texture": "data:image/png;base64,...",          // 同梱するなら Data URL。ファイル名なら別に画像を読み込む
     "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}]}   // 移動の経路
  ],
  "props": [{"name": "floor", "model": {...1...}, "texture": "data:..."}],   // 骨の無い置き物
  "duration": 5
}
STL / OBJ / GLB の形状を見たい・測りたい場合は3Dモデルビューアを、 1枚の写真に動きを付けたい場合はMovo Blocksをご利用ください。 データやWebの仕組みをやさしく図解した学習ポスター(無料配布)もあわせてどうぞ。

よくある質問(FAQ)

どんなファイルを用意すれば動かせますか?

最小はポリゴンの JSON 1つです。頂点の座標と面(頂点番号の並び)があれば表示できます。関節を動かすには骨格の JSON(骨の親子と位置、頂点ごとの重み)と、動きの JSON(骨ごとの角度のキーフレーム)を足します。カメラの JSON は位置・注視点・画角のキーフレームで、無ければマウスで自由に見られます。テクスチャは PNG や JPEG の画像ファイルをそのまま読み込みます。4つの JSON をまとめた「場面 JSON」にすると、複数の人物や小道具を1ファイルで持てます。

骨と頂点の紐づけ(重み)を書かないとどうなりますか?

骨格 JSON に weights が無いときは、各頂点から一番近い骨(親の位置から子の位置までの線分)を探して自動で紐づけます。近い骨2本を距離で按分するので、関節付近の頂点は両方の骨に少しずつ引かれます。箱を組んだような低ポリゴンのモデルなら自動でほぼ足りますが、狙いどおりに曲げたい場合は weights を書いてください。

PS1 風(粗い解像度・頂点のぶれ)にできますか?

できます。カメラ JSON か場面 JSON の style で resolution(描画する解像度、例 320x240)、nearest(テクスチャを拡大してもぼかさない)、vertexSnap(頂点の位置を画面の格子に丸めて、初期の 3D ゲームのように頂点がぶれる)を指定します。画面上のチェックボックスでも切り替えられます。テクスチャの歪み(アフィン補間)までは再現していません。

動画はどの形式で、長さやコマ数は正確ですか?

WebM(VP9 または VP8)で保存します。実時間の録画ではなく、1コマずつ描いて確定させる方式なので、描画が重い端末でもコマが落ちず、指定したフレームレートと長さのとおりに書き出されます。大きさはカメラ JSON の size(例 640x480)で決まり、無ければ画面の大きさになります。この方式に対応していないブラウザでは実時間の録画に切り替わります。

モデルや画像はサーバーに送られますか?

いいえ。読み込み・描画・動画の書き出しは、すべてお使いのブラウザの中だけで行います。描画に使う three.js のライブラリだけを配信元(jsDelivr)から読み込みます。書き出した動画もそのまま端末に保存されます。