Writes the part's mesh, its placement in an assembly, and its volume and mass to an OpenUSD file in meters with Z up.
How the precision is kept
Mesh points are divided by 1000 and written as point3f[], the 32-bit point type of a USD mesh, so they carry about 7 significant digits in meters. Placement matrices, volume, mass and density are written as 64-bit values.
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.
Converts the part's mesh vertices for the USD file.
(x, y, z) mm → (x, −z, y) ÷ 1000 m
Each coordinate is divided by 1000 in 64-bit and stored in a Float32Array, because the mesh is written as point3f[]. That 32-bit store is the file format's point type. A point 10 m from the origin keeps a resolution of about 1 µm.
usd-partcraft.js
lines 30 to 36
PartCraft 0.8.1
function body(b, prim, mesh, mat) {
const P = mesh.positions, n = P.length / 3;
const pts = new Float32Array(P.length);
for (let i = 0; i < n; i++) { pts[i * 3] = P[i * 3] / 1000; pts[i * 3 + 1] = -P[i * 3 + 2] / 1000; pts[i * 3 + 2] = P[i * 3 + 1] / 1000; }
const nt = mesh.indices.length / 3;
b.mesh(prim, 'Body', { points: pts, counts: new Int32Array(nt).fill(3), indices: Int32Array.from(mesh.indices) }, { material: mat });
}
Instance placement
64-bit
Turns an assembly instance's placement matrix from millimeters, Y up, to meters, Z up.
M′ = A · M · A⁻¹; translation ÷ 1000
A and its inverse hold only 0, 1 and −1, so the two products move and negate entries without rounding. Only the three translation entries are divided by 1000. The matrix is passed on as 64-bit numbers.
usd-partcraft.js
lines 26 to 27
PartCraft 0.8.1
/** A placement (mm, Y up) → metres, Z up: A·M·A⁻¹ with the translation in metres. */
function place(M) { const m = mmul(A, mmul(M, AI)); m[12] /= 1000; m[13] /= 1000; m[14] /= 1000; return m; }
Volume and mass attributes
64-bit
The volume in cubic meters and the mass in kilograms written on each part.
volume m³ = V mm³ × 10⁻⁹; mass kg = V mm³ × ρ g/cm³ × 10⁻⁶
Both are 64-bit products written as double attributes. The volume itself comes from the build's statistics. Mass is written only when the part has a material with a finite density.
usd-partcraft.js
lines 37 to 48
PartCraft 0.8.1
function partData(b, prim, part, stats) {
const S = (n, v) => { if (v !== null && v !== undefined && v !== '') b.attr(prim, n, 'string', String(v), { custom: true, uniform: true }); };
S('cadcraft:partNumber', part.number || part.drawing?.title?.number || null);
if (part.material) {
S('cadcraft:material', part.material.name);
if (Number.isFinite(part.material.density)) b.attr(prim, 'cadcraft:density', 'double', part.material.density, { custom: true, uniform: true, meta: unit('g/cm3') });
}
if (stats && Number.isFinite(stats.volume)) {
b.attr(prim, 'cadcraft:volume', 'double', stats.volume * 1e-9, { custom: true, uniform: true, meta: unit('m3') });
if (part.material && Number.isFinite(part.material.density)) b.attr(prim, 'cadcraft:mass', 'double', stats.volume * part.material.density * 1e-6, { custom: true, uniform: true, meta: unit('kg') });
}
}
In detail
Method
Axis change (x, y, z) → (x, −z, y) and millimeters to meters; placements as A · M · A⁻¹ with the translation divided by 1000.
Number types
Float32Array for mesh points (point3f[]); 64-bit numbers for matrices and the custom attributes.
Limits
Mesh points are 32-bit in the file. The factors 1e-9 and 1e-6 are not exact in binary, so each product with them is rounded once.
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.