見出し画像

Vue 3 と Three.js で3Dモデルを表示

Vue3 + Three.js|NAYUTA株式会社 シリーズ記事の第2弾です。
https://github.com/NAYUTA-tech/tutorial-three-vue にソースコードも公開しています。

今回作るもの

前回記事の続きです。
今回は、glTF形式(厳密にはglTFのバイナリ版であるglb)の3Dモデルを読みこみます。Three.jsドキュメントの Loading 3D models – three.js docs と同等のことを、Vue3と組み合わせて行うということですね。

この記事内では『バチャこみ』登場予定の店舗を使用しています

3Dモデルの読込み

`/public/`以下に、表示したいglbファイルを置きましょう。この記事では`public/3d/copain.glb`として、弊社で開発中の『バチャこみ』で登場予定の店舗コパンを使用しています。

前回の`this.cube`と同様、下記のようにreturnの外で`this.shop`を定義しましょう。

data() {
  // 略
  this.cube = null
  this.shop = null

  return {}
},

`addBox()`を一般的なモデル読込み関数にしたいので、`addModels()`に変更します。

mounted() {
  this.init()
  this.addModels()  // this.addBox()から変更
  this.animate()
},

続いて、店舗モデルを読み込むクラスを作ります。

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'

// 略

class Shop {
  constructor(scene) {
    const loader = new GLTFLoader()

    loader.load(
      '/3d/copain.glb',

      (gltf) => {
        scene.add(gltf.scene)
      },

      undefined,

      (error) => {
        console.error(error)
      }
    )
  }
}
addModels() {  // addBox()から変更
  // 箱
  const geometry = new THREE.BoxGeometry()
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
  this.cube = new THREE.Mesh(geometry, material)
  this.scene.add(this.cube)

  // お店
  this.shop = new Shop(this.scene)
},

この時点での注意点は、`loader.load()`に渡している第2引数である`(gltf)=>{}`が、glbファイルの読込後に遅れて実行される点です。これがあるため、Shopクラスのコンストラクタにsceneを渡すという、一見わかりにくい処理をしています。

この時点で一度動かしてみてください。暗い画面にかろうじて緑の箱が見えるかどうかという状況になってるのではないでしょうか?3Dのプログラミングをやったことがあれば良くある話で、光源の設定が必要になります。

光源を設定する

init() {
  // 略

  // 光源
  const light = new THREE.AmbientLight(0xe0e0e0)
  this.scene.add(light)

  // カメラ位置
  this.camera.position.z = 10
  this.camera.position.y = 3
},

環境光を設置して、カメラをちょっと引いてみました。(使用したモデルによりますが)これで全て表示されたと思います。