1
import {math} from "@xeokit/xeokit-sdk/dist/xeokit-sdk.es.js";
3
const MAX_KD_TREE_DEPTH = 15;
4
const kdTreeDimLength = new Float32Array(3);
9
export class ObjectsKdTree3 {
14
throw "Parameter expected: cfg";
18
throw "Parameter expected: cfg.viewer";
21
this.viewer = cfg.viewer;
23
this._maxTreeDepth = cfg.maxTreeDepth || MAX_KD_TREE_DEPTH;
25
this._needsRebuild = true;
27
this._onModelLoaded = this.viewer.scene.on("modelLoaded", (modelId) => {
28
this._needsRebuild = true;
31
this._onModelUnloaded = this.viewer.scene.on("modelUnloaded", (modelId) => {
32
this._needsRebuild = true;
40
if (this._needsRebuild) {
47
const viewer = this.viewer;
48
const scene = viewer.scene;
53
for (let objectId in scene.objects) {
54
const entity = scene.objects[objectId];
55
this._insertEntity(this._root, entity, depth + 1);
57
this._needsRebuild = false;
60
_insertEntity(node, entity, depth) {
62
const entityAABB = entity.aabb;
64
if (depth >= this._maxTreeDepth) {
65
node.entities = node.entities || [];
66
node.entities.push(entity);
70
if (math.containsAABB3(node.left.aabb, entityAABB)) {
71
this._insertEntity(node.left, entity, depth + 1);
76
if (math.containsAABB3(node.right.aabb, entityAABB)) {
77
this._insertEntity(node.right, entity, depth + 1);
81
const nodeAABB = node.aabb;
82
kdTreeDimLength[0] = nodeAABB[3] - nodeAABB[0];
83
kdTreeDimLength[1] = nodeAABB[4] - nodeAABB[1];
84
kdTreeDimLength[2] = nodeAABB[5] - nodeAABB[2];
86
if (kdTreeDimLength[1] > kdTreeDimLength[dim]) {
89
if (kdTreeDimLength[2] > kdTreeDimLength[dim]) {
93
const aabbLeft = nodeAABB.slice();
94
aabbLeft[dim + 3] = ((nodeAABB[dim] + nodeAABB[dim + 3]) / 2.0);
98
if (math.containsAABB3(aabbLeft, entityAABB)) {
99
this._insertEntity(node.left, entity, depth + 1);
104
const aabbRight = nodeAABB.slice();
105
aabbRight[dim] = ((nodeAABB[dim] + nodeAABB[dim + 3]) / 2.0);
109
if (math.containsAABB3(aabbRight, entityAABB)) {
110
this._insertEntity(node.right, entity, depth + 1);
114
node.entities = node.entities || [];
115
node.entities.push(entity);
122
const scene = this.viewer.scene;
123
scene.off(this._onModelLoaded);
124
scene.off(this._onModelUnloaded);
126
this._needsRebuild = true;