UNPKG

@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
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