Skip to content

Instantly share code, notes, and snippets.

@bxt
Last active December 15, 2015 14:49
Show Gist options
  • Save bxt/5277223 to your computer and use it in GitHub Desktop.
Save bxt/5277223 to your computer and use it in GitHub Desktop.
Some 3D icosahedra
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>3D Icosahedron based on Javascript and Canvas</title>
<style>
* {padding:0;margin:0;}
body {text-align:center;font-size:8px;}
</style>
</head>
<body>
<a href="http://bernhardhaeussner.de/">Bernhard Häussner</a>
<br/>
<canvas id="space" width="640" height="480">
Ein dreidimensionale Ikosaeder. Baisert auf HTML-Canvas.
</canvas>
<script>
function rotate(vec,degBog) {
return [Math.cos(degBog)*vec[0]-Math.sin(degBog)*vec[2],vec[1],Math.sin(degBog)*vec[0]+Math.cos(degBog)*vec[2]];
}
function Mesh(){this.edges=[];this.faces=[];}
Mesh.prototype={
addEdge:function(e) {
this.edges.push(e);
return this;
},
addFace:function(f) {
this.faces.push(f);
return this;
},
display:function(canvas,cam){
this.faces.sort(function(f1,f2){return f1.getAvgZ(cam)-f2.getAvgZ(cam);});
for (var i=this.faces.length-1;i>=0;i--) {
this.faces[i].display(canvas,cam);
}
for (var i=this.edges.length-1;i>=0;i--) {
this.edges[i].display(canvas,cam);
}
}
}
function Face4(p1,p2,p3,p4,fill){this.p1=p1;this.p2=p2;this.p3=p3;this.p4=p4;this.fill=fill;}
function _F4(p1,p2,p3,p4,fill) {return new Face4(p1,p2,p3,p4,fill);}
Face4.prototype={
display:function(canvas,cam){
},
getAvgZ:function(cam){
return (cam.CalcPicZ(this.p1)+cam.CalcPicZ(this.p2)+cam.CalcPicZ(this.p3)+cam.CalcPicZ(this.p4))/4;
}
}
function Edge(p1,p2){this.p1=p1;this.p2=p2;}
function _E(p1,p2){return new Edge(p1,p2);}
Edge.prototype={
display:function(canvas,cam){
var lform=cam.CalcPicpoint(this.p1);
var lto =cam.CalcPicpoint(this.p2);
if (isFinite(lform[0])&&isFinite(lform[1])&&isFinite(lto[0])&&isFinite(lto[1])) {
canvas.strokeStyle = "rgba(0,0,0,0.3)";
canvas.beginPath();
canvas.moveTo(C[0]/2+lform[0],C[1]/2+lform[1]);
canvas.lineTo(C[0]/2+lto[0],C[1]/2+lto[1]);
canvas.closePath();
canvas.stroke();
}
}
}
function Cam() {}
Cam.prototype = {
SetProjection:function(distToViewplane,distToCoord) {
this.distToViewplane=distToViewplane;
this.distToCoord=distToCoord;
this.rot=0;
this.roundedRot=0;
},
CalcPicpoint:function(vec) {
vec=rotate(vec,this.rot);
return [ (vec[0]*this.distToViewplane)/(vec[2]+this.distToCoord),
(vec[1]*this.distToViewplane)/(vec[2]+this.distToCoord) ];
},
CalcPicZ:function(vec) {
vec=rotate(vec,this.roundedRot);
return vec[2];
},
SetRotation:function(degBog) {
this.rot=degBog;
this.roundedRot = Math.round((this.rot-Math.PI/4)/(Math.PI/2))*(Math.PI/2)+Math.PI/4; //fix some bugs for icosahedron
}
}
function Icosahedron(h) {
h=h||0;
var einheit=e=20;
var golden=g=e*(1+Math.sqrt(5))/2;
var icosahedron=new Mesh();
var
O =[ 0, h, 0],
A1 =[ g, h, e],
A12=[ 0, h, e],
A2 =[ -g, h, e],
A23=[ -g, h, 0],
A3 =[ -g, h, -e],
A34=[ 0, h, -e],
A4 =[ g, h, -e],
A41=[ g, h, 0],
B1 =[ 0, e+h, g],
B12=[ 0, h, g],
B2 =[ 0, -e+h, g],
B23=[ 0, -e+h, 0],
B3 =[ 0, -e+h, -g],
B34=[ 0, h, -g],
B4 =[ 0, e+h, -g],
B41=[ 0, e+h, 0],
C1 =[ e, g+h, 0],
C12=[ 0, g+h, 0],
C2 =[ -e, g+h, 0],
C23=[ -e, h, 0],
C3 =[ -e, -g+h, 0],
C34=[ 0, -g+h, 0],
C4 =[ e, -g+h, 0]
C41=[ e, h, 0]
;
var
alpha = "0.6)"
Acol = "rgba(255,150,0," + alpha
Bcol = "rgba(0,150,0," + alpha
Ccol = "rgba(20,0,150," + alpha
return icosahedron
.addFace(_F4(A1,A12,O,A41,Acol))
.addFace(_F4(A2,A23,O,A12,Acol))
.addFace(_F4(A3,A34,O,A23,Acol))
.addFace(_F4(A4,A41,O,A34,Acol))
.addFace(_F4(B1,B12,O,B41,Bcol))
.addFace(_F4(B2,B23,O,B12,Bcol))
.addFace(_F4(B3,B34,O,B23,Bcol))
.addFace(_F4(B4,B41,O,B34,Bcol))
.addFace(_F4(C1,C12,O,C41,Ccol))
.addFace(_F4(C2,C23,O,C12,Ccol))
.addFace(_F4(C3,C34,O,C23,Ccol))
.addFace(_F4(C4,C41,O,C34,Ccol))
.addEdge(_E(A1,C1))
.addEdge(_E(A1,C4))
.addEdge(_E(A4,C1))
.addEdge(_E(A4,C4))
.addEdge(_E(A2,C2))
.addEdge(_E(A2,C3))
.addEdge(_E(A3,C2))
.addEdge(_E(A3,C3))
.addEdge(_E(B1,C1))
.addEdge(_E(B1,C2))
.addEdge(_E(B4,C1))
.addEdge(_E(B4,C2))
.addEdge(_E(B2,C3))
.addEdge(_E(B2,C4))
.addEdge(_E(B3,C3))
.addEdge(_E(B3,C4))
.addEdge(_E(A1,B1))
.addEdge(_E(A1,B2))
.addEdge(_E(A2,B1))
.addEdge(_E(A2,B2))
.addEdge(_E(A3,B3))
.addEdge(_E(A3,B4))
.addEdge(_E(A4,B3))
.addEdge(_E(A4,B4))
;
}
function Scene() {
var cam=new Cam();
cam.SetProjection(300,100);
var canvas=document.getElementById('space').getContext('2d');
var icosahedron=Icosahedron(20);
this.iterCount=0;
this.iterCount=939;
this.iterate=function () {
cam.SetRotation((this.iterCount/160)*Math.PI);
//canvas.clearRect(0,0,C[0],C[1]); // clear canvas
canvas.fillStyle = "rgba(255,255,255,0.04)"; canvas.fillRect(0,0,C[0],C[1]);
icosahedron.display(canvas,cam);
this.iterCount++;
this.nestTimeout();
};
this.nestTimeout=function(){
TTT=setTimeout(function (obj){obj.iterate();},10,this);
};
}
function bog2deg(bog) {
return Math.round(bog/Math.PI*180%360)
}
var C=[640,480];
window.onload = function(){(new Scene()).iterate()};
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>3D Icosahedron based on Javascript and Canvas</title>
<style>
* {padding:0;margin:0;}
body {text-align:center;font-size:8px;}
</style>
</head>
<body>
<a href="http://bernhardhaeussner.de/">Bernhard Häussner</a>
<br/>
<canvas id="space" width="640" height="480">
Ein dreidimensionale Ikosaeder. Baisert auf HTML-Canvas.
</canvas>
<script>
function rotate(vec,degBog) {
return [Math.cos(degBog)*vec[0]-Math.sin(degBog)*vec[2],vec[1],Math.sin(degBog)*vec[0]+Math.cos(degBog)*vec[2]];
}
function Mesh(){this.edges=[];this.faces=[];}
Mesh.prototype={
addEdge:function(e) {
this.edges.push(e);
return this;
},
addFace:function(f) {
this.faces.push(f);
return this;
},
display:function(canvas,cam){
this.faces.sort(function(f1,f2){return f1.getAvgZ(cam)-f2.getAvgZ(cam);});
for (var i=this.faces.length-1;i>=0;i--) {
this.faces[i].display(canvas,cam);
}
for (var i=this.edges.length-1;i>=0;i--) {
this.edges[i].display(canvas,cam);
}
}
}
function Face4(p1,p2,p3,p4,fill){this.p1=p1;this.p2=p2;this.p3=p3;this.p4=p4;this.fill=fill;}
function _F4(p1,p2,p3,p4,fill) {return new Face4(p1,p2,p3,p4,fill);}
Face4.prototype={
display:function(canvas,cam){
var p1=cam.CalcPicpoint(this.p1);
var p2=cam.CalcPicpoint(this.p2);
var p3=cam.CalcPicpoint(this.p3);
var p4=cam.CalcPicpoint(this.p4);
if ( isFinite(p1[0])&&isFinite(p1[1])
&& isFinite(p2[0])&&isFinite(p2[1])
&& isFinite(p3[0])&&isFinite(p3[1])
&& isFinite(p4[0])&&isFinite(p4[1]) ) {
canvas.fillStyle = this.fill;
canvas.strokeStyle = "rgba(0,0,0,0.3)";
canvas.beginPath();
canvas.moveTo(C[0]/2+p1[0],C[1]/2+p1[1]);
canvas.lineTo(C[0]/2+p2[0],C[1]/2+p2[1]);
canvas.lineTo(C[0]/2+p3[0],C[1]/2+p3[1]);
canvas.lineTo(C[0]/2+p4[0],C[1]/2+p4[1]);
canvas.closePath();
canvas.fill();
//canvas.stroke();
}
},
getAvgZ:function(cam){
return (cam.CalcPicZ(this.p1)+cam.CalcPicZ(this.p2)+cam.CalcPicZ(this.p3)+cam.CalcPicZ(this.p4))/4;
}
}
function Edge(p1,p2){this.p1=p1;this.p2=p2;}
function _E(p1,p2){return new Edge(p1,p2);}
Edge.prototype={
display:function(canvas,cam){
var lform=cam.CalcPicpoint(this.p1);
var lto =cam.CalcPicpoint(this.p2);
if (isFinite(lform[0])&&isFinite(lform[1])&&isFinite(lto[0])&&isFinite(lto[1])) {
canvas.strokeStyle = "rgba(0,0,0,0.1)";
canvas.beginPath();
canvas.moveTo(C[0]/2+lform[0],C[1]/2+lform[1]);
canvas.lineTo(C[0]/2+lto[0],C[1]/2+lto[1]);
canvas.closePath();
canvas.stroke();
}
}
}
function Cam() {}
Cam.prototype = {
SetProjection:function(distToViewplane,distToCoord) {
this.distToViewplane=distToViewplane;
this.distToCoord=distToCoord;
this.rot=0;
this.roundedRot=0;
},
CalcPicpoint:function(vec) {
vec=rotate(vec,this.rot);
return [ (vec[0]*this.distToViewplane)/(vec[2]+this.distToCoord),
(vec[1]*this.distToViewplane)/(vec[2]+this.distToCoord) ];
},
CalcPicZ:function(vec) {
vec=rotate(vec,this.roundedRot);
return vec[2];
},
SetRotation:function(degBog) {
this.rot=degBog;
this.roundedRot = Math.round((this.rot-Math.PI/4)/(Math.PI/2))*(Math.PI/2)+Math.PI/4; //fix some bugs for icosahedron
}
}
function Icosahedron(h) {
h=h||0;
var einheit=e=20;
var golden=g=e*(1+Math.sqrt(5))/2;
var icosahedron=new Mesh();
var
O =[ 0, h, 0],
A1 =[ g, h, e],
A12=[ 0, h, e],
A2 =[ -g, h, e],
A23=[ -g, h, 0],
A3 =[ -g, h, -e],
A34=[ 0, h, -e],
A4 =[ g, h, -e],
A41=[ g, h, 0],
B1 =[ 0, e+h, g],
B12=[ 0, h, g],
B2 =[ 0, -e+h, g],
B23=[ 0, -e+h, 0],
B3 =[ 0, -e+h, -g],
B34=[ 0, h, -g],
B4 =[ 0, e+h, -g],
B41=[ 0, e+h, 0],
C1 =[ e, g+h, 0],
C12=[ 0, g+h, 0],
C2 =[ -e, g+h, 0],
C23=[ -e, h, 0],
C3 =[ -e, -g+h, 0],
C34=[ 0, -g+h, 0],
C4 =[ e, -g+h, 0]
C41=[ e, h, 0]
;
var
alpha = "0.6)"
Acol = "rgba(255,150,0," + alpha
Bcol = "rgba(0,150,0," + alpha
Ccol = "rgba(20,0,150," + alpha
return icosahedron
.addFace(_F4(A1,A12,O,A41,Acol))
.addFace(_F4(A2,A23,O,A12,Acol))
.addFace(_F4(A3,A34,O,A23,Acol))
.addFace(_F4(A4,A41,O,A34,Acol))
.addFace(_F4(B1,B12,O,B41,Bcol))
.addFace(_F4(B2,B23,O,B12,Bcol))
.addFace(_F4(B3,B34,O,B23,Bcol))
.addFace(_F4(B4,B41,O,B34,Bcol))
.addFace(_F4(C1,C12,O,C41,Ccol))
.addFace(_F4(C2,C23,O,C12,Ccol))
.addFace(_F4(C3,C34,O,C23,Ccol))
.addFace(_F4(C4,C41,O,C34,Ccol))
.addEdge(_E(A1,C1))
.addEdge(_E(A1,C4))
.addEdge(_E(A4,C1))
.addEdge(_E(A4,C4))
.addEdge(_E(A2,C2))
.addEdge(_E(A2,C3))
.addEdge(_E(A3,C2))
.addEdge(_E(A3,C3))
.addEdge(_E(B1,C1))
.addEdge(_E(B1,C2))
.addEdge(_E(B4,C1))
.addEdge(_E(B4,C2))
.addEdge(_E(B2,C3))
.addEdge(_E(B2,C4))
.addEdge(_E(B3,C3))
.addEdge(_E(B3,C4))
.addEdge(_E(A1,B1))
.addEdge(_E(A1,B2))
.addEdge(_E(A2,B1))
.addEdge(_E(A2,B2))
.addEdge(_E(A3,B3))
.addEdge(_E(A3,B4))
.addEdge(_E(A4,B3))
.addEdge(_E(A4,B4))
;
}
function Scene() {
var cam=new Cam();
cam.SetProjection(300,100);
var canvas=document.getElementById('space').getContext('2d');
var icosahedron=Icosahedron(20);
this.iterCount=0;
this.iterCount=939;
this.iterate=function () {
cam.SetRotation((this.iterCount/160)*Math.PI);
canvas.clearRect(0,0,C[0],C[1]); // clear canvas
icosahedron.display(canvas,cam);
this.iterCount++;
this.nestTimeout();
};
this.nestTimeout=function(){
TTT=setTimeout(function (obj){obj.iterate();},10,this);
};
}
function bog2deg(bog) {
return Math.round(bog/Math.PI*180%360)
}
var C=[640,480];
window.onload = function(){(new Scene()).iterate()};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment