UNPKG

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.

77 lines (71 loc) 3.1 kB
import {Box2, BufferAttribute, Camera, InterleavedBufferAttribute, Mesh, Object3D, Vector2, Vector3} from 'three' export function computeScreenSpaceBoundingBox(obj: Object3D, camera: Camera) { let min: Vector2|undefined let max: Vector2|undefined // Is this an array of objects? if (Array.isArray(obj)) { for (const oo of obj) { const box2 = computeScreenSpaceBoundingBox(oo, camera) if (min === undefined || max === undefined) { min = box2.min.clone() max = box2.max.clone() } else { min.min(box2.min) max.max(box2.max) } } } // Does this object have geometry? const mesh = obj as Mesh if (mesh.geometry !== undefined) { const vertices = (mesh.geometry as any).vertices // legacy Geometry support if (vertices === undefined && mesh.geometry.attributes !== undefined && 'position' in mesh.geometry.attributes) { // Buffered geometry const vertex = new Vector3() const pos = mesh.geometry.attributes.position as any as BufferAttribute | InterleavedBufferAttribute for (let i = 0; i < pos.count * pos.itemSize; i += pos.itemSize) { vertex.set(pos.array[i], pos.array[i + 1], pos.array[1 + 2]) const vertexWorldCoord = vertex.applyMatrix4(obj.matrixWorld) const vertexScreenSpace = vertexWorldCoord.project(camera) const vertexScreenSpaced = new Vector2(vertexScreenSpace.x, vertexScreenSpace.y) if (min === undefined || max === undefined) { min = vertexScreenSpaced.clone() max = vertexScreenSpaced.clone() } else { min.min(vertexScreenSpaced) max.max(vertexScreenSpaced) } } } else { // legacy Geometry support for (const vertex of vertices) { const vertexWorldCoord = vertex.clone().applyMatrix4(obj.matrixWorld) const vertexScreenSpace = vertexWorldCoord.project(camera) const vertexScreenSpaced = new Vector2(vertexScreenSpace.x, vertexScreenSpace.y) if (min === undefined || max === undefined) { min = vertexScreenSpaced.clone() max = vertexScreenSpaced.clone() } else { min.min(vertexScreenSpaced) max.max(vertexScreenSpaced) } } } } // Does this object have children? if (obj.children !== undefined) { for (const oo of obj.children) { const box2 = computeScreenSpaceBoundingBox(oo, camera) if (min === undefined || max === undefined) { min = box2.min.clone() max = box2.max.clone() } else { min.min(box2.min) max.max(box2.max) } } } return new Box2(min, max) }