Scene, Renderer, Camera
Three.jsで何かを表現するため必要な一番基本的な3つのScene、Renderer、Cameraについて説明します。
Scene(シーン)
Three.jsで3Dグラフィックを実装する時、最も基本的な要素はSceneです。Sceneは3D世界のコンテナとして、私たちが表現したいすべての3Dオブジェクトが配置される空間です。例えば、映画の撮影現場を思い浮かべてみましょう。俳優、小道具、照明などすべての要素がセット内に配置されるように、Three.jsのSceneもすべての3Dオブジェクトが配置される空間です。
// Sceneの生成
const scene = new THREE.Scene();
Scene Graph
Sceneはツリー構造で構成されたScene Graphを使ってオブジェクトを管理します。これは、親子関係を通じてオブジェクトを体系的に構成することができます。
ここで、各ノードはそれぞれのローカル空間(local space)を指します。また、子オブジェクトは親オブジェクトの変換(位置、サイズ、回転)を継承します。
// 親オブジェクトの生成
const parent = new THREE.Object3D();
scene.add(parent);
// 子オブジェクトの生成と親への追加
const child = new THREE.Mesh(geometry, material);
parent.add(child);
このようなプロパティをうまく利用すれば、複雑なアニメーションも比較的簡単に計算して実装することができます。以下はその例です。
-
グループ化
// Scene Graphを使わずにそれぞれのオブジェクトを個別に管理する場合
car.position.x += 10;
wheel1.position.x += 10;
wheel2.position.x += 10;
wheel3.position.x += 10;
wheel4.position.x += 10;
// Scene Graphを使う場合
carGroup.position.x += 10; // すべての子オブジェクトが自動的に一緒に移動します。
-
相対位置/回転/サイズ
// 親オブジェクトに対する相対的な位置指定
const door = new THREE.Mesh(doorGeometry, doorMaterial);
door.position.set(1, 0, 0); // ドアは家を基準にして右側に位置します。
house.add(door);
// 家が移動すると、ドアも自動的に追従します。
house.position.set(10, 0, 0);
// 腕を振るアニメーションの場合
// Scene Graphなしで実装すると、肩の位置を基準に毎回計算する必要があります。
arm.position.x = shoulder.position.x + Math.sin(time) * armLength;
arm.position.y = shoulder.position.y + Math.cos(time) * armLength;
// Scene Graphを使うと単純に回転させるだけです。
shoulder.add(arm);
shoulder.rotation.z = Math.sin(time);
Cameraについて
Three.jsでは、Cameraは3Dシーンをどの視点で見るかを決める要素です。実際のカメラと同様に、位置、方向、視野角などを調整することで、好きなシーンを表現することができます。4種類の
PerspectiveCamera (パースペクティブカメラ)
実際の人間の目やカメラのように遠近感を持つカメラである。PerspectiveCameraは
、4つの属性をもとに切頭体を作る。
- FOV (Field of View、視野角)
- カメラが見る視野の角度(degree単位)。
- Aspect Ratio (アスペクト比)
- カメラビューポートのアスペクト比
- 通常、ブラウザウィンドウのwidth/height比率を使用
- 4:3、16:9などの比率でも設定可能。
- 画面がつぶれないようにする重要な属性です。
- Near (最小距離)
- カメラが見ることができる最小距離
- この距離より近いオブジェクトは見えません。
- Far (最大距離)
- カメラが見ることができる最大距離
- この距離より遠くにあるオブジェクトは見えません。
Renderer
RendererはSceneとCameraの情報を受け取り、私たちが実際に画面で見ることができる画像に変換する役割をします。例えば、映画製作過程で撮影されたオリジナルフィルムを実際の観客が見ることができる映画に現像して処理する作業だと考えてください。
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();
参考文献