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
JavaScript
;
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;
}