threepipe
Version:
A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.
122 lines • 5.52 kB
JavaScript
import { Box2, Box3, BufferGeometry, Vector3 } from 'three';
export class Box3B extends Box3 {
constructor() {
super(...arguments);
this._vector = new Vector3();
}
expandByObject(object, precise = false, ignoreInvisible = false, ignoreObject) {
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. add else block to support custom computeBoundingBox without BufferGeometry
// 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);
const geometry = object.geometry;
if (geometry !== undefined) {
const positionAttribute = geometry.getAttribute('position');
// precise AABB computation based on vertex data requires at least a position attribute.
// instancing isn't supported so far and uses the normal (conservative) code path.
if (precise === true && positionAttribute !== undefined && Object.getPrototypeOf(geometry).computeBoundingBox === BufferGeometry.prototype.computeBoundingBox) {
for (let i = 0, l = positionAttribute.count; i < l; i++) {
if (object.isMesh === true) {
object.getVertexPosition(i, this._vector);
}
else {
this._vector.fromBufferAttribute(positionAttribute, i);
}
this._vector.applyMatrix4(object.matrixWorld);
this.expandByPoint(this._vector);
}
}
else {
if (object.boundingBox !== undefined) {
// object-level bounding box
if ((precise || object.boundingBox === null) && typeof object.computeBoundingBox === 'function') {
// @ts-expect-error why?
object.computeBoundingBox();
}
// _box.copy(object.boundingBox)
if (object.boundingBox !== null) {
Box3B._box.copy(object.boundingBox);
Box3B._box.applyMatrix4(object.matrixWorld);
this.union(Box3B._box);
}
else {
console.warn('Box3B - Unable to compute bounds for', object);
}
}
else {
// geometry-level bounding box
if (geometry.boundingBox === null) {
geometry.computeBoundingBox();
}
if (geometry.boundingBox) {
Box3B._box.copy(geometry.boundingBox);
Box3B._box.applyMatrix4(object.matrixWorld);
this.union(Box3B._box);
}
else {
console.warn('Box3B - Unable to compute bounds for', object, geometry);
}
}
}
}
else if (object.boundingBox !== undefined) {
// object-level bounding box
if ((precise || object.boundingBox === null) && typeof object.computeBoundingBox === 'function') {
// @ts-expect-error why?
object.computeBoundingBox();
}
// _box.copy(object.boundingBox)
if (object.boundingBox !== null) {
Box3B._box.copy(object.boundingBox);
Box3B._box.applyMatrix4(object.matrixWorld);
this.union(Box3B._box);
}
else {
console.warn('Box3B - Unable to compute bounds for', object);
}
}
const children = object.children;
for (let i = 0, l = children.length; i < l; i++) {
this.expandByObject(children[i], precise, ignoreInvisible);
}
return this;
}
expandByObjects(objects, precise = false, ignoreInvisible = false) {
for (let i = 0, l = objects.length; i < l; i++)
this.expandByObject(objects[i], precise, ignoreInvisible);
return this;
}
/**
* Get corner points.
*/
getPoints() {
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) {
const vertices = this.getPoints();
const box = new Box2();
for (const vertex of vertices) {
const vertexScreenSpace = vertex.project(camera);
box.min.min(vertexScreenSpace);
box.max.max(vertexScreenSpace);
}
return box;
}
}
Box3B._box = new Box3B();
//# sourceMappingURL=Box3B.js.map