Spaces:
Sleeping
Sleeping
| import { Vector3 } from '../math/Vector3.js'; | |
| import { Object3D } from '../core/Object3D.js'; | |
| const _v1 = /*@__PURE__*/ new Vector3(); | |
| const _v2 = /*@__PURE__*/ new Vector3(); | |
| class LOD extends Object3D { | |
| constructor() { | |
| super(); | |
| this._currentLevel = 0; | |
| this.type = 'LOD'; | |
| Object.defineProperties(this, { | |
| levels: { | |
| enumerable: true, | |
| value: [], | |
| }, | |
| isLOD: { | |
| value: true, | |
| }, | |
| }); | |
| this.autoUpdate = true; | |
| } | |
| copy(source) { | |
| super.copy(source, false); | |
| const levels = source.levels; | |
| for (let i = 0, l = levels.length; i < l; i++) { | |
| const level = levels[i]; | |
| this.addLevel(level.object.clone(), level.distance); | |
| } | |
| this.autoUpdate = source.autoUpdate; | |
| return this; | |
| } | |
| addLevel(object, distance = 0) { | |
| distance = Math.abs(distance); | |
| const levels = this.levels; | |
| let l; | |
| for (l = 0; l < levels.length; l++) { | |
| if (distance < levels[l].distance) { | |
| break; | |
| } | |
| } | |
| levels.splice(l, 0, { distance: distance, object: object }); | |
| this.add(object); | |
| return this; | |
| } | |
| getCurrentLevel() { | |
| return this._currentLevel; | |
| } | |
| getObjectForDistance(distance) { | |
| const levels = this.levels; | |
| if (levels.length > 0) { | |
| let i, l; | |
| for (i = 1, l = levels.length; i < l; i++) { | |
| if (distance < levels[i].distance) { | |
| break; | |
| } | |
| } | |
| return levels[i - 1].object; | |
| } | |
| return null; | |
| } | |
| raycast(raycaster, intersects) { | |
| const levels = this.levels; | |
| if (levels.length > 0) { | |
| _v1.setFromMatrixPosition(this.matrixWorld); | |
| const distance = raycaster.ray.origin.distanceTo(_v1); | |
| this.getObjectForDistance(distance).raycast(raycaster, intersects); | |
| } | |
| } | |
| update(camera) { | |
| const levels = this.levels; | |
| if (levels.length > 1) { | |
| _v1.setFromMatrixPosition(camera.matrixWorld); | |
| _v2.setFromMatrixPosition(this.matrixWorld); | |
| const distance = _v1.distanceTo(_v2) / camera.zoom; | |
| levels[0].object.visible = true; | |
| let i, l; | |
| for (i = 1, l = levels.length; i < l; i++) { | |
| if (distance >= levels[i].distance) { | |
| levels[i - 1].object.visible = false; | |
| levels[i].object.visible = true; | |
| } else { | |
| break; | |
| } | |
| } | |
| this._currentLevel = i - 1; | |
| for (; i < l; i++) { | |
| levels[i].object.visible = false; | |
| } | |
| } | |
| } | |
| toJSON(meta) { | |
| const data = super.toJSON(meta); | |
| if (this.autoUpdate === false) data.object.autoUpdate = false; | |
| data.object.levels = []; | |
| const levels = this.levels; | |
| for (let i = 0, l = levels.length; i < l; i++) { | |
| const level = levels[i]; | |
| data.object.levels.push({ | |
| object: level.object.uuid, | |
| distance: level.distance, | |
| }); | |
| } | |
| return data; | |
| } | |
| } | |
| export { LOD }; | |