Created
May 28, 2013 02:26
-
-
Save edom18/5660155 to your computer and use it in GitHub Desktop.
簡易3D表現
This file contains hidden or 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
| #簡易3D表現 | |
| まだ製作途中です。 | |
| 行列を使わずに、比較的簡単な方法で3D的表現ができるように目指します。 |
This file contains hidden or 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
| @import "compass/reset"; |
This file contains hidden or 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
| <canvas id="cv" width="400" height="400"></canvas> | |
| <script> | |
| /* | |
| * Forked by John Resig's Simple JavaScript Inheritance (http://ejohn.org/) | |
| * MIT Licensed. | |
| */ | |
| (function (win, doc, exports, undefined) { | |
| 'use strict'; | |
| var fnTest, initialize; | |
| fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; | |
| initialize = false; | |
| function Class() { /* noop. */ } | |
| Class.extend = function (props) { | |
| var SuperClass, prototype; | |
| SuperClass = this; | |
| initialize = true; | |
| prototype = new this(); | |
| initialize = false; | |
| function Class() { | |
| if (initialize !== true && typeof this.init === 'function') { | |
| this.init.apply(this, arguments); | |
| } | |
| } | |
| for (var key in props) { | |
| var prop = props[key], | |
| _super = SuperClass.prototype[key], | |
| isMethodOverride = (typeof prop === 'function' && typeof _super === 'function' && fnTest.test(prop)); | |
| if (isMethodOverride) { | |
| prototype[key] = (function (fn, _super) { | |
| return function () { | |
| var ret, | |
| tmp = this._super; | |
| this._super = _super; | |
| ret = fn.apply(this, arguments); | |
| this._super = tmp; | |
| return ret; | |
| }; | |
| }(prop, _super)); | |
| } | |
| else { | |
| prototype[key] = prop; | |
| } | |
| } | |
| Class.prototype = prototype; | |
| Class.prototype.constructor = Class; | |
| Class.extend = SuperClass.extend; | |
| return Class; | |
| }; | |
| exports.Class = Class; | |
| }(window, window.document, window)); | |
| </script> |
This file contains hidden or 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
| (function (win, doc, Class) { | |
| 'use strict'; | |
| /* --------------------------------- | |
| IMPORT | |
| ------------------------------------ */ | |
| var cos = Math.cos, | |
| sin = Math.sin, | |
| PI = Math.PI, | |
| sqrt = Math.sqrt, | |
| floor = Math.floor, | |
| pow = Math.pow, | |
| random = Math.random; | |
| var Vertex3d = Class.extend({ | |
| init: function (x, y, z) { | |
| this.x = x || 0; | |
| this.y = y || 0; | |
| this.z = z || 0; | |
| }, | |
| setAttribute: function (name, val) { | |
| this[name] = val; | |
| }, | |
| getAttribute: function (name) { | |
| return this[name]; | |
| } | |
| }); | |
| var Particle = Vertex3d.extend({ | |
| init: function (x, y, z, opt) { | |
| this._super.apply(this, arguments); | |
| opt || (opt = {}); | |
| this.size = opt.size || 5; | |
| this.sp = opt.sp || 5; | |
| this.color = opt.color || 'red'; | |
| this.camera = camera; | |
| }, | |
| update: function () { | |
| var temp = affine.rotate.y(this.sp * PI / 180, this); | |
| this.x = temp.x; | |
| this.y = temp.y; | |
| this.z = temp.z; | |
| }, | |
| draw: function (ctx) { | |
| var m = this.camera.applyView(this); | |
| //var m = this.camera.perspective(this.camera.applyTranslate(this)); | |
| m.r = this.size; | |
| ctx.save(); | |
| ctx.beginPath(); | |
| ctx.arc(m.x, m.y, m.r * m.z / m.w, 0, PI * 2, false); | |
| ctx.fillStyle = this.color; | |
| ctx.fill(); | |
| ctx.closePath(); | |
| ctx.restore(); | |
| } | |
| }); | |
| var camera = { | |
| focus: 300, | |
| position: { | |
| x: 0, | |
| y: 0, | |
| z: 0 | |
| }, | |
| rotate: { | |
| x: 0, | |
| y: 0, | |
| z: 0 | |
| }, | |
| up: { | |
| x: 0, | |
| y: 1, | |
| z: 0 | |
| }, | |
| applyView: function (target) { | |
| var ret = target; | |
| ret = this.applyRotate(ret); | |
| ret = this.applyTranslate(ret); | |
| ret = this.perspective(ret); | |
| return ret; | |
| }, | |
| applyRotate: function (target) { | |
| var xrad = this.rotate.x * PI / 180, | |
| yrad = this.rotate.y * PI / 180, | |
| zrad = this.rotate.z * PI / 180, | |
| ret = target; | |
| ret = affine.rotate.x(xrad, ret); | |
| ret = affine.rotate.y(yrad, ret); | |
| ret = affine.rotate.z(zrad, ret); | |
| return ret; | |
| }, | |
| applyTranslate: function (target) { | |
| var x = this.position.x, | |
| y = this.position.y, | |
| z = this.position.z; | |
| return { | |
| x: target.x - x, | |
| y: target.y - y, | |
| z: target.z - z | |
| }; | |
| }, | |
| perspective: function (position) { | |
| var fl = this.focus - this.position.z, | |
| x = position.x, | |
| y = position.y, | |
| z = position.z; | |
| return { | |
| x: x * (fl / (fl - z)), | |
| y: y * (fl / (fl - z)), | |
| z: z * (fl / (fl - z)), | |
| w: z | |
| }; | |
| } | |
| }; | |
| var affine = { | |
| rotate: { | |
| x: function (rad, position) { | |
| return { | |
| x: position.x, | |
| y: position.y * cos(rad) + position.z * sin(rad), | |
| z: position.y * -sin(rad) + position.z * cos(rad) | |
| }; | |
| }, | |
| y: function (rad, position) { | |
| return { | |
| x: position.x * cos(rad) + position.z * -sin(rad), | |
| y: position.y, | |
| z: position.x * sin(rad) + position.z * cos(rad) | |
| }; | |
| }, | |
| z: function (rad, position) { | |
| return { | |
| x: position.x * cos(rad) + position.y * sin(rad), | |
| y: position.x * -sin(rad) + position.y * cos(rad), | |
| z: position.z | |
| }; | |
| } | |
| } | |
| }; | |
| var cv = doc.getElementById('cv'); | |
| var ctx = cv.getContext('2d'); | |
| var w = cv.width; | |
| var h = cv.height; | |
| var point = null; | |
| var particles = []; | |
| var particleNum = 30; | |
| function setCenter() { | |
| ctx.translate(w / 2, h / 2); | |
| } | |
| function init() { | |
| for (var i = 0; i < particleNum; i++) { | |
| var size = ~~(random() * 20) + 5; | |
| var x = ~~(random() * w / 2) - w / 2; | |
| var y = ~~(random() * h / 2) - h / 2; | |
| var z = ~~(random() * 100); | |
| var sp = ~~(random() * 10); | |
| var r = ~~(random() * 255); | |
| var g = ~~(random() * 255); | |
| var b = ~~(random() * 255); | |
| var color = 'rgb(' + r + ', ' + g + ', ' + b + ')'; | |
| var p = new Particle(x, y, z, { | |
| size: size, | |
| sp: sp, | |
| color: color | |
| }); | |
| particles.push(p); | |
| } | |
| var isTouch = 'ontouchstart' in window; | |
| var M_DOWN = isTouch ? 'touchstart' : 'mousedown'; | |
| var M_MOVE = isTouch ? 'touchmove' : 'mousemove'; | |
| var M_UP = isTouch ? 'touchend' : 'mouseup'; | |
| var prevX = 0; | |
| var prevY = 0; | |
| var dragging = false; | |
| doc.addEventListener(M_DOWN, function (e) { | |
| dragging = true; | |
| prevX = (isTouch ? e.touches[0].pageX : e.pageX); | |
| prevY = (isTouch ? e.touches[0].pageY : e.pageY); | |
| }); | |
| doc.addEventListener(M_MOVE, function (e) { | |
| if (!dragging) { | |
| return; | |
| } | |
| var x = (isTouch ? e.touches[0].pageX : e.pageX) - prevX; | |
| var y = (isTouch ? e.touches[0].pageY : e.pageY) - prevY; | |
| camera.rotate.x -= x; | |
| camera.rotate.y -= y; | |
| prevX = e.pageX; | |
| prevY = e.pageY; | |
| }, false); | |
| doc.addEventListener(M_UP, function (e) { | |
| dragging = false; | |
| }, false); | |
| loop(); | |
| } | |
| function drawAxis() { | |
| ctx.save(); | |
| ctx.beginPath(); | |
| ctx.strokeStyle = '#666'; | |
| ctx.moveTo(0, cv.height / 2); | |
| ctx.lineTo(cv.width, cv.height / 2); | |
| ctx.moveTo(cv.width / 2, 0); | |
| ctx.lineTo(cv.width / 2, cv.height); | |
| ctx.stroke(); | |
| ctx.closePath(); | |
| ctx.restore(); | |
| } | |
| function draw() { | |
| ctx.save(); | |
| ctx.beginPath(); | |
| ctx.fillStyle = 'rgba(30, 30, 30, 0.5)'; | |
| ctx.fillRect(0, 0, w, h); | |
| drawAxis(); | |
| setCenter(); | |
| for (var i = 0, l = particles.length; i < l; i++) { | |
| var p = particles[i]; | |
| p.update(); | |
| p.draw(ctx); | |
| } | |
| ctx.restore(); | |
| } | |
| function loop() { | |
| draw(); | |
| setTimeout(loop, 32); | |
| } | |
| doc.addEventListener('DOMContentLoaded', init, false); | |
| }(window, window.document, window.Class)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment