深入解析 Three.js 中的三维三次贝塞尔曲线(CubicBezierCurve3)使用

person 少陵野老    watch_later 2024-11-17 10:02:51
visibility 17    class 三维三次贝塞尔曲线,CubicBezierCurve3    bookmark 专栏

CubicBezierCurve3 是 Three.js 提供的一种三维曲线,用于定义三次贝塞尔曲线的三维版本。它通过四个控制点灵活地创建曲线,可用于动画路径、复杂形状构造以及动态几何体生成。

本文将详细介绍 CubicBezierCurve3 的基本用法、属性方法以及实际案例,帮助你在 Three.js 项目中灵活使用这一强大的工具。


一、CubicBezierCurve3 简介

1.1 定义与作用

三维三次贝塞尔曲线的数学公式与二维类似:

B(t) = (1 - t)^3 P_0 + 3(1 - t)^2 t P_1 + 3(1 - t)t^2 P_2 + t^3 P_3 \quad (t \in [0, 1])

其中:

  • \( P_0 \): 起点。
  • \( P_1 \): 第一个控制点,决定曲线靠近起点的形状。
  • \( P_2 \): 第二个控制点,决定曲线靠近终点的形状。
  • \( P_3 \): 终点。

与二维版本的 CubicBezierCurve 不同,CubicBezierCurve3 工作在三维空间,所有控制点均是 Vector3 类型。


1.2 构造函数

const curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3);

参数说明:

  • v0: Vector3,起点。
  • v1: Vector3,第一个控制点。
  • v2: Vector3,第二个控制点。
  • v3: Vector3,终点。

二、CubicBezierCurve3 的属性和方法

2.1 属性

  • type: 曲线的类型,默认为 'CubicBezierCurve3'
  • v0, v1, v2, v3: 曲线的四个控制点。

2.2 方法

2.2.1 getPoint(t)

返回曲线在参数 \( t \) 处的点。

const point = curve.getPoint(0.5);
console.log(point); // Vector3 { x: ..., y: ..., z: ... }

2.2.2 getPoints(divisions)

返回曲线上分布的点数组。

const points = curve.getPoints(50);
console.log(points); // [Vector3, Vector3, ...]

2.2.3 getTangent(t)

返回曲线在参数 \( t \) 处的切线方向。

const tangent = curve.getTangent(0.5);
console.log(tangent); // Vector3 { x: ..., y: ..., z: ... }

2.2.4 clone()

克隆当前曲线对象。

const clonedCurve = curve.clone();
console.log(clonedCurve);

2.2.5 toJSON()

将曲线序列化为 JSON。

const json = curve.toJSON();
console.log(json);

2.2.6 fromJSON(json)

从 JSON 对象还原曲线。

const restoredCurve = new THREE.CubicBezierCurve3().fromJSON(json);
console.log(restoredCurve);

三、应用实例

3.1 基本三维曲线绘制

// 定义控制点
const v0 = new THREE.Vector3(0, 0, 0);
const v1 = new THREE.Vector3(10, 15, 5);
const v2 = new THREE.Vector3(20, -15, 5);
const v3 = new THREE.Vector3(30, 0, 0);

// 创建曲线
const curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3);

// 获取曲线上的点
const points = curve.getPoints(100);

// 转换为几何体
const geometry = new THREE.BufferGeometry().setFromPoints(points);

// 定义材质
const material = new THREE.LineBasicMaterial({ color: 0xff0000 });

// 创建线条并添加到场景
const line = new THREE.Line(geometry, material);
scene.add(line);

3.2 沿曲线移动的动画

以下代码展示如何让物体沿 CubicBezierCurve3 运动。

const sphere = new THREE.Mesh(
  new THREE.SphereGeometry(0.5, 16, 16),
  new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
scene.add(sphere);

let t = 0;
function animate() {
  t += 0.01;
  if (t > 1) t = 0;

  const point = curve.getPoint(t);
  sphere.position.set(point.x, point.y, point.z);

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

3.3 使用 TubeGeometry 创建三维管道

CubicBezierCurve3 可用于生成三维管道,适合制作隧道、轨道等场景。

const tubeGeometry = new THREE.TubeGeometry(curve, 100, 1, 16, false);
const material = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const tube = new THREE.Mesh(tubeGeometry, material);
scene.add(tube);

3.4 动态控制点生成曲线

允许用户通过拖动点动态更新曲线。

const controlPoint = new THREE.Mesh(
  new THREE.SphereGeometry(0.5),
  new THREE.MeshBasicMaterial({ color: 0xffff00 })
);
controlPoint.position.copy(v1);
scene.add(controlPoint);

function updateCurve() {
  curve.v1.copy(controlPoint.position);
  const points = curve.getPoints(100);
  geometry.setFromPoints(points);
}

controlPoint.addEventListener('drag', updateCurve);

四、进阶应用

4.1 结合多个 CubicBezierCurve3 创建复杂路径

const path = new THREE.CurvePath();
path.add(new THREE.CubicBezierCurve3(v0, v1, v2, v3));
path.add(new THREE.CubicBezierCurve3(v3, v4, v5, v6));

const geometry = new THREE.TubeGeometry(path, 200, 0.5, 16, false);
const material = new THREE.MeshBasicMaterial({ color: 0xffa500 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

4.2 创建空间轨迹

结合粒子系统,沿曲线生成一条动态轨迹。

const particles = new THREE.Points(
  new THREE.BufferGeometry().setFromPoints(curve.getPoints(100)),
  new THREE.PointsMaterial({ size: 0.1, color: 0x00ffcc })
);
scene.add(particles);

五、总结

CubicBezierCurve3 是 Three.js 提供的三维曲线工具,用于创建灵活的三次贝塞尔路径。无论是简单的路径绘制、动态动画,还是复杂的几何体构造,它都能胜任。通过掌握本文介绍的属性方法及实际案例,相信你可以在项目中自如地应用这一工具,打造丰富的三维场景效果。

评论区
评论列表
menu