Spaces:
Running
Running
File size: 1,741 Bytes
352fb85 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
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 };
|