@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.
274 lines (271 loc) • 9.73 kB
JavaScript
import { ag as TYPE_SIZES, c as computeAabb, ah as initMeshTransform, ai as U32, aj as resolveAccessor, j as U8, U as U16, F as F32, ak as DV, d as createMappedBuffer, B as BU } from './index-By0tcgYN.esm.js';
import { computeSmoothNormals } from './gltf-normals-DEUAzhrX.esm.js';
const FLOAT = 5126;
const UNSIGNED_SHORT = 5123;
const UNSIGNED_INT = 5125;
const UNSIGNED_BYTE = 5121;
const COMP_BYTES = { [UNSIGNED_BYTE]: 1, [UNSIGNED_SHORT]: 2, [UNSIGNED_INT]: 4, [FLOAT]: 4 };
function createSequentialIndices(vertexCount) {
const indices = vertexCount > 65535 ? new U32(vertexCount) : new U16(vertexCount);
for (let i = 0; i < vertexCount; i++) {
indices[i] = i;
}
return indices;
}
function accessorIsStrided(json, idx) {
const a = json.accessors[idx];
const bv = json.bufferViews[a.bufferView];
const stride = bv.byteStride;
if (stride === void 0) {
return false;
}
const elemBytes = (TYPE_SIZES[a.type] ?? 1) * (COMP_BYTES[a.componentType] ?? 4);
return stride !== elemBytes;
}
function resolveStrided(json, binChunk, accessorIdx) {
const accessor = json.accessors[accessorIdx];
const bufferView = json.bufferViews[accessor.bufferView];
const ab = binChunk.buffer;
return {
_bufferView: accessor.bufferView,
_stride: bufferView.byteStride,
_offset: accessor.byteOffset ?? 0,
_componentType: accessor.componentType,
_componentCount: TYPE_SIZES[accessor.type] ?? 1,
_count: accessor.count,
_slice: new U8(ab, binChunk.byteOffset + (bufferView.byteOffset ?? 0), bufferView.byteLength)
};
}
function destrideToTight(il) {
const dv = new DV(il._slice.buffer, il._slice.byteOffset, il._slice.byteLength);
const cb = COMP_BYTES[il._componentType] ?? 4;
const ct = il._componentType;
const cc = il._componentCount;
const out = new F32(il._count * cc);
for (let v = 0; v < il._count; v++) {
const rowBase = il._offset + v * il._stride;
for (let c = 0; c < cc; c++) {
const off = rowBase + c * cb;
out[v * cc + c] = ct === FLOAT ? dv.getFloat32(off, true) : ct === UNSIGNED_SHORT ? dv.getUint16(off, true) : ct === UNSIGNED_INT ? dv.getUint32(off, true) : dv.getUint8(off);
}
}
return out;
}
function resolveColorVec4(json, binChunk, idx) {
const accessor = json.accessors[idx];
const ct = accessor.componentType;
const cb = COMP_BYTES[ct] ?? 4;
const comps = TYPE_SIZES[accessor.type] ?? 4;
const bv = json.bufferViews[accessor.bufferView];
const stride = bv.byteStride ?? comps * cb;
const inv = ct === UNSIGNED_BYTE ? 1 / 255 : ct === UNSIGNED_SHORT ? 1 / 65535 : 1;
const base = (bv.byteOffset ?? 0) + (accessor.byteOffset ?? 0);
const out = new F32(accessor.count * 4);
for (let v = 0; v < accessor.count; v++) {
const row = base + v * stride;
for (let c = 0; c < 4; c++) {
if (c === 3 && comps < 4) {
out[v * 4 + 3] = 1;
break;
}
const off = row + c * cb;
const raw = ct === FLOAT ? binChunk.getFloat32(off, true) : ct === UNSIGNED_SHORT ? binChunk.getUint16(off, true) : binChunk.getUint8(off);
out[v * 4 + c] = raw * inv;
}
}
return out;
}
async function buildInterleavedPartial(json, binChunk, primitive, worldMatrix, nodeIdx) {
const attrs = primitive.attributes;
let anyStrided = false;
for (const name in attrs) {
if (accessorIsStrided(json, attrs[name])) {
anyStrided = true;
break;
}
}
if (!anyStrided) {
return void 0;
}
const vb = {};
let vertexCount = 0;
const resolveOne = (name, eager) => {
const idx = attrs[name];
if (idx === void 0) {
return { _tight: null, _count: 0 };
}
if (accessorIsStrided(json, idx)) {
const il = resolveStrided(json, binChunk, idx);
const elemBytes = il._componentCount * (COMP_BYTES[il._componentType] ?? 4);
if (il._offset + elemBytes > il._stride) {
return { _tight: destrideToTight(il), _count: il._count };
}
return { _tight: eager ? destrideToTight(il) : null, _il: il, _count: il._count };
}
const av = resolveAccessor(json, binChunk, idx);
return { _tight: av._data, _count: av._count };
};
const pos = resolveOne("POSITION", false);
vb._p = pos._il;
vertexCount = pos._count;
const nrm = resolveOne("NORMAL", false);
vb._n = nrm._il;
const uvIdx = attrs["TEXCOORD_0"];
const uv = uvIdx !== void 0 && json.accessors[uvIdx].componentType !== FLOAT ? { _tight: (await import('./gltf-uv-denorm-BG4PirBz.esm.js')).resolveUvVec2(json, binChunk, uvIdx), _count: json.accessors[uvIdx].count } : resolveOne("TEXCOORD_0", false);
vb._u = uv._il;
const tan = resolveOne("TANGENT", true);
vb._t = tan._il;
const uv2 = resolveOne("TEXCOORD_1", true);
vb._u2 = uv2._il;
const colorIdx = attrs["COLOR_0"];
const colors = colorIdx !== void 0 ? resolveColorVec4(json, binChunk, colorIdx) : null;
const positions = pos._tight;
let normals = nrm._tight;
let uvs = uv._tight;
const tangents = tan._tight;
const uv2s = uv2._tight;
const idxData = primitive.indices !== void 0 ? resolveAccessor(json, binChunk, primitive.indices) : null;
const indices = idxData ? idxData._data instanceof U32 ? new U32(idxData._data) : idxData._data instanceof U8 ? Uint16Array.from(idxData._data) : new U16(idxData._data.buffer, idxData._data.byteOffset, idxData._count) : createSequentialIndices(vertexCount);
if (!normals && !vb._n) {
const tightPos = positions ?? (vb._p ? destrideToTight(vb._p) : new F32(vertexCount * 3));
normals = computeSmoothNormals(tightPos, indices, vertexCount);
}
if (!uvs && !vb._u) {
uvs = new F32(vertexCount * 2);
}
const flatNormal = !nrm._tight && !vb._n;
return {
_positions: positions,
_normals: normals,
_tangents: tangents,
_uvs: uvs,
_uv2s: uv2s,
_colors: colors,
_flatNormal: flatNormal,
_indices: indices,
_vertexCount: vertexCount,
_indexCount: indices.length,
_worldMatrix: worldMatrix,
_vb: vb,
_nodeIndex: nodeIdx,
_primitive: primitive
};
}
function buildInterleavedGpu(engine, m) {
const vbsrc = m._vb;
const shared = /* @__PURE__ */ new Map();
const vbuf = (a, tight) => {
if (!a) {
return tight ? createMappedBuffer(engine, tight, BU.VERTEX) : null;
}
let b = shared.get(a._bufferView);
if (!b) {
shared.set(a._bufferView, b = createMappedBuffer(engine, a._slice, BU.VERTEX));
}
return b;
};
const k = (a) => `${a?._stride ?? 0},${a?._offset ?? 0}`;
return {
positionBuffer: vbuf(vbsrc._p, m._positions),
normalBuffer: vbuf(vbsrc._n, m._normals),
tangentBuffer: m._tangents ? vbuf(vbsrc._t, m._tangents) : null,
uvBuffer: vbuf(vbsrc._u, m._uvs),
uv2Buffer: m._uv2s ? vbuf(vbsrc._u2, m._uv2s) : null,
colorBuffer: m._colors ? vbuf(vbsrc._c, m._colors) : null,
indexBuffer: createMappedBuffer(engine, m._indices, BU.INDEX),
indexCount: m._indexCount,
indexFormat: m._indices instanceof U32 ? "uint32" : "uint16",
_vbLayout: vbsrc,
_vbKey: `vb${k(vbsrc._p)}.${k(vbsrc._n)}.${k(vbsrc._t)}.${k(vbsrc._u)}`
};
}
function buildInterleavedMesh(engine, m, index, material, name, source) {
const gpu = source?._gpu ?? buildInterleavedGpu(engine, m);
const [boundMin, boundMax] = m._vb._p ? computeAabbStrided(m._vb._p, m._worldMatrix) : computeAabb(m._positions, m._worldMatrix);
const mesh = {
name: name || `gltf_mesh_${index}`,
material,
receiveShadows: false,
boundMin,
boundMax,
_gpu: gpu,
_flatNormal: m._flatNormal
};
initMeshTransform(mesh);
installLazyCpu(mesh, m);
mesh._cpuIndices = source?._cpuIndices ?? (m._indices instanceof U32 ? m._indices : new U32(m._indices));
engine._dlr?.m(mesh, m._uv2s, m._tangents, m._colors, m._indices, gpu.indexFormat);
return mesh;
}
function computeAabbStrided(il, world) {
const dv = new DV(il._slice.buffer, il._slice.byteOffset, il._slice.byteLength);
let minX = Infinity, minY = Infinity, minZ = Infinity;
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
for (let v = 0; v < il._count; v++) {
const base = il._offset + v * il._stride;
const lx = dv.getFloat32(base, true);
const ly = dv.getFloat32(base + 4, true);
const lz = dv.getFloat32(base + 8, true);
let x = lx, y = ly, z = lz;
if (world) {
x = world[0] * lx + world[4] * ly + world[8] * lz + world[12];
y = world[1] * lx + world[5] * ly + world[9] * lz + world[13];
z = world[2] * lx + world[6] * ly + world[10] * lz + world[14];
}
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
if (y < minY) {
minY = y;
}
if (y > maxY) {
maxY = y;
}
if (z < minZ) {
minZ = z;
}
if (z > maxZ) {
maxZ = z;
}
}
return [
[minX, minY, minZ],
[maxX, maxY, maxZ]
];
}
function installLazyCpu(mesh, m) {
const vb = m._vb;
if (vb._p) {
Object.defineProperty(mesh, "_cpuPositions", lazyCpuDesc(vb._p));
} else if (m._positions) {
mesh._cpuPositions = m._positions;
}
if (vb._n) {
Object.defineProperty(mesh, "_cpuNormals", lazyCpuDesc(vb._n));
} else if (m._normals) {
mesh._cpuNormals = m._normals;
}
if (vb._u) {
Object.defineProperty(mesh, "_cpuUvs", lazyCpuDesc(vb._u));
} else if (m._uvs) {
mesh._cpuUvs = m._uvs;
}
}
function lazyCpuDesc(il) {
let local;
return {
configurable: true,
enumerable: true,
get() {
return local ?? (il._cpu ??= destrideToTight(il));
},
set(v) {
local = v;
}
};
}
export { accessorIsStrided, buildInterleavedMesh, buildInterleavedPartial, computeAabbStrided, installLazyCpu };
//# sourceMappingURL=gltf-interleave-BSIzL9AK.esm.js.map