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.

274 lines (271 loc) 9.73 kB
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