UNPKG

threepipe

Version:

A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.

99 lines (75 loc) 3.71 kB
import {Box2, Box3, BufferAttribute, Camera, InterleavedBufferAttribute, Mesh, Object3D, Vector3} from 'three' import type {IObject3D} from '../../core' export class Box3B extends Box3 { private static _box = new Box3B() private _vector = new Vector3() expandByObject(object: Object3D|IObject3D, precise = false, ignoreInvisible = false, ignoreObject?: (obj: Object3D)=>boolean): this { if (object.userData?.bboxVisible === false) return this if (!object.visible && ignoreInvisible) return this if (ignoreObject && ignoreObject(object)) return this // copied the whole function from three.js to pass in ignoreInvisible // Computes the world-axis-aligned bounding box of an object (including its children), // accounting for both the object's, and children's, world transforms object.updateWorldMatrix(false, false) // InstancedMesh has boundingBox = null, so it can be computed if ((object as any).boundingBox !== undefined) { if ((object as any).boundingBox === null) { (object as any).computeBoundingBox() } Box3B._box.copy((object as any).boundingBox) Box3B._box.applyMatrix4(object.matrixWorld) this.union(Box3B._box) } else { const geometry = (object as Mesh).geometry if (geometry !== undefined) { if (precise && geometry.attributes != undefined && geometry.attributes.position !== undefined) { const position = geometry.attributes.position as any as BufferAttribute | InterleavedBufferAttribute for (let i = 0, l = position.count; i < l; i++) { this._vector.fromBufferAttribute(position, i).applyMatrix4(object.matrixWorld) this.expandByPoint(this._vector) } } else { if (geometry.boundingBox === null) geometry.computeBoundingBox() Box3B._box.copy(geometry.boundingBox!) Box3B._box.applyMatrix4(object.matrixWorld) this.union(Box3B._box) } } } const children = object.children for (let i = 0, l = children.length; i < l; i++) { this.expandByObject(children[ i ], precise, ignoreInvisible) } return this } expandByObjects(objects: (Object3D|IObject3D)[], precise = false, ignoreInvisible = false): this { for (let i = 0, l = objects.length; i < l; i++) this.expandByObject(objects[i], precise, ignoreInvisible) return this } /** * Get corner points. */ getPoints(): Vector3[] { return [ new Vector3(this.min.x, this.min.y, this.min.z), // 000 new Vector3(this.min.x, this.min.y, this.max.z), // 001 new Vector3(this.min.x, this.max.y, this.min.z), // 010 new Vector3(this.min.x, this.max.y, this.max.z), // 011 new Vector3(this.max.x, this.min.y, this.min.z), // 100 new Vector3(this.max.x, this.min.y, this.max.z), // 101 new Vector3(this.max.x, this.max.y, this.min.z), // 110 new Vector3(this.max.x, this.max.y, this.max.z), // 111 ] } getScreenSpaceBounds(camera: Camera): Box2 { const vertices = this.getPoints() const box = new Box2() for (const vertex of vertices) { const vertexScreenSpace = vertex.project(camera) box.min.min(vertexScreenSpace as any) box.max.max(vertexScreenSpace as any) } return box } }