threepipe
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

SpotLightHelper2.ts 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import {ColorRepresentation, Object3D, SpotLight, Vector3} from 'three'
  2. import {LineGeometry} from 'three/examples/jsm/lines/LineGeometry.js'
  3. import {LineSegments2} from 'three/examples/jsm/lines/LineSegments2.js'
  4. import {LineSegmentsGeometry} from 'three/examples/jsm/lines/LineSegmentsGeometry.js'
  5. import {onChange} from 'ts-browser-helpers'
  6. import {ALightHelperWidget} from './ALightHelperWidget'
  7. import {IUiConfigContainer, uiSlider} from 'uiconfig.js'
  8. import {LineMaterial2} from '../../core'
  9. export class SpotLightHelper2 extends ALightHelperWidget {
  10. color: ColorRepresentation | undefined
  11. cone: LineSegments2
  12. light: (SpotLight & IUiConfigContainer) | undefined
  13. @onChange(SpotLightHelper2.prototype.update)
  14. material: LineMaterial2
  15. @onChange(SpotLightHelper2.prototype.update)
  16. @uiSlider(undefined, [0.1, 20], 0.01)
  17. lineWidth = 5
  18. constructor(light: SpotLight, size?: number, color?: ColorRepresentation) {
  19. super(light)
  20. this.color = color
  21. if (size === undefined) size = 0.5
  22. let geometry = new LineSegmentsGeometry()
  23. const positions = [
  24. 0, 0, 0, 0, 0, 1,
  25. 0, 0, 0, 1, 0, 1,
  26. 0, 0, 0, -1, 0, 1,
  27. 0, 0, 0, 0, 1, 1,
  28. 0, 0, 0, 0, -1, 1,
  29. ]
  30. for (let i = 0, j = 1, l = 32; i < l; i++, j++) {
  31. const p1 = i / l * Math.PI * 2
  32. const p2 = j / l * Math.PI * 2
  33. positions.push(
  34. Math.cos(p1), Math.sin(p1), 1,
  35. Math.cos(p2), Math.sin(p2), 1
  36. )
  37. }
  38. geometry.setPositions(positions)
  39. this.material = new LineMaterial2({
  40. color: 0xff0000,
  41. linewidth: 0.005, // in world units with size attenuation, pixels otherwise
  42. vertexColors: false,
  43. dashed: false,
  44. alphaToCoverage: true,
  45. toneMapped: false,
  46. transparent: true,
  47. depthTest: false,
  48. depthWrite: false,
  49. })
  50. this.cone = new LineSegments2(geometry, this.material)
  51. this.add(this.cone)
  52. geometry = new LineGeometry()
  53. geometry.setPositions([0, 0, 0, 0, 0, 1])
  54. this.update()
  55. this.traverse(o => {
  56. o.userData.__keepShadowDef = true
  57. o.castShadow = false
  58. o.receiveShadow = false
  59. })
  60. }
  61. dispose() {
  62. this.cone.geometry.dispose()
  63. this.cone.material.dispose()
  64. super.dispose()
  65. }
  66. private _v1 = new Vector3()
  67. update() {
  68. if (!this.light || !this.cone) return
  69. this.light.updateWorldMatrix(true, false)
  70. this.light.target.updateWorldMatrix(true, false)
  71. const coneLength = this.light.distance ? this.light.distance : 1000
  72. const coneWidth = coneLength * Math.tan(this.light.angle)
  73. this.cone.scale.set(coneWidth, coneWidth, coneLength)
  74. this._v1.setFromMatrixPosition(this.light.target.matrixWorld)
  75. this.cone.lookAt(this._v1)
  76. this.material.color.set(this.color ?? this.light.color)
  77. this.material.linewidth = this.lineWidth * 0.001
  78. super.update()
  79. }
  80. static Check(light: Object3D) {
  81. return (light as SpotLight).isSpotLight
  82. }
  83. static Create(light: Object3D) {
  84. return new SpotLightHelper2(light as SpotLight)
  85. }
  86. }