degToRad函数
用于将角度(度)转换为弧度,是 Three.js 中处理角度与弧度转换的基础工具函数。
js
/**
*
* @param {number} degrees - 角度(度)
* @return {number} 弧度
*/
function degToRad( degrees ) {
return degrees * DEG2RAD;
}
应用场景
- 在设置相机视场角(FOV)时,将用户输入的度数转换为弧度(如
camera.fov = MathUtils.degToRad(75)
)。 - 物体旋转时,将直观的角度值(如 "旋转 45 度")转换为 Three.js 旋转属性所需的弧度(如
mesh.rotation.y = MathUtils.degToRad(45))
。 - 配合三角函数(如
Math.sin
、Math.cos
)使用时,将角度参数转换为函数所需的弧度单位。
该函数逻辑简洁,是 Three.js 中角度单位转换的核心工具,确保了开发过程中角度参数的一致性和正确性。
radToDeg函数
用于将弧度转换为角度,是 Three.js 中角度单位转换的核心工具函数。
js
/**
*
* @param {number} radians - 弧度
* @return {number} 角度(度)
*/
function radToDeg( radians ) {
return radians * RAD2DEG;
}
应用场景
- 在获取物体旋转角度(如
mesh.rotation.y
以弧度存储)后,转换为角度用于显示或交互(如 UI 展示 "当前旋转 45 度")。 - 配合三角函数计算结果的转换(如
Math.sin
返回的弧度相关值,通过此函数转为角度)。 - 调试时将程序内部的弧度值转换为可读的角度,便于理解和验证。
该函数逻辑简洁,与 degToRad
函数形成互补,共同确保 Three.js 中角度单位转换的准确性。
isPowerOfTwo函数
用于判断一个数字是否为 2 的幂(Power of Two,POT),是 Three.js 中常用的数学工具函数。
js
/**
* @param {number} value - 待检查的数字
* @return {boolean}
*/
function isPowerOfTwo( value ) {
return ( value & ( value - 1 ) ) === 0 && value !== 0;
}
应用场景
在 Three.js 中常用于:
- 检查纹理尺寸是否为 2 的幂(许多 WebGL 实现对非 2 的幂纹理有兼容性限制)。
- 优化算法(如在需要按 2 的幂对齐的场景中,提前验证输入合法性)。
- 图形渲染相关的性能优化(如 mipmap 生成通常要求纹理尺寸为 2 的幂)。
该函数是判断 2 的幂的经典实现,利用二进制特性实现了高效且简洁的逻辑。
示例
js
console.log(isPowerOfTwo(8)); // 输出: true
console.log(isPowerOfTwo(10)); // 输出: false
console.log(isPowerOfTwo(0)); // 输出: false
ceilPowerOfTwo函数
用于计算大于或等于给定数值的最小 2 的幂(Power of Two,POT),是 Three.js 中处理 2 的幂运算的重要工具函数。
js
/**
* @param {number} value - 待处理的数值
* @return {number} 返回值为 "大于或等于 value 的最小 2 的幂"(例如,输入 10 时返回 16,输入 8 时返回 8)。
*/
function ceilPowerOfTwo( value ) {
return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
}
应用场景
在 Three.js 中常用于:
- 纹理处理:将非 2 的幂尺寸(如 100x100)转换为最小的 2 的幂尺寸(如 128x128),以兼容需要 POT 纹理的 WebGL 特性(如 mipmap)。
- 性能优化:在需要按 2 的幂对齐的数据结构(如缓冲区)中,确保尺寸符合要求以提升计算效率。
- 算法适配:某些图形算法(如 FFT、分形生成)仅对 2 的幂长度的输入有效,需提前转换。
示例
js
console.log(ceilPowerOfTwo(10)); // 输出: 16
console.log(ceilPowerOfTwo(16)); // 输出: 16
console.log(ceilPowerOfTwo(7)); // 输出: 8
floorPowerOfTwo函数
用于计算小于或等于给定数值的最大 2 的幂(Power of Two,POT),是 Three.js 中处理 2 的幂运算的重要工具函数,与 ceilPowerOfTwo 功能互补。
js
/**
* @param {number} value - 待处理的数值
* @return {number} 返回值为 "小于或等于 value 的最大 2 的幂"(例如,输入 10 时返回 8,输入 16 时返回 16)。
*/
function floorPowerOfTwo( value ) {
return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
}
应用场景
在 Three.js 中常用于:
- 纹理处理:将非 2 的幂尺寸(如 100x100)转换为不超过该尺寸的最大 2 的幂(如 64x64),用于资源压缩或兼容性处理。
- 数据结构优化:在需要按 2 的幂对齐的缓冲区或数组中,获取不超过目标长度的最大 2 的幂,避免内存浪费。
- 算法适配:某些分治或迭代算法(如二进制搜索、金字塔层级计算)需基于 2 的幂长度,需提前转换输入。
示例
js
console.log(floorPowerOfTwo函数(15)); // 输出: 8
console.log(floorPowerOfTwo函数(32)); // 输出: 32
console.log(floorPowerOfTwo函数(5)); // 输出: 4
setQuaternionFromProperEuler函数
用于根据内在 proper
欧拉角(Intrinsic Proper Euler Angles) 计算并设置四元数(Quaternion
),是 Three.js 中处理 3D 旋转转换的核心工具函数。
js
/**
* @param {Quaternion} q - 待设置的四元数(用于存储计算结果)。
* @param {number} a - 旋转角度(单位为弧度)
* @param {number} b - 旋转角度(单位为弧度)
* @param {number} c - 旋转角度(单位为弧度)
* @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - 旋转轴顺序
*/
function setQuaternionFromProperEuler( q, a, b, c, order ) {
const cos = Math.cos;
const sin = Math.sin;
const c2 = cos( b / 2 );
const s2 = sin( b / 2 );
const c13 = cos( ( a + c ) / 2 );
const s13 = sin( ( a + c ) / 2 );
const c1_3 = cos( ( a - c ) / 2 );
const s1_3 = sin( ( a - c ) / 2 );
const c3_1 = cos( ( c - a ) / 2 );
const s3_1 = sin( ( c - a ) / 2 );
switch ( order ) {
case 'XYX':
q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
break;
case 'YZY':
q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
break;
case 'ZXZ':
q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
break;
case 'XZX':
q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
break;
case 'YXY':
q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
break;
case 'ZYZ':
q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
break;
default:
console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
}
}
应用场景
- 在 3D 物体旋转控制中,将用户输入的欧拉角(如通过 UI 滑动条设置的
XYZ
旋转角度)转换为四元数,用于更新物体的quaternion
属性。 - 动画系统中,将关键帧定义的欧拉角旋转转换为四元数,以便进行平滑的旋转插值(slerp)。
- 物理引擎中,将欧拉角表示的旋转状态转换为四元数,提高旋转计算效率。
例如,若需将 "先绕 X
轴转 a
弧度,再绕 Y
轴转 b
弧度,最后绕 X
轴转 c
弧度" 的旋转转换为四元数,可调用 setQuaternionFromProperEuler(q, a, b, c, 'XYX')
。
关键细节
- 内在旋转 vs 外在旋转:此处处理的是 "内在旋转"(绕物体自身坐标系轴旋转),与 "外在旋转"(绕固定世界坐标系轴旋转)的转换公式不同。
- Proper 欧拉角特性:旋转轴顺序必须满足 "首轴 = 尾轴"(如 XYX、YZY),即第一次和第三次旋转围绕同一轴,这是 proper 欧拉角的定义。
- 避免万向锁:四元数相比欧拉角的优势是无万向锁问题,因此该函数常用于将用户输入的欧拉角(易理解)转换为四元数(适合计算)。
- 轴顺序影响结果:不同 order 对应的旋转效果完全不同,必须与欧拉角定义的旋转顺序一致,否则会导致旋转错误。
denormalize函数
用于将类型化数组(TypedArray)中的数值转换为标准化的浮点数(通常在 [0, 1] 或 [-1, 1] 范围),是 Three.js 中处理数据类型转换的工具函数。
js
/**
* @param {number} value - 类型化数组中的原始数值(如 Uint8Array 中的 0-255 整数)。
* @param {TypedArray} array - 类型化数组实例(如 Uint8Array、Int16Array 等),用于确定 value 的数据类型。
* @return {number} 转换后的浮点数,根据数组类型不同,范围通常为 [0, 1](无符号类型)或 [-1, 1](有符号类型)。
*/
function denormalize( value, array ) {
switch ( array.constructor ) {
case Float32Array:
return value;
case Uint32Array:
return value / 4294967295.0;
case Uint16Array:
return value / 65535.0;
case Uint8Array:
return value / 255.0;
case Int32Array:
return Math.max( value / 2147483647.0, - 1.0 );
case Int16Array:
return Math.max( value / 32767.0, - 1.0 );
case Int8Array:
return Math.max( value / 127.0, - 1.0 );
default:
throw new Error( 'Invalid component type.' );
}
}
应用场景
在 Three.js 中常用于:
- 纹理数据处理:将纹理像素的原始整数数据(如
Uint8Array
存储的RGB
值)转换为shader
所需的 [0, 1] 浮点数。 - 缓冲区数据解析:从类型化数组(如顶点属性的
Int16Array
数据)中读取数值并转换为标准化浮点数,用于计算或显示。 - 数据格式转换:在不同数据格式(如
Uint8
与Float32)之间转换时,保持数值的相对比例。
示例
- 若
value = 128
且array
是Uint8Array,则
denormalize(128, new Uint8Array())
返回128/255 ≈ 0.50196
。 - 若
value = -64
且array
是Int8Array
,则返回-64/127 ≈ -0.5039
(在 [-1, 1] 范围内)。
normalize函数
用于将 [0, 1] 范围内的浮点数 转换为 对应类型化数组(TypedArray)的数值,是 Three.js 中处理数据类型转换的核心工具函数,与 denormalize
函数互为逆操作。
js
/**
* @param {number} value - 待转换的浮点数,范围需在 [0, 1] 之间(通常是经过 denormalize 处理后的结果)。
* @param {TypedArray} array - 类型化数组实例(如 Uint8Array、Int16Array 等),用于指定目标数据类型。
* @return {number} 转换后的数值,类型与 array 一致(如 Uint8 类型的整数、Int32 类型的整数等)。
*/
function normalize( value, array ) {
switch ( array.constructor ) {
case Float32Array:
return value;
case Uint32Array:
return Math.round( value * 4294967295.0 );
case Uint16Array:
return Math.round( value * 65535.0 );
case Uint8Array:
return Math.round( value * 255.0 );
case Int32Array:
return Math.round( value * 2147483647.0 );
case Int16Array:
return Math.round( value * 32767.0 );
case Int8Array:
return Math.round( value * 127.0 );
default:
throw new Error( 'Invalid component type.' );
}
}
应用场景
在 Three.js 中常用于:
- 纹理数据编码:将 shader 输出的 [0, 1] 浮点颜色值转换为 Uint8Array 等类型化数组的整数像素值(如 RGB 分量),用于存储或传输。
- 缓冲区数据写入:将计算得到的浮点数(如顶点属性、法向量)转换为类型化数组的整数格式,减少内存占用或适配硬件要求。
- 数据格式转换:在浮点数与整数类型化数组之间转换时,保持数值的相对比例(如将 0.3 转换为 Uint8 类型的 77,即 0.3×255≈76.5 四舍五入)。
例如:
- 若
value=0.3
且array
是Uint8Array
,则normalize(0.3, new Uint8Array())
返回77
(0.3×255=76.5
四舍五入)。 - 若
value=0.8
且array
是Int16Array
,则返回26214
(0.8×32767=26213.6
四舍五入)。