Resources Numerical accuracy Calculation policy

FBX reader: number types as stored

Reads the numbers of an FBX file, binary or text, into the node tree the importer uses.

How the precision is kept

Each value is read with the type the file gives it and is not scaled or rounded here. Single-precision properties and arrays stay 32-bit because the file stores them so; doubles are 64-bit. Whole numbers of 64 bits are kept exactly up to 2⁵³ and as decimal text beyond that.

Calculations under this policy

3 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.

io/fbx-parse.js ModelCraft 0.8.1 64-bit 3 calculations Reviewed

Tests tools/modelcraft-test/fbx.mjs

Single values by type

64-bit

Reads one property value with the width the file states.

A 32-bit float is read with getFloat32 and held as a 64-bit number with the same value; nothing is added to or taken from the file's digits. Doubles are read with getFloat64.

  • io/fbx-parse.js
  • lines 93 to 98
  • ModelCraft 0.8.1
case 'Y': need(2); props.push(dv.getInt16(q, true)); q += 2; break;
case 'C': need(1); props.push(b[q] !== 0); q += 1; break;
case 'I': need(4); props.push(dv.getInt32(q, true)); q += 4; break;
case 'F': need(4); props.push(dv.getFloat32(q, true)); q += 4; break;
case 'D': need(8); props.push(dv.getFloat64(q, true)); q += 8; break;
case 'L': need(8); props.push(i64(dv, q)); q += 8; break;

64-bit whole numbers

Exact

Reads a signed 64-bit whole number from two 32-bit halves.

v = hi × 2³² + lo when −2²¹ ≤ hi < 2²¹; otherwise decimal text

Inside that range the value is below 2⁵³ in magnitude and the sum is exact. Larger values are built with BigInt and returned as text, so no digit is lost.

  • io/fbx-parse.js
  • lines 154 to 160
  • ModelCraft 0.8.1
/** A signed 64-bit integer: a Number when it fits exactly, else its decimal text (object ids can be that large). */
function i64(dv, q) {
  const lo = dv.getUint32(q, true);
  const hi = dv.getInt32(q + 4, true);
  if (hi >= -0x200000 && hi < 0x200000) return hi * 4294967296 + lo;
  return ((BigInt(hi) << 32n) | BigInt(lo)).toString();
}

Arrays by type

64-bit

Reads an array of floats, doubles or whole numbers.

Float arrays go into a Float32Array and double arrays into a Float64Array, each as stored. An array of 64-bit whole numbers goes into a Float64Array; a value that i64 returned as text is converted with Number() and so rounded above 2⁵³.

  • io/fbx-parse.js
  • lines 162 to 171
  • ModelCraft 0.8.1
function typedArray(tc, raw, n) {
  const dv = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);
  if (tc === 'f') { const a = new Float32Array(n); for (let i = 0; i < n; i++) a[i] = dv.getFloat32(i * 4, true); return a; }
  if (tc === 'd') { const a = new Float64Array(n); for (let i = 0; i < n; i++) a[i] = dv.getFloat64(i * 8, true); return a; }
  if (tc === 'i') { const a = new Int32Array(n); for (let i = 0; i < n; i++) a[i] = dv.getInt32(i * 4, true); return a; }
  if (tc === 'l') { const a = new Float64Array(n); for (let i = 0; i < n; i++) { const v = i64(dv, i * 8); a[i] = typeof v === 'number' ? v : Number(v); } return a; }
  const a = new Uint8Array(n);
  for (let i = 0; i < n; i++) a[i] = tc === 'b' ? (raw[i] ? 1 : 0) : raw[i];   // b: booleans; c: bytes (seen in files, e.g. edge crease flags)
  return a;
}

In detail

Method
DataView reads by type letter: Y 16-bit, I 32-bit, F 32-bit float, D 64-bit float, L 64-bit whole number; arrays f, d, l, i, b, c. Text files: Number() of each token.
Number types
Float32Array for f arrays, Float64Array for d and l arrays, Int32Array for i arrays, 64-bit numbers for single values.
Limits
In an array of 64-bit whole numbers a value of 2⁵³ or more is converted with Number() and rounded to the nearest 64-bit float. Accuracy of 32-bit values is the file's own.

Approach: 64-bit, stated limit

The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.

Every policy that takes this approach