Spaces:
Running
Running
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 }; | |