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