javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > Three.js实现OBBHelper

Three.js中实现一个OBBHelper实例详解

作者:当时明月在曾照彩云归

这篇文章主要介绍了Three.js中实现一个OBBHelper,本文参考Box3Helper源码,并写出一个OBBHelper,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下

本文参考Box3Helper源码,并写出一个OBBHelper

1. 引言

Three.js中,Box3对象指的是AABB式的包围盒,这种包围盒会随物体的旋转而变换大小,精度较差

Three.js中还有OBB对象,这是一种能表现物体主要特征的、不随物体的旋转而变换大小的包围盒

两者如下图所示:

Three.js中虽然有OBB,却没有OBB Helper,即OBB包围盒线框对象

本文参考Box3Helper源码,并写出一个OBBHelper

2. Box3Helper

以下是Three.js源码中的Box3Helper:

import { LineSegments } from '../objects/LineSegments.js';
import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
import { BufferAttribute, Float32BufferAttribute } from '../core/BufferAttribute.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
class Box3Helper extends LineSegments {
	constructor( box, color = 0xffff00 ) {
		const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
		const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ];
		const geometry = new BufferGeometry();
		geometry.setIndex( new BufferAttribute( indices, 1 ) );
		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
		this.box = box;
		this.type = 'Box3Helper';
		this.geometry.computeBoundingSphere();
	}
	updateMatrixWorld( force ) {
		const box = this.box;
		if ( box.isEmpty() ) return;
		box.getCenter( this.position );
		box.getSize( this.scale );
		this.scale.multiplyScalar( 0.5 );
		super.updateMatrixWorld( force );
	}
	dispose() {
		this.geometry.dispose();
		this.material.dispose();
	}
}
export { Box3Helper };
 

这段代码是一个名为 Box3Helper 的类的定义,它继承自 LineSegments 类。 Box3Helper 类用于创建一个辅助框,用来可视化 Box3 对象的边界框。

代码中首先导入了一些依赖的模块,包括 LineSegments LineBasicMaterial BufferAttribute Float32BufferAttribute BufferGeometry

Box3Helper 类的构造函数中,首先创建了一个表示边界框的索引数组 indices ,然后创建了一个表示边界框的顶点坐标数组 positions

接下来,创建了一个 BufferGeometry 对象,并使用 indices 数组创建了一个 BufferAttribute 对象来表示索引,使用 positions 数组创建了一个 Float32BufferAttribute 对象来表示顶点坐标。然后将这两个属性设置到 geometry 对象中。

然后调用父类 LineSegments 的构造函数,传入 geometry 和一个 LineBasicMaterial 对象作为参数,来创建一个可视化边界框的线段对象。

接着,将传入构造函数的 box 参数赋值给 this.box 属性。

然后设置 this.type 属性为 'Box3Helper'

最后调用 geometry 对象的 computeBoundingSphere 方法来计算边界球。

Box3Helper 类还定义了一个 updateMatrixWorld 方法,用于更新辅助框的世界矩阵。在该方法中,首先获取 this.box 的中心点和尺寸,然后根据尺寸缩放辅助框的比例,并调用父类的 updateMatrixWorld 方法来更新世界矩阵。

最后,定义了一个 dispose 方法,用于释放资源,包括释放 geometry material 对象。

最后通过 export 语句将 Box3Helper 类导出,以便在其他地方使用。

3. OBBHelper

参考上面的代码。给出OBBHelper的代码如下:

import {
	Vector3, LineSegments, LineBasicMaterial,
	BufferAttribute, Float32BufferAttribute, BufferGeometry
} from 'three';
class OBBHelper extends LineSegments {
	constructor(obb, object, color = 0xffff00) {
		const indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7, 0, 2, 1, 3, 4, 6, 5, 7]);
		const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ];
		const geometry = new BufferGeometry();
		geometry.setIndex(new BufferAttribute(indices, 1));
		geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
		super(geometry, new LineBasicMaterial({ color: color, toneMapped: false }));
		this.obb = obb;
		this.object = object;
		this.type = 'OBBHelper';
		this.lastMatrix4 = object.matrixWorld.clone();
	}
	updateMatrixWorld(force) {
		this.obb.applyMatrix4(this.lastMatrix4.invert())
		this.obb.applyMatrix4(this.object.matrixWorld);
		this.lastMatrix4 = this.object.matrixWorld.clone();
		const positions = this.geometry.attributes.position.array;
		const halfSize = this.obb.halfSize;
		const center = this.obb.center;
		const rotation = this.obb.rotation;
		const corners = [];
		for (let i = 0; i < 8; i++) {
			const corner = new Vector3();
			corner.x = (i & 1) ? center.x + halfSize.x : center.x - halfSize.x;
			corner.y = (i & 2) ? center.y + halfSize.y : center.y - halfSize.y;
			corner.z = (i & 4) ? center.z + halfSize.z : center.z - halfSize.z;
			corner.applyMatrix3(rotation);
			corners.push(corner);
		}
		for (let i = 0; i < corners.length; i++) {
			const corner = corners[i];
			positions[i * 3] = corner.x;
			positions[i * 3 + 1] = corner.y;
			positions[i * 3 + 2] = corner.z;
		}
		this.geometry.attributes.position.needsUpdate = true;
		super.updateMatrixWorld(force);
	}
	dispose() {
		this.geometry.dispose();
		this.material.dispose();
	}
}
export { OBBHelper };

这段代码是一个自定义的 OBBHelper 类,用于创建一个辅助对象来显示一个方向包围盒(OBB)的边界框。以下是代码的解释:

导入了所需的 Three.js 模块和类。这些模块和类包括 Vector3 LineSegments LineBasicMaterial BufferAttribute Float32BufferAttribute BufferGeometry

OBBHelper 类继承自 LineSegments 类,因此它是一个线段对象。

OBBHelper 构造函数接收三个参数: obb object color obb 是一个方向包围盒对象, object 是一个 Three.js 对象, color 是边界框的颜色,默认为黄色(0xffff00)。

通过使用这个 OBBHelper 类,可以创建一个辅助对象来显示一个方向包围盒的边界框,并将其添加到场景中以进行渲染和显示。

实现的效果如下(黄色为Box3Helper,红色为OBBHelper):

4. 参考资料

[1] OBB – three.js docs (three3d.cn)

[2] three.js/src/helpers/Box3Helper.js at master · mrdoob/three.js (github.com)

[3] three.js examples (three3d.cn)

[4] three.js/examples/jsm/math/OBB.js at master · mrdoob/three.js (github.com)

[5] BufferGeometry.boundingBox的应用:BoxHelper的实现 

[6] 113 Three.js的obb (OrientedboundingBox)方向包围盒的使用

到此这篇关于Three.js中实现一个OBBHelper的文章就介绍到这了,更多相关Three.js实现OBBHelper内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文