Builds the meshes, edges, lights and overlay lines that draw the 3D model on screen.
How the precision is kept
The view copies the model's 64-bit coordinates into 32-bit buffers for the graphics card and draws the 2D overlay from projected points. Nothing here is written back to the model. Dimension text in the overlay is formatted from the model's own 64-bit lengths.
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.
The vertex positions, normals and colors of a definition's faces as the arrays the graphics card draws.
Positions are copied from the model's 64-bit points into Float32Array buffers. The buffers are only drawn; nothing reads them back into the model.
m3d/view3d.js
lines 150 to 166
CadCraft 0.8.2
const pos = new Float32Array(ni * 3), nor = new Float32Array(ni * 3), col = new Float32Array(ni * 3);
const index = ni < 65536 ? new Uint16Array(ni) : new Uint32Array(ni);
let nv = 0, k = 0;
for (const [fid, n, c, tris] of plain) {
const at = new Map();
for (const t of tris) for (const v of t) {
let j = at.get(v);
if (j === undefined) {
j = nv++; at.set(v, j);
const p = def.verts.get(v), q = smooth.get(fid + '|' + v) || n, o = j * 3;
pos[o] = p[0]; pos[o + 1] = p[1]; pos[o + 2] = p[2];
nor[o] = q[0]; nor[o + 1] = q[1]; nor[o + 2] = q[2];
col[o] = c.r; col[o + 1] = c.g; col[o + 2] = c.b;
}
index[k++] = j;
}
}
Box of a placement as drawn
32-bit, display only
The world-space box of one placed definition, used to frame the view and place the lights.
Each vertex is transformed in 64-bit and folded into a min and max box, kept per placement matrix.
m3d/view3d.js
lines 544 to 560
CadCraft 0.8.2
/**
* The model's box in world space as drawn (shown placements), from each definition's own box under each placement's
* matrix, kept with its geometry: a moved placement costs its own vertices, the rest nothing.
*/
placedBox(def, g, wm) {
const key = wm.join(',');
g.boxes ||= new Map();
let bb = g.boxes.get(key);
if (bb === undefined) {
bb = null;
if (def.mesh) { const S = def.shown, P = S.P; for (let v = 0; v < S.nv; v++) if (!S.vertDead(v)) bb = bboxAdd(bb, apply(wm, [P[v * 3], P[v * 3 + 1], P[v * 3 + 2]])); }
else for (const p of def.verts.values()) bb = bboxAdd(bb, apply(wm, p));
if (g.boxes.size > 4096) g.boxes.clear();
g.boxes.set(key, bb);
}
return bb;
}
Overlay line clipped to the near plane
32-bit, display only
A 3D line cut at the camera's near plane and projected to screen points for the 2D overlay.
cut at depth 1.01 × near: a′ = a + (b − a) × (near′ − da) ÷ (db − da)
The clipping is 64-bit; the result is used only to stroke the overlay canvas.
m3d/view3d.js
lines 808 to 820
CadCraft 0.8.2
// ---- the 2D overlay ----
seg(a, b, vp) {
// clip to the near plane before projecting, so lines through the eye still draw
if (this.cam.persp) {
const z = this.cam.axes().z, e = this.cam.eye, nearD = this.cam.near * 1.01;
const da = -dot(sub(a, e), z), db = -dot(sub(b, e), z);
if (da < nearD && db < nearD) return null;
if (da < nearD) a = add(a, mul(sub(b, a), (nearD - da) / (db - da)));
else if (db < nearD) b = add(b, mul(sub(a, b), (nearD - db) / (da - db)));
}
const A = this.cam.project(a, vp), B = this.cam.project(b, vp);
return A && B ? [A, B] : null;
}
In detail
Method
One indexed mesh and one edge set per definition, built with three.js and shared by every placement.
Number types
Float32Array vertex, normal and color buffers; Uint16Array or Uint32Array indexes; 64-bit numbers for the bounding box and the overlay.
Limits
Far from the origin the 32-bit vertex buffers limit what the picture can show; the stored model is not affected.
Approach: Display only
Computed to draw the screen, often in 32-bit on the graphics processor. No number a person reads, saves or exports comes from it.