import { Plane } from './Plane' import { Vec3 } from '../../math/Vec3'; import { Mat4 } from '../../math/Mat4'; import { BufferGeometry } from '../../render/geometry'; import { Sphere } from './Sphere'; import { applyMat4 } from '../../alg/pointset'; import { Segment } from './Segment'; import { Path } from './Path'; const _sphere = new Sphere() /** * 视锥体 */ export class Frustum { planes: Plane[] = [new Plane(), new Plane(), new Plane(), new Plane(), new Plane(), new Plane()]; constructor() { } get front(): Plane { return this.planes[0] } get back(): Plane { return this.planes[1] } get top(): Plane { return this.planes[2] } get bottom(): Plane { return this.planes[3] } get left(): Plane { return this.planes[4] } get right(): Plane { return this.planes[5] } /** * 从投影矩阵计算视锥体 * @param m * @returns */ setFromProjectionMatrix(m: Mat4) { const planes = this.planes; const me = m.elements; const me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3]; const me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7]; const me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11]; const me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15]; planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me12 - me15).normalize(); planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me12 + me15).normalize(); planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me13 + me15).normalize(); planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me13 - me15).normalize(); planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me14 - me15).normalize(); planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me14 + me15).normalize(); return this; } static fromProjectionMatrix(m: Mat4) { return new Frustum().setFromProjectionMatrix(m); } setFromPerspective(position: Vec3, target: Vec3, up: Vec3, fov: number, aspect: number, near: number, far: number) { const direction = target.clone().sub(position); } intersectsObject(geometry: BufferGeometry, mat: Mat4) { if (!geometry.boundingSphere) geometry.computeBoundingSphere(); _sphere.copy(geometry.boundingSphere!).applyMat4(mat); return this.intersectsSphere(_sphere); } // intersectsSprite(sprite) { // _sphere.center.set(0, 0, 0); // _sphere.radius = 0.7071067811865476; // _sphere.applyMatrix4(sprite.matrixWorld); // return this.intersectsSphere(_sphere); // } intersectsSphere(sphere: Sphere) { const planes = this.planes; const center = sphere.center; const negRadius = - sphere.radius; for (let i = 0; i < 6; i++) { const distance = planes[i].distancePoint(center); if (distance < negRadius) { return false; } } return true; } containsPoint(point: Vec3) { const planes = this.planes; for (let i = 0; i < 6; i++) { if (planes[i].distancePoint(point) < 0) { return false; } } return true; } intersectSegment(segment: Segment | Vec3[]) { const planes = this.planes; for (let i = 0; i < 6; i++) { const intersectPoint = planes[i].intersectSegmentLw(segment) if (intersectPoint !== null) { return intersectPoint; } } return null; } simpleIntersectVS(vs: Vec3[]) { const contains: boolean[] = vs.map(v => this.containsPoint(v)) const res = [] let oneres = [] for (let i = 0; i < vs.length - 1; i++) { const p: Vec3 = vs[i]; const p1: Vec3 = vs[i + 1]; const c0 = contains[i] const c1 = contains[i + 1] if (c0) { oneres.push(p); if (!c1) { oneres.push(p1) res.push(oneres); oneres = [] } } else { if (c1) { oneres.push(c0); } res.push(c1) } } //添加末段 if (oneres.length > 0) res.push(oneres); return res; } copy(frustum: Frustum) { } clone() { return new (this as any).constructor().copy(this); } }