UNPKG

blaze-2d

Version:

A fast and simple WebGL 2 2D game engine written in TypeScript

99 lines 3.86 kB
import { vec2 } from "gl-matrix"; export class kdNode { constructor(particle, left, right) { this.particle = particle; this.left = left; this.right = right; } /** * Determines wether the node is a leaf node or not. * * @returns Wether the node is a leaf node or not */ isLeaf() { return !this.left && !this.right; } } /** * Represents a kdTree that contains {@link Particle}s. */ export default class kdTree { /** * Creates a {@link kdTree}. * * @param particles The particles to add to the tree */ constructor(particles) { this.build(particles); } /** * Builds the {@link kdTree}. * * @param particles The particles to add to the tree */ build(particles, depth = 0) { if (particles.length === 0) return; const k = 2; const axis = depth % k; // TODO - Use median of medians partition algorithm to split particles array // @see - https://en.wikipedia.org/wiki/Median_of_medians particles.sort((a, b) => a.getPosition()[axis] - b.getPosition()[axis]); const median = Math.floor(particles.length / 2); if (depth === 0) { // console.log(particles[median]); this.root = new kdNode(particles[median], this.build(particles.slice(0, median), depth + 1), this.build(particles.slice(median + 1), depth + 1)); return this.root; } else { return new kdNode(particles[median], this.build(particles.slice(0, median), depth + 1), this.build(particles.slice(median + 1), depth + 1)); } } /** * Finds all the neighbours of a particle within the given distance. * * @param particle The particle to find neighbours of * @param dist The maximum distance a neighbour can be from the particle * @param distSqr The maximum distance squared a neighbour can be from the particle */ findNeighbours(particle, dist, distSqr) { const neighbours = []; if (this.root) this.findNeighboursHelper(particle, particle.getPosition(), dist, distSqr, this.root, 0, neighbours); return neighbours; } findNeighboursHelper(particle, pos, dist, distSqr, node, depth, neighbours) { if (!node) return; if (node.isLeaf()) { // check if particle is close enough to be considered a neighbour const d = vec2.sqrDist(pos, node.particle.getPosition()); if (d < distSqr && node.particle !== particle) { neighbours.push(node.particle); return; } } else { const k = 2; const axis = depth % k; // check if particle is close enough to be considered a neighbour const d = vec2.sqrDist(pos, node.particle.getPosition()); if (d < distSqr && node.particle !== particle) { neighbours.push(node.particle); } if (pos[axis] < node.particle.getPosition()[axis]) { // search left first this.findNeighboursHelper(particle, pos, dist, distSqr, node.left, depth + 1, neighbours); if (pos[axis] + dist >= node.particle.getPosition()[axis]) this.findNeighboursHelper(particle, pos, dist, distSqr, node.right, depth + 1, neighbours); } else { // search right first this.findNeighboursHelper(particle, pos, dist, distSqr, node.right, depth + 1, neighbours); if (pos[axis] - dist < node.particle.getPosition()[axis]) this.findNeighboursHelper(particle, pos, dist, distSqr, node.left, depth + 1, neighbours); } } } } //# sourceMappingURL=kdTree.js.map