UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

114 lines (111 loc) 3.39 kB
import { GSplatOctreeNode } from './gsplat-octree-node.js'; import { path } from '../../core/path.js'; const _toDelete = []; class GSplatOctree { constructor(assetFileUrl, data){ this.fileResources = new Map(); this.cooldowns = new Map(); this.lodLevels = data.lodLevels; this.assetFileUrl = assetFileUrl; const baseDir = path.getDirectory(assetFileUrl); this.files = data.filenames.map((url)=>({ url: path.isRelativePath(url) ? path.join(baseDir, url) : url, lodLevel: -1 })); this.fileRefCounts = new Int32Array(this.files.length); const leafNodes = []; this._extractLeafNodes(data.tree, leafNodes); this.nodes = leafNodes.map((nodeData)=>{ const lods = []; for(let i = 0; i < this.lodLevels; i++){ const lodData = nodeData.lods[i.toString()]; if (lodData) { lods.push({ file: this.files[lodData.file].url || '', fileIndex: lodData.file, offset: lodData.offset || 0, count: lodData.count || 0 }); this.files[lodData.file].lodLevel = i; } else { lods.push({ file: '', fileIndex: -1, offset: 0, count: 0 }); } } return new GSplatOctreeNode(lods, nodeData.bound); }); } _traceLodCounts() {} _extractLeafNodes(node, leafNodes) { if (node.lods) { leafNodes.push({ lods: node.lods, bound: node.bound }); } else if (node.children) { for (const child of node.children){ this._extractLeafNodes(child, leafNodes); } } } getFileResource(fileIndex) { return this.fileResources.get(fileIndex); } incRefCount(fileIndex) { const count = this.fileRefCounts[fileIndex] + 1; this.fileRefCounts[fileIndex] = count; this.cooldowns.delete(fileIndex); } decRefCount(fileIndex, cooldownTicks) { const count = this.fileRefCounts[fileIndex] - 1; this.fileRefCounts[fileIndex] = count; if (count === 0) { this.cooldowns.set(fileIndex, cooldownTicks); } } unloadResource(fileIndex, assetLoader) { if (this.fileResources.has(fileIndex)) { const fullUrl = this.files[fileIndex].url; assetLoader.unload(fullUrl); this.fileResources.delete(fileIndex); this._traceLodCounts(); } } updateCooldownTick(assetLoader) { if (this.cooldowns.size > 0) { this.cooldowns.forEach((remaining, fileIndex)=>{ if (remaining <= 1) { if (this.fileRefCounts[fileIndex] === 0) { this.unloadResource(fileIndex, assetLoader); } _toDelete.push(fileIndex); } else { this.cooldowns.set(fileIndex, remaining - 1); } }); _toDelete.forEach((idx)=>this.cooldowns.delete(idx)); _toDelete.length = 0; } } ensureFileResource(fileIndex, assetLoader) { if (this.fileResources.has(fileIndex)) { return; } const fullUrl = this.files[fileIndex].url; const res = assetLoader.getResource(fullUrl); if (res) { this.fileResources.set(fileIndex, res); if (this.fileRefCounts[fileIndex] === 0) { this.cooldowns.set(fileIndex, assetLoader.cooldownTicks); } this._traceLodCounts(); return; } assetLoader.load(fullUrl); } } export { GSplatOctree };