オリジナルのglTFファイルをthree.jsを使用してweb上に表示する
オリジナルの3Dオブジェクトファイルをwebに表示を行ったため、そのときのメモ。
表示するオブジェクトの用意
オリジナルで用意を行う場合、blenderのソフトから作成を行うことができますが、turbosquidのサイトからFreeで3Dオブジェクトを使用することもできるため、今回はturbosquidを使用します。
今回・使用するオブジェクトについては、以下になります。
必要なパッケージ
version: ^0.124.0
実装手順
1. レンダラー・シーンの追加
html, レンダラーの追加を初めに行います。
<canvas class="js-three"></canvas>
import * as THREE from "three" // 画面幅の取得 const width = window.innerWidth const height = window.innerHeight // htmlからcanvasのclass名の取得 const canvas = document.querySelector('.js-three') // レンダラーを作成 const renderer = new THREE.WebGLRenderer({ canvas: canvas, alpha: true }) renderer.setPixelRatio(window.devicePixelRatio) renderer.setSize(width, height) // シーンを作成 const scene = new THREE.Scene() // カメラを作成 const camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 10000); camera.position.set(3, 1, 1) const controls = new OrbitControls(camera, renderer.domElement) // ライトの作成 const light = new THREE.DirectionalLight(0xefefef, 2) light.position.set(1, 5, 5).normalize() scene.add(light) // ここから下に続きます。
2. glTFのオブジェクトの読み込み
モジュールの読み込み
glTFの読み込むためには、別途モジュールが必要なため、モジュールの読み込みを行います。
// モジュールの読み込み import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
2021.02時点では非推奨になっていますが、 three-orbitcontrols
のパッケージを使う方法もあります。
上記のパッケージにも記載してありますが、2021.02時点では three
のパッケージのみで使用することができます。
コードの内容
// GLTFLoaderの読み込み const loader = new GLTFLoader() // 使用するオブジェクトのパス const url = '/assets/img/stone.gltf' loader.load( url, (gltf) => { // オブジェクトの読み込みが完了したタイミングで実行 scene.add(gltf.scene) }, (xhr) => { // オブジェクトを読み込んでいるタイミングで実行 console.log( `${( xhr.loaded / xhr.total * 100 )}% loaded` ); }, (error) => { // オブジェクトの読み込みが失敗したタイミングで実行 console.log(error) } )
3. OrbitControlsを使用して、回転・拡大,縮小を行う
モジュールの読み込み
OrbitControlsについても、先ほどと同様に別途モジュールが必要なため、モジュールの読み込みを行います。
// モジュールの読み込み import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
2021.02時点では非推奨になっていますが、 three-orbitcontrols
のパッケージを使う方法もあります。
こちらも先ほどと同様に上記のパッケージにも記載してありますが、2021.02時点では three
のパッケージのみで使用することができます。
コードの内容
// OrbitControlsの読み込み const controls = new OrbitControls(camera, renderer.domElement) const tick = () => { controls.update() renderer.render(scene, camera) requestAnimationFrame(tick) } tick()
全体のコード
<canvas class="js-three"></canvas>
import * as THREE from "three" import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { OrbitControls } from "three/examples/jsm/controls/OrbitControls" // 画面幅の取得 const width = window.innerWidth const height = window.innerHeight // htmlからcanvasのclass名の取得 const canvas = document.querySelector('.js-three') // レンダラーを作成 const renderer = new THREE.WebGLRenderer({ canvas: canvas, alpha: true }) renderer.setPixelRatio(window.devicePixelRatio) renderer.setSize(width, height) // シーンを作成 const scene = new THREE.Scene() // カメラを作成 const camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 10000); camera.position.set(3, 1, 1) const controls = new OrbitControls(camera, renderer.domElement) // OrbitControlsの読み込み const controls = new OrbitControls(camera, renderer.domElement) // ライトの作成 const light = new THREE.DirectionalLight(0xefefef, 2) light.position.set(1, 5, 5).normalize() scene.add(light) // GLTFLoaderの読み込み const loader = new GLTFLoader() // 使用するオブジェクトのパス const url = '/assets/img/stone.gltf' loader.load( url, (gltf) => { // オブジェクトの読み込みが完了したタイミングで実行 scene.add(gltf.scene) }, (xhr) => { // オブジェクトを読み込んでいるタイミングで実行 console.log( `${( xhr.loaded / xhr.total * 100 )}% loaded` ); }, (error) => { // オブジェクトの読み込みが失敗したタイミングで実行 console.log(error) } ) const tick = () => { controls.update() renderer.render(scene, camera) requestAnimationFrame(tick) } tick()
詰まったところ
オブジェクトが表示されない
自分が詰まった原因として、
// カメラ const camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 10000); camera.position.set(3, 1, 1) // GLTFLoaderの読み込み const loader = new GLTFLoader() // 使用するオブジェクトのパス const url = '/assets/img/stone.gltf' loader.load( url, (gltf) => { // オブジェクトの読み込みが完了したタイミングで実行 scene.add(gltf.scene) }, (xhr) => { // オブジェクトを読み込んでいるタイミングで実行 console.log( `${( xhr.loaded / xhr.total * 100 )}% loaded` ); }, (error) => { // オブジェクトの読み込みが失敗したタイミングで実行 console.log(error) } ) // ライト const light = new THREE.DirectionalLight(0xefefef, 2) light.position.set(1, 5, 5).normalize() scene.add(light)
のような感じで、 「カメラ → オブジェクト → ライト」 の順番で書き込みを行っていたのが原因で表示されない場合があったため、表示されなかった場合は順番を 「カメラ →ライト →オブジェクト」 にしたら解決しました。