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

GeometryGeneratorPlugin.ts 4.8KB

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