CX's Hatena Blog

はてなブログを使ってみるテスト

Three.js + Oimo.js で物理演算してみるテスト

WebGL アドベントカレンダーということで、今日は、3D 物理演算のライブラリ「Oimo.js」を紹介したいと思います。

f:id:cx20:20141213212821p:plain

以前、Three.js + Cannon.js でゴゴゴとドドドを物理演算してみるテストにて、少し紹介しましたが、有名どころの JavaScript の 3D 物理演算ライブラリとして

と、いったライブラリがあります。

それぞれ、一長一短な部分があるのですが、個人的には、Oimo.js がファイルサイズがコンパクトなのとパフォーマンス的に優れているのでオススメです。

なお、Oimo.js は、Saharan さんの ActionScript 3.0 版物理演ライブラリ「OimoPhysics」を lo-th さんが、JavaScript にコンバージョンしたものになります。

拙作ですが、jsdo.it に投稿した作品を何点か紹介したいと思います。

チョコレート菓子

消しゴム

ノート

ゴゴゴ

ドミノ

ドミノのコード(抜粋)

サンプルを見ているだけではつまらないと思うので、少しコードの説明をしたいと思います。 Oimo.js を用いた、物理演算コードの基本的な流れとしては、

  1. 床を作る
  2. 物理演算用のオブジェクトを設定する(形とサイズと位置を指定)
  3. 表示用のオブジェクトを設定する(形と色とサイズと位置を指定)

という流れになります。

以下は、該当箇所の抜粋です。

function populate(n) {
    // 初期化処理
    clearMesh();
    world.clear();

    // 床の設定
    var ground = new OIMO.Body({
        size: [400, 40, 400],
        pos: [0, -50, 0],
        world: world
    });

    // ドミノ碑のサイズ
    var w = DOT_SIZE * 0.2;
    var h = DOT_SIZE * 1.5;
    var d = DOT_SIZE;

    var color;
    var i;
    // ドミノ碑を16x16個、整列させる
    for (var x = 0; x < 16; x++) {
        for (var z = 0; z < 16; z++) {
            y = 0;
            // 物理演算用のオブジェクトを設定
            bodys[i] = new OIMO.Body({
                type: 'box',
                size: [w, h, d],
                pos: [-120 + x * DOT_SIZE, y * DOT_SIZE, -120 + z * DOT_SIZE * 1.2],
                move: true,
                world: world
            });
            // ドミノ碑の色を設定(ドット絵になるよう色を変更)
            i = x + z * 16;
            color = getRgbColor(dataSet[i]);
            var material = new THREE.MeshLambertMaterial({
                color: color
            });
            // 表示用のオブジェクトを設定
            meshs[i] = new THREE.Mesh(geoBox, material);
            meshs[i].scale.set(w, h, d);
            scene.add(meshs[i]);
        }
    }

    // ドミノ碑を倒す為に、赤色の立方体×16個、配置する。
    var size = bodys.length;
    for (i = 0; i < 16; i++) {
        w = DOT_SIZE;
        h = DOT_SIZE;
        d = DOT_SIZE;
        x = 0;
        y = 2;
        z = i;

        // 物理演算用のオブジェクトを設定
        bodys[size + i] = new OIMO.Body({
            type: 'box',
            size: [w, h, d],
            pos: [-125 + x * DOT_SIZE, y * DOT_SIZE, -120 + z * DOT_SIZE * 1.2],
            move: true,
            world: world
        });
        // 立方体の色を設定(赤色)
        var material = new THREE.MeshLambertMaterial({
            color: "#f00"
        });
        // 表示用のオブジェクトを設定
        meshs[size + i] = new THREE.Mesh(geoBox, material);
        meshs[size + i].scale.set(w, h, d);
        scene.add(meshs[size + i]);
    }
}

如何でしょうか?恐らく、Three.js を使ったことがある人であれば、大体イメージがつかめるのではないかと思います。

他にも、jsdo.it にサンプルを投稿しているので、興味がある方はどうぞ。

http://jsdo.it/cx20

それでは、みなさま、良い、物理演算ライフを!

明日は、naotaro0123 さんです。