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. 03颜色和 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 轴朝上:

轴方向说明
X向右正方向朝屏幕右侧
Y向上正方向朝天花板
Z朝向观察者正方向从屏幕向外

导入转换规则:

来源坐标约定转换方式
BlenderZ 轴朝上glTF 导出器会自动转换
FBXZ 轴朝上FBXLoader 会自动转换
OBJ无标准加载后务必检查方向
IFCZ 轴朝上务必应用绕 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)
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()。

切勿使用 lerp() 为 Color 创建色相变化动画——这会产生浑浊的中间色。要在不同色相之间过渡,务必使用 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。用于齐次坐标和着色器 uniform。


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。使用 premultiply(m) 执行左乘(this = m * this)。

工厂方法: 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

表示旋转且不会发生万向节锁。对于插值动画和复合旋转,务必优先使用 Quaternion,而非 Euler。

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,再应用当前四元数)、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 degrees 时会发生万向节锁。症状:出现意外跳变、丢失一个旋转轴。

方法: 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 不同。


边界体

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

评论

支持 Markdown