シーン、レンダラー、カメラ
Three.jsで何かを表現するために必要な最も基本的な3つの要素、シーン、レンダラー、カメラについて学びましょう。
シーン
Three.jsで3Dグラフィックを実装する際の最も基本的な要素はシーンです。シーンは3D世界のコンテナとして、私たちが表現したいすべての3Dオブジェクトが配置される空間です。例えば、映画の撮影セットを思い浮かべてみましょう。俳優、小道具、照明などすべての要素がセット内に配置されるように、Three.jsのシーンもすべての3Dオブジェクトが配置される空間です。
// シーンの作成
const scene = new THREE.Scene();
シーングラフ
シーンはツリー構造で構成されるシーングラフを使用してオブジェクトを管理します。これにより、親子関係を通じてオブジェクトを体系的に構成することができます。
この構造の各ノードはそれぞれのローカル空間(local space)を表します。また、子オブジェクトは親オブジェクトの変換(位置、サイズ、回転)を継承します。
// 親オブジェクトの作成
const parent = new THREE.Object3D();
scene.add(parent);
// 子オブジェクトの作成と親への追加
const child = new THREE.Mesh(geometry, material);
parent.add(child);
これらの特性をうまく活用すると、複雑なアニメーションも比較的簡単に計算して実装することができます。以下は例です:
-
グループ化
javascript// シーングラフなしで各オブジェクトを個別に管理する場合 car.position.x += 10; wheel1.position.x += 10; wheel2.position.x += 10; wheel3.position.x += 10; wheel4.position.x += 10; // シーングラフを使用する場合 carGroup.position.x += 10; // すべての子オブジェクトが自動的に一緒に動く
-
相対的な位置/回転/スケール
typescript// 親オブジェクトに対する相対的な位置の指定 const door = new THREE.Mesh(doorGeometry, doorMaterial); door.position.set(1, 0, 0); // ドアは家を基準に右側に位置する house.add(door); // 家が移動するとドアも自動的についていく house.position.set(10, 0, 0); // 腕を振るアニメーションの場合 // シーングラフなしで実装すると肩の位置を基準に毎回計算する必要がある arm.position.x = shoulder.position.x + Math.sin(time) * armLength; arm.position.y = shoulder.position.y + Math.cos(time) * armLength; // シーングラフを使用すると単に回転させるだけでよい shoulder.add(arm); shoulder.rotation.z = Math.sin(time);
カメラ
Three.jsでは、カメラは3Dシーンをどの視点から見るかを決定する要素です。実際のカメラと同様に、位置、方向、視野角などを調整して望む場面を表現することができます。
PerspectiveCamera(透視カメラ)
実際の人間の目やカメラのように遠近感を持つカメラです。PerspectiveCamera
は4つの属性に基づいて錐台を作成します。
- FOV(Field of View、視野角)
- カメラが見る視野の角度(度単位)
- アスペクト比(縦横比)
- カメラビューポートの幅/高さの比率
- 通常はブラウザウィンドウのwidth/height比率を使用
- 4:3、16:9などの比率でも設定可能
- 画面が歪んで見えないようにするための重要な属性
- Near(最小距離)
- カメラが見ることができる最小距離
- この距離より近くにあるオブジェクトは表示されない
- Far(最大距離)
- カメラが見ることができる最大距離
- この距離より遠くにあるオブジェクトは表示されない
レンダラー
レンダラーはシーンとカメラの情報を受け取り、私たちが実際に画面で見ることができる画像に変換する役割を果たします。例えば、映画制作過程で撮影された原本フィルムを実際の観客が見ることができる映画として現像し処理する作業と考えるとよいでしょう。
const canvas = document.getElementById('canvas') as HTMLCanvasElement
const renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true })
renderer.setSize(window.innerWidth, window.innerHeight); // スクリーンサイズの設定
document.body.appendChild(renderer.domElement); // HTMLに追加
// 毎フレームごとに新しいシーンを作り出すプロセス
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
参照