Dracoのインストール
Emscriptenのインストール
私はMac環境なのでhomebrewでemscriptenをbrew install emscripten
でインストールしました。
インストール後は一度emcc
を動かしbrew info emscripten
の指示に従って~/.emscripten
を編集しましょう
Dracoのビルド
Dracoのビルドは公式のREADME.mdに従うとうまくいきます。ファイルがゴリッと生成されるので作業用フォルダを作ってその中でやるのを忘れないようにしましょう。
export EMSCRIPTEN=
にどの値を設定するかは~/.emscripten
のEMSCRIPTEN_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に登録します。
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でロードしようとして
<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の中で簡単にロードできます
<a-scene>
<a-sky color="#ECFFFF"></a-sky>
<a-entity drc-model="drcUrl: ./bunny.drc" position="0 1.25 -2"></a-entity>
</a-scene>
のようにしてシーンにウサギのモデルを載せます。
結果
これでこのようにAFrame上にDracoで圧縮されていたモデルがデコードされて表示され無事VRで見ることができました。
コード
今回のコードはpocket7878/draco-aframe-exampleにアップロードしておきました.