export class Frustum { constructor(planes) { if(!Frustum.#validatePlanes(planes)) throw(new Error('Invalid frustum planes')) this.planes = planes.map(p => ({ ...p })) } static #validatePlanes(planes) { if(!Array.isArray(planes) || planes.length !== 6) return(false) for(const p of planes) { if(!p || typeof(p) !== 'object') return(false) if(typeof(p.nx) !== 'number' || Number.isNaN(p.nx)) return(false) if(typeof(p.ny) !== 'number' || Number.isNaN(p.ny)) return(false) if(typeof(p.nz) !== 'number' || Number.isNaN(p.nz)) return(false) if(typeof(p.d) !== 'number' || Number.isNaN(p.d)) return(false) } return(true) } static fromPlanes(planes) { if(!Frustum.#validatePlanes(planes)) return(null) return(new Frustum(planes)) } containsPoint(position) { for(const p of this.planes) { const dist = p.nx * position.x + p.ny * position.y + p.nz * position.z + p.d if(dist < 0) return(false) } return(true) } }