「JavaScriptとcanvasで3Dなポリゴンを回転させる」の続き。
複数のcanvas使うと、こんなこともできるよ〜。という感じかな。
黒いやつの中に、青いやつが入ってぐりぐり回転します。
昨日のコードからの変化は、HighLightの指定,ポリゴンカラーの指定,不透明度の指定などが可能になったことぐらい。基本的に変わりません。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>polygon test</title> <style> #canvas0 { position: absolute; top: 0; left: 0; } #canvas1 { position: absolute; top: 0; left: 0; } </style> </head> <body> <canvas id="canvas0" width="640" height="480"></canvas> <canvas id="canvas1" width="640" height="480"></canvas> <script type="text/javascript"> window.onload = function() { var poly1 = new polygon(); poly1.initialize(document.getElementById("canvas0"), 50, 0x00, 0x000000, 1.0, { x: 200, y: 200 }, 800); poly1.draw(); var poly2 = new polygon(); poly2.initialize(document.getElementById("canvas1"), 50, 0x80, 0x000080, 1.0, { x: 200, y: 200 }, 600); poly2.draw(); } </script> <script type="text/javascript"> function polygon() { } polygon.prototype = { /** 初期化 * * @param element elm <canvas>要素を指定します。 * @param number fps 1秒間に表示するフレーム数の指定です。 * フレーム数を多くすると滑らかになりますが負荷も増えます。 * 25を指定すると約40msで1回描画します。 * @param number highLight ハイライトの強さを0x0〜0xffで指定します。 * @param number color ポリゴンの色を指定します。0xff0000で赤, 0x00ff00で緑, 0x0000ffで青になります。 * @param number alpha アルファブレンド(透明度)を0.0〜1.0の値で指定します。 * @param pos pos ポリゴンの座標を { x, y } で指定します。 * @param number zoom ポリゴンの拡大倍率を数値で指定します。 */ initialize: function(elm, fps, highLight, color, alpha, pos, zoom) { this.ctx = elm.getContext("2d"); this.fps = 1000 / fps; this.prop = { highLight: highLight, color: color, alpha: alpha, pos: pos, zoom: zoom }; this.poly = [[], [], [], [], [], []]; // polygon data this.theta = 0.5; // vertical this.phi = 0.5; // horizontal // create polygon data var i = 0, v1, v2; for (; i < 5; ++i) { v1 = (!i) ? 0 : Math.SQRT2 * Math.cos((0.5 * i - 0.25) * Math.PI); v2 = (!i) ? 0 : Math.SQRT2 * Math.sin((0.5 * i - 0.25) * Math.PI); this.poly[0].push([ v1, v2, 1]); this.poly[1].push([ 1, v1, v2]); this.poly[2].push([ v2, 1, v1]); this.poly[3].push([-v1, -v2, -1]); this.poly[4].push([ -1, -v1, -v2]); this.poly[5].push([-v2, -1, -v1]); } }, draw: function() { var me = this; var phi = Math.PI / 100; // 0.03141592653589793 var theta = Math.PI / 80; window.setInterval( function() { me.theta += theta; me.phi += phi; me.__drawPolygon(me.ctx, me.poly, me.theta, me.phi, me.prop); }, this.fps ); }, __drawPolygon: function(ctx, poly, theta, phi, prop) { var sinP = Math.sin(phi), cosP = Math.cos(phi); var sinT = Math.sin(theta), cosT = Math.cos(theta); // vector data var vX = [-sinP, cosP, 0]; var vY = [-cosT * cosP, -cosT * sinP, sinT]; var vZ = [-sinT * cosP, -sinT * sinP, -cosT]; var info = []; var x, y, z; var i, j; var surface; // 2D bitmap surface for (i = 0; i < poly.length; ++i) { surface = [0, -(vZ[0] * poly[i][0][0] + vZ[1] * poly[i][0][1] + vZ[2] * poly[i][0][2])]; for (j = 1; j < poly[i].length; ++j) { z = vZ[0] * poly[i][j][0] + vZ[1] * poly[i][j][1] + vZ[2] * poly[i][j][2]; surface.push([vX[0] * poly[i][j][0] + vX[1] * poly[i][j][1] + vX[2] * poly[i][j][2], vY[0] * poly[i][j][0] + vY[1] * poly[i][j][1] + vY[2] * poly[i][j][2], z]); surface[0] += z; } info.push(surface); } info.sort(this.__sort); // canvas clear ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); var light; for (i = 0; i < info.length; ++i) { info[i].shift(); light = info[i].shift(); if (light >= 0) { for (j = 0; j < info[i].length; ++j) { x = prop.zoom * info[i][j][0] / (10 + info[i][j][2]); y = prop.zoom * info[i][j][1] / (10 + info[i][j][2]); if (!j) { ctx.beginPath(); ctx.moveTo(prop.pos.x + x, prop.pos.y + -y); ctx.fillStyle = this.__rgba(parseInt(light * prop.highLight) + prop.color, prop.alpha); } else { ctx.lineTo(prop.pos.x + x, prop.pos.y + -y); } } ctx.closePath(); ctx.fill(); } } }, __sort: function(a, b) { if (a[0] === b[0]) { return 0; } return a[0] < b[0] ? 1: -1; }, __rgba: function(color, alpha) { var rv = [color & 0xff0000, color & 0xff00, color & 0xff, alpha]; return "rgba(" + rv.join(",") + ")"; } }; </script> </body> </html>