| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- import { Vector3 } from '../math/Vector3.js';
- import { Object3D } from '../core/Object3D.js';
- const _v1 = new Vector3();
- const _v2 = new Vector3();
- function LOD() {
- Object3D.call( this );
- this._currentLevel = 0;
- this.type = 'LOD';
- Object.defineProperties( this, {
- levels: {
- enumerable: true,
- value: []
- }
- } );
- this.autoUpdate = true;
- }
- LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
- constructor: LOD,
- isLOD: true,
- copy: function ( source ) {
- Object3D.prototype.copy.call( this, 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: function ( 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: function () {
- return this._currentLevel;
- },
- getObjectForDistance: function ( 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: function ( 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: function ( 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: function ( meta ) {
- const data = Object3D.prototype.toJSON.call( this, 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 };
|