LOD.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import { Vector3 } from '../math/Vector3.js';
  2. import { Object3D } from '../core/Object3D.js';
  3. const _v1 = /*@__PURE__*/ new Vector3();
  4. const _v2 = /*@__PURE__*/ new Vector3();
  5. class LOD extends Object3D {
  6. constructor() {
  7. super();
  8. this._currentLevel = 0;
  9. this.type = 'LOD';
  10. Object.defineProperties( this, {
  11. levels: {
  12. enumerable: true,
  13. value: []
  14. },
  15. isLOD: {
  16. value: true,
  17. }
  18. } );
  19. this.autoUpdate = true;
  20. }
  21. copy( source ) {
  22. super.copy( source, false );
  23. const levels = source.levels;
  24. for ( let i = 0, l = levels.length; i < l; i ++ ) {
  25. const level = levels[ i ];
  26. this.addLevel( level.object.clone(), level.distance, level.hysteresis );
  27. }
  28. this.autoUpdate = source.autoUpdate;
  29. return this;
  30. }
  31. addLevel( object, distance = 0, hysteresis = 0 ) {
  32. distance = Math.abs( distance );
  33. const levels = this.levels;
  34. let l;
  35. for ( l = 0; l < levels.length; l ++ ) {
  36. if ( distance < levels[ l ].distance ) {
  37. break;
  38. }
  39. }
  40. levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } );
  41. this.add( object );
  42. return this;
  43. }
  44. removeLevel( distance ) {
  45. const levels = this.levels;
  46. for ( let i = 0; i < levels.length; i ++ ) {
  47. if ( levels[ i ].distance === distance ) {
  48. const removedElements = levels.splice( i, 1 );
  49. this.remove( removedElements[ 0 ].object );
  50. return true;
  51. }
  52. }
  53. return false;
  54. }
  55. getCurrentLevel() {
  56. return this._currentLevel;
  57. }
  58. getObjectForDistance( distance ) {
  59. const levels = this.levels;
  60. if ( levels.length > 0 ) {
  61. let i, l;
  62. for ( i = 1, l = levels.length; i < l; i ++ ) {
  63. let levelDistance = levels[ i ].distance;
  64. if ( levels[ i ].object.visible ) {
  65. levelDistance -= levelDistance * levels[ i ].hysteresis;
  66. }
  67. if ( distance < levelDistance ) {
  68. break;
  69. }
  70. }
  71. return levels[ i - 1 ].object;
  72. }
  73. return null;
  74. }
  75. raycast( raycaster, intersects ) {
  76. const levels = this.levels;
  77. if ( levels.length > 0 ) {
  78. _v1.setFromMatrixPosition( this.matrixWorld );
  79. const distance = raycaster.ray.origin.distanceTo( _v1 );
  80. this.getObjectForDistance( distance ).raycast( raycaster, intersects );
  81. }
  82. }
  83. update( camera ) {
  84. const levels = this.levels;
  85. if ( levels.length > 1 ) {
  86. _v1.setFromMatrixPosition( camera.matrixWorld );
  87. _v2.setFromMatrixPosition( this.matrixWorld );
  88. const distance = _v1.distanceTo( _v2 ) / camera.zoom;
  89. levels[ 0 ].object.visible = true;
  90. let i, l;
  91. for ( i = 1, l = levels.length; i < l; i ++ ) {
  92. let levelDistance = levels[ i ].distance;
  93. if ( levels[ i ].object.visible ) {
  94. levelDistance -= levelDistance * levels[ i ].hysteresis;
  95. }
  96. if ( distance >= levelDistance ) {
  97. levels[ i - 1 ].object.visible = false;
  98. levels[ i ].object.visible = true;
  99. } else {
  100. break;
  101. }
  102. }
  103. this._currentLevel = i - 1;
  104. for ( ; i < l; i ++ ) {
  105. levels[ i ].object.visible = false;
  106. }
  107. }
  108. }
  109. toJSON( meta ) {
  110. const data = super.toJSON( meta );
  111. if ( this.autoUpdate === false ) data.object.autoUpdate = false;
  112. data.object.levels = [];
  113. const levels = this.levels;
  114. for ( let i = 0, l = levels.length; i < l; i ++ ) {
  115. const level = levels[ i ];
  116. data.object.levels.push( {
  117. object: level.object.uuid,
  118. distance: level.distance,
  119. hysteresis: level.hysteresis
  120. } );
  121. }
  122. return data;
  123. }
  124. }
  125. export { LOD };
粤ICP备19079148号