custom-graphics-element
custom-graphics-element copied to clipboard
implement homogeneous projection.
function setup() {
setSize(600, 400);
setBorder(1, `black`);
setGrid(20, `grey`);
play();
}
function draw() {
clear(`#333`);
randomSeed(3);
center();
drawCube(100, ([x, y, z]) =>
hproject(
x, y, z,
frame / 100, frame / 150, frame / 200,
250
)
);
}
function drawCube(s, pproject) {
const top = [[-s, s, s], [-s, -s, s], [s, -s, s], [s, s, s]];
const bottom = [[-s, s, -s], [-s, -s, -s], [s, -s, -s], [s, s, -s]];
const cube = [top, bottom].map(pts => pts.map(pproject));
cube.forEach(pts => {
setColor(randomColor());
pts.forEach((p, i) => {
point(...p);
const q = pts[(i + 1) % pts.length];
line(...p, ...q);
})
});
setColor(randomColor());
range(0, top.length, 1, i => line(...cube[0][i], ...cube[1][i]));
}
function hproject(Vx, Vy, Vz, yaw = 0, pitch = 0, roll = 0, w = Infinity, Tx = 0, Ty = 0, Tz = 0, Sx = 1, Sy = 1, Sz = 1) {
const [y, p, r] = [yaw, pitch, roll];
const cy = cos(y), sy = sin(y);
const cp = cos(p), sp = sin(p);
const cr = cos(r), sr = sin(r);
// homogenous affine transform matrix
const M = [
Sx * cp * cy, Sx * (cy * sp * sr - cr * sy), Sx * (cr * cy * sp + sr * sy), Tx,
Sy * cp * sy, Sy * (cr * cy + sp * sr * sy), Sy * (cr * sp * sy - cy * sr), Ty,
-Sz * sp, Sz * cp * sr, Sz * cp * cr, Tz,
sp / w, -cp * sr / w, -cp * cr / w, 1,
];
// homogeneous transformed input vector
const P = [
Vx * M[0] + Vy * M[1] + Vz * M[2] + M[3],
Vx * M[4] + Vy * M[5] + Vz * M[6] + M[7],
Vx * M[8] + Vy * M[9] + Vz * M[10] + M[11],
Vx * M[12] + Vy * M[13] + Vz * M[14] + M[15],
]
// screen coordinate
return [P[0] / P[3], P[1] / P[3]];
}
Partly done. Arc: in 3d:
function setup() {
setSize(600, 400);
setBorder(1, `black`);
setProjector(HOMOGENEOUS).setInfinity(Infinity);
rotateProjector(0.1, -0.2, -0.8);
play();
}
function draw() {
setCursor(`none`);
clear(`white`);
center();
noFill();
setStroke(`black`);
rotateProjector(0.1, -0.2, frame/100);
const d = 100;
line(-d,0,0, d,0,0);
line(0,-d,0, 0,d,0);
line(0,0,-d, 0,0,d);
point(0,0,0)
point(d,0,0)
point(0,d,0)
point(0,0,d)
const a = [50, 20, 0];
const b = [20, 80, 50];
const pts = [a];
for (let t=0; t<=TAU; t+=0.01) {
pts.push(lerp3d(t, a, b));
}
poly(pts);
setStroke(`lightgrey`);
poly(pts.map(p => [p[0],p[1],0]));
poly(pts.map(p => [p[0],0,p[2]]));
poly(pts.map(p => [0,p[1],p[2]]));
}
function pointerMove() {
redraw();
}
function lerp3d(t, a, b) {
return [
cos(t) * a[0] + sin(t) * b[0],
cos(t) * a[1] + sin(t) * b[1],
cos(t) * a[2] + sin(t) * b[2],
]
}