123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js';
- export const quadtree = (function() {
- class CubeQuadTree {
- constructor(params) {
- this._params = params;
- this._sides = [];
- const r = params.radius;
- let m;
- const transforms = [];
- // +Y
- m = new THREE.Matrix4();
- m.makeRotationX(-Math.PI / 2);
- m.premultiply(new THREE.Matrix4().makeTranslation(0, r, 0));
- transforms.push(m);
- // -Y
- m = new THREE.Matrix4();
- m.makeRotationX(Math.PI / 2);
- m.premultiply(new THREE.Matrix4().makeTranslation(0, -r, 0));
- transforms.push(m);
- // +X
- m = new THREE.Matrix4();
- m.makeRotationY(Math.PI / 2);
- m.premultiply(new THREE.Matrix4().makeTranslation(r, 0, 0));
- transforms.push(m);
- // -X
- m = new THREE.Matrix4();
- m.makeRotationY(-Math.PI / 2);
- m.premultiply(new THREE.Matrix4().makeTranslation(-r, 0, 0));
- transforms.push(m);
- // +Z
- m = new THREE.Matrix4();
- m.premultiply(new THREE.Matrix4().makeTranslation(0, 0, r));
- transforms.push(m);
-
- // -Z
- m = new THREE.Matrix4();
- m.makeRotationY(Math.PI);
- m.premultiply(new THREE.Matrix4().makeTranslation(0, 0, -r));
- transforms.push(m);
- for (let t of transforms) {
- this._sides.push({
- transform: t.clone(),
- worldToLocal: t.clone().getInverse(t),
- quadtree: new QuadTree({
- size: r,
- min_node_size: params.min_node_size,
- localToWorld: t
- }),
- });
- }
- }
- GetChildren() {
- const children = [];
- for (let s of this._sides) {
- const side = {
- transform: s.transform,
- children: s.quadtree.GetChildren(),
- }
- children.push(side);
- }
- return children;
- }
- Insert(pos) {
- for (let s of this._sides) {
- s.quadtree.Insert(pos);
- }
- }
- }
- class QuadTree {
- constructor(params) {
- const s = params.size;
- const b = new THREE.Box3(
- new THREE.Vector3(-s, -s, 0),
- new THREE.Vector3(s, s, 0));
- this._root = {
- bounds: b,
- children: [],
- center: b.getCenter(new THREE.Vector3()),
- sphereCenter: b.getCenter(new THREE.Vector3()),
- size: b.getSize(new THREE.Vector3()),
- root: true,
- };
- this._params = params;
- this._root.sphereCenter = this._root.center.clone();
- this._root.sphereCenter.applyMatrix4(this._params.localToWorld);
- this._root.sphereCenter.normalize();
- this._root.sphereCenter.multiplyScalar(this._params.size);
- }
- GetChildren() {
- const children = [];
- this._GetChildren(this._root, children);
- return children;
- }
- _GetChildren(node, target) {
- if (node.children.length == 0) {
- target.push(node);
- return;
- }
- for (let c of node.children) {
- this._GetChildren(c, target);
- }
- }
- Insert(pos) {
- this._Insert(this._root, pos);
- }
- _Insert(child, pos) {
- const distToChild = this._DistanceToChild(child, pos);
- if (distToChild < child.size.x * 1.0 && child.size.x > this._params.min_node_size) {
- child.children = this._CreateChildren(child);
- for (let c of child.children) {
- this._Insert(c, pos);
- }
- }
- }
- _DistanceToChild(child, pos) {
- return child.sphereCenter.distanceTo(pos);
- }
- _CreateChildren(child) {
- const midpoint = child.bounds.getCenter(new THREE.Vector3());
- // Bottom left
- const b1 = new THREE.Box3(child.bounds.min, midpoint);
- // Bottom right
- const b2 = new THREE.Box3(
- new THREE.Vector3(midpoint.x, child.bounds.min.y, 0),
- new THREE.Vector3(child.bounds.max.x, midpoint.y, 0));
- // Top left
- const b3 = new THREE.Box3(
- new THREE.Vector3(child.bounds.min.x, midpoint.y, 0),
- new THREE.Vector3(midpoint.x, child.bounds.max.y, 0));
- // Top right
- const b4 = new THREE.Box3(midpoint, child.bounds.max);
- const children = [b1, b2, b3, b4].map(
- b => {
- return {
- bounds: b,
- children: [],
- center: b.getCenter(new THREE.Vector3()),
- size: b.getSize(new THREE.Vector3())
- };
- });
- for (let c of children) {
- c.sphereCenter = c.center.clone();
- c.sphereCenter.applyMatrix4(this._params.localToWorld);
- c.sphereCenter.normalize()
- c.sphereCenter.multiplyScalar(this._params.size);
- }
- return children;
- }
- }
- return {
- QuadTree: QuadTree,
- CubeQuadTree: CubeQuadTree,
- }
- })();
|