playcanvas
Version:
PlayCanvas WebGL game engine
120 lines (117 loc) • 3.78 kB
JavaScript
import { GSplatManager } from './gsplat-manager.js';
const tempLayersToRemove = [];
class GSplatLayerData {
constructor(device, director, layer, cameraNode){
this.gsplatManager = new GSplatManager(device, director, layer, cameraNode);
}
destroy() {
this.gsplatManager.destroy();
}
}
class GSplatCameraData {
destroy() {
this.layersMap.forEach((layerData)=>layerData.destroy());
this.layersMap.clear();
}
removeLayerData(layer) {
const layerData = this.layersMap.get(layer);
if (layerData) {
layerData.destroy();
this.layersMap.delete(layer);
}
}
getLayerData(device, director, layer, cameraNode) {
let layerData = this.layersMap.get(layer);
if (!layerData) {
layerData = new GSplatLayerData(device, director, layer, cameraNode);
this.layersMap.set(layer, layerData);
const material = layerData.gsplatManager.material;
if (material && director.eventHandler) {
director.eventHandler.fire('material:created', material, cameraNode.camera, layer);
}
}
return layerData;
}
constructor(){
this.layersMap = new Map();
}
}
class GSplatDirector {
constructor(device, renderer, scene, eventHandler){
this.camerasMap = new Map();
this.device = device;
this.renderer = renderer;
this.scene = scene;
this.eventHandler = eventHandler;
}
destroy() {
this.camerasMap.forEach((cameraData)=>cameraData.destroy());
this.camerasMap.clear();
}
getCameraData(camera) {
let cameraData = this.camerasMap.get(camera);
if (!cameraData) {
cameraData = new GSplatCameraData();
this.camerasMap.set(camera, cameraData);
}
return cameraData;
}
update(comp) {
this.camerasMap.forEach((cameraData, camera)=>{
if (!comp.camerasSet.has(camera)) {
cameraData.destroy();
this.camerasMap.delete(camera);
} else {
cameraData.layersMap.forEach((layerData, layer)=>{
if (!camera.layersSet.has(layer.id) || !layer.enabled) {
tempLayersToRemove.push(layer);
}
});
for(let i = 0; i < tempLayersToRemove.length; i++){
const layer = tempLayersToRemove[i];
const layerData = cameraData.layersMap.get(layer);
if (layerData) {
layerData.destroy();
cameraData.layersMap.delete(layer);
}
}
tempLayersToRemove.length = 0;
}
});
let gsplatCount = 0;
const camerasComponents = comp.cameras;
for(let i = 0; i < camerasComponents.length; i++){
const camera = camerasComponents[i].camera;
let cameraData = this.camerasMap.get(camera);
const layerIds = camera.layers;
for(let j = 0; j < layerIds.length; j++){
const layer = comp.getLayerById(layerIds[j]);
if (layer?.enabled) {
if (layer.gsplatPlacementsDirty || !cameraData) {
const placements = layer.gsplatPlacements;
if (placements.length === 0) {
if (cameraData) {
cameraData.removeLayerData(layer);
}
} else {
cameraData ??= this.getCameraData(camera);
const layerData = cameraData.getLayerData(this.device, this, layer, camera.node);
layerData.gsplatManager.reconcile(placements);
}
}
}
}
if (cameraData) {
for (const layerData of cameraData.layersMap.values()){
gsplatCount += layerData.gsplatManager.update();
}
}
}
this.renderer._gsplatCount = gsplatCount;
this.scene.gsplat.dirty = false;
for(let i = 0; i < comp.layerList.length; i++){
comp.layerList[i].gsplatPlacementsDirty = false;
}
}
}
export { GSplatDirector };