Sets lamp strength, soft sun shadows and where a material's texture falls on a surface for the fast render and the 3D views.
How the precision is kept
64-bit arithmetic whose results go to the graphics library as light settings and 32-bit texture coordinates. Nothing is written to the model.
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.
A direction inside a small cone around the sun, one per render pass, for soft shadow edges.
r = √h₅ × tan(degrees × π ÷ 180); a = 2π h₇
Halton values in bases 5 and 7 place a point in a disc; the direction is normalized with Math.hypot.
render/looks.js
lines 317 to 323
BimCraft 0.8.1
/** Pass i's sun: a point in a disc of `degrees` around the sun's direction (the sun is ~0.5° across; wider = softer). */
export function sunDisc(dir, i, degrees = 1.5) {
const { up: d, e1, e2 } = basis(dir);
const r = Math.sqrt(halton(i + 1, 5)) * Math.tan((degrees * Math.PI) / 180), a = 2 * Math.PI * halton(i + 1, 7);
const x = r * Math.cos(a), y = r * Math.sin(a);
return vnorm([d[0] + e1[0] * x + e2[0] * y, d[1] + e1[1] * x + e2[1] * y, d[2] + e1[2] * x + e2[2] * y]);
}
Where a point of a surface falls on its material's texture, in meters along and up the surface.
u = p · (up × n) ÷ |up × n|; v = p · (n × u axis)
64-bit dot and cross products. A surface whose normal is within 0.999 of up or down is treated as level and uses fixed axes, which avoids dividing by a near-zero length. The caller stores the result in a Float32Array for the graphics card.
render/materials.js
lines 88 to 104
BimCraft 0.8.1
/** u level along the surface, v up it (metres). n need not be unit length. */
export function planarUV(p, n, up = [0, 0, 1]) {
const nl = Math.hypot(n[0], n[1], n[2]) || 1, nx = n[0] / nl, ny = n[1] / nl, nz = n[2] / nl;
const ud = nx * up[0] + ny * up[1] + nz * up[2];
let ux, uy, uz;
if (Math.abs(ud) > 0.999) {
// a level surface: u along the first axis square to up (X for Z up and for Y up), v along the other
if (Math.abs(up[0]) < 0.9) { ux = 1; uy = 0; uz = 0; } else { ux = 0; uy = 1; uz = 0; }
const vx = up[1] * uz - up[2] * uy, vy = up[2] * ux - up[0] * uz, vz = up[0] * uy - up[1] * ux; // up × u
return [p[0] * ux + p[1] * uy + p[2] * uz, p[0] * vx + p[1] * vy + p[2] * vz];
}
// u = up × n (level, along the surface), v = n × u (up the surface)
ux = up[1] * nz - up[2] * ny; uy = up[2] * nx - up[0] * nz; uz = up[0] * ny - up[1] * nx;
const ul = Math.hypot(ux, uy, uz); ux /= ul; uy /= ul; uz /= ul;
const vx = ny * uz - nz * uy, vy = nz * ux - nx * uz, vz = nx * uy - ny * ux;
return [p[0] * ux + p[1] * uy + p[2] * uz, p[0] * vx + p[1] * vy + p[2] * vz];
}
In detail
Method
Lumens to candela for a point (Φ ÷ 4π) or a flat panel (Φ ÷ π), times the scene's brightness scale of 0.02. Sun samples from a Halton sequence in a small disc. Texture coordinates by projecting a point onto axes level along and up the surface.
Number types
64-bit numbers; texture coordinates stored in a Float32Array.
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.