three.js概論#2

2024/6/8

オブジェクトの変形

シーン内のオブジェクトを変形させる4つのプロパティ

  • position - 位置
  • scale - 大きさ
  • rotation - 回転
  • quaternion - クォータニオン

これらのプロパティはマトリックスと呼ばれるものにコンパイルされる。
マトリックスは、位置、回転、大きさを表す4x4の行列で、three.jsの内部、WebGL、そしてGPUでオブジェクトの変形に使われる。
マトリックスを自分で操作する必要はなく、three.jsはこれらのプロパティを直接操作することができる。

position

positionはオブジェクトの位置を表す3次元ベクトルで、xyzの3つの値を持つ。
各軸の方向は、環境によって変化するが、three.jsでは通常、x軸が右、y軸が上、z軸が手前と考える。
positionVector3クラスのインスタンスで、他にも様々なメソッドを持つ。

positionの設定
mesh.position.x = 0.7;
mesh.position.y = -0.6;
mesh.position.z = 1;
// setメソッドを使っても同じ
mesh.position.set(0.7, -0.6, 1);
// ベクトルの長さを取得
mesh.position.length();
// 他のベクトルとの距離を取得
mesh.position.distanceTo(camera.position);
// ベクトルの長さを1に正規化
mesh.position.normalize();

軸ヘルパー

3D空間上の軸を表示するヘルパーとしてAxesHelperを使うことができる。

AxesHelperは、x、y、z軸に対応する3本の線を表示し、それぞれがシーンの中心から始まり、対応する方向に進む。

軸ヘルパーの作成
// 引数の2は軸の長さ
const axesHelper = new THREE.AxesHelper(2);
scene.add(axesHelper);

scale

scaleVector3クラスのインスタンスで、デフォルト値は(1, 1, 1)で、各軸の拡大率を表す。

scaleの設定
mesh.scale.x = 2;
mesh.scale.y = 0.25;
mesh.scale.z = 0.5;

オブジェクトの回転

オブジェクトの回転は、rotationプロパティまたはquaternionプロパティを使って行う。
three.jsは両方をサポートしており、一方を更新すると他方も自動的に更新される。

一般的にはrotationプロパティを使うことが多い。

rotation

rotationはオブジェクトの回転を表す3次元ベクトルで、xyzの3つの値を持つ。
こちらはVector3ではなく、Eulerクラスのインスタンス。

各軸の値はラジアン単位で表される。ラジアンは角度の単位で、円周率πを使って表す。
例えば、90度はπ/2ラジアン、180度はπラジアン、270度は3π/2ラジアンとなる。
JavaScriptでは、Math.PIを使ってπを表すことができる。

rotationの設定
mesh.rotation.x = Math.PI * 0.25;
mesh.rotation.y = Math.PI * 0.25;

回転はx,y,zの順に適用され、それぞれの軸はローカル座標系で回転する。
reorder()メソッドを使って回転の順序を変更することもできる。

rotationの順序変更
mesh.rotation.reorder("YXZ");

quaternion

quaternionプロパティもオブジェクトの回転を表すが、Eulerクラスとは異なり、Quaternionクラスのインスタンス。
quaternionは3Dコンピュータグラフィックスやロボティクスなどでよく使われる数学的な表現。

lookAt

Object3Dクラスのインスタンスが持つlookAtメソッドを使うと、オブジェクトを指定した位置に向けることができる。

lookAtメソッド
camera.lookAt(mesh.position);

オブジェクトをグループ化

複数のオブジェクトをグループ化するGroupクラスを使うことで、一つのオブジェクトとして扱うことができる。

オブジェクトをグループ化することで、一つのオブジェクトとして扱うことができるため、位置、回転、拡大縮小などを一括で操作することができる。

オブジェクトのグループ化
// グループを作成
const group = new THREE.Group();
group.scale.y = 2;
group.rotation.y = 0.2;
scene.add(group);
// オブジェクトを作成
const cube1 = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({ color: 0xff0000 }),
);
cube1.position.x = -1.5;
const cube2 = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({ color: 0xff0000 }),
);
cube2.position.x = 0;
const cube3 = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({ color: 0xff0000 }),
);
cube3.position.x = 1.5;
// グループにオブジェクトを追加
group.add(cube1);
group.add(cube2);
group.add(cube3);
back