123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- import { Vector3 } from "../../Maths/math.vector.js";
- import { BoundingBox } from "../../Culling/boundingBox.js";
- /**
- * Class used to store a cell in an octree
- * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/optimizeOctrees
- */
- export class OctreeBlock {
- /**
- * Creates a new block
- * @param minPoint defines the minimum vector (in world space) of the block's bounding box
- * @param maxPoint defines the maximum vector (in world space) of the block's bounding box
- * @param capacity defines the maximum capacity of this block (if capacity is reached the block will be split into sub blocks)
- * @param depth defines the current depth of this block in the octree
- * @param maxDepth defines the maximal depth allowed (beyond this value, the capacity is ignored)
- * @param creationFunc defines a callback to call when an element is added to the block
- */
- constructor(minPoint, maxPoint, capacity, depth, maxDepth, creationFunc) {
- /**
- * Gets the content of the current block
- */
- this.entries = [];
- this._boundingVectors = new Array();
- this._capacity = capacity;
- this._depth = depth;
- this._maxDepth = maxDepth;
- this._creationFunc = creationFunc;
- this._minPoint = minPoint;
- this._maxPoint = maxPoint;
- this._boundingVectors.push(minPoint.clone());
- this._boundingVectors.push(maxPoint.clone());
- this._boundingVectors.push(minPoint.clone());
- this._boundingVectors[2].x = maxPoint.x;
- this._boundingVectors.push(minPoint.clone());
- this._boundingVectors[3].y = maxPoint.y;
- this._boundingVectors.push(minPoint.clone());
- this._boundingVectors[4].z = maxPoint.z;
- this._boundingVectors.push(maxPoint.clone());
- this._boundingVectors[5].z = minPoint.z;
- this._boundingVectors.push(maxPoint.clone());
- this._boundingVectors[6].x = minPoint.x;
- this._boundingVectors.push(maxPoint.clone());
- this._boundingVectors[7].y = minPoint.y;
- }
- // Property
- /**
- * Gets the maximum capacity of this block (if capacity is reached the block will be split into sub blocks)
- */
- get capacity() {
- return this._capacity;
- }
- /**
- * Gets the minimum vector (in world space) of the block's bounding box
- */
- get minPoint() {
- return this._minPoint;
- }
- /**
- * Gets the maximum vector (in world space) of the block's bounding box
- */
- get maxPoint() {
- return this._maxPoint;
- }
- // Methods
- /**
- * Add a new element to this block
- * @param entry defines the element to add
- */
- addEntry(entry) {
- if (this.blocks) {
- for (let index = 0; index < this.blocks.length; index++) {
- const block = this.blocks[index];
- block.addEntry(entry);
- }
- return;
- }
- this._creationFunc(entry, this);
- if (this.entries.length > this.capacity && this._depth < this._maxDepth) {
- this.createInnerBlocks();
- }
- }
- /**
- * Remove an element from this block
- * @param entry defines the element to remove
- */
- removeEntry(entry) {
- if (this.blocks) {
- for (let index = 0; index < this.blocks.length; index++) {
- const block = this.blocks[index];
- block.removeEntry(entry);
- }
- return;
- }
- const entryIndex = this.entries.indexOf(entry);
- if (entryIndex > -1) {
- this.entries.splice(entryIndex, 1);
- }
- }
- /**
- * Add an array of elements to this block
- * @param entries defines the array of elements to add
- */
- addEntries(entries) {
- for (let index = 0; index < entries.length; index++) {
- const mesh = entries[index];
- this.addEntry(mesh);
- }
- }
- /**
- * Test if the current block intersects the frustum planes and if yes, then add its content to the selection array
- * @param frustumPlanes defines the frustum planes to test
- * @param selection defines the array to store current content if selection is positive
- * @param allowDuplicate defines if the selection array can contains duplicated entries
- */
- select(frustumPlanes, selection, allowDuplicate) {
- if (BoundingBox.IsInFrustum(this._boundingVectors, frustumPlanes)) {
- if (this.blocks) {
- for (let index = 0; index < this.blocks.length; index++) {
- const block = this.blocks[index];
- block.select(frustumPlanes, selection, allowDuplicate);
- }
- return;
- }
- if (allowDuplicate) {
- selection.concat(this.entries);
- }
- else {
- selection.concatWithNoDuplicate(this.entries);
- }
- }
- }
- /**
- * Test if the current block intersect with the given bounding sphere and if yes, then add its content to the selection array
- * @param sphereCenter defines the bounding sphere center
- * @param sphereRadius defines the bounding sphere radius
- * @param selection defines the array to store current content if selection is positive
- * @param allowDuplicate defines if the selection array can contains duplicated entries
- */
- intersects(sphereCenter, sphereRadius, selection, allowDuplicate) {
- if (BoundingBox.IntersectsSphere(this._minPoint, this._maxPoint, sphereCenter, sphereRadius)) {
- if (this.blocks) {
- for (let index = 0; index < this.blocks.length; index++) {
- const block = this.blocks[index];
- block.intersects(sphereCenter, sphereRadius, selection, allowDuplicate);
- }
- return;
- }
- if (allowDuplicate) {
- selection.concat(this.entries);
- }
- else {
- selection.concatWithNoDuplicate(this.entries);
- }
- }
- }
- /**
- * Test if the current block intersect with the given ray and if yes, then add its content to the selection array
- * @param ray defines the ray to test with
- * @param selection defines the array to store current content if selection is positive
- */
- intersectsRay(ray, selection) {
- if (ray.intersectsBoxMinMax(this._minPoint, this._maxPoint)) {
- if (this.blocks) {
- for (let index = 0; index < this.blocks.length; index++) {
- const block = this.blocks[index];
- block.intersectsRay(ray, selection);
- }
- return;
- }
- selection.concatWithNoDuplicate(this.entries);
- }
- }
- /**
- * Subdivide the content into child blocks (this block will then be empty)
- */
- createInnerBlocks() {
- OctreeBlock._CreateBlocks(this._minPoint, this._maxPoint, this.entries, this._capacity, this._depth, this._maxDepth, this, this._creationFunc);
- this.entries.splice(0);
- }
- /**
- * @internal
- */
- static _CreateBlocks(worldMin, worldMax, entries, maxBlockCapacity, currentDepth, maxDepth, target, creationFunc) {
- target.blocks = new Array();
- const blockSize = new Vector3((worldMax.x - worldMin.x) / 2, (worldMax.y - worldMin.y) / 2, (worldMax.z - worldMin.z) / 2);
- // Segmenting space
- for (let x = 0; x < 2; x++) {
- for (let y = 0; y < 2; y++) {
- for (let z = 0; z < 2; z++) {
- const localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
- const localMax = worldMin.add(blockSize.multiplyByFloats(x + 1, y + 1, z + 1));
- const block = new OctreeBlock(localMin, localMax, maxBlockCapacity, currentDepth + 1, maxDepth, creationFunc);
- block.addEntries(entries);
- target.blocks.push(block);
- }
- }
- }
- }
- }
- //# sourceMappingURL=octreeBlock.js.map
|