9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DracoとAFrameを組み合わせて使ってみた

Last updated at Posted at 2017-01-17

Dracoのインストール

Emscriptenのインストール

私はMac環境なのでhomebrewでemscriptenをbrew install emscriptenでインストールしました。
インストール後は一度emccを動かしbrew info emscriptenの指示に従って~/.emscriptenを編集しましょう

Dracoのビルド

Dracoのビルドは公式のREADME.mdに従うとうまくいきます。ファイルがゴリッと生成されるので作業用フォルダを作ってその中でやるのを忘れないようにしましょう。
export EMSCRIPTEN=にどの値を設定するかは~/.emscriptenEMSCRIPTEN_ROOTの値を参考にしましょう。

AFrameのビルド

AFrameにはthree.jsが埋め込まれているのですが、現状の最新のリリース版(0.4.0)ではthree.jsが82系をつかっており、一方Dracoの方は83系をつかっているので想定しているAPIのバージョンが合わないので上手く使えません。しかし、Aframeのmasterでは(2017/01/18 01:58 確認)83系をつかっているのでこちらをビルドして使いましょう。ビルドについてはREADME.mdに従えば問題ありません。aframe-master.min.jsができるのでこれを利用します。

DRACOLoader.jsの取得

DracoのサンプルにDRACOファイルをthree.jsのBufferGeometryに変換するためのDRACOLoader.jsが用意されています
https://github.com/google/draco/blob/master/javascript/example/DRACOLoader.js

今回はコレからサンプルに強く紐付いている箇所を削除し利用しています

サンプルデータのダウンロード

サンプルのdraco圧縮されたファイルはexample/modelsフォルダ内に入っているウサギのモデルを今回は利用しました。
もとのオブジェクトデータはhttps://graphics.stanford.edu/data/3Dscanrep/にあるようです。

コード

Dracoファイルをロードするdraco-modelコンポーネントを登録

汎用的に利用できるようにするためにdracoのモデルをURLからロードするdrc-modelというコンポーネントを
AFrameに登録します。

draco_model_component.js
const DracoModule = Module;

AFRAME.registerComponent('drc-model', {
    schema: {
        drcUrl: {type: 'string'}
    },
    init: function() {
        this.model = null;
        this.drcLoader = new THREE.DRACOLoader();
        this.drcLoader.crossOrigin = '';
    },
    
    update: function() {
        var data = this.data;
        if (!data.drcUrl) { return ; }
        this.remove();
        this.loadObj(data.drcUrl);
    },
    
    remove: function() {
        if (!this.model) { return; }
        this.el.removeObject3D('mesh');
    },
    
    loadObj: function(drcUrl) {
        var self = this;
        var el = this.el;
        var drcLoader = this.drcLoader;
        drcLoader.load(drcUrl, function(bufferGeometry) {
            var material = new THREE.MeshStandardMaterial({vertexColors: THREE.VertexColors});

            let geometry;
            // Point cloud does not have face indices.
            if (bufferGeometry.index == null) {
              geometry = new THREE.Points(bufferGeometry, material);
            } else {
              bufferGeometry.computeVertexNormals();
              geometry = new THREE.Mesh(bufferGeometry, material);
            }
            
            // Compute range of the geometry coordinates for proper rendering.
            bufferGeometry.computeBoundingBox();
            const sizeX = bufferGeometry.boundingBox.max.x - bufferGeometry.boundingBox.min.x;
            const sizeY = bufferGeometry.boundingBox.max.y - bufferGeometry.boundingBox.min.y;
            const sizeZ = bufferGeometry.boundingBox.max.z - bufferGeometry.boundingBox.min.z;
            const diagonalSize = Math.sqrt(sizeX * sizeX + sizeY * sizeY + sizeZ * sizeZ);
            const scale = 1.0 / diagonalSize;
            const midX = (bufferGeometry.boundingBox.min.x + bufferGeometry.boundingBox.max.x) / 2;
            const midY = (bufferGeometry.boundingBox.min.y + bufferGeometry.boundingBox.max.y) / 2;
            const midZ = (bufferGeometry.boundingBox.min.z + bufferGeometry.boundingBox.max.z) / 2;

            geometry.scale.multiplyScalar(scale);
            geometry.position.x = -midX * scale;
            geometry.position.y = -midY * scale;
            geometry.position.z = -midZ * scale;
            geometry.castShadow = true;
            geometry.receiveShadow = true;
            self.model = geometry;
            
            el.setObject3D('mesh', geometry);
            el.emit('model-loaded', {format: 'drc', model: geometry});
        });
    }
});

アセット経由でロードできない

現状ではa-asset-itemでロードしようとして

asset-item-example
<a-asset-item id="banny-drc" src="banny.obj></a-asset-item>

というふうにすると、上手くロードできません。
Three.jsのキャッシュやらa-asset-itemのロードのresponseTypeやらの兼ね合いで上手くロードできませんので、
現状はURL経由でdrc-model内部でTHREE.DRACOLoader()でロードしています。

a-scene上で利用する

上記のようなコンポーネントを登録しておくとa-sceneの中で簡単にロードできます

asset-scene
<a-scene>
      <a-sky color="#ECFFFF"></a-sky>
      <a-entity drc-model="drcUrl: ./bunny.drc" position="0 1.25 -2"></a-entity>
</a-scene>

のようにしてシーンにウサギのモデルを載せます。

結果

スクリーンショット 2017-01-18 03.05.02.png

これでこのようにAFrame上にDracoで圧縮されていたモデルがデコードされて表示され無事VRで見ることができました。

コード

今回のコードはpocket7878/draco-aframe-exampleにアップロードしておきました.

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?