Spaces:
Running
Running
| import { Camera } from "../../../cameras/Camera"; | |
| import { Vector3 } from "../../../math/Vector3"; | |
| import { Splat } from "../../../splats/Splat"; | |
| import { RenderProgram } from "../programs/RenderProgram"; | |
| import { Box3 } from "../../../math/Box3"; | |
| import { BVH } from "../../../math/BVH"; | |
| import { RenderData } from "./RenderData"; | |
| class IntersectionTester { | |
| testPoint: (x: number, y: number) => Splat | null; | |
| constructor(renderProgram: RenderProgram, maxDistance: number = 100, resolution: number = 1.0) { | |
| let vertexCount = 0; | |
| let bvh: BVH | null = null; | |
| let lookup: Splat[] = []; | |
| const build = () => { | |
| if (renderProgram.renderData === null) { | |
| console.error("IntersectionTester cannot be called before renderProgram has been initialized"); | |
| return; | |
| } | |
| lookup = []; | |
| const renderData = renderProgram.renderData as RenderData; | |
| const boxes = new Array<Box3>(renderData.offsets.size); | |
| let i = 0; | |
| const bounds = new Box3( | |
| new Vector3(Infinity, Infinity, Infinity), | |
| new Vector3(-Infinity, -Infinity, -Infinity), | |
| ); | |
| for (const splat of renderData.offsets.keys()) { | |
| const splatBounds = splat.bounds; | |
| boxes[i++] = splatBounds; | |
| bounds.expand(splatBounds.min); | |
| bounds.expand(splatBounds.max); | |
| lookup.push(splat); | |
| } | |
| bounds.permute(); | |
| bvh = new BVH(bounds, boxes); | |
| vertexCount = renderData.vertexCount; | |
| }; | |
| this.testPoint = (x: number, y: number) => { | |
| if (renderProgram.renderData === null || renderProgram.camera === null) { | |
| console.error("IntersectionTester cannot be called before renderProgram has been initialized"); | |
| return null; | |
| } | |
| build(); | |
| if (bvh === null) { | |
| console.error("Failed to build octree for IntersectionTester"); | |
| return null; | |
| } | |
| const renderData = renderProgram.renderData as RenderData; | |
| const camera = renderProgram.camera as Camera; | |
| if (vertexCount !== renderData.vertexCount) { | |
| console.warn("IntersectionTester has not been rebuilt since the last render"); | |
| } | |
| const ray = camera.screenPointToRay(x, y); | |
| for (let x = 0; x < maxDistance; x += resolution) { | |
| const point = camera.position.add(ray.multiply(x)); | |
| const minPoint = new Vector3( | |
| point.x - resolution / 2, | |
| point.y - resolution / 2, | |
| point.z - resolution / 2, | |
| ); | |
| const maxPoint = new Vector3( | |
| point.x + resolution / 2, | |
| point.y + resolution / 2, | |
| point.z + resolution / 2, | |
| ); | |
| const queryBox = new Box3(minPoint, maxPoint); | |
| const points = bvh.queryRange(queryBox); | |
| if (points.length > 0) { | |
| return lookup[points[0]]; | |
| } | |
| } | |
| return null; | |
| }; | |
| } | |
| } | |
| export { IntersectionTester }; | |