@babylonjs/viewer
Version:
The Babylon Viewer aims to simplify a specific but common Babylon.js use case: loading, viewing, and interacting with a 3D model.
153 lines (150 loc) • 4.46 kB
JavaScript
import { aj as resolveAccessor, T as ThrowLiteError, a_ as setThinInstances, a$ as mat4ComposeInto, F as F32, c as computeAabb, b0 as getLoaderTmpInstance } from './index-By0tcgYN.esm.js';
import { m as mat4Multiply } from './mat4-multiply-fXsV9rc-.esm.js';
function collectMeshesUnderNode(tn) {
const out = [];
for (const c of tn?.children ?? []) {
if (c && typeof c === "object" && "material" in c) {
out.push(c);
}
}
return out;
}
function buildInstanceMatrices(translation, rotation, scale, count) {
const matrices = new F32(count * 16);
for (let i = 0; i < count; i++) {
const tx = translation ? translation[i * 3] : 0;
const ty = translation ? translation[i * 3 + 1] : 0;
const tz = translation ? translation[i * 3 + 2] : 0;
const qx = rotation ? rotation[i * 4] : 0;
const qy = rotation ? rotation[i * 4 + 1] : 0;
const qz = rotation ? rotation[i * 4 + 2] : 0;
const qw = rotation ? rotation[i * 4 + 3] : 1;
const sx = scale ? scale[i * 3] : 1;
const sy = scale ? scale[i * 3 + 1] : 1;
const sz = scale ? scale[i * 3 + 2] : 1;
mat4ComposeInto(matrices, i * 16, tx, ty, tz, qx, qy, qz, qw, sx, sy, sz);
}
return matrices;
}
const ext = {
id: "EXT_mesh_gpu_instancing",
async applyAsset(_meshes, _root, ctx) {
const { _json: json, _binChunk: binChunk, _nodeMap: nodeMap } = ctx;
if (!nodeMap) {
return {};
}
const nodes = json.nodes ?? [];
for (let nodeIdx = 0; nodeIdx < nodes.length; nodeIdx++) {
const attrs = nodes[nodeIdx]?.extensions?.EXT_mesh_gpu_instancing?.attributes;
if (!attrs) {
continue;
}
const tn = nodeMap[nodeIdx];
if (!tn) {
continue;
}
const meshesForNode = collectMeshesUnderNode(tn);
if (meshesForNode.length === 0) {
continue;
}
const tAcc = attrs.TRANSLATION !== void 0 ? resolveAccessor(json, binChunk, attrs.TRANSLATION) : null;
const rAcc = attrs.ROTATION !== void 0 ? resolveAccessor(json, binChunk, attrs.ROTATION) : null;
const sAcc = attrs.SCALE !== void 0 ? resolveAccessor(json, binChunk, attrs.SCALE) : null;
let count = 0;
for (const acc of [tAcc, rAcc, sAcc]) {
if (!acc) {
continue;
}
if (count === 0) {
count = acc._count;
} else if (acc._count !== count) {
ThrowLiteError(85, nodeIdx);
}
}
if (count === 0) {
continue;
}
const matrices = buildInstanceMatrices(
tAcc ? tAcc._data : null,
rAcc ? rAcc._data : null,
sAcc ? sAcc._data : null,
count
);
const nodeWorld = ctx._worldMatrixCache.get(nodeIdx);
for (const mesh of meshesForNode) {
setThinInstances(mesh, matrices, count);
expandMeshAabbForInstances(mesh, matrices, count, nodeWorld);
}
}
return {};
}
};
function expandMeshAabbForInstances(mesh, matrices, count, nodeWorld) {
const positions = mesh._cpuPositions;
if (!positions || !nodeWorld || count === 0) {
return;
}
const [lmin, lmax] = computeAabb(positions);
if (!isFinite(lmin[0])) {
return;
}
const corners = new F32([
lmin[0],
lmin[1],
lmin[2],
lmax[0],
lmin[1],
lmin[2],
lmin[0],
lmax[1],
lmin[2],
lmax[0],
lmax[1],
lmin[2],
lmin[0],
lmin[1],
lmax[2],
lmax[0],
lmin[1],
lmax[2],
lmin[0],
lmax[1],
lmax[2],
lmax[0],
lmax[1],
lmax[2]
]);
let wMinX = Infinity, wMinY = Infinity, wMinZ = Infinity;
let wMaxX = -Infinity, wMaxY = -Infinity, wMaxZ = -Infinity;
const instWorld = getLoaderTmpInstance();
const instBuf = instWorld;
for (let i = 0; i < count; i++) {
for (let k = 0; k < 16; k++) {
instBuf[k] = matrices[i * 16 + k];
}
const combined = mat4Multiply(nodeWorld, instWorld);
const [imin, imax] = computeAabb(corners, combined);
if (imin[0] < wMinX) {
wMinX = imin[0];
}
if (imin[1] < wMinY) {
wMinY = imin[1];
}
if (imin[2] < wMinZ) {
wMinZ = imin[2];
}
if (imax[0] > wMaxX) {
wMaxX = imax[0];
}
if (imax[1] > wMaxY) {
wMaxY = imax[1];
}
if (imax[2] > wMaxZ) {
wMaxZ = imax[2];
}
}
mesh.boundMin = [wMinX, wMinY, wMinZ];
mesh.boundMax = [wMaxX, wMaxY, wMaxZ];
}
export { ext as default };
//# sourceMappingURL=gltf-feature-gpu-instancing-BNBgA0Y7.esm.js.map