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

ThreeGaussianSplatPlugin.ts 3.0KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import {AViewerPluginSync, createStyles, IGeometryEvent, ILoader, Importer, ThreeViewer} from 'threepipe'
  2. import styles from './ThreeGaussianSplatPlugin.css?inline'
  3. import {GaussianSplatMesh} from './index'
  4. import {AnyOptions} from 'ts-browser-helpers'
  5. import {SplatLoader} from './loaders/SplatLoader'
  6. import {SortWorkerManager} from './cpp-sorter/SortWorkerManager'
  7. import {GaussianSplatGeometry} from './geometry/GaussianSplatGeometry'
  8. export class ThreeGaussianSplatPlugin extends AViewerPluginSync<string> {
  9. public static readonly PluginType: string = 'ThreeGaussianSplatPlugin'
  10. enabled = true
  11. dependencies = []
  12. toJSON: any = null
  13. constructor() {
  14. super()
  15. }
  16. splats: GaussianSplatMesh[] = []
  17. private _ready = false
  18. onAdded(viewer: ThreeViewer) {
  19. super.onAdded(viewer)
  20. createStyles(styles)
  21. viewer.assetManager.importer.addImporter(this._importer)
  22. viewer.scene.addEventListener('mainCameraUpdate', this._activeCameraUpdate)
  23. viewer.scene.addEventListener('geometryUpdate', this._geometryUpdate)
  24. this._ready = true
  25. }
  26. onRemove(viewer: ThreeViewer) {
  27. viewer.assetManager.importer.removeImporter(this._importer)
  28. }
  29. private _activeCameraUpdate = () => {
  30. if (!this._ready || this.isDisabled()) return
  31. this.splats.forEach(async splat=>splat.update(this._viewer!.scene.mainCamera, this._viewer!.renderManager.webglRenderer))
  32. }
  33. private _geometryUpdate = (event: IGeometryEvent) => {
  34. if (!this._ready || this.isDisabled() || !(event.geometry as GaussianSplatGeometry)?.isGaussianSplatGeometry) return
  35. event.geometry!.appliedMeshes.forEach(async(splat: GaussianSplatMesh)=>splat.update ? splat.update(this._viewer!.scene.mainCamera, this._viewer!.renderManager.webglRenderer) : undefined)
  36. }
  37. private _sortWorkerManager = new SortWorkerManager() // todo: dispose?
  38. protected _importer = new Importer(class extends SplatLoader implements ILoader {
  39. onDispose: (mesh: GaussianSplatMesh)=>void = ()=>{return}
  40. onCreate: (mesh: GaussianSplatMesh)=>void = ()=>{return}
  41. transform(res: GaussianSplatMesh, _: AnyOptions): any {
  42. res.addEventListener('dispose', ()=>this.onDispose(res))
  43. this.onCreate(res)
  44. return res
  45. }
  46. }, ['splat'], [], true, (l)=>{
  47. if (!l) return l
  48. l.sortWorkerManager = this._sortWorkerManager
  49. l.onDispose = (mesh: GaussianSplatMesh)=>{ // todo: dispose should only remove from GPU?
  50. this.splats = this.splats.filter(splat=>splat !== mesh)
  51. }
  52. l.onCreate = (mesh: GaussianSplatMesh)=>{
  53. this.splats.push(mesh)
  54. }
  55. l.onGeometryLoad = (_)=>{
  56. // console.log('geometry loaded')
  57. // console.log(geometry.boundingBox)
  58. this._viewer?.setDirty()
  59. }
  60. return l
  61. })
  62. // protected _viewerListeners = {
  63. // preRender: (_: IViewerEvent) => {
  64. // },
  65. // }
  66. }