Skip to content

Instantly share code, notes, and snippets.

@bzdgn
Last active April 29, 2017 09:34
Show Gist options
  • Save bzdgn/7153f7793489f867839fc59daac36a57 to your computer and use it in GitHub Desktop.
Save bzdgn/7153f7793489f867839fc59daac36a57 to your computer and use it in GitHub Desktop.
3D Face Model Rotation Example
<!DOCTYPE html>
<html>
<head>
<title>3d Rotation Face Example</title>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body onload="doTimer()">
<canvas id='mainCanvas' width="800" height="600" style="border:1px solid #000000;" />
<script>
<!-- Written by Levent Divilioglu on 16/01/2017 -->
<!-- 3d knowledge and math based on this tutorial; -->
<!-- http://petercollingridge.appspot.com/3D-tutorial -->
// canvas setup
var canvas = document.getElementById('mainCanvas');
var ctx = canvas.getContext('2d');
// nodes of cube
var node0 = [ -70, 15, -130 ];
var node1 = [ 70, 15, -130 ];
var node2 = [ -50, 200, -130 ];
var node3 = [ 50, 200, -130 ];
var node4 = [ -30, 250, -100 ];
var node5 = [ 30, 250, -100 ];
var node6 = [ -90, 0, 30 ]; // node0 -z
var node7 = [ 90, 0, 30 ]; // node1 -z
var node8 = [ -60, 180, -10 ]; // node2 -z
var node9 = [ 60, 180, -10 ]; // node3 -z
// left eyebrow
var node10 = [ -50, 90, -130 ];
var node11 = [ -10, 90, -130 ];
var node12 = [ -10, 95, -130 ];
var node13 = [ -50, 95, -130 ];
// left eye
var node18 = [ -50, 118, -130 ];
var node19 = [ -32, 110, -130 ];
var node20 = [ -18, 112, -130 ];
var node21 = [ -10, 120, -130 ];
var node22 = [ -22, 130, -130 ];
var node23 = [ -38, 130, -130 ];
// right eyebrow
var node14 = [ 50, 90, -130 ];
var node15 = [ 10, 90, -130 ];
var node16 = [ 10, 95, -130 ];
var node17 = [ 50, 95, -130 ];
// right eye
var node24 = [ 50, 118, -130 ];
var node25 = [ 32, 110, -130 ];
var node26 = [ 18, 112, -130 ];
var node27 = [ 10, 120, -130 ];
var node28 = [ 22, 130, -130 ];
var node29 = [ 38, 130, -130 ];
// node
var node30 = [ -5, 105, -130 ];
var node31 = [ 5, 105, -130 ];
var node32 = [ 10, 180, -130 ];
var node33 = [ -10, 180, -130 ];
var node34 = [ 0, 170, -155 ];
// mouth
var node35 = [ -30, 210, -130 ];
var node36 = [ -12, 200, -130 ];
var node37 = [ 0, 205, -130 ];
var node38 = [ 12, 200, -130 ];
var node39 = [ 30, 210, -130 ];
var node40 = [ 15, 220, -130 ];
var node41 = [ -15, 220, -130 ];
// nodes array
var nodes = [
node0, node1, node2, node3,
node4, node5, node6, node7,
node8, node9, node10, node11,
node12, node13, node14, node15,
node16, node17, node18, node19,
node20, node21, node22, node23,
node24, node25, node26, node27,
node28, node29, node30, node31,
node32, node33, node34, node35,
node36, node37, node38, node39,
node40, node41
];
// edges of cube (wireframe, lines)
var edge0 = [0, 1];
var edge1 = [1, 3];
var edge2 = [3, 5];
var edge3 = [5, 4];
var edge4 = [4, 2];
var edge5 = [2, 0];
var edge6 = [6, 7];
var edge7 = [7, 9];
var edge8 = [9, 8];
var edge9 = [8, 6];
var edge10 = [6, 0];
var edge11 = [7, 1];
var edge12 = [8, 4];
var edge13 = [9, 5];
var edge14 = [8, 2];
var edge15 = [9, 3];
var edge16 = [10, 11];
var edge17 = [11, 12];
var edge18 = [12, 13];
var edge19 = [13, 10];
var edge20 = [14, 15];
var edge21 = [15, 16];
var edge22 = [16, 17];
var edge23 = [17, 14];
var edge24 = [18, 19];
var edge25 = [19, 20];
var edge26 = [20, 21];
var edge27 = [21, 22];
var edge28 = [22, 23];
var edge29 = [23, 18];
var edge30 = [24, 25];
var edge31 = [25, 26];
var edge32 = [26, 27];
var edge33 = [27, 28];
var edge34 = [28, 29];
var edge35 = [29, 24];
var edge36 = [30, 31];
var edge37 = [31, 32];
var edge38 = [32, 33];
var edge39 = [33, 30];
var edge40 = [30, 34];
var edge41 = [31, 34];
var edge42 = [32, 34];
var edge43 = [33, 34];
var edge44 = [35, 36];
var edge45 = [36, 37];
var edge46 = [37, 38];
var edge47 = [38, 39];
var edge48 = [39, 40];
var edge49 = [40, 41];
var edge50 = [41, 35];
var edge51 = [35, 39];
// edges array
var edges = [
edge0 , edge1 , edge2 , edge3 ,
edge4 , edge5 , edge6 , edge7 ,
edge8 , edge9 , edge10 , edge11 ,
edge12 , edge13 , edge14 , edge15 ,
edge16 , edge17 , edge18 , edge19 ,
edge20 , edge21 , edge22 , edge23 ,
edge24 , edge25 , edge26 , edge27 ,
edge28 , edge29 , edge30 , edge31 ,
edge32 , edge33 , edge34 , edge35 ,
edge36 , edge37 , edge38 , edge39 ,
edge40 , edge41 , edge42 , edge43 ,
edge44 , edge45 , edge46 , edge47 ,
edge48 , edge49 , edge50 , edge51
];
// setup
//var backgroundColor = color(255, 255, 255);
var backgroundColor = color(0 , 0, 0);
var nodeColor = color(34 , 68, 204);
var edgeColor = color(0 , 255, 0);
var nodeSize = 3;
// rotation degree
var rotDegreeX = 1;
var rotDegreeY = 2;
var rotDegreeZ = 3;
var transformQuotient = Math.PI/180;
// XO, YO
var XO = 350;
var YO = 150;
// functions
// rgb color string helper function
function color(x, y, z) {
var c = 'rgba(' + x + ',' + y + ',' + z + ',1' + ')';
return c;
}
// draw function
function clearScreen() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function fillScreen(color) {
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = color;
ctx.fill();
}
function refreshScreen() {
clearScreen();
fillScreen(backgroundColor);
}
function point(x, y, color) {
ctx.beginPath();
ctx.rect(x, y, 1, 1);
ctx.fillStyle = color;
ctx.fill();
}
function circle(x, y, r, color) {
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(x, y, r,0,2*Math.PI);
ctx.fill();
};
function line(x1, y1, x2, y2, color) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.strokeStyle = color;
ctx.stroke();
}
function drawNodes(nodes) {
for(var n = 0; n < nodes.length; n++) {
var node = nodes[n];
var x = node[0];
var y = node[1];
// var z = node[2]; // we dont care z axis, we will use z parameter for rotation calculations
circle(x, y, nodeSize, nodeColor);
}
}
function drawEdges(edges) {
for(var e = 0; e < edges.length; e++) {
var edge = edges[e];
var e1 = edge[0];
var e2 = edge[1];
var n1 = nodes[e1];
var n2 = nodes[e2];
var x1 = n1[0];
var y1 = n1[1];
var x2 = n2[0];
var y2 = n2[1];
line(x1, y1, x2, y2, edgeColor);
}
}
// rotates node by theta around z-axis
function rotateNode3DonZ(node, theta) {
var x = node[0];
var y = node[1];
theta *= transformQuotient;
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
var x = node[0];
var y = node[1];
node[0] = x * cosTheta - y * sinTheta;
node[1] = x * sinTheta + y * cosTheta;
}
// rotates nodes by theta around z-axis
function rotateNodes3DonZ(nodes, theta) {
for(var n = 0; n < nodes.length; n++) {
rotateNode3DonZ(nodes[n], theta);
}
}
// rotates node by theta around x-axis
function rotateNode3DonX(node, theta) {
var y = node[1];
var z = node[2];
theta *= transformQuotient;
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
var y = node[1];
var z = node[2];
node[1] = y * cosTheta - z * sinTheta;
node[2] = y * sinTheta + z * cosTheta;
}
// rotates nodes by theta around x-axis
function rotateNodes3DonX(nodes, theta) {
for(var n = 0; n < nodes.length; n++) {
rotateNode3DonX(nodes[n], theta);
}
}
// rotates node by theta around y-axis
function rotateNode3DonY(node, theta) {
var x = node[0];
var z = node[2];
theta *= transformQuotient;
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
var x = node[0];
var z = node[2];
node[0] = x * cosTheta - z * sinTheta;
node[2] = x * sinTheta + z * cosTheta;
}
// rotates nodes by theta around y-axis
function rotateNodes3DonY(nodes, theta) {
for(var n = 0; n < nodes.length; n++) {
rotateNode3DonY(nodes[n], theta);
}
}
function handleAnimation() {
refreshScreen();
ctx.save();
ctx.translate(XO, YO);
drawNodes(nodes);
drawEdges(edges);
rotateNodes3DonX(nodes, rotDegreeX);
rotateNodes3DonY(nodes, rotDegreeY);
rotateNodes3DonZ(nodes, rotDegreeZ);
ctx.restore();
}
function log() {
console.log("hit");
}
function doTimer() {
//window.requestAnimationFrame(handleAnimation);
timerID = setInterval( "handleAnimation()", 20 );
}
</script>
</body>
</html>
@bzdgn
Copy link
Author

bzdgn commented Jan 17, 2017

Here is a sample screenshot;

3dface

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment