xtorcga
Version:
Xtor Compute Geometry Algorithm Libary 计算几何算法库
190 lines (136 loc) • 4.83 kB
text/typescript
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);
}
}