playcanvas
Version:
PlayCanvas WebGL game engine
85 lines (82 loc) • 2.71 kB
JavaScript
import { Mat4 } from '../../core/math/mat4.js';
import { Vec4 } from '../../core/math/vec4.js';
import { BoundingBox } from '../../core/shape/bounding-box.js';
import { GSplatIntervalTexture } from './gsplat-interval-texture.js';
const vecs = [];
class GSplatInfo {
constructor(device, resource, placement){
this.activeSplats = 0;
this.intervals = [];
this.lineStart = 0;
this.lineCount = 0;
this.padding = 0;
this.viewport = new Vec4();
this.previousWorldTransform = new Mat4();
this.aabb = new BoundingBox();
this.intervalTexture = null;
this.device = device;
this.resource = resource;
this.node = placement.node;
this.lodIndex = placement.lodIndex;
this.numSplats = resource.numSplats;
this.aabb.copy(placement.aabb);
this.updateIntervals(placement.intervals);
}
destroy() {
this.intervals.length = 0;
this.intervalTexture?.destroy();
}
setLines(start, count, textureSize, activeSplats) {
this.lineStart = start;
this.lineCount = count;
this.padding = textureSize * count - activeSplats;
this.viewport.set(0, start, textureSize, count);
}
updateIntervals(intervals) {
const resource = this.resource;
this.intervals.length = 0;
this.activeSplats = resource.numSplats;
if (intervals.size > 0) {
let totalCount = 0;
let used = 0;
for (const interval of intervals.values()){
totalCount += interval.y - interval.x + 1;
vecs[used++] = interval;
}
if (totalCount !== this.numSplats) {
vecs.length = used;
vecs.sort((a, b)=>a.x - b.x);
this.intervals.length = used * 2;
let k = 0;
let currentStart = vecs[0].x;
let currentEnd = vecs[0].y;
for(let i = 1; i < used; i++){
const p = vecs[i];
if (p.x === currentEnd + 1) {
currentEnd = p.y;
} else {
this.intervals[k++] = currentStart;
this.intervals[k++] = currentEnd + 1;
currentStart = p.x;
currentEnd = p.y;
}
}
this.intervals[k++] = currentStart;
this.intervals[k++] = currentEnd + 1;
this.intervals.length = k;
this.intervalTexture = new GSplatIntervalTexture(this.device);
this.activeSplats = this.intervalTexture.update(this.intervals, totalCount);
}
vecs.length = 0;
}
}
update() {
const worldMatrix = this.node.getWorldTransform();
const worldMatrixChanged = !this.previousWorldTransform.equals(worldMatrix);
if (worldMatrixChanged) {
this.previousWorldTransform.copy(worldMatrix);
}
return worldMatrixChanged;
}
}
export { GSplatInfo };