import { AbstractMesh } from '@babylonjs/core' export interface ParsedMeshData { meshes: unknown[] boundingBox: { min: { x: number; y: number; z: number } max: { x: number; y: number; z: number } } metadata: { modelPath: string parsedAt: string totalVertices: number totalIndices: number } } export const getCacheFileName = (modelPath: string) => { const fileName = modelPath.split('/').pop()?.replace('.gltf', '') || 'model' return `${fileName}_parsed.json` } export const loadCachedData = async (cacheFileName: string): Promise => { try { const response = await fetch(`/data/${cacheFileName}`) if (response.ok) { const cachedData = await response.json() console.log('📦 Loaded cached mesh data:', cachedData.metadata) return cachedData } } catch (error) { console.log('❌ No cached data found, will parse scene') } return null } export const extractAllMeshData = (mesh: AbstractMesh) => { const meshData: Record = {} const safeStringify = (obj: unknown): unknown => { try { JSON.stringify(obj) return obj } catch { return '[Circular Reference]' } } const extractValue = (value: unknown): unknown => { if (value === null || value === undefined) { return value } if (typeof value === 'function') { return '[Function]' } if (typeof value === 'object' && value !== null) { const obj = value as Record if (obj.constructor.name === 'Vector3') { return { x: obj.x, y: obj.y, z: obj.z } } else if (obj.constructor.name === 'Quaternion') { return { x: obj.x, y: obj.y, z: obj.z, w: obj.w } } else if (obj.constructor.name === 'Color3') { return { r: obj.r, g: obj.g, b: obj.b } } else if (obj.constructor.name === 'Color4') { return { r: obj.r, g: obj.g, b: obj.b, a: obj.a } } else if (Array.isArray(value)) { return value.map(item => extractValue(item)) } else { return safeStringify(value) } } return value } for (const key in mesh) { try { const value = (mesh as unknown as Record)[key] meshData[key] = extractValue(value) } catch (error) { meshData[key] = '[Error accessing property]' } } meshData.geometry = { vertices: mesh.getVerticesData('position') ? Array.from(mesh.getVerticesData('position')!) : [], indices: mesh.getIndices() ? Array.from(mesh.getIndices()!) : [], normals: mesh.getVerticesData('normal') ? Array.from(mesh.getVerticesData('normal')!) : [], uvs: mesh.getVerticesData('uv') ? Array.from(mesh.getVerticesData('uv')!) : [], colors: mesh.getVerticesData('color') ? Array.from(mesh.getVerticesData('color')!) : [], tangents: mesh.getVerticesData('tangent') ? Array.from(mesh.getVerticesData('tangent')!) : [], matricesWeights: mesh.getVerticesData('matricesWeights') ? Array.from(mesh.getVerticesData('matricesWeights')!) : [], matricesIndices: mesh.getVerticesData('matricesIndices') ? Array.from(mesh.getVerticesData('matricesIndices')!) : [], totalVertices: mesh.getTotalVertices(), totalIndices: mesh.getIndices() ? mesh.getIndices()!.length : 0 } return meshData } export const parseAndCacheScene = async (meshes: AbstractMesh[], cacheFileName: string, modelPath: string): Promise => { const parsedMeshes = meshes.map(mesh => extractAllMeshData(mesh)) const boundingBox = meshes[0].getHierarchyBoundingVectors() const totalVertices = parsedMeshes.reduce((sum, mesh) => { const meshData = mesh as Record const geometry = meshData.geometry as Record const vertices = geometry.vertices as number[] return sum + vertices.length / 3 }, 0) const totalIndices = parsedMeshes.reduce((sum, mesh) => { const meshData = mesh as Record const geometry = meshData.geometry as Record const indices = geometry.indices as number[] return sum + indices.length }, 0) const parsedData: ParsedMeshData = { meshes: parsedMeshes, boundingBox: { min: boundingBox.min, max: boundingBox.max }, metadata: { modelPath, parsedAt: new Date().toISOString(), totalVertices: Math.floor(totalVertices), totalIndices } } console.log('💾 Caching parsed mesh data:', parsedData.metadata) try { console.log('💾 Attempting to cache mesh data...') console.log('💾 Cache file name:', cacheFileName) console.log('💾 Data size:', JSON.stringify(parsedData).length, 'bytes') const response = await fetch('/api/cache-mesh-data', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ fileName: cacheFileName, data: parsedData }) }) console.log('💾 Response status:', response.status) console.log('💾 Response ok:', response.ok) if (response.ok) { const result = await response.json() console.log('✅ Mesh data cached successfully:', result) } else { const errorText = await response.text() console.warn('⚠️ Failed to cache mesh data:', response.status, errorText) } } catch (error) { console.warn('⚠️ Could not cache mesh data:', error) console.error('💾 Full error details:', error) } return parsedData }