Prepares the 3D model for a rendered picture: the sun's direction, the light fixtures as lamps, and which library material each painted face shows.
How the precision is kept
These functions feed the renderer and the 3D view. They pass the view's own mesh buffers on unchanged and work out directions and lamp positions for drawing only. Nothing here is a stored measurement or a reported quantity.
Calculations under this policy
3 calculations in 2 source files. 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.
model = east × dₓ + north × d_y, with d_z kept; view = (mₓ, m_z, −m_y), normalized
The sun library's direction is turned by the site's true north, changed from Z up to Y up and normalized with Math.hypot. The time zone is the longitude ÷ 15 rounded to a whole hour. Used to light the picture only.
render-bim.js
lines 63 to 74
BimCraft 0.8.1
export function bimSun(site, settings, place = null) {
const base = bimSunBase(site);
const s = sunPosition(settings && settings.sun ? { ...base, ...settings.sun } : base);
if (!s.up) return null;
// east / north / up → the model's IFC axes (TrueNorth turns north in the plan) → viewer (Y up)
const n = site?.north || [0, 1], e = [n[1], -n[0]], d = s.dir;
const m = [e[0] * d[0] + n[0] * d[1], e[1] * d[0] + n[1] * d[1], d[2]];
let v = [m[0], m[2], -m[1]];
if (place) v = [place[0] * v[0] + place[4] * v[1] + place[8] * v[2], place[1] * v[0] + place[5] * v[1] + place[9] * v[2], place[2] * v[0] + place[6] * v[1] + place[10] * v[2]];
const l = Math.hypot(v[0], v[1], v[2]) || 1;
return [v[0] / l, v[1] / l, v[2] / l];
}
Lamps from light fixtures
32-bit, display only
A lamp for each light fixture: where it is, how bright and how wide.
lumens = stored value, else watts × 80, else 800; position = middle of the fixture's box, just under it
Lumens are clamped to 1 … 200000 and rounded to a whole number, the beam angle to whole degrees between 5 and 170. The position comes from the view's bounding box of the fixture. Used to light the picture only.
Names the axis of the element's placement that a face normal runs along, to pick the material painted on that side.
axis = the placement column with the largest |n · column|
The placement's three columns are normalized with Math.hypot and compared by dot product; the largest wins, with ties going to the earlier axis. It decides which painted material a face shows, not a dimension.
paint-bim.js
lines 123 to 133
BimCraft 0.8.1
export function faceAxis(api, mid, id, nFile, axesCache = null) {
let ax = axesCache ? axesCache.get(id) : undefined;
if (ax === undefined) { ax = placementAxes(api, mid, id); axesCache?.set(id, ax); }
const A = ax || [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
let best = -1, at = null;
for (let i = 0; i < 3; i++) {
const d = nFile[0] * A[i][0] + nFile[1] * A[i][1] + nFile[2] * A[i][2];
if (Math.abs(d) > best) { best = Math.abs(d); at = 'XYZ'[i] + (d >= 0 ? '+' : '-'); }
}
return at; // the axis the face is nearest (any unit normal has a component ≥ 0.577)
}
In detail
Method
Sun position from render/sun.js turned by the site's true north; lamp position from the fixture's bounding box; a face's material from the placement axis its normal is nearest.
Number types
64-bit numbers for directions; the mesh position and normal buffers are the 3D view's own.
Limits
A fixture without a lumen value is given its wattage × 80, or 800. Lumens and beam angle are stored as whole numbers. Without a site the sun uses 40° N, 105° W.
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.