こんにちは|こんばんは。カエルのアイコンで活動しております @kyamaz です。
はじめに
本稿は、@0taUtanさん、@enumura1さんや@nannany_storesさんの次の寄稿を参考にThree.jsをVue3のコンポーネントにして、Blenderで作成したオブジェクトを読み込む手順を取り上げます。
Blenderでモデルを作成する
3Dモデルのサンプルとして、@PlusFさんの『BlenderでカーボンナノチューブのCGをつくる』を参考にカーボンナノチューブ(CNT)のモデルを作成します。
BlenderのメニューからFile → Export → glTF 2.0 (.glb/gltf)
を選択して、任意の場所に glTFファイル へエクスポートします。
ファイル名を"CNT.glb"とします。
Vue 3 + TypeScript + Vite の環境を整える
拙稿『p5.jsをVue3のコンポーネントにする』と同じ手順で環境を整えます。そしてHome.vue
を、次のようにコンポーネントHelloWorld
を使うように変更します。
<script lang="ts">
import HelloWorld from './components/HelloWorld.vue'
export default {
components: {
HelloWorld
}
}
</script>
<template>
<div>
<HelloWorld />
</div>
</template>
<style scoped>
</style>
Three.jsをコンポーネントとして活用する
Three.jsのモジュールを使用できるようにインストールします。同時にTypeScriptで型チェックができるように、開発のためのモジュール@types/threeもインストールします。
% npm install three
% npm install -D @types/three
Three.jsをコンポーネントにするには次のように書きます。
HelloWorld.vueのソースコード全体
<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
import {
Color,
GridHelper,
PerspectiveCamera,
PointLight,
Scene,
WebGLRenderer
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
export default defineComponent({
name: "HelloWorld",
setup() {
// 描画するDOMの指定
const container = ref();
// Three.js
const scene = new Scene();
const camera = new PerspectiveCamera();
const renderer = new WebGLRenderer();
const light = new PointLight();
const loader = new GLTFLoader();
const controls = new OrbitControls(camera, renderer.domElement);
// 初期化
const init = () => {
if (container.value instanceof HTMLElement) {
// DOMのサイズを取得
const { clientWidth, clientHeight } = container.value;
// 背景のグリッドの追加
scene.add(new GridHelper(50));
scene.background = new Color(0xcccccc);
// ライトの設定
light.color.setHex(0xffffff);
light.position.set(10, 10, 0);
scene.add(light);
// オブジェクトの追加
loader.load("assets/cnt.glb", (gltf: GLTF) => {
const model = gltf.scene;
model.scale.set(0.25, 0.25, 0.25);
scene.add(model);
});
// カメラの設定
camera.aspect = clientWidth / clientHeight;
camera.updateProjectionMatrix();
camera.position.set(10, 10, 0);
camera.lookAt(0, 0, 0);
// rendererの設定
renderer.setSize(clientWidth, clientHeight);
renderer.setPixelRatio(clientWidth / clientHeight);
container.value.appendChild(renderer.domElement);
// 描画
animate();
}
};
// 描画
const animate = () => {
const frame = () => {
// 描画
renderer.render(scene, camera);
// 画面を更新
requestAnimationFrame(frame);
};
frame();
};
// マウント時に初期化して描画
onMounted(() => {
init();
});
return {
container,
};
},
});
</script>
<template>
<div ref="container" class="fixed w-full h-full top-0 left-0"></div>
</template>
<style scoped>
.fixed { position: fixed; }
.w-full { width: 100%; }
.h-full { height: 100%; }
.top-0 { top: 0px; }
.left-0 { left: 0px; }
</style>
<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
import {
Color,
GridHelper,
PerspectiveCamera,
PointLight,
Scene,
WebGLRenderer
} from "three";
export default defineComponent({
name: "HelloWorld",
setup() {
// 描画するDOMの指定
const container = ref();
// Three.js
const scene = new Scene();
const camera = new PerspectiveCamera();
const renderer = new WebGLRenderer();
const light = new PointLight();
// 初期化
const init = () => {
if (container.value instanceof HTMLElement) {
// DOMのサイズを取得
const { clientWidth, clientHeight } = container.value;
// :
// :
// 描画
animate();
}
};
// 描画
const animate = () => {
const frame = () => {
// 描画
renderer.render(scene, camera);
// 画面を更新
requestAnimationFrame(frame);
};
frame();
};
// マウント時に初期化して描画
onMounted(() => {
init();
});
return {
container,
};
},
});
</script>
Three.js にて glTFファイル をロードする
上記で作成した"CNT.glb"をプロジェクトフォルダのpublic/assets/
に移動しておきます。そして、HelloWorld.vue に次のようにGLTFLoader
を読み込むためのimport文を記載をします。
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
さらに、オブジェクトを追加するところにファイルをロードする処理を記述します。
// オブジェクトの追加
loader.load("assets/cnt.glb", (gltf: GLTF) => {
const model = gltf.scene;
model.scale.set(0.25, 0.25, 0.25);
scene.add(model);
});
これをnpm run dev
で試してみると、次のようにモデルがブラウザで表示されます。
npm run build
でビルドする際には、OrbitControls
のローカル変数のところでエラーになるため、tsconfig.json
のパラメータを"noUnusedLocals": false
に書き換えておく必要があります。
おわりに
本稿では、いくつかの記事を参考にして、Three.jsをVue3で扱えるようにした環境で、Blenderで作成したカーボンナノチューブのモデルをブラウザに表示する手順を取り上げました。
本稿の環境
本稿のために使用した環境は以下となります。
macOS: Sonoma 14.4 (chip: Apple M1)
Blender: 4.0.2
anyenv: 1.1.5(homebrewにてインストール)
node: 18.19.0(anyenvのnodenvでインストール)
npm: 10.5.0
@vue/cli 5.0.8
three: 0.162.0
vue: 3.4.21
vue-router: 4.3.0
typescript:5.2.2
vite: 5.2.0
(●)(●) Happy Hacking!
/"" __""\