Skip to content

Instantly share code, notes, and snippets.

@edom18
Created May 28, 2013 02:26
Show Gist options
  • Select an option

  • Save edom18/5660155 to your computer and use it in GitHub Desktop.

Select an option

Save edom18/5660155 to your computer and use it in GitHub Desktop.
簡易3D表現
#簡易3D表現
まだ製作途中です。
行列を使わずに、比較的簡単な方法で3D的表現ができるように目指します。
@import "compass/reset";
<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>
(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