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.

138 lines (134 loc) 4.95 kB
import { T as ThrowLiteError, aq as resolveAccessor, bp as setThinInstances, bq as mat4ComposeInto, F as F32 } from './index-DMbDahsc.esm.js'; function expandThinInstanceWorldBounds(bounds, mesh) { const boundMin = mesh.boundMin; const boundMax = mesh.boundMax; const world = mesh.worldMatrix; const thinInstances = mesh.thinInstances; const matrices = thinInstances.matrices; const count = Math.min(thinInstances.count, matrices.length / 16 | 0); const center = [(boundMin[0] + boundMax[0]) * 0.5, (boundMin[1] + boundMax[1]) * 0.5, (boundMin[2] + boundMax[2]) * 0.5]; const extent = [(boundMax[0] - boundMin[0]) * 0.5, (boundMax[1] - boundMin[1]) * 0.5, (boundMax[2] - boundMin[2]) * 0.5]; for (let instanceIndex = 0; instanceIndex < count; instanceIndex++) { const matrixOffset = instanceIndex * 16; let linearSize = 0; for (let row = 0; row < 3; row++) { for (let column = 0; column < 3; column++) { linearSize += Math.abs(matrices[matrixOffset + column * 4 + row]); } } if (linearSize < 1e-9) { continue; } for (let row = 0; row < 3; row++) { let transformedCenter = world[12 + row]; let transformedRadius = 0; for (let column = 0; column < 3; column++) { let coefficient = 0; for (let inner = 0; inner < 3; inner++) { coefficient += world[inner * 4 + row] * matrices[matrixOffset + column * 4 + inner]; } transformedCenter += coefficient * center[column]; transformedRadius += Math.abs(coefficient) * extent[column]; } for (let inner = 0; inner < 3; inner++) { transformedCenter += world[inner * 4 + row] * matrices[matrixOffset + 12 + inner]; } const min = transformedCenter - transformedRadius; const max = transformedCenter + transformedRadius; const minKey = row === 0 ? "minX" : row === 1 ? "minY" : "minZ"; const maxKey = row === 0 ? "maxX" : row === 1 ? "maxY" : "maxZ"; if (min < bounds[minKey]) { bounds[minKey] = min; } if (max > bounds[maxKey]) { bounds[maxKey] = max; } } } } function enableThinInstanceWorldBounds(mesh) { if (!mesh.thinInstances) { ThrowLiteError(279); } mesh._expandWorldBounds = expandThinInstanceWorldBounds; } 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(95, nodeIdx); } } if (count === 0) { continue; } const matrices = buildInstanceMatrices( tAcc ? tAcc._data : null, rAcc ? rAcc._data : null, sAcc ? sAcc._data : null, count ); for (const mesh of meshesForNode) { setThinInstances(mesh, matrices, count); enableThinInstanceWorldBounds(mesh); } } return {}; } }; export { ext as default }; //# sourceMappingURL=gltf-feature-gpu-instancing-DulaRY6V.esm.js.map