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.

245 lines (242 loc) 8.38 kB
import { aO as mat4Invert, aP as mat4Identity, aQ as getLoaderTmpAnim, av as mat4MultiplyInto, F as F32, aL as computeNodeWorldMatrix, aj as resolveAccessor, aR as INTERP_CUBICSPLINE, aS as INTERP_STEP, aT as INTERP_LINEAR, aU as PATH_WEIGHTS, aV as PATH_SCALE, aW as PATH_ROTATION, aX as PATH_TRANSLATION, aY as findParent } from './index-By0tcgYN.esm.js'; let _parsePointerChannel = null; function _installPointerHandlers(parser) { _parsePointerChannel = parser; } let _convertSampler = null; function _installSamplerConverter(converter) { _convertSampler = converter; } function toSamplerFloat32(src, length, normalized) { if (_convertSampler) { return _convertSampler(src, length, normalized); } return new F32(src.buffer, src.byteOffset, length); } function resolveIBMs(json, binChunk, skin) { const jointCount = skin.joints.length; if (skin.inverseBindMatrices !== void 0) { const ibmData = resolveAccessor(json, binChunk, skin.inverseBindMatrices); return new F32(ibmData._data.buffer, ibmData._data.byteOffset, jointCount * 16); } const out = new F32(jointCount * 16); for (let i = 0; i < jointCount; i++) { const o = i * 16; out[o] = out[o + 5] = out[o + 10] = out[o + 15] = 1; } return out; } function extractSkin(json, binChunk, skinIdx, meshWorldMatrix, parentMap, worldMatrixCache) { const skin = json.skins[skinIdx]; const jointNodes = skin.joints; const inverseBindMatrices = resolveIBMs(json, binChunk, skin); const jointWorldMatrices = jointNodes.map((nodeIdx) => computeNodeWorldMatrix(json, nodeIdx, parentMap, worldMatrixCache)); return { jointNodes, inverseBindMatrices, jointWorldMatrices, meshWorldMatrix }; } function computeBoneTextureData(skin) { const numBones = skin.jointNodes.length; const data = new F32(numBones * 16); const invMeshWorld = mat4Invert(skin.meshWorldMatrix) ?? mat4Identity(); const tmp = getLoaderTmpAnim(); for (let i = 0; i < numBones; i++) { mat4MultiplyInto(tmp, 0, invMeshWorld, 0, skin.jointWorldMatrices[i], 0); mat4MultiplyInto(data, i * 16, tmp, 0, skin.inverseBindMatrices, i * 16); } return data; } const INTERP_MAP = { LINEAR: INTERP_LINEAR, STEP: INTERP_STEP, CUBICSPLINE: INTERP_CUBICSPLINE }; const PATH_MAP = { translation: PATH_TRANSLATION, rotation: PATH_ROTATION, scale: PATH_SCALE, weights: PATH_WEIGHTS }; function parseAnimationData(json, binChunk, meshes, parentMap, worldMatrixCache, nodeMap, boneOverrides) { if (!json.animations || json.animations.length === 0) { return null; } let pointerChannelCount = 0; const clips = []; for (const anim of json.animations) { const samplers = []; for (const s of anim.samplers) { const inputAcc = resolveAccessor(json, binChunk, s.input); const outputAcc = resolveAccessor(json, binChunk, s.output); const inNorm = json.accessors[s.input]?.normalized === true; const outNorm = json.accessors[s.output]?.normalized === true; samplers.push({ input: toSamplerFloat32(inputAcc._data, inputAcc._count, inNorm), output: toSamplerFloat32(outputAcc._data, outputAcc._count * outputAcc._componentCount, outNorm), interpolation: INTERP_MAP[s.interpolation ?? "LINEAR"] ?? INTERP_LINEAR }); } const channels = []; for (const c of anim.channels) { const ptr = c.target?.extensions?.KHR_animation_pointer?.pointer; if (ptr) { if (!_parsePointerChannel) { continue; } const ch = _parsePointerChannel(ptr, c, nodeMap, json, meshes); if (ch) { channels.push(ch); pointerChannelCount++; } continue; } if (c.target.node === void 0) { continue; } const path = PATH_MAP[c.target.path]; if (path === void 0) { continue; } channels.push({ samplerIdx: c.sampler, nodeIdx: c.target.node, path }); } let duration = 0; for (const s of samplers) { if (s.input.length > 0) { const last = s.input[s.input.length - 1]; if (last > duration) { duration = last; } } } clips.push({ name: anim.name ?? "", channels, samplers, duration }); } const nodeCount = json.nodes?.length ?? 0; const nodes = []; for (let i = 0; i < nodeCount; i++) { const n = json.nodes[i]; const t = n.translation ?? [0, 0, 0]; const r = n.rotation ?? [0, 0, 0, 1]; const s = n.scale ?? [1, 1, 1]; nodes.push({ parentIdx: findParent(parentMap, i), _matrix: n.matrix, tx: t[0], ty: t[1], tz: t[2], rx: r[0], ry: r[1], rz: r[2], rw: r[3], sx: s[0], sy: s[1], sz: s[2] }); } const nodeToMeshIndices = /* @__PURE__ */ new Map(); let gpuIdx = 0; for (let ni = 0; ni < nodeCount; ni++) { const node = json.nodes[ni]; if (node.mesh === void 0) { continue; } const mesh = json.meshes[node.mesh]; const indices = []; for (let p = 0; p < mesh.primitives.length; p++) { indices.push(gpuIdx++); } nodeToMeshIndices.set(ni, indices); } const skeletons = []; for (let nodeIdx = 0; nodeIdx < nodeCount; nodeIdx++) { const node = json.nodes[nodeIdx]; if (node.skin === void 0 || !json.skins) { continue; } const meshIndices = nodeToMeshIndices.get(nodeIdx); if (!meshIndices) { continue; } const skin = json.skins[node.skin]; const jointNodes = skin.joints; const inverseBindMatrices = resolveIBMs(json, binChunk, skin); const meshWorldMatrix = computeNodeWorldMatrix(json, nodeIdx, parentMap, worldMatrixCache); const invMeshWorld = mat4Invert(meshWorldMatrix) ?? mat4Identity(); for (const mi of meshIndices) { const mesh = meshes[mi]; const skeleton = mesh?.skeleton; if (!skeleton) { continue; } skeletons.push({ jointNodes, inverseBindMatrices, invMeshWorld, boneTexture: skeleton.boneTexture, boneCount: jointNodes.length, boneMatrices: skeleton.boneMatrices, runtimeSkeleton: skeleton }); } } const morphBindings = []; for (let nodeIdx = 0; nodeIdx < nodeCount; nodeIdx++) { const node = json.nodes[nodeIdx]; if (node.mesh === void 0) { continue; } const gltfMesh = json.meshes[node.mesh]; if (!gltfMesh.primitives?.[0]?.targets?.length) { continue; } const meshIndices = nodeToMeshIndices.get(nodeIdx); if (!meshIndices) { continue; } for (const mi of meshIndices) { const mesh = meshes[mi]; const morphTargets = mesh?.morphTargets; if (!morphTargets) { continue; } morphBindings.push({ nodeIdx, weightsBuffer: morphTargets.weightsBuffer, weights: morphTargets.weights, targetCount: morphTargets.count, runtimeMorphTargets: morphTargets }); } } const nodeTargets = nodeMap ?? []; const excludedNodeIndices = /* @__PURE__ */ new Set(); for (const skin of json.skins ?? []) { for (const ji of skin.joints ?? []) { excludedNodeIndices.add(ji); } } for (let ni = 0; ni < nodeCount; ni++) { if (json.nodes[ni]?.skin === void 0) { continue; } let p = ni; while (p >= 0 && !excludedNodeIndices.has(p)) { excludedNodeIndices.add(p); p = findParent(parentMap, p); } } if (clips.length === 0 || skeletons.length === 0 && morphBindings.length === 0 && pointerChannelCount === 0 && !hasWritableNodeChannel(clips, nodeTargets, excludedNodeIndices)) { return null; } const nodeNames = (json.nodes ?? []).map((n) => n?.name); return { clips, nodes, skeletons, morphBindings, nodeTargets, excludedNodeIndices, nodeNames, boneOverrides }; } function hasWritableNodeChannel(clips, nodeTargets, excludedNodeIndices) { for (const clip of clips) { for (const ch of clip.channels) { if ((ch.path === PATH_TRANSLATION || ch.path === PATH_ROTATION || ch.path === PATH_SCALE) && ch.nodeIdx >= 0 && !excludedNodeIndices.has(ch.nodeIdx) && nodeTargets[ch.nodeIdx]) { return true; } } } return false; } export { _installPointerHandlers, _installSamplerConverter, computeBoneTextureData, extractSkin, parseAnimationData }; //# sourceMappingURL=gltf-animation-CvJhPzAe.esm.js.map