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.

126 lines (122 loc) 4.7 kB
import { j as U8, ai as U32, I as I32, F as F32 } from './index-By0tcgYN.esm.js'; let dracoBaseUrl = "/"; let modulePromise = null; let scriptLoadPromise = null; function loadDracoScript() { if (scriptLoadPromise) { return scriptLoadPromise; } scriptLoadPromise = new Promise((resolve, reject) => { const existing = globalThis.DracoDecoderModule; if (existing) { resolve(existing); return; } const script = document.createElement("script"); script.src = dracoBaseUrl + "draco_decoder.js"; script.onload = () => { const factory = globalThis.DracoDecoderModule; if (!factory) { reject(new Error("draco_decoder.js loaded but DracoDecoderModule is undefined")); } else { resolve(factory); } }; script.onerror = () => reject(new Error("Failed to load draco_decoder.js from " + script.src)); document.head.appendChild(script); }); return scriptLoadPromise; } async function getDracoModule() { if (modulePromise) { return modulePromise; } modulePromise = (async () => { const factory = await loadDracoScript(); return factory({ locateFile: (f) => dracoBaseUrl + f }); })(); return modulePromise; } async function decodeDracoPrimitive(compressed, attributeMap, accessorTypes) { const module = await getDracoModule(); const decoder = new module.Decoder(); const buffer = new module.DecoderBuffer(); buffer.Init(compressed, compressed.byteLength); const mesh = new module.Mesh(); const status = decoder.DecodeBufferToMesh(buffer, mesh); if (!status.ok()) { const err = status.error_msg(); module.destroy(buffer); module.destroy(mesh); module.destroy(decoder); throw new Error("Draco decode failed: " + err); } const numPoints = mesh.num_points(); const numFaces = mesh.num_faces(); const indexCount = numFaces * 3; const indexByteLength = indexCount * 4; const indexPtr = module._malloc(indexByteLength); decoder.GetTrianglesUInt32Array(mesh, indexByteLength, indexPtr); const indices = new U32(module.HEAPU32.buffer, indexPtr, indexCount).slice(); module._free(indexPtr); const attributes = /* @__PURE__ */ new Map(); for (const name of Object.keys(attributeMap)) { const uniqueId = attributeMap[name]; const attr = decoder.GetAttributeByUniqueId(mesh, uniqueId); const componentCount = accessorTypes[name] ?? 3; const totalComponents = numPoints * componentCount; const isIntAttr = name === "JOINTS_0" || name === "JOINTS_1"; const bytesPerElement = 4; const byteLength = totalComponents * bytesPerElement; const ptr = module._malloc(byteLength); const dataType = isIntAttr ? module.DT_INT32 : module.DT_FLOAT32; decoder.GetAttributeDataArrayForAllPoints(mesh, attr, dataType, byteLength, ptr); if (isIntAttr) { attributes.set(name, new I32(module.HEAP32.buffer, ptr, totalComponents).slice()); } else { attributes.set(name, new F32(module.HEAPF32.buffer, ptr, totalComponents).slice()); } module._free(ptr); } module.destroy(buffer); module.destroy(mesh); module.destroy(decoder); return { _attributes: attributes, _indices: indices, _vertexCount: numPoints, _indexCount: indexCount }; } function getDracoBufferViewBytes(json, binChunk, bufferViewIdx) { const view = json.bufferViews[bufferViewIdx]; if (!view) { throw new Error(`Draco bufferView ${bufferViewIdx} not found`); } const offset = binChunk.byteOffset + (view.byteOffset ?? 0); return new U8(binChunk.buffer, offset, view.byteLength); } const TYPE_COMPONENT_COUNTS = { SCALAR: 1, VEC2: 2, VEC3: 3, VEC4: 4, MAT2: 4, MAT3: 9, MAT4: 16 }; const feature = { id: "KHR_draco_mesh_compression", async preMesh(jsonIn, binChunk) { const json = jsonIn; const out = /* @__PURE__ */ new Map(); for (const mesh of json.meshes ?? []) { for (const primitive of mesh.primitives ?? []) { const ext = primitive.extensions?.KHR_draco_mesh_compression; if (!ext) { continue; } const bytes = getDracoBufferViewBytes(json, binChunk, ext.bufferView); const accessorTypes = {}; for (const name of Object.keys(ext.attributes)) { const accIdx = primitive.attributes?.[name]; if (accIdx !== void 0 && json.accessors?.[accIdx]) { accessorTypes[name] = TYPE_COMPONENT_COUNTS[json.accessors[accIdx].type] ?? 3; } } const decoded = await decodeDracoPrimitive(bytes, ext.attributes, accessorTypes); out.set(primitive, decoded); } } return out; } }; export { feature as default }; //# sourceMappingURL=gltf-feature-draco-DSCbuFAk.esm.js.map