UNPKG

fbx-parser

Version:

This parser will parse FBX text files and convert them into a JavaScript-Object structure.

117 lines (116 loc) 4.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseBinary = void 0; var binary_reader_1 = require("@picode/binary-reader"); var pako_1 = require("pako"); var MAGIC = Uint8Array.from('Kaydara FBX Binary\x20\x20\x00\x1a\x00'.split(''), function (v) { return v.charCodeAt(0); }); // For debug purposes: // const IND = ' ' // let ind = '' /** * Returns a list of FBXNodes * @param binary the FBX binary file content */ function parseBinary(binary) { if (binary.length < MAGIC.length) throw 'Not a binary FBX file'; var data = new binary_reader_1.BinaryReader(binary); var magic = data.readUint8Array(MAGIC.length).every(function (v, i) { return v === MAGIC[i]; }); if (!magic) throw 'Not a binary FBX file'; var fbxVersion = data.readUint32(); // console.log(`FBX Version: ${fbxVersion}`) var header64 = fbxVersion >= 7500; var fbx = []; while (true) { var subnode = readNode(data, header64); if (subnode === null) break; fbx.push(subnode); } return fbx; } exports.parseBinary = parseBinary; function readNode(data, header64) { var endOffset = header64 ? Number(data.readUint64()) : data.readUint32(); if (endOffset === 0) return null; var numProperties = header64 ? Number(data.readUint64()) : data.readUint32(); var propertyListLen = header64 ? Number(data.readUint64()) : data.readUint32(); var nameLen = data.readUint8(); var name = data.readArrayAsString(nameLen); var node = { name: name, props: [], nodes: [], }; // console.log(`${ind}Node offset ${data.offset}:`, endOffset, numProperties, propertyListLen, nameLen, `"${name}"`) // ind += IND // Properties for (var i = 0; i < numProperties; ++i) { node.props.push(readProperty(data)); } // Node List while (endOffset - data.offset > 13) { var subnode = readNode(data, header64); if (subnode !== null) node.nodes.push(subnode); } data.offset = endOffset; // ind = ind.substr(0, ind.length - IND.length) return node; } function readProperty(data) { var typeCode = data.readUint8AsString(); var read = { Y: function () { return data.readInt16(); }, C: function () { return data.readUint8AsBool(); }, I: function () { return data.readInt32(); }, F: function () { return data.readFloat32(); }, D: function () { return data.readFloat64(); }, L: function () { return data.readInt64(); }, f: function () { return readPropertyArray(data, function (r) { return r.readFloat32(); }); }, d: function () { return readPropertyArray(data, function (r) { return r.readFloat64(); }); }, l: function () { return readPropertyArray(data, function (r) { return r.readInt64(); }); }, i: function () { return readPropertyArray(data, function (r) { return r.readInt32(); }); }, b: function () { return readPropertyArray(data, function (r) { return r.readUint8AsBool(); }); }, S: function () { return data.readArrayAsString(data.readUint32()); }, R: function () { return Array.from(data.readUint8Array(data.readUint32())); }, }; if (typeof read[typeCode] === 'undefined') throw "Unknown Property Type " + typeCode.charCodeAt(0); var value = read[typeCode](); // convert BigInt when ever possible var convertBigInt = function (v) { if (value < Number.MIN_SAFE_INTEGER || v > Number.MAX_SAFE_INTEGER) return v; return Number(v); }; if (typeCode === 'L') { value = convertBigInt(value); } else if (typeCode === 'l') { for (var i = 0; i < value.length; ++i) { value[i] = convertBigInt(value[i]); } } // replace '\x00\x01' by '::' and flip like in the text files if (typeCode === 'S' && value.indexOf('\x00\x01') != -1) { value = value.split('\x00\x01').reverse().join('::'); } return value; } function readPropertyArray(data, reader) { var arrayLength = data.readUint32(); var encoding = data.readUint32(); var compressedLength = data.readUint32(); var arrayData = new binary_reader_1.BinaryReader(data.readUint8Array(compressedLength)); if (encoding == 1) { arrayData = new binary_reader_1.BinaryReader(pako_1.inflate(arrayData.binary)); } var value = []; for (var i = 0; i < arrayLength; ++i) { value.push(reader(arrayData)); } return value; }