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