feat: add 3D kitchen planner with collaboration and export
This commit is contained in:
87
apps/fabrikanabytok/lib/three/loaders.ts
Normal file
87
apps/fabrikanabytok/lib/three/loaders.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Advanced Model Loaders
|
||||
*/
|
||||
|
||||
import * as THREE from 'three'
|
||||
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
|
||||
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
|
||||
|
||||
export interface CachedModel {
|
||||
scene: THREE.Group
|
||||
animations: THREE.AnimationClip[]
|
||||
cameras: THREE.Camera[]
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
export class ModelLoader {
|
||||
private static instance: ModelLoader
|
||||
private gltfLoader: GLTFLoader
|
||||
private dracoLoader: DRACOLoader
|
||||
private modelCache: Map<string, CachedModel> = new Map()
|
||||
private loadingPromises: Map<string, Promise<CachedModel>> = new Map()
|
||||
|
||||
private constructor() {
|
||||
this.gltfLoader = new GLTFLoader()
|
||||
this.dracoLoader = new DRACOLoader()
|
||||
this.dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/')
|
||||
this.gltfLoader.setDRACOLoader(this.dracoLoader)
|
||||
}
|
||||
|
||||
static getInstance(): ModelLoader {
|
||||
if (!ModelLoader.instance) {
|
||||
ModelLoader.instance = new ModelLoader()
|
||||
}
|
||||
return ModelLoader.instance
|
||||
}
|
||||
|
||||
async loadModel(url: string, options?: { onProgress?: (progress: number) => void }): Promise<CachedModel> {
|
||||
if (this.modelCache.has(url)) {
|
||||
const cached = this.modelCache.get(url)!
|
||||
return { ...cached, scene: cached.scene.clone() }
|
||||
}
|
||||
|
||||
if (this.loadingPromises.has(url)) {
|
||||
return this.loadingPromises.get(url)!
|
||||
}
|
||||
|
||||
const loadPromise = new Promise<CachedModel>((resolve, reject) => {
|
||||
this.gltfLoader.load(
|
||||
url,
|
||||
(gltf) => {
|
||||
const processed: CachedModel = {
|
||||
scene: gltf.scene,
|
||||
animations: gltf.animations || [],
|
||||
cameras: gltf.cameras || [],
|
||||
timestamp: Date.now()
|
||||
}
|
||||
|
||||
this.modelCache.set(url, processed)
|
||||
this.loadingPromises.delete(url)
|
||||
resolve({ ...processed, scene: processed.scene.clone() })
|
||||
},
|
||||
(progress) => {
|
||||
if (options?.onProgress) {
|
||||
const percent = (progress.loaded / progress.total) * 100
|
||||
options.onProgress(percent)
|
||||
}
|
||||
},
|
||||
reject
|
||||
)
|
||||
})
|
||||
|
||||
this.loadingPromises.set(url, loadPromise)
|
||||
return loadPromise
|
||||
}
|
||||
|
||||
getCacheStats() {
|
||||
return {
|
||||
size: this.modelCache.size,
|
||||
urls: Array.from(this.modelCache.keys())
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.dracoLoader.dispose()
|
||||
this.modelCache.clear()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user