Skip to content

Instantly share code, notes, and snippets.

@derekmc
Last active May 2, 2021 16:44
Show Gist options
  • Save derekmc/7975e944f5c1e19a8fbec5d6ecf2b29d to your computer and use it in GitHub Desktop.
Save derekmc/7975e944f5c1e19a8fbec5d6ecf2b29d to your computer and use it in GitHub Desktop.
<canvas id="Canvas"></canvas>
<script>
Canvas.width = window.innerWidth - 16;
Canvas.height = window.innerHeight - 16;
let Ctx = Canvas.getContext("2d");
let X=0, Y=0;
let Distance=3;
let PointSize=0.015;
let LineWidth= 0.005;
let Center = [0.65,0.8,0.5];
const EPS = 0.00001;
window.addEventListener("load", Init);
document.body.addEventListener("keydown", KeyPress);
let Drawing = null
function Init(){
let cube1 = Cube([0,0,0], 1);
let cube2 = Cube([0,0,4], 1);
let cube3 = Cube([1.25,1.25,4], 1);
let cube4 = Cube([1.25,0,4], 1);
Drawing = MergeDrawings(cube1, cube2, cube3,cube4);
//console.log(Drawing);
Ctx.save();
RescaleCanvas();
Draw(Drawing, Center);
}
function RescaleCanvas(){
let w2 = Canvas.width/2, h2 = Canvas.height/2;
let s2 = Math.min(w2, h2);
let S2 = Math.max(w2, h2);
Ctx.translate(w2,h2);
Ctx.scale(s2, -s2);
}
function Cube(center, side){
let points = [];
let lines = [];
let s = side/2;
for(let i=0; i<8; ++i){
let p = [];
p.push(center[0] + (i&1? s : -s));
p.push(center[1] + (i&2? s : -s));
p.push(center[2] + (i&4? s : -s));
points.push(p);
}
// create all lines hamming distance 1
for(let a=0; a<7; ++a){
for(let b=a+1; b<8; ++b){
let different = 0;
if(points[a][0] != points[b][0]) ++different;
if(points[a][1] != points[b][1]) ++different;
if(points[a][2] != points[b][2]) ++different;
if(different == 1) lines.push([a,b]);
}
}
return {points, lines};
}
// similar triangles
// from (x, z)
// to (xx=?, zz)
// xx = zz * x/z
// depth of screen
//get progressive scalars for how much to scale each point
// result is a flattened array of all projected points.
function ProjectPoints(result, points, center, depth){
if(result == null) result = [];
for(let i=0; i<points.length; ++i){
let p = points[i];
let x = p[0] - center[0];
let y = p[1] - center[1];
let z = p[2] - center[2];
let s = (z > -depth + EPS)? depth / (z + depth) : 1000 * 1000;
if(!(z > -depth + EPS)) console.log("behind screen");
result[2*i] = s*x;
result[2*i + 1] = s*y;
}
return result;
}
function Copy(x){
return JSON.parse(JSON.stringify(x));
}
function MergeDrawings(...drawings){
//console.log(drawings);
let points = [];
let lines = [];
let n = 0;
for(let drawing of drawings){
//console.log('drawing', drawing);
for(let i=0; i<drawing.points.length; ++i){
points.push(drawing.points[i].slice(0)); }
for(let i=0; i<drawing.lines.length; ++i){
lines.push(drawing.lines[i].map(x => x + n)); }
n += drawing.points.length;
}
return {points, lines};
}
function Dot(a, b){
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
function Draw(drawing, center){
let array = [];
Ctx.fillStyle="#e4e4e4";
Ctx.fillRect(-1, -1, 2, 2);
Ctx.fillStyle="#000";
ProjectPoints(array, drawing.points, center, Distance);
for(let i=0; i<array.length; i += 2){
let x = array[i];
let y = array[i+1];
//console.log(x, y);
Ctx.fillRect(x-PointSize/2,y-PointSize/2, PointSize, PointSize);
}
Ctx.beginPath();
Ctx.lineWidth = LineWidth;
for(let i=0; i<drawing.lines.length; ++i){
let a = drawing.lines[i][0];
let b = drawing.lines[i][1];
//console.log(array[2*a], array[2*a + 1]);
//console.log(array[2*b], array[2*b + 1]);
Ctx.moveTo(array[2*a], array[2*a + 1]);
Ctx.lineTo(array[2*b], array[2*b + 1]);
}
Ctx.stroke();
// Ctx.fillStyle="#000";
// Ctx.fillRect(-1/2, 0, 1, 1);
// Ctx.fillStyle="#e4e4e4";
// Ctx.fillRect(0, 0, Canvas.width, Canvas.height);
// Ctx.fillStyle="#000";
// Ctx.fillRect(X,Y,40,40);
}
function KeyPress(){
X = (X + 10) % (Canvas.width - 40);
Y = Math.random() * (Canvas.height - 40);
Draw();
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment