Three.js 数学工具:构建精确3D世界的基石

文章目录

    • 前言
    • 一、向量(Vectors)
    • 二、矩阵(Matrices)
    • 三、四元数(Quaternions)
    • [四、欧拉角(Euler Angles)](#四、欧拉角(Euler Angles))
    • 五、颜色(Colors)
    • [六、几何体生成器(Geometry Generators)](#六、几何体生成器(Geometry Generators))
    • [七、随机数生成(Random Number Generation)](#七、随机数生成(Random Number Generation))
    • [八、时间和动画(Time and Animation)](#八、时间和动画(Time and Animation))
    • [九、光线追踪与碰撞检测(Ray Tracing and Collision Detection)](#九、光线追踪与碰撞检测(Ray Tracing and Collision Detection))
    • [十、曲线与路径(Curves and Paths)](#十、曲线与路径(Curves and Paths))
    • [十一、数学常量与实用函数(Math Constants and Utility Functions)](#十一、数学常量与实用函数(Math Constants and Utility Functions))
    • 结语

前言

在创建复杂的3D图形和动画时,数学扮演着不可或缺的角色。Three.js 提供了一套强大且易于使用的数学工具库,这些工具帮助开发者处理从基本的几何变换到高级物理模拟的各种任务。本文将深入探讨 Three.js 中提供的数学工具,并通过具体的代码示例来说明如何利用它们为你的项目增添精度与灵活性。


一、向量(Vectors)

向量是表示位置、方向或速度等概念的基础数据结构。Three.js 支持多种类型的向量,包括 Vector2, Vector3Vector4,分别用于二维、三维和四维空间中的计算。

创建和操作向量

javascript 复制代码
// 创建一个三维向量
const vector = new THREE.Vector3(1, 0, 0);

// 执行基本运算
vector.add(new THREE.Vector3(0, 1, 0)); // 加法
vector.sub(new THREE.Vector3(0, 1, 0)); // 减法
vector.multiplyScalar(2);               // 标量乘法
vector.normalize();                     // 归一化

// 计算两个向量之间的角度
const angle = vector.angleTo(new THREE.Vector3(0, 1, 0));

// 计算点积和叉积
const dotProduct = vector.dot(new THREE.Vector3(0, 1, 0));
const crossProduct = vector.cross(new THREE.Vector3(0, 1, 0));

// 应用到对象的位置或旋转
object.position.copy(vector);
object.quaternion.setFromUnitVectors(object.up, vector);

二、矩阵(Matrices)

矩阵用于描述物体的空间变换,如平移、旋转和缩放。Three.js 提供了 Matrix4 类来进行这些操作,并支持矩阵之间的乘法以组合多个变换。

应用矩阵变换

javascript 复制代码
// 创建一个四元数并应用旋转
const quaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 4);
const matrix = new THREE.Matrix4();
matrix.makeRotationFromQuaternion(quaternion);

// 将矩阵应用于对象
object.applyMatrix4(matrix);

// 组合平移、旋转和缩放
const translateMatrix = new THREE.Matrix4().makeTranslation(1, 0, 0);
const rotationMatrix = new THREE.Matrix4().makeRotationX(Math.PI / 4);
const scaleMatrix = new THREE.Matrix4().makeScale(2, 1, 1);

// 组合所有变换
const combinedMatrix = new THREE.Matrix4();
combinedMatrix.multiplyMatrices(translateMatrix, rotationMatrix);
combinedMatrix.multiply(scaleMatrix);

// 应用组合后的矩阵
object.applyMatrix4(combinedMatrix);

三、四元数(Quaternions)

四元数是一种高效的旋转表示方法,避免了万向锁问题。Three.js 的 Quaternion 类提供了简单易用的接口来管理旋转。

使用四元数进行旋转

javascript 复制代码
// 创建一个四元数并设置旋转角度
const quaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 4);

// 应用旋转到对象
object.quaternion.copy(quaternion);

// 插值两个四元数之间的旋转
const targetQuaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
quaternion.slerp(targetQuaternion, 0.5); // 线性插值

// 更新对象的旋转
object.quaternion.copy(quaternion);

四、欧拉角(Euler Angles)

欧拉角提供了一种直观的方式来指定旋转顺序,尽管它容易导致万向锁的问题。Three.js 的 Euler 类允许你定义绕 X、Y 和 Z 轴的旋转角度。

使用欧拉角进行旋转

javascript 复制代码
// 创建一个欧拉角实例
const euler = new THREE.Euler(Math.PI / 4, 0, 0, 'XYZ');

// 应用到对象的旋转属性
object.rotation.setFromEuler(euler);

// 修改欧拉角的值
euler.x += Math.PI / 8;
object.rotation.setFromEuler(euler);

// 注意:避免直接修改 rotation 属性,因为这可能导致不一致的状态

五、颜色(Colors)

颜色不仅是视觉效果的重要组成部分,而且在材质和光照中也起着关键作用。Three.js 的 Color 类简化了颜色的创建和操作。

创建和操作颜色

javascript 复制代码
// 创建一个颜色实例
const color = new THREE.Color(0xff0000); // 红色

// 修改颜色值
color.setRGB(0, 1, 0); // 变为绿色
color.setHSL(0.5, 1, 0.5); // 使用 HSL 设置颜色

// 应用到材质
material.color.copy(color);

// 获取颜色的十六进制表示
console.log(`颜色的十六进制表示: ${color.getHexString()}`);

// 设置颜色的透明度
material.opacity = 0.5;
material.transparent = true; // 必须开启透明度

六、几何体生成器(Geometry Generators)

Three.js 提供了一系列内置的几何体生成器,如 BoxGeometry, SphereGeometry 等,用于快速创建常见形状。此外,还可以通过自定义顶点和面来构建复杂的几何体。

创建几何体

javascript 复制代码
// 创建一个立方体几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);

// 创建一个球体几何体
const sphereGeometry = new THREE.SphereGeometry(0.5, 32, 32);

// 自定义几何体
const customGeometry = new THREE.Geometry();
customGeometry.vertices.push(
    new THREE.Vector3(-1, -1, 0),
    new THREE.Vector3(1, -1, 0),
    new THREE.Vector3(0, 1, 0)
);
customGeometry.faces.push(new THREE.Face3(0, 1, 2));

// 创建网格并添加到场景
const mesh = new THREE.Mesh(customGeometry, material);
scene.add(mesh);

七、随机数生成(Random Number Generation)

虽然 Three.js 没有直接提供随机数生成函数,但可以结合 JavaScript 的 Math.random() 来实现这一功能,这对于创建程序化内容非常有用。

生成随机数

javascript 复制代码
// 生成介于 min 和 max 之间的随机浮点数
function getRandomFloat(min, max) {
    return (max - min) * Math.random() + min;
}

// 示例:生成随机位置的球体
for (let i = 0; i < 100; i++) {
    const sphere = new THREE.Mesh(
        new THREE.SphereGeometry(0.1, 16, 16),
        new THREE.MeshBasicMaterial({ color: 0xffffff * Math.random() })
    );
    sphere.position.set(
        getRandomFloat(-5, 5),
        getRandomFloat(-5, 5),
        getRandomFloat(-5, 5)
    );
    scene.add(sphere);
}

八、时间和动画(Time and Animation)

时间管理对于创建流畅的动画至关重要。Three.js 提供了 Clock 类来跟踪时间,并结合 requestAnimationFrame 实现平滑的动画更新。

管理时间和动画

javascript 复制代码
// 创建一个时钟实例
const clock = new THREE.Clock();

// 在动画循环中获取经过的时间
function animate() {
    requestAnimationFrame(animate);

    const delta = clock.getDelta(); // 获取上一帧到当前帧的时间差
    object.rotation.x += delta * 0.1; // 根据时间调整旋转速度

    renderer.render(scene, camera);
}
animate();

// 使用 Tween.js 进行补间动画
import { Tween } from '@tweenjs/tween.js';

new Tween(object.position)
    .to({ x: 5 }, 1000) // 目标位置和持续时间
    .start();

九、光线追踪与碰撞检测(Ray Tracing and Collision Detection)

光线追踪用于模拟光的行为,而碰撞检测则用于确定物体是否相交。Three.js 提供了 Raycaster 类来实现这两种功能。

javascript 复制代码
// 创建 Raycaster 和鼠标位置变量
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

// 监听鼠标点击事件
window.addEventListener('click', (event) => {
    // 将鼠标位置标准化为设备坐标 (-1 到 +1)
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    // 更新 Raycaster 的方向向量
    raycaster.setFromCamera(mouse, camera);

    // 检查交点
    const intersects = raycaster.intersectObjects(scene.children);
    if (intersects.length > 0) {
        console.log('点击的对象:', intersects[0].object);
    }
});

// 碰撞检测
function checkCollisions(objectA, objectB) {
    const distance = objectA.position.distanceTo(objectB.position);
    return distance < (objectA.geometry.boundingSphere.radius + objectB.geometry.boundingSphere.radius);
}

十、曲线与路径(Curves and Paths)

曲线和路径用于定义物体的运动轨迹或其他复杂形状。Three.js 提供了多种曲线类型,如 LineCurve3, CubicBezierCurve3SplineCurve

创建和使用曲线

javascript 复制代码
// 创建一条贝塞尔曲线
const curve = new THREE.CubicBezierCurve3(
    new THREE.Vector3(-1, 0, 0),
    new THREE.Vector3(-0.5, 1, 0),
    new THREE.Vector3(0.5, 1, 0),
    new THREE.Vector3(1, 0, 0)
);

// 获取曲线上某一点的位置
const point = curve.getPoint(0.5);

// 创建路径并添加到场景
const path = new THREE.Path(curve.getPoints(50));
const geometry = path.createPointsGeometry();
const material = new THREE.LineBasicMaterial({ color: 0x0000ff });
const line = new THREE.Line(geometry, material);
scene.add(line);

十一、数学常量与实用函数(Math Constants and Utility Functions)

Three.js 提供了一些常用的数学常量和实用函数,如 MathUtils,方便进行各种数学运算。

使用数学常量和实用函数

javascript 复制代码
// 使用 PI 常量
const pi = Math.PI;

// 使用 MathUtils 中的方法
const radians = THREE.MathUtils.degToRad(90); // 将度数转换为弧度
const degrees = THREE.MathUtils.radToDeg(radians); // 将弧度转换为度数

// 计算两点间的距离
const distance = THREE.MathUtils.euclideanModulo(pointA.x - pointB.x, 10);

结语

Three.js 的数学工具不仅限于上述几种方式,还包括更多高级特性,如光线追踪、碰撞检测等。掌握这些数学工具,可以帮助你在创建3D内容时提供更加精确和灵活的操作。无论你是希望构建一个教育性的演示文稿,还是开发一款复杂的游戏,Three.js 的数学能力都能为你提供强有力的支持。

相关推荐
万物得其道者成14 分钟前
在高德地图上加载3DTilesLayer图层模型/天地瓦片
前端·javascript·3d
你挚爱的强哥1 小时前
基于element UI el-dropdown打造表格操作列的“更多⌵”上下文关联菜单
javascript·vue.js·elementui
林涧泣2 小时前
【Uniapp-Vue3】uniapp创建组件
前端·javascript·uni-app
sunly_2 小时前
Flutter:文章详情页,渲染富文本
android·javascript·flutter
丁总学Java2 小时前
[Vue warn]: Unknown custom element:
javascript·vue.js·ecmascript
摇光933 小时前
js状态模式
开发语言·javascript·状态模式
_未知_开摆4 小时前
css盒子水平垂直居中
前端·javascript·html
MossGrower4 小时前
58. Three.js案例-创建一个带有红蓝配置的半球光源的场景
three.js·webglrender·hemispherelig·spheregeometry
长风清留扬4 小时前
小程序在智慧城市构建中的角色与功能研究
javascript·css·人工智能·微信小程序·小程序·html·智慧城市
大嘴史努比5 小时前
前端-如何做一个关键字生成组件
前端·javascript·css