UNPKG

@three.ez/instanced-mesh

Version:

Enhanced InstancedMesh with frustum culling, fast raycasting (using BVH), sorting, visibility management and more.

128 lines 4.42 kB
import { ShaderMaterial } from 'three'; import { InstancedMesh2 } from '../InstancedMesh2.js'; InstancedMesh2.prototype.getObjectLODIndexForDistance = function (levels, distance) { for (let i = levels.length - 1; i > 0; i--) { const level = levels[i]; const levelDistance = level.distance - (level.distance * level.hysteresis); if (distance >= levelDistance) return i; } return 0; }; InstancedMesh2.prototype.setFirstLODDistance = function (distance = 0, hysteresis = 0) { if (this._parentLOD) { throw new Error('Cannot create LOD for this InstancedMesh2.'); } if (!this.LODinfo) { this.LODinfo = { render: null, shadowRender: null, objects: [this] }; } if (!this.LODinfo.render) { this.LODinfo.render = { levels: [{ distance, hysteresis, object: this }], count: [0] }; } return this; }; InstancedMesh2.prototype.addLOD = function (geometry, material, distance = 0, hysteresis = 0) { if (this._parentLOD) { throw new Error('Cannot create LOD for this InstancedMesh2.'); } if (!this.LODinfo?.render && distance === 0) { throw new Error('Cannot set distance to 0 for the first LOD. Use "setFirstLODDistance" before use "addLOD".'); } this.setFirstLODDistance(0, hysteresis); this.addLevel(this.LODinfo.render, geometry, material, distance, hysteresis); return this; }; InstancedMesh2.prototype.addShadowLOD = function (geometry, distance = 0, hysteresis = 0) { if (this._parentLOD) { throw new Error('Cannot create LOD for this InstancedMesh2.'); } if (!this.LODinfo) { this.LODinfo = { render: null, shadowRender: null, objects: [this] }; } if (!this.LODinfo.shadowRender) { this.LODinfo.shadowRender = { levels: [], count: [] }; } const object = this.addLevel(this.LODinfo.shadowRender, geometry, null, distance, hysteresis); object.castShadow = true; this.castShadow = true; return this; }; InstancedMesh2.prototype.addLevel = function (renderList, geometry, material, distance, hysteresis) { const objectsList = this.LODinfo.objects; const levels = renderList.levels; let index; let object; distance = distance ** 2; // to avoid to use Math.sqrt every time const objIndex = objectsList.findIndex((e) => e.geometry === geometry); if (objIndex === -1) { const params = { capacity: this._capacity, renderer: this._renderer }; object = new InstancedMesh2(geometry, material ?? new ShaderMaterial(), params, this); object.frustumCulled = false; this.patchLevel(object); objectsList.push(object); this.add(object); // TODO handle render order? } else { object = objectsList[objIndex]; if (material) object.material = material; } for (index = 0; index < levels.length; index++) { if (distance < levels[index].distance) break; } levels.splice(index, 0, { distance, hysteresis, object }); renderList.count.push(0); return object; }; InstancedMesh2.prototype.patchLevel = function (obj) { Object.defineProperty(obj, '_lastRenderInfo', { get() { return this._parentLOD._lastRenderInfo; } }); Object.defineProperty(obj, 'matricesTexture', { get() { return this._parentLOD.matricesTexture; } }); Object.defineProperty(obj, 'colorsTexture', { get() { return this._parentLOD.colorsTexture; } }); Object.defineProperty(obj, 'uniformsTexture', { get() { return this._parentLOD.uniformsTexture; } }); Object.defineProperty(obj, 'morphTexture', { get() { return this._parentLOD.morphTexture; } }); Object.defineProperty(obj, 'boneTexture', { get() { return this._parentLOD.boneTexture; } }); Object.defineProperty(obj, 'skeleton', { get() { return this._parentLOD.skeleton; } }); Object.defineProperty(obj, 'bindMatrixInverse', { get() { return this._parentLOD.bindMatrixInverse; } }); Object.defineProperty(obj, 'bindMatrix', { get() { return this._parentLOD.bindMatrix; } }); }; //# sourceMappingURL=LOD.js.map