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

GeometryGeneratorPlugin.ts 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import {
  2. AViewerPluginSync,
  3. BufferGeometry,
  4. BufferGeometry2,
  5. IGeometry,
  6. IMaterial,
  7. Mesh2,
  8. type Object3DGeneratorPlugin,
  9. PhysicalMaterial,
  10. ThreeViewer,
  11. } from 'threepipe'
  12. import {TorusGeometryGenerator} from './primitives/TorusGeometryGenerator'
  13. import {CircleGeometryGenerator} from './primitives/CircleGeometryGenerator'
  14. import {BoxGeometryGenerator} from './primitives/BoxGeometryGenerator'
  15. import {SphereGeometryGenerator} from './primitives/SphereGeometryGenerator'
  16. import {PlaneGeometryGenerator} from './primitives/PlaneGeometryGenerator'
  17. import {CylinderGeometryGenerator} from './primitives/CylinderGeometryGenerator'
  18. import {GeometryGenerator, updateUi} from './AGeometryGenerator'
  19. import {Class} from 'ts-browser-helpers'
  20. /**
  21. * GeometryGeneratorPlugin
  22. *
  23. * Geometry generator plugin to create updatable parametric objects/geometries.
  24. * Includes support for several primitive types from three.js
  25. */
  26. export class GeometryGeneratorPlugin extends AViewerPluginSync {
  27. public static readonly PluginType = 'GeometryGeneratorPlugin'
  28. enabled = true
  29. toJSON: any = undefined
  30. generators: Record<string, GeometryGenerator> = {
  31. plane: new PlaneGeometryGenerator('plane'),
  32. sphere: new SphereGeometryGenerator('sphere'),
  33. box: new BoxGeometryGenerator('box'),
  34. circle: new CircleGeometryGenerator('circle'),
  35. torus: new TorusGeometryGenerator('torus'),
  36. cylinder: new CylinderGeometryGenerator('cylinder'),
  37. }
  38. defaultMaterialClass: Class<IMaterial> = PhysicalMaterial
  39. defaultGeometryClass: Class<BufferGeometry> = BufferGeometry2
  40. generateObject(type: string, params?: any) {
  41. const generator = this.generators[type]
  42. if (!generator) throw new Error('Unknown generator type: ' + type)
  43. const obj = new Mesh2(params?.geometry ?? new this.defaultGeometryClass(), params?.material ?? new this.defaultMaterialClass())
  44. generator.generate(obj.geometry, params)
  45. obj.name = type
  46. obj.geometry.name = 'Generated ' + type
  47. return obj
  48. }
  49. generateGeometry(type: string, params: any, geometry?: IGeometry) {
  50. const generator = this.generators[type]
  51. if (!generator) throw new Error('Unknown generator type: ' + type)
  52. const g = generator.generate(geometry, params)
  53. g.name = 'Generated ' + type
  54. return g
  55. }
  56. updateGeometry(geometry: IGeometry, params: any) {
  57. if (!geometry.userData.generationParams?.type) throw new Error('Geometry is not generated')
  58. const generator = this.generators[geometry.userData.generationParams.type]
  59. if (!generator) throw new Error('Unknown generator type: ' + geometry.userData.generationParams.type)
  60. generator.generate(geometry, params)
  61. }
  62. onAdded(v: ThreeViewer) {
  63. super.onAdded(v)
  64. v.scene.addEventListener('sceneUpdate', this._sceneUpdate)
  65. this.refreshObject3DGenerator()
  66. }
  67. onRemove(viewer: ThreeViewer) {
  68. this._removeObject3DGenerators()
  69. super.onRemove(viewer)
  70. }
  71. protected _removeObject3DGenerators(refresh = true) {
  72. const object3DGenerator = this._viewer?.getPlugin<Object3DGeneratorPlugin>('Object3DGeneratorPlugin')
  73. if (!object3DGenerator) return
  74. object3DGenerator.generators = Object.fromEntries(Object.entries(object3DGenerator.generators)
  75. .filter(([k, _]) => !k.startsWith('geometry-'))) as any
  76. refresh && object3DGenerator.uiConfig?.uiRefresh?.(true)
  77. return object3DGenerator
  78. }
  79. refreshObject3DGenerator() {
  80. const object3DGenerator = this._removeObject3DGenerators(false)
  81. if (!object3DGenerator) return
  82. Object.keys(this.generators).forEach(key=>{
  83. object3DGenerator.generators['geometry-' + key] = (params: any)=>{
  84. const obj = this.generateObject(key, params)
  85. obj.name = key
  86. return obj
  87. }
  88. })
  89. object3DGenerator.uiConfig?.uiRefresh?.(true)
  90. }
  91. protected _sceneUpdate = (e: any)=>{
  92. if (e.hierarchyChanged) {
  93. const obj = e.object || this._viewer?.scene.modelRoot
  94. if (obj) {
  95. obj.traverse((o: any)=>{
  96. const type = o.geometry?.userData?.generationParams?.type
  97. if (!type) return
  98. updateUi(o.geometry, ()=>{
  99. const gen = this.generators[type]
  100. return gen?.createUiConfig ? gen.createUiConfig(o.geometry) ?? [] : []
  101. })
  102. })
  103. }
  104. }
  105. }
  106. uiConfig = {
  107. type: 'folder',
  108. label: 'Generate Geometry',
  109. children:
  110. [()=>Object.keys(this.generators).map((v) => ({
  111. type: 'button',
  112. uuid: 'generate_' + v,
  113. label: 'Generate ' + v,
  114. value: async() => {
  115. const obj = this.generateObject(v)
  116. obj.name = v
  117. this._viewer?.scene.addObject(obj)
  118. },
  119. }))],
  120. }
  121. }