Last active
April 29, 2017 09:34
-
-
Save bzdgn/7153f7793489f867839fc59daac36a57 to your computer and use it in GitHub Desktop.
3D Face Model Rotation Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is a sample screenshot;