mcpField
T
threejs-core-math

threejs-core-math

github.com/impertio-studio開発23136 回インストール30 週間前に更新
リポジトリ

threejs-core-math について

threejs-core-mathは、Three.jsの数学APIを扱う開発者向けのリファレンススキルです。主要クラス、変換、補間、座標規約、よくある注意点をまとめています。

主な機能

  1. 01ベクトルと行列のAPIリファレンス
  2. 02QuaternionとEulerによる回転の指針
  3. 03ColorとMathUtilsの操作
  4. 04境界ボリュームの判定
  5. 05座標と変更時の注意点

活用シーン

  1. 01オブジェクト変換の実装
  2. 02滑らかな回転アニメーションの作成
  3. 03交差と境界の確認
  4. 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 と一緒にインストールされる参考資料やスクリプト。

.gitkeep
references/
anti-patterns.md
examples.md
methods.md

詳細

threejs-core-math

クイックリファレンス

座標系

Three.js は Y-up の 右手系座標系を使用します。

軸方向備考
X右正の方向は画面の右側
Y上正の方向は天井側
Z視点側正の方向は画面の手前

インポート時の変換ルール:

ソース規約変換
BlenderZ-upglTF エクスポーターが自動的に変換します
FBXZ-upFBXLoader が自動的に変換します
OBJ標準なし読み込み後は必ず向きを確認してください
IFCZ-up必ず X 軸を -90 度回転するか、変換対応ローダーを使用してください

インポートしたモデルが Three.js の規約に合っていると決して想定しないでください。読み込み後は必ず向きを確認してください。

コア数学クラス
クラス用途単位元/デフォルト
Vector3位置、方向、スケール(0, 0, 0)
Vector2UV 座標、2D 位置(0, 0)
Vector4同次座標、シェーダーデータ(0, 0, 0, 0)
Matrix44x4 変換行列単位行列
Quaternionジンバルロックのない回転(0, 0, 0, 1)
Euler人が読みやすい回転角(0, 0, 0, 'XYZ')
ColorRGB カラー(0~1 の範囲)(1, 1, 1) 白
Box3軸に沿った境界ボックス空(最小値 +Inf、最大値 -Inf)
Sphere境界球中心は原点、半径は -1
Plane無限平面法線 (1,0,0)、定数 0
Ray原点 + 方向原点 (0,0,0)、方向 (0,0,-1)
Frustum6 平面の視錐台--
重要な警告

オブジェクト間で共有されている 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()

参考リンク

Official Sources

コメント