threejs-core-math について
threejs-core-mathは、Three.jsの数学APIを扱う開発者向けのリファレンススキルです。主要クラス、変換、補間、座標規約、よくある注意点をまとめています。
主な機能
- 01ベクトルと行列のAPIリファレンス
- 02QuaternionとEulerによる回転の指針
- 03ColorとMathUtilsの操作
- 04境界ボリュームの判定
- 05座標と変更時の注意点
活用シーン
- 01オブジェクト変換の実装
- 02滑らかな回転アニメーションの作成
- 03交差と境界の確認
- 04よくある数学上の誤りの回避
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ impertio-studio/ three.js-claude-skill-package --skill threejs-core-mathインストール後、Claude Code で/threejs-core-mathを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.gitkeepreferences/anti-patterns.mdexamples.mdmethods.md詳細
threejs-core-math
クイックリファレンス
座標系
Three.js は Y-up の 右手系座標系を使用します。
| 軸 | 方向 | 備考 |
|---|---|---|
| X | 右 | 正の方向は画面の右側 |
| Y | 上 | 正の方向は天井側 |
| Z | 視点側 | 正の方向は画面の手前 |
インポート時の変換ルール:
| ソース | 規約 | 変換 |
|---|---|---|
| Blender | Z-up | glTF エクスポーターが自動的に変換します |
| FBX | Z-up | FBXLoader が自動的に変換します |
| OBJ | 標準なし | 読み込み後は必ず向きを確認してください |
| IFC | Z-up | 必ず X 軸を -90 度回転するか、変換対応ローダーを使用してください |
インポートしたモデルが Three.js の規約に合っていると決して想定しないでください。読み込み後は必ず向きを確認してください。
コア数学クラス
| クラス | 用途 | 単位元/デフォルト |
|---|---|---|
Vector3 | 位置、方向、スケール | (0, 0, 0) |
Vector2 | UV 座標、2D 位置 | (0, 0) |
Vector4 | 同次座標、シェーダーデータ | (0, 0, 0, 0) |
Matrix4 | 4x4 変換行列 | 単位行列 |
Quaternion | ジンバルロックのない回転 | (0, 0, 0, 1) |
Euler | 人が読みやすい回転角 | (0, 0, 0, 'XYZ') |
Color | RGB カラー(0~1 の範囲) | (1, 1, 1) 白 |
Box3 | 軸に沿った境界ボックス | 空(最小値 +Inf、最大値 -Inf) |
Sphere | 境界球 | 中心は原点、半径は -1 |
Plane | 無限平面 | 法線 (1,0,0)、定数 0 |
Ray | 原点 + 方向 | 原点 (0,0,0)、方向 (0,0,-1) |
Frustum | 6 平面の視錐台 | -- |
重要な警告
オブジェクト間で共有されている Vector3/Matrix4/Quaternion を決して変更しないでください。ほとんどのメソッドはその場で値を変更します。共有インスタンスを変更する前に、必ず .clone() を使用してください。
// WRONG: mutates the shared vector
const offset = new Vector3(1, 0, 0);
meshA.position.add(offset);
meshB.position.add(offset); // offset is still (1, 0, 0) BUT if you
// had stored meshA.position somewhere,
// it would be mutated
// CORRECT: clone before mutation
const pos = sharedPosition.clone().add(offset);
Euler 角を直接補間するのは決して避けてください。不正な回転経路が生じ、ジンバルロックが発生します。必ず Quaternion に変換して slerp() を使い、必要に応じて元に戻してください。
Quaternion の x、y、z、w の値は、クォータニオンの数学を理解していない限り、決して手動で設定しないでください。必ず setFromAxisAngle()、setFromEuler()、または slerp() を使用してください。
色相を変化させるアニメーションで Color に lerp() を決して使用しないでください。中間色が濁ります。異なる色相間を遷移するには、必ず lerpHSL() を使用してください。
Three.js がラジアンを期待する場合は、必ず MathUtils.degToRad() を使用してください。すべての回転メソッドで使用するのは度数ではなくラジアンです。
Vector3
最もよく使われる数学クラスです。値を変更するすべてのメソッドは、メソッドチェーン用に this を返します。
算術: add(v)、addScalar(s)、sub(v)、multiply(v)、multiplyScalar(s)、divide(v)、divideScalar(s)、negate()
幾何: dot(v): number、cross(v)、length(): number、lengthSq(): number、normalize()、setLength(l)、reflect(normal)、project(camera)、unproject(camera)
距離: distanceTo(v): number、distanceToSquared(v): number、manhattanDistanceTo(v): number
補間: lerp(v, alpha)、lerpVectors(v1, v2, t)、clamp(min, max)、clampLength(min, max)
変換: applyMatrix4(m)、applyQuaternion(q)、applyAxisAngle(axis, angle)、applyEuler(euler)
変換/変換元: setFromMatrixPosition(m)、setFromMatrixScale(m)、setFromSphericalCoords(r, phi, theta)、toArray(arr?, offset?)、fromArray(arr, offset?)
代入: set(x, y, z)、copy(v)、clone()、equals(v): boolean
Vector2 の違い:持つのは x と y のみです。cross() はありません(cross(v): number によりスカラーを返します)。3D 変換もありません。
Vector4 の違い:x、y、z、w を持ちます。同次座標とシェーダーユニフォームに使用します。
Matrix4
列優先の格納方式(WebGL の規約)です。elements 配列に 16 個の浮動小数点数を格納します。
elements[0] elements[4] elements[8] elements[12] // Translation = [12,13,14]
elements[1] elements[5] elements[9] elements[13]
elements[2] elements[6] elements[10] elements[14]
elements[3] elements[7] elements[11] elements[15]
合成: compose(position, quaternion, scale) / decompose(position, quaternion, scale) -- 標準的な TRS(平行移動・回転・スケーリング)パターンです。
乗算順序: 右から左です。M1.multiply(M2) は、まず M2 を適用し、次に M1 を適用することを意味します。左乗算(this = m * this)には premultiply(m) を使用します。
ファクトリーメソッド: makeTranslation(x,y,z)、makeScale(x,y,z)、makeRotationX(theta)、makeRotationY(theta)、makeRotationZ(theta)、makeRotationAxis(axis, angle)、lookAt(eye, target, up)
操作: invert()、transpose()、determinant(): number、identity()、extractBasis(x, y, z)、extractRotation(m)、setPosition(v)
Quaternion
ジンバルロックを起こさずに回転を表現します。補間アニメーションや複合回転には、常に Euler より Quaternion を優先してください。
import { Quaternion } from 'three';
const q = new Quaternion(); // identity: (0, 0, 0, 1)
セッター: setFromAxisAngle(axis, angle)、setFromEuler(euler)、setFromRotationMatrix(m)、setFromUnitVectors(vFrom, vTo)
操作: multiply(q)(まず q を適用し、次に this を適用します)、premultiply(q)、slerp(qb, t)、slerpQuaternions(qa, qb, t)、rotateTowards(q, step)、conjugate()、invert()、normalize()
比較: dot(q): number、angleTo(q): number、equals(q): boolean
Euler
回転順序を指定した、人が読みやすいラジアン単位の回転表現です。
import { Euler } from 'three';
const e = new Euler(0, Math.PI / 2, 0, 'XYZ');
回転順序: 'XYZ'(デフォルト)、'YXZ'、'ZXY'、'ZYX'、'YZX'、'XZY'
ジンバルロック: 'XYZ' の順序では、Y = +/- 90 度でジンバルロックが発生します。症状として、予期しないスナップや、回転軸の 1 つが失われることがあります。
メソッド: setFromRotationMatrix(m)、setFromQuaternion(q, order?)、reorder(newOrder)、equals(euler): boolean
Euler と Quaternion の使い分け
| シナリオ | 使用するもの |
|---|---|
| 固定された回転を設定する | Euler -- 人が読みやすい |
| 滑らかな回転アニメーション | Quaternion + slerp() |
| 複数の回転を組み合わせる | Quaternion + multiply() |
| ジンバルロックを回避する | Quaternion |
| ユーザー入力(度)から回転を読み取る | Euler。quaternion.setFromEuler(euler) で変換します |
| シーングラフに回転を保存する | object.rotation(Euler)は object.quaternion と自動的に同期します |
Color
import { Color } from 'three';
new Color(0xff0000); // hex integer
new Color('red'); // CSS color name
new Color('rgb(255, 0, 0)'); // CSS rgb string
new Color('#ff0000'); // CSS hex string
new Color('hsl(0, 100%, 50%)'); // CSS hsl string
new Color(1.0, 0.0, 0.0); // RGB floats (0-1 range)
プロパティ: r、g、b(数値、範囲は 0~1)。
セッター: set(value)、setHex(hex)、setRGB(r,g,b)、setHSL(h,s,l)、setStyle(css)、setColorName(name)
ゲッター: getHex(): number、getHexString(): string、getHSL(target): {h,s,l}、getStyle(): string
補間: lerp(color, alpha)(RGB)、lerpHSL(color, alpha)(色相の変化をより知覚的に自然に補間します)、lerpColors(c1, c2, alpha)
色空間: convertSRGBToLinear()、convertLinearToSRGB() -- 物理的に正確なレンダリングのため、テクスチャの色は必ず線形空間に変換してください。
MathUtils
静的ユーティリティメソッドです。インスタンス化せず、必ず MathUtils.method() でアクセスしてください。
import { MathUtils } from 'three';
MathUtils.degToRad(90); // 1.5707...
MathUtils.clamp(value, 0, 1); // clamp to range
MathUtils.lerp(0, 100, 0.5); // 50
MathUtils.mapLinear(5, 0, 10, 0, 100); // 50
MathUtils.smoothstep(0.5, 0, 1); // Hermite ease
MathUtils.damp(current, target, lambda, dt); // frame-rate-independent damping
MathUtils.generateUUID(); // RFC 4122 v4 UUID
damp() は、滑らかなカメラ追従や UI アニメーションに特に便利です。アニメーションループ内で単純な lerp を使う場合と異なり、フレームレートに依存しない指数減衰を生成します。
Bounding Volumes
Box3(軸平行境界ボックス)
import { Box3, Vector3 } from 'three';
const box = new Box3();
box.setFromObject(mesh); // compute from mesh
box.containsPoint(new Vector3(1, 2, 3)); // boolean
box.intersectsBox(otherBox); // boolean
box.getCenter(new Vector3()); // center point
box.getSize(new Vector3()); // dimensions
Sphere、Plane、Ray、Frustum
- Sphere:
containsPoint()、intersectsBox()、intersectsSphere()、distanceToPoint() - Plane:
distanceToPoint()、projectPoint()、intersectLine() - Ray:
intersectBox()、intersectSphere()、intersectPlane()、distanceToPoint() - Frustum:
setFromProjectionMatrix(m)、containsPoint()、intersectsObject()、intersectsBox()
参考リンク
- references/methods.md -- Vector3、Matrix4、Quaternion、Euler、Color、MathUtils、Box3、Sphere、Plane、Ray の全メソッドシグネチャ
- references/examples.md -- よく使われる 3D 数学演算の実用的なコード例
- references/anti-patterns.md -- Three.js の数学クラスで避けるべきこと
Official Sources
- https://threejs.org/docs/#api/en/math/Vector3
- https://threejs.org/docs/#api/en/math/Matrix4
- https://threejs.org/docs/#api/en/math/Quaternion
- https://threejs.org/docs/#api/en/math/Euler
- https://threejs.org/docs/#api/en/math/Color
- https://threejs.org/docs/#api/en/math/MathUtils
- https://threejs.org/docs/#api/en/math/Box3