Three.js教程
入门
辅助对象

Three.js 的辅助对象

在 Three.js 中,辅助对象(Helpers)是非常有用的工具,它们帮助开发者在调试 3D 场景时更直观地理解对象的布局、方向和空间关系。本文将介绍 Three.js 提供的几种主要辅助对象,并演示它们的使用方式。

辅助对象是 Three.js 提供的一些用于可视化 3D 场景元素的工具。它们通常不会在最终渲染的场景中出现,而是作为开发和调试的参考。

这篇文章,我们来介绍下 ArrowHelper 、AxesHelper 、BoxHelper 、Box3Helper、CameraHelper。

ArrowHelper

用于在 3D 场景中显示一个箭头,通常用于可视化方向向量,帮助调试坐标方向、法线、速度向量等。

import * as THREE from "three";
// 创建场景
const scene = new THREE.Scene();
// 定义箭头的方向(必须归一化)
const direction = new THREE.Vector3(1, 1, 0).normalize();
// 定义箭头的起点
const origin = new THREE.Vector3(0, 0, 0);
// 定义箭头长度
const length = 2;
// 定义箭头颜色
const color = 0xffff00; // 黄色
// 创建箭头助手
const arrowHelper = new THREE.ArrowHelper(direction, origin, length, color);
// 添加到场景
scene.add(arrowHelper);

参数

ArrowHelper(dir : Vector3 (opens in a new tab), origin : Vector3 (opens in a new tab), length : Number, hex : Number, headLength : Number, headWidth : Number )

  • dir: 基于箭头原点的方向. 必须为单位向量.
  • origin: 箭头的原点.
  • length: 箭头的长度. 默认为 1.
  • hex: 定义的 16 进制颜色值. 默认为 0xffff00.
  • headLengt: 箭头头部的长度,默认值为 0.2 * length
  • headWidth : 箭头头部的宽度,默认值为 0.2 * headLength

AxesHelper

AxesHelper 用于在 3D 场景中可视化坐标轴,帮助开发者更直观地理解物体的方向和旋转状态。通常用于调试 Three.js 场景中的坐标系。

红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.

const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

参数

AxesHelper( size : Number )

  • size:  (可选的) 表示代表轴的线段长度. 默认为  1.

BoxHelper

BoxHelper 用于在 3D 场景中可视化物体的包围盒 (Bounding Box),通常用于调试和检测物体的边界。

// 创建 BoxHelper,并添加到场景
const boxHelper = new THREE.BoxHelper(cube, 0xff0000); // 红色边框
scene.add(boxHelper);

参数

BoxHelper( object : Object3D (opens in a new tab), color : Color (opens in a new tab) )

  • object: (可选的) 被展示世界轴心对齐的包围盒的对象.
  • color :(可选的) 线框盒子的 16 进制颜色值. 默认为 0xffff00.

Box3Helper

Box3Helper 用于可视化 Box3(轴对齐包围盒,AABB,Axis-Aligned Bounding Box)
通常用于调试模型边界碰撞检测计算物体包围范围等场景。

BoxHelper 适用于单个 MeshGroup,会自动计算物体的包围盒,但不会用于碰撞检测;而 Box3Helper 适用于手动定义 Box3 包围盒,可以计算多个对象的整体边界,并支持碰撞检测。若需简单可视化 Mesh 的边界,用 BoxHelper;若需手动设定范围或合并多个物体的边界,用 Box3Helper

// 创建立方体
const group = new THREE.Group();
 
// 立方体
const cube = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), new THREE.MeshBasicMaterial({ color: 0x00ff00 }));
group.add(cube);
 
// 球体
const sphere = new THREE.Mesh(new THREE.SphereGeometry(1), new THREE.MeshBasicMaterial({ color: 0xff0000 }));
sphere.position.set(3, 0, 0); // 移动球体
group.add(sphere);
 
// 计算整个 Group 的包围盒
const groupBox = new THREE.Box3().setFromObject(group);
const box3Helper = new THREE.Box3Helper(groupBox, 0xffff00);
scene.add(box3Helper);
scene.add(group);

参数

Box3Helper( box : Box3 (opens in a new tab), color : Color (opens in a new tab) )

  • box:被模拟的 3 维包围盒.
  • color: (可选的) 线框盒子的颜色. 默认为 0xffff00.

CameraHelper

CameraHelper 会在 3D 场景中绘制摄像机的视锥体,用来表示摄像机的视野范围近平面、远平面等信息。
适用于:

  • 调试相机位置、方向
  • 查看相机视锥体是否正确覆盖目标
  • 检查 shadowCamera(阴影相机)是否对物体完全照射

为了演示效果,我们需要创建两个摄像机,一个用来创建 helper,一个用来观察 helper。

  • 创建 mainCamera 作为观察相机
  • targetCamera 旋转移动
  • 添加 cube 作为参考物体
import * as THREE from "three";
 
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
 
// 创建场景
const scene = new THREE.Scene();
 
//  创建主摄像机(用于观察 CameraHelper)
const mainCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 20);
mainCamera.position.set(5, 5, 10);
mainCamera.lookAt(0, 0, 0);
scene.add(mainCamera);
 
//  创建需要被观察的摄像机
const targetCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10);
targetCamera.position.set(2, 2, 5);
scene.add(targetCamera);
 
//  可视化 targetCamera
const cameraHelper = new THREE.CameraHelper(targetCamera);
scene.add(cameraHelper);
 
//  添加一个立方体方便参考
const cube = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0x00ff00 }));
scene.add(cube);
 
// 添加环境光,让场景更清晰
const light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);
 
//  动画循环
function animate() {
  requestAnimationFrame(animate);
 
  // 让被观察的相机(targetCamera)旋转,以观察 CameraHelper 变化
  targetCamera.position.x = Math.sin(Date.now() * 0.001) * 3;
  targetCamera.position.z = Math.cos(Date.now() * 0.001) * 3;
  targetCamera.lookAt(0, 0, 0);
 
  // 更新 CameraHelper
  cameraHelper.update();
 
  // 渲染场景,使用 mainCamera 作为主相机
  renderer.render(scene, mainCamera);
}
animate();

参数

CameraHelper( camera : Camera (opens in a new tab) )

  • camera:被模拟的相机.