Skip to content

Instantly share code, notes, and snippets.

@Bolloxim
Created August 16, 2014 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bolloxim/bb14acfbee230940c46e to your computer and use it in GitHub Desktop.
Save Bolloxim/bb14acfbee230940c46e to your computer and use it in GitHub Desktop.
A Pen by Andi Smithers.

Animated cone/cylinder

Useful 2D geometry rendered to look 3D cylinders are useful to tie sysems and moels together

A Pen by Andi Smithers on CodePen.

License.

<body>
<canvas id='cone-cylinder'></canvas>
</body>
// conceptualized and written by andi smithers
// copyright andi smithers.
// freely distributable in whole or in partial
// please retain credit and comment if distributed
// thank you.
// constant options
const focalDepth = 80;
const focalPoint = 256;
// variables
var centreX;
var centreY;
var mouseX;
var mouseY;
var spawnX;
var spawnY;
var frameCount=0;
// test multiple groups
// initialization
function init()
{
// setup canvas and context
canvas = document.getElementById('cone-cylinder');
context = canvas.getContext('2d');
// set canvas to be window dimensions
resize();
// create event listeners
canvas.addEventListener('mousemove', mouseMove);
canvas.addEventListener('click', mouseClick);
window.addEventListener('resize', resize);
// initialze variables
}
// input functions
function mouseMove(event)
{
var rect = canvas.getBoundingClientRect();
mouseX = event.clientX - rect.left,
mouseY = event.clientY - rect.top
}
function mouseClick()
{
}
function resize()
{
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// compute centre of screen
centreX = canvas.width/2;
centreY = canvas.height/2;
}
// rendering functions
var demoAngle = Math.PI*1.44;
function render()
{
context.fillStyle = 'black';
context.clearRect(0, 0, canvas.width, canvas.height);
var x = centreX;
var y = centreY;
var r = 200;
demoAngle=(demoAngle+0.01)%(Math.PI*2);
RenderBasestar(x, y, r, demoAngle);
context.globalAlpha = 1.0;
context.font = '20pt Calibri';
context.fillStyle = 'rgb(255,255,255)';
context.textAlign = "center";
context.fillText('3D Cylinder/Cone rendering on a 2D canvas', canvas.width/2, 40);
context.fillText('Basestar for star-raiders', canvas.width/2, canvas.height-80);
context.fillText('combines 2 hemispheres an inverted cylinder with r, -r', canvas.width/2, canvas.height-60); context.fillText('plus 2 side cylinders at the side to show well cylinders', canvas.width/2, canvas.height-40);
}
// star base construction - eer well it was but its a cool blue marble demo for now
// to rotate horizontally switch out the x/y registers. I should probably make this generic .. however just want to use this for the starbase construction in star-raiders
var lazerLength = 50;
var lazerAngle = 0;
function RenderBasestar(x, y, r, baseAngle)
{
var len = 20;
r = 100;
var r2 = -100;
// compute y
var y1 = y+len*2*Math.cos(baseAngle+Math.PI*0.5);
var y2 = y-len*2*Math.cos(baseAngle+Math.PI*0.5);
if (baseAngle<Math.PI*0.5 || baseAngle>Math.PI*1.5)
{
RenderHemisphere(x, y2, r, baseAngle, '#808080', '#808080');
RenderCylinder(x, y, r2, r, len*2, baseAngle, '#808080', '#808080', 'darkred');
RenderLazers(x,y,baseAngle);
RenderHemisphere(x, y1, r, (baseAngle+Math.PI)%(Math.PI*2),'#808080', '#808080');
}
else
{
RenderHemisphere(x, y1, r, (baseAngle+Math.PI)%(Math.PI*2), '#808080', '#808080');
RenderCylinder(x, y, r2, r, len*2, baseAngle, '#808080', '#808080', 'darkred');
RenderLazers(x,y,baseAngle);
RenderHemisphere(x, y2, r, baseAngle, '#808080', '#808080');
}
}
function RenderLazers(x,y, baseAngle)
{
// context.rotate(Math.PI*0.5);
// context.translate(-x+y,-y-x);
var r = 10;
var r2 = 10;
var y3 = y;
RenderCylinder(x-150, y3, r2, r, lazerLength, baseAngle+Math.PI*0.5, 'rgba(255,255,0,1)','rgba(255,128,0,1)','rgba(255,0,0,1)');
RenderCylinder(x+150, y3, r2, r, lazerLength, baseAngle+Math.PI*0.5, 'rgba(255,255,0,1)','rgba(255,128,0,1)','rgba(255,0,0,1)');
}
function RenderHemisphere(x, y, r, angle, colTop, colBot)
{
// rotation
m = 0.5522848;
tr =r*Math.cos(angle)*0.5; // top hemisphere angle *rad
br =r*Math.cos(angle)*0.5; // bottom angle *rad
xkr = m*r; // kappa * r
tkr = m*tr; // top height * kappa
bkr = m*br; // bottom height * kappa
context.beginPath()
context.moveTo(x+r, y)
context.bezierCurveTo(x+r, y-tkr, x+xkr, y-tr, x, y-tr) // top r
context.bezierCurveTo(x-xkr, y-tr, x-r, y-tkr, x-r, y) // top l
context.bezierCurveTo(x-r, y+bkr, x-xkr, y+br, x, y+br) // bot l
context.bezierCurveTo(x+xkr, y+br, x+r, y+bkr, x+r, y) // bot r
context.closePath();
context.lineWidth = 1;
context.fillStyle = colBot;
context.fill();
// drow the blue surface
tr =r*Math.cos(angle+Math.PI); // top hemisphere angle *rad
br =r*Math.cos(angle+Math.PI); // bottom angle *rad
if (angle<Math.PI) br = r*0.5;
if (angle>Math.PI) tr = r*0.5;
xkr = m*r; // kappa * r
tkr = m*tr; // top height * kappa
bkr = m*br; // bottom height * kappa
context.beginPath()
context.moveTo(x+r, y)
context.bezierCurveTo(x+r, y-tkr, x+xkr, y-tr, x, y-tr) // top r
context.bezierCurveTo(x-xkr, y-tr, x-r, y-tkr, x-r, y) // top l
context.bezierCurveTo(x-r, y+bkr, x-xkr, y+br, x, y+br) // bot l
context.bezierCurveTo(x+xkr, y+br, x+r, y+bkr, x+r, y) // bot r
context.closePath();
context.lineWidth = 1;
context.fillStyle = colTop;
context.fill();
}
function RenderCylinder(x, y, r1, r2, side, angle, colTop, colBot, colSide)
{
// rotation
var m = 0.5522848;
var tr =r1*Math.cos(angle); // top hemisphere angle *rad
var br =r1*Math.cos(angle); // bottom angle *rad
var xkr = m*r1; // kappa * r
var tkr = m*tr; // top height * kappa
var bkr = m*br; // bottom height * kappa
var y1 = y - side* Math.sin(angle);
// drow the blue surface
var tr2 =r2*Math.cos(angle); // top hemisphere angle *rad
var br2 =r2*Math.cos(angle); // bottom angle *rad
var xkr2 = m*r2; // kappa * r
var tkr2 = m*tr2; // top height * kappa
var bkr2 = m*br2; // bottom height * kappa
// compute x, y
var y2 = y + side*Math.sin(angle);
// render front side
context.beginPath();
context.moveTo(x+r1, y1)
context.bezierCurveTo(x+r1, y1-tkr, x+xkr, y1-tr, x, y1-tr) // top r
context.bezierCurveTo(x-xkr, y1-tr, x-r1, y1-tkr, x-r1, y1) // top l
context.lineTo(x-r2, y2);
context.bezierCurveTo(x-r2, y2-bkr2, x-xkr2, y2-br2, x, y2-br2) // bot l
context.bezierCurveTo(x+xkr2, y2-br2, x+r2, y2-bkr2, x+r2, y2) // bot r
context.closePath();
// context.fillStyle = colSide;
var gradient = context.createRadialGradient(x, y, 0, x, y, Math.abs(r1));
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, '#404040');
context.fillStyle = gradient;
context.fill();
context.beginPath();
context.moveTo(x+r1, y1)
context.bezierCurveTo(x+r1, y1+tkr, x+xkr, y1+tr, x, y1+tr) // top r
context.bezierCurveTo(x-xkr, y1+tr, x-r1, y1+tkr, x-r1, y1) // top l
context.lineTo(x-r2, y2);
context.bezierCurveTo(x-r2, y2+bkr2, x-xkr2, y2+br2, x, y2+br2) // bot l
context.bezierCurveTo(x+xkr2, y2+br2, x+r2, y2+bkr2, x+r2, y2) // bot r
context.closePath();
// context.fillStyle = colSide;
context.fillStyle = gradient;
context.fill();
if (angle>Math.PI*0.5 && angle<Math.PI*1.5)
{
context.beginPath()
context.moveTo(x+r2, y2)
context.bezierCurveTo(x+r2, y2-tkr2, x+xkr2, y2-tr2, x, y2-tr2) // top r
context.bezierCurveTo(x-xkr2, y2-tr2, x-r2, y2-tkr2, x-r2, y2) // top l
context.bezierCurveTo(x-r2, y2+bkr2, x-xkr2, y2+br2, x, y2+br2) // bot l
context.bezierCurveTo(x+xkr2, y2+br2, x+r2, y2+bkr2, x+r2, y2) // bot r
context.closePath();
context.lineWidth = 0;
context.fillStyle = colTop;
context.fill();
}
else
{
context.beginPath()
context.moveTo(x+r1, y1)
context.bezierCurveTo(x+r1, y1-tkr, x+xkr, y1-tr, x, y1-tr) // top r
context.bezierCurveTo(x-xkr, y1-tr, x-r1, y1-tkr, x-r1, y1) // top l
context.bezierCurveTo(x-r1, y1+bkr, x-xkr, y1+br, x, y1+br) // bot l
context.bezierCurveTo(x+xkr, y1+br, x+r1, y1+bkr, x+r1, y1) // bot r
context.closePath();
context.lineWidth = 1;
context.fillStyle = colBot;
context.fill();
}
}
// movement functions
function update()
{
}
// per frame tick functions
function animate()
{
frameCount++;
// movement update
update();
// render update
render();
// trigger next frame
requestAnimationFrame(animate);
}
// entry point
init();
animate();
body{
background:#000000;
margin: 0px;
padding: 0px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment