CircleAreaLightHelper.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import {
  2. BackSide,
  3. BufferGeometry,
  4. Float32BufferAttribute,
  5. Line,
  6. LineBasicMaterial,
  7. Mesh,
  8. MeshBasicMaterial
  9. } from 'three';
  10. /**
  11. * Creates a visual aid for circle area lights.
  12. *
  13. * `CircleAreaLightHelper` must be added as a child of the light.
  14. *
  15. * ```js
  16. * const light = new THREE.CircleAreaLight( 0xffffbb, 1.0, 5 );
  17. * const helper = new CircleAreaLightHelper( light );
  18. * light.add( helper );
  19. * ```
  20. *
  21. * @augments Line
  22. * @three_import import { CircleAreaLightHelper } from 'three/addons/helpers/CircleAreaLightHelper.js';
  23. */
  24. class CircleAreaLightHelper extends Line {
  25. /**
  26. * Constructs a new circle area light helper.
  27. *
  28. * @param {CircleAreaLight} light - The light to visualize.
  29. * @param {number|Color|string} [color] - The helper's color.
  30. * If this is not the set, the helper will take the color of the light.
  31. */
  32. constructor( light, color ) {
  33. // Create circle outline (32 segments for smooth appearance)
  34. const segments = 32;
  35. const positions = [];
  36. for ( let i = 0; i <= segments; i ++ ) {
  37. const angle = ( i / segments ) * Math.PI * 2;
  38. positions.push( Math.cos( angle ), Math.sin( angle ), 0 );
  39. }
  40. const geometry = new BufferGeometry();
  41. geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
  42. geometry.computeBoundingSphere();
  43. const material = new LineBasicMaterial( { fog: false } );
  44. super( geometry, material );
  45. /**
  46. * The light to visualize.
  47. *
  48. * @type {CircleAreaLight}
  49. */
  50. this.light = light;
  51. /**
  52. * The helper's color. If `undefined`, the helper will take the color of the light.
  53. *
  54. * @type {number|Color|string|undefined}
  55. */
  56. this.color = color;
  57. this.type = 'CircleAreaLightHelper';
  58. //
  59. // Create filled circle mesh (triangulated circle)
  60. const positions2 = [];
  61. // Center vertex
  62. positions2.push( 0, 0, 0 );
  63. // Circle vertices
  64. for ( let i = 0; i <= segments; i ++ ) {
  65. const angle = ( i / segments ) * Math.PI * 2;
  66. positions2.push( Math.cos( angle ), Math.sin( angle ), 0 );
  67. }
  68. // Create triangle fan indices
  69. const indices = [];
  70. for ( let i = 0; i < segments; i ++ ) {
  71. indices.push( 0, i + 1, i + 2 );
  72. }
  73. const geometry2 = new BufferGeometry();
  74. geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
  75. geometry2.setIndex( indices );
  76. geometry2.computeBoundingSphere();
  77. this.add( new Mesh( geometry2, new MeshBasicMaterial( { side: BackSide, fog: false } ) ) );
  78. }
  79. updateMatrixWorld() {
  80. this.scale.set( this.light.radius, this.light.radius, 1 );
  81. if ( this.color !== undefined ) {
  82. this.material.color.set( this.color );
  83. this.children[ 0 ].material.color.set( this.color );
  84. } else {
  85. this.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
  86. // prevent hue shift
  87. const c = this.material.color;
  88. const max = Math.max( c.r, c.g, c.b );
  89. if ( max > 1 ) c.multiplyScalar( 1 / max );
  90. this.children[ 0 ].material.color.copy( this.material.color );
  91. }
  92. // ignore world scale on light
  93. this.matrixWorld.extractRotation( this.light.matrixWorld ).scale( this.scale ).copyPosition( this.light.matrixWorld );
  94. this.children[ 0 ].matrixWorld.copy( this.matrixWorld );
  95. }
  96. /**
  97. * Frees the GPU-related resources allocated by this instance. Call this
  98. * method whenever this instance is no longer used in your app.
  99. */
  100. dispose() {
  101. this.geometry.dispose();
  102. this.material.dispose();
  103. this.children[ 0 ].geometry.dispose();
  104. this.children[ 0 ].material.dispose();
  105. }
  106. }
  107. export { CircleAreaLightHelper };
粤ICP备19079148号