Builds the starting meshes: plane, grid, cube, circle, cylinder, cone, UV sphere, ico sphere and torus, at the sizes asked for.
How the precision is kept
Every vertex is one 64-bit expression of the size, the radius and an index; angles are 2π × index ÷ count, computed from the index each time and never accumulated. Positions go into a Float64Array. Sizes are clamped to fixed ranges and segment counts are rounded to whole numbers.
Calculations under this policy
6 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.
A flat grid of nx by ny quads, size s, centered on the origin.
p(i, j) = [(i ÷ nx − 0.5)·s, (j ÷ ny − 0.5)·s, 0]
One division, one subtraction and one multiplication per coordinate. The outer rows use 0 − 0.5 and 1 − 0.5, so they land on ±s ÷ 2 without rounding. The UVs written in the same loop go to the 32-bit uv layer.
mesh/primitives.js
lines 47 to 50
ModelCraft 0.8.1
case 'grid': {
const s = clampNum(o.size, 1e-4, 1e5, 2), nx = clampInt(o.x, 1, 1000, 10), ny = clampInt(o.y, 1, 1000, nx);
const pts = [], faces = [], uvs = [];
for (let j = 0; j <= ny; j++) for (let i = 0; i <= nx; i++) pts.push([(i / nx - 0.5) * s, (j / ny - 0.5) * s, 0]);
Cube
64-bit
A cube of side s standing on z = 0, centered in x and y.
h = s ÷ 2; corners (±h, ±h, 0) and (±h, ±h, s)
Halving is exact in binary, and the eight corners are written from h and s with no further arithmetic.
A ring of n points of radius r at z = 0, with a second ring at height h for a cylinder or one apex for a cone.
a = 2π·i ÷ n; p = [r·cos a, r·sin a, 0 or h]; apex = [0, 0, h]
The angle comes from the index each time and the ring has n distinct points, with no repeated point at 2π. The top ring evaluates the same expression as the bottom one, so the two match exactly in x and y. The result is an n-sided prism or pyramid inscribed in the true shape.
mesh/primitives.js
lines 77 to 81
ModelCraft 0.8.1
case 'cylinder': case 'cone': {
const r = clampNum(o.r, 1e-4, 1e5, 1), hh = clampNum(o.h, 1e-4, 1e5, 2), n = clampInt(o.segs, 3, 1024, 32), cone = name === 'cone';
const pts = [], faces = [], uvs = [];
for (let i = 0; i < n; i++) { const a = (2 * Math.PI * i) / n; pts.push([r * Math.cos(a), r * Math.sin(a), 0]); }
if (cone) pts.push([0, 0, hh]); else for (let i = 0; i < n; i++) { const a = (2 * Math.PI * i) / n; pts.push([r * Math.cos(a), r * Math.sin(a), hh]); }
UV sphere
64-bit
A sphere of radius r resting on z = 0, made of k rings of n points between two poles.
The poles are written as [0, 0, 0] and [0, 0, 2r] without trigonometry. On the rings next to the bottom pole z = r − r·cos θ subtracts two nearly equal numbers, so a small z keeps the absolute accuracy of r but fewer significant digits of its own.
mesh/primitives.js
lines 94 to 98
ModelCraft 0.8.1
case 'uvsphere': {
const r = clampNum(o.r, 1e-4, 1e5, 1), n = clampInt(o.segs, 3, 512, 32), k = clampInt(o.rings, 2, 512, 16);
const pts = [[0, 0, 0]]; // bottom pole (the sphere stands on the ground: centre at z = r)
for (let j = 1; j < k; j++) { const th = (Math.PI * j) / k; for (let i = 0; i < n; i++) { const ph = (2 * Math.PI * i) / n; pts.push([r * Math.sin(th) * Math.cos(ph), r * Math.sin(th) * Math.sin(ph), r - r * Math.cos(th)]); } }
pts.push([0, 0, 2 * r]);
Ico sphere
64-bit
A sphere of radius r resting on z = 0, from an icosahedron whose triangles are split into four a number of times.
g = (1 + √5) ÷ 2; corners = unit(±1, ±g, 0) and its rotations; midpoint = unit((a + b) ÷ 2); p = unit point·r + [0, 0, r]
Every corner and every midpoint is divided by its own Math.hypot length before it is scaled by r, so each vertex lies on the sphere to rounding. A midpoint is computed once per edge and shared by the two triangles on it.
mesh/primitives.js
lines 106 to 118
ModelCraft 0.8.1
case 'icosphere': {
const r = clampNum(o.r, 1e-4, 1e5, 1), sub = clampInt(o.subdiv, 0, 6, 2), g = (1 + Math.sqrt(5)) / 2;
let pts = [[-1, g, 0], [1, g, 0], [-1, -g, 0], [1, -g, 0], [0, -1, g], [0, 1, g], [0, -1, -g], [0, 1, -g], [g, 0, -1], [g, 0, 1], [-g, 0, -1], [-g, 0, 1]];
let faces = [[0, 11, 5], [0, 5, 1], [0, 1, 7], [0, 7, 10], [0, 10, 11], [1, 5, 9], [5, 11, 4], [11, 10, 2], [10, 7, 6], [7, 1, 8], [3, 9, 4], [3, 4, 2], [3, 2, 6], [3, 6, 8], [3, 8, 9], [4, 9, 5], [2, 4, 11], [6, 2, 10], [8, 6, 7], [9, 8, 1]];
const unit = (p) => { const l = Math.hypot(...p); return [p[0] / l, p[1] / l, p[2] / l]; };
pts = pts.map(unit);
for (let s = 0; s < sub; s++) {
const mid = new Map(), next = [];
const mp = (a, b) => { const kk = a < b ? a + ',' + b : b + ',' + a; if (!mid.has(kk)) { pts.push(unit([(pts[a][0] + pts[b][0]) / 2, (pts[a][1] + pts[b][1]) / 2, (pts[a][2] + pts[b][2]) / 2])); mid.set(kk, pts.length - 1); } return mid.get(kk); };
for (const [a, b, c] of faces) { const ab = mp(a, b), bc = mp(b, c), ca = mp(c, a); next.push([a, ab, ca], [b, bc, ab], [c, ca, bc], [ab, bc, ca]); }
faces = next;
}
const P = pts.map((p) => [p[0] * r, p[1] * r, p[2] * r + r]);
Torus
64-bit
A torus of ring radius R and tube radius r resting on z = 0.
a = 2π·i ÷ n, b = 2π·j ÷ k; w = R + r·cos b; p = [w·cos a, w·sin a, r + r·sin b]
One 64-bit expression per coordinate with both angles computed from their indices. z = r + r·sin b is near zero at the bottom of the tube, where the sum of two nearly opposite numbers keeps the absolute accuracy of r.
mesh/primitives.js
lines 122 to 125
ModelCraft 0.8.1
case 'torus': {
const R = clampNum(o.R, 1e-4, 1e5, 1), rr = clampNum(o.r, 1e-5, 1e5, 0.25), n = clampInt(o.segs, 3, 512, 48), k = clampInt(o.ring, 3, 512, 12);
const pts = [], faces = [], uvs = [];
for (let i = 0; i < n; i++) { const a = (2 * Math.PI * i) / n; for (let j = 0; j < k; j++) { const b = (2 * Math.PI * j) / k; const w = R + rr * Math.cos(b); pts.push([w * Math.cos(a), w * Math.sin(a), rr + rr * Math.sin(b)]); } }
In detail
Method
Closed-form coordinates from sine and cosine of evenly spaced angles; the ico sphere from a normalized icosahedron whose edges are halved and pushed back onto the unit sphere.
Number types
64-bit numbers; Float64Array positions; Int32Array face lists.
Tolerances
Sizes and radii are clamped to 1e-4…1e5 (the torus tube radius to 1e-5…1e5); segments to 3…1024 for the circle, cylinder and cone and 3…512 for the UV sphere and torus; grid cells to 1…1000; ico sphere subdivisions to 0…6.
Limits
Round shapes are faceted: their vertices lie on the true surface and their faces are flat between them, so areas and volumes are those of the facets, not of the true circle, cylinder, cone, sphere or torus.
Approach: 64-bit, direct
Every value is a 64-bit number from input to result. Formulas are closed form or a direct solve, and every comparison uses a stated tolerance.