bilca's picture
Upload 56 files
352fb85 verified
raw
history blame
1.74 kB
import { Box3 } from "./Box3";
class BVHNode {
public left: BVHNode | null = null;
public right: BVHNode | null = null;
public pointIndices: number[] = [];
constructor(
public bounds: Box3,
public boxes: Box3[],
pointIndices: number[],
) {
if (pointIndices.length > 1) {
this.split(bounds, boxes, pointIndices);
} else if (pointIndices.length > 0) {
this.pointIndices = pointIndices;
}
}
private split(bounds: Box3, boxes: Box3[], pointIndices: number[]) {
const axis = bounds.size().maxComponent();
pointIndices.sort((a, b) => boxes[a].center().getComponent(axis) - boxes[b].center().getComponent(axis));
const mid = Math.floor(pointIndices.length / 2);
const leftIndices = pointIndices.slice(0, mid);
const rightIndices = pointIndices.slice(mid);
this.left = new BVHNode(bounds, boxes, leftIndices);
this.right = new BVHNode(bounds, boxes, rightIndices);
}
public queryRange(range: Box3): number[] {
if (!this.bounds.intersects(range)) {
return [];
} else if (this.left !== null && this.right !== null) {
return this.left.queryRange(range).concat(this.right.queryRange(range));
} else {
return this.pointIndices.filter((index) => range.intersects(this.boxes[index]));
}
}
}
class BVH {
public root: BVHNode;
constructor(bounds: Box3, boxes: Box3[]) {
const pointIndices = boxes.map((_, index) => index);
this.root = new BVHNode(bounds, boxes, pointIndices);
}
public queryRange(range: Box3) {
return this.root.queryRange(range);
}
}
export { BVH };