SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

JavaScriptとWebGLによるはじめての3Dプログラミング

「three.js」でつくるお手軽3Dマンガ作成ソフト - 中編

JavaScriptとWebGLによるはじめての3Dプログラミング(2)

ダウンロード サンプル (335.2 KB)

レイキャスターを利用した移動1

レイキャスターを利用した移動1
レイキャスターを利用した移動1

 3Dオブジェクトの移動、回転、拡縮の操作を行えるようになりました。しかし、3D空間内のオブジェクトを選択したり、その選択したオブジェクトをドラッグしたりはできていません。そういったことができれば、ゲームやツールが非常に作りやすくなります。

 「three.js」では、こういった処理を比較的簡単に行うための機能が用意されています。それが「Raycaster」です。レイキャスターという名前のとおり、ある点から光を照射して、その光線がオブジェクトに交差するか否かを判定させることができます。

 この「Raycaster」を使い、カメラの位置から、マウスをクリックした場所に光線を放ち、3Dオブジェクトに光が当たるかどうかを判定します。そして、見事当たれば、その3Dオブジェクトをマウスで選択していると判断して、ドラッグ操作を行う処理ができます。

 この判定結果は「Raycaster」の「intersectObject」関数で取得できます。この関数の第1引数は、判定を行う3dオブジェクトです。第2引数は、再帰処理を行うか否かです。この第2引数の使い方は、次の「レイキャスターを利用した移動2」で紹介していきます。

 「intersectObject」は、結果を配列で戻します。配列が1以上であれば、光線が交差したオブジェクトが存在します。ここではオブジェクトを1つだけ指定するので、配列の数は0か1になります。

 以下、レイキャスターを利用して、3Dオブジェクトを移動する「crocro.bc.useRaycaster1.js」を掲載します。

「crocro.bc.useRaycaster1.js」
//= サンプル:レイキャスターを利用した移動1

//== レイキャスターを利用した移動1
crocro.bc.useRaycaster1 = function() {
    // 変数の初期化
    var d3 = crocro.bc.d3;    // 3D格納用

    // 要素の作成と格納
    plt = crocro.bc.mkColPlate(0xff0000);
    plt.scale.x = 2;
    plt.scale.y = 2;
    plt.scale.z = 2;
    d3.scene.add(plt);

    crocro.bc.render();

    // マウス操作の作成
    d3.tgt = plt;
    crocro.bc.useRaycaster1_setMouse();

    // 終了処理
    crocro.bc.setFinalize(function() {
        var d3 = crocro.bc.d3;    // 3D格納用
        d3.tgt = null;
        d3.prjctr = null;
    })
};

//== マウス操作の作成
crocro.bc.useRaycaster1_setMouse = function() {
    // 変数の初期化
    var d3 = crocro.bc.d3;    // 3D格納用
    var cntnr = crocro.bc.cntnr;    // コンテナー

    var isAct = false;
    var posX, posY;
    var prjctr = new THREE.Projector();    // プロジェクター
    var offset = new THREE.Vector3();

    //=== イベントを元に光線の交差判定
    var chckIntrsct = function(event) {
        // 中心からの位置の取得
        posX = event.pageX - cntnr.offset().left;
        posY = event.pageY - cntnr.offset().top;

        // 描画範囲の比率に変換
        posX =  (posX / d3.w) * 2 - 1;
        posY = -(posY / d3.h) * 2 + 1;

        // マウス座標の作成
        var vector = new THREE.Vector3(posX, posY, 1);

        // スクリーン座標系をオブジェクトの座標系に変換
        prjctr.unprojectVector(vector, d3.camera);

        // レイキャスターを作成
        var ray = new THREE.Raycaster(
            d3.camera.position,        // 始点
            vector.sub(d3.camera.position).normalize()    // 向きベクトル
        );

        // 交差判定
        var intersects = ray.intersectObject(d3.tgt, false);

        // 結果を戻す
        return intersects;
    };

    //=== マウス操作 開始
    var msStrt = function(event) {
        isAct = true;    // 動作状態に移行

        // イベントを元に光線の交差判定
        var intersects = chckIntrsct(event);

        // 有効か確認
        if (intersects.length > 0) {
            // 交差したのでオフセットを記録
            offset.copy(intersects[0].point).sub(d3.tgt.position);
        } else {
            isAct = false;    // 動作状態を解除
        }
    };

    //=== マウス操作 移動
    var msMv = function(event) {
        // 動作状態でなければ終了
        if (! isAct) {return;}

        // イベントを元に光線の交差判定
        var intersects = chckIntrsct(event);

        // 有効か確認
        if (intersects.length > 0) {
            // 交差しているので移動
            var pos = intersects[0].point.sub(offset);
            d3.tgt.position = pos;
        }

        // レンダリング
        crocro.bc.render();
    };

    //=== マウス操作 終了
    var msEnd = function() {
        isAct = false;    // 動作状態を解除
    };

    //=== マウス操作の登録
    cntnr.mousedown(msStrt);
    cntnr.mousemove(msMv);
    cntnr.mouseup(msEnd);
    $(window).blur(msEnd);
}

次のページ
レイキャスターを利用した移動2

この記事は参考になりましたか?

JavaScriptとWebGLによるはじめての3Dプログラミング連載記事一覧

もっと読む

この記事の著者

柳井 政和(ヤナイ マサカズ)

クロノス・クラウン合同会社 代表社員http://crocro.com/オンラインソフトを多数公開。プログラムを書いたり、ゲームを作ったり、記事を執筆したり、マンガを描いたり、小説を書いたりしています。「めもりーくりーなー」でオンラインソフト大賞に入賞。最近は、小説家デビューして小説も書いています(『裏切りのプログラム』他)。面白いことなら何でもOKのさすらいの企画屋です。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/7209 2013/06/24 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー