JavaScript
const beep8 = {};
// beep8.g3d — Blitz-like API with two renderers (stroke|solid)
beep8.g3d = () => {
// ---------- math
const v = (x=0,y=0,z=0)=>({x,y,z});
const add = (a,b)=>v(a.x+b.x,a.y+b.y,a.z+b.z);
const sub = (a,b)=>v(a.x-b.x,a.y-b.y,a.z-b.z);
const dot = (a,b)=>a.x*b.x+a.y*b.y+a.z*b.z;
const cross = (a,b)=>v(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
function rotXYZ(rx=0,ry=0,rz=0){
const cx=Math.cos(rx),sx=Math.sin(rx);
const cy=Math.cos(ry),sy=Math.sin(ry);
const cz=Math.cos(rz),sz=Math.sin(rz);
const Rx=[1,0,0, 0,cx,-sx, 0,sx,cx];
const Ry=[cy,0,sy, 0,1,0, -sy,0,cy];
const Rz=[cz,-sz,0, sz,cz,0, 0,0,1];
return mul3(mul3(Rz,Ry),Rx);
}
function mul3(a,b){ // 3x3 * 3x3
return [
a[0]*b[0]+a[1]*b[3]+a[2]*b[6], a[0]*b[1]+a[1]*b[4]+a[2]*b[7], a[0]*b[2]+a[1]*b[5]+a[2]*b[8],
a[3]*b[0]+a[4]*b[3]+a[5]*b[6], a[3]*b[1]+a[4]*b[4]+a[5]*b[7], a[3]*b[2]+a[4]*b[5]+a[5]*b[8],
a[6]*b[0]+a[7]*b[3]+a[8]*b[6], a[6]*b[1]+a[7]*b[4]+a[8]*b[7], a[6]*b[2]+a[7]*b[5]+a[8]*b[8],
];
}
function applyMat(p,m){ return v(
p.x*m[0]+p.y*m[1]+p.z*m[2],
p.x*m[3]+p.y*m[4]+p.z*m[5],
p.x*m[6]+p.y*m[7]+p.z*m[8]
);}
// ---------- camera
function createCamera(opts={}){
return {
x:0,y:0,z:opts.z??8, rx:0,ry:0,rz:0,
fov: opts.fov ?? 60, ortho: !!opts.ortho
};
}
// ---------- core object
function makeObject(kind, data){
const o = {
kind, data,
x:0,y:0,z:0, rx:0,ry:0,rz:0, sx:1,sy:1,sz:1,
mode: data.mode || "solid",
layer: data.layer|0 || 0,
colour: data.colour || "#999",
stroke: data.stroke|0 || 12,
texture: null,
move(dx,dy,dz){ this.x+=dx; this.y+=dy; this.z+=dz; return this; },
rotate(dx,dy,dz){ this.rx+=dx; this.ry+=dy; this.rz+=dz; return this; },
scale(kx,ky=kx,kz=kx){ this.sx*=kx; this.sy*=ky; this.sz*=kz; return this; },
setTexture(tex){ this.texture=tex; return this; }
};
return o;
}
// ---------- primitives
function...