|
(function () { |
|
"use strict"; |
|
/* ==== definitions ==== */ |
|
var Xi = 0, Yi = 0, Zi = 0; |
|
var screen = ge1doot.screen; |
|
var drag = ge1doot.drag; |
|
|
|
/* ==== setup camera ==== */ |
|
var cameraView = { |
|
x: 0, |
|
y: 0, |
|
z: 140, |
|
rotation: 0, |
|
upAngle: 0, |
|
xcos: 0, |
|
xsin: 0, |
|
ycos: 0, |
|
ysin: 0, |
|
zoom: 0, |
|
rotate: function (rotation, upAngle) { |
|
this.rotation = rotation; |
|
this.upAngle = upAngle; |
|
this.xcos = Math.cos(rotation); |
|
this.xsin = Math.sin(rotation); |
|
this.ycos = Math.cos(upAngle); |
|
this.ysin = Math.sin(upAngle); |
|
} |
|
} |
|
|
|
/* ==== vertex constructor ==== */ |
|
var Point = function (x, y, z) { |
|
this.x = x; |
|
this.y = y; |
|
this.z = z; |
|
this.X = 0; |
|
this.Y = 0; |
|
} |
|
|
|
Point.prototype.project = function () { |
|
var x = this.x; |
|
var y = this.y; |
|
var z = this.z; |
|
var tx = cameraView.xcos * x - cameraView.xsin * z; |
|
var tz = cameraView.xsin * x + cameraView.xcos * z; |
|
x = tx; |
|
z = tz; |
|
var ty = cameraView.ycos * y - cameraView.ysin * z; |
|
tz = cameraView.ysin * y + cameraView.ycos * z; |
|
y = ty; |
|
z = tz; |
|
this.X = screen.width * 0.5 + ((cameraView.z * ((x * cameraView.zoom) - cameraView.x) / (cameraView.z + z))) + cameraView.x; |
|
this.Y = screen.height * 0.5 + ((cameraView.z * ((y * cameraView.zoom) - cameraView.y) / (cameraView.z + z))) + cameraView.y; |
|
} |
|
|
|
/* ==== face constructor ==== */ |
|
var Polygon = function (points, id) { |
|
this.points = []; |
|
for (var i = 0, n = points.length; i < n; i++) { |
|
this.points.push(listPoints.points[points[i]]); |
|
} |
|
this.img = new CSS3Dtransform(document.getElementById(id)); |
|
} |
|
|
|
Polygon.prototype.draw = function () { |
|
var |
|
x0 = this.points[0].X, |
|
y0 = this.points[0].Y, |
|
x1 = this.points[1].X, |
|
y1 = this.points[1].Y, |
|
x2 = this.points[2].X, |
|
y2 = this.points[2].Y, |
|
x3 = this.points[3].X, |
|
y3 = this.points[3].Y; |
|
|
|
if ((x1-x0)*(y2-y0) < (x2-x0)*(y1-y0)) { |
|
this.img.elem.style.visibility = "hidden"; |
|
} else { |
|
this.img.elem.style.visibility = "visible"; |
|
this.img.transform(x0, y0, x1, y1, x2, y2, x3, y3); |
|
} |
|
} |
|
|
|
/* ==== points ==== */ |
|
var listPoints = { |
|
points: [], |
|
add: function (p) { |
|
this.points.push(new Point(p[0], p[1], p[2])); |
|
}, |
|
project: function () { |
|
for (var i = 0, n = this.points.length; i < n; i++ ) { |
|
this.points[i].project(); |
|
} |
|
} |
|
} |
|
|
|
/* ==== polygons ==== */ |
|
var listPolygons = { |
|
polygons: [], |
|
add: function (points, id) { |
|
this.polygons.push(new Polygon(points, id)); |
|
}, |
|
draw: function () { |
|
for (var i = 0, n = this.polygons.length; i < n; i++ ) { |
|
this.polygons[i].draw(); |
|
} |
|
} |
|
} |
|
|
|
/* ==== magic 2D to 3D projective transformation ==== */ |
|
var CSS3Dtransform = function (element) { |
|
this.elem = element; |
|
this.w = element.offsetWidth; |
|
this.h = element.offsetHeight; |
|
var t = ["transform", "msTransform", "MozTransform", "WebkitTransform", "OTransform"]; |
|
for (var test, i = 0; test = t[i++];) { |
|
if (typeof document.body.style[test] != "undefined") { |
|
this.CSSTransform = test; |
|
break; |
|
} |
|
} |
|
this.elem.style[this.CSSTransform+"Origin"] = "0 0"; |
|
} |
|
|
|
|
|
CSS3Dtransform.prototype.transform = function (x1, y1, x2, y2, x3, y3, x4, y4) { |
|
|
|
// projective transformation (reduced) |
|
|
|
var v0, v1, v2; |
|
var m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23; |
|
var a0, a1, a2, a3, a4, a5, a6, a7, a8, b0, b1, b2, b3, b4, b5, b6, b7, b8; |
|
v0 = (y2-y3)*x4+(x3-x2)*y4+(x2*y3-x3*y2); |
|
v1 = (y3-y1)*x4+(x1-x3)*y4+(x3*y1-x1*y3); |
|
v2 = (y1-y2)*x4+(x2-x1)*y4+(x1*y2-x2*y1); |
|
m1 = (x1+x2+x3-y1-y2-2)*v1; |
|
m2 = (x1-y1)*v1; |
|
m3 = y2*(-v0-v1+v2); |
|
m4 = (-x1+y1+y2)*(v0+v1); |
|
m5 = -(y1+y2)*v0; |
|
m6 = x1*v0; |
|
m7 = (-x1+2)*v0; |
|
m9 = -2*v0; |
|
m11 = -v0-v1; |
|
m12 = (-x3+2)*v1; |
|
m13 = (x3-1)*v1; |
|
m16 = -(-x3+y2+y3)*v2; |
|
m17 = -(x3-y3)*v2; |
|
m18 = (y2+y3)*v2; |
|
a0 = m6; |
|
a1 = m1+m4+m5+m6+m12; |
|
a2 = m6+m7+m9+m16+m18; |
|
a3 = m2+m3+m4+m6+m16+m17; |
|
a4 = m2+m4+m5+m6; |
|
a5 = m16+m17+m18; |
|
a6 = m6+m7+m11+m12+m13; |
|
a7 = m12+m13; |
|
a8 = m6+m7+m9+v2; |
|
b0 = this.h; |
|
b2 = -this.w*this.h; |
|
b4 = -this.w; |
|
m1 = (a0+a1+a2-a3-a4-a7-a8)*b4; |
|
m2 = (a0-a3)*b4; |
|
m3 = -a4*b4; |
|
m4 = (-a0+a3+a4)*(b0+b4); |
|
m5 = -(a3+a4)*b0; |
|
m6 = a0*b0; |
|
m7 = (-a0+a6+a7)*(b0-b2); |
|
m8 = (-a0+a6)*b2; |
|
m9 = (a6+a7)*(-b0+b2); |
|
m11 = a7*b2; |
|
m15 = (a7+a8)*b4; |
|
m19 = a1*b0; |
|
m20 = a5*b4; |
|
m21 = a3*b2; |
|
a8 = m6+m7+m8+m9; |
|
a0 = (m6+m19)/a8; |
|
a1 = (m1+m4+m5+m6+m15)/a8; |
|
a2 = (m6+m7+m9)/a8; |
|
a3 = (m2+m3+m4+m6)/a8; |
|
a4 = (m2+m4+m5+m6+m20)/a8; |
|
a5 = m21/a8; |
|
a6 = (m6+m7+m8+m11)/a8; |
|
a7 = m15/a8; |
|
var t = "matrix3d(" + |
|
a0 + ", " + a3 + ", 0, " + a6 + ", " + |
|
a1 + ", " + a4 + ", 0, " + a7 + ", 0, 0, 1, 0, " + |
|
a2 + ", " + a5 + ", 0, 1)"; |
|
this.elem.style[this.CSSTransform] = t; |
|
} |
|
|
|
/* ==== init script ==== */ |
|
var init = function (param) { |
|
screen.init("screen", function () { |
|
cameraView.zoom = screen.width / 170; |
|
}, true); |
|
drag.init(screen); |
|
/* ==== init cubes ==== */ |
|
for (var i = 0; i < param.points.length; i++) { |
|
listPoints.add(param.points[i]); |
|
} |
|
for (var i = 0; i < param.poly.length; i++) { |
|
listPolygons.add(param.poly[i][0], param.poly[i][1]); |
|
} |
|
cameraView.rotate(0, 0); |
|
run(); |
|
} |
|
|
|
// ==== main loop ==== |
|
var run = function () { |
|
|
|
Xi += (drag.x - Xi) / 10; |
|
Yi += (drag.y - Yi) / 10; |
|
cameraView.rotate(Zi + Xi / 100, Zi / 4 + Yi / 100); |
|
listPoints.project(); |
|
listPolygons.draw(); |
|
Zi += 0.01; |
|
|
|
requestAnimationFrame(run); |
|
|
|
} |
|
|
|
return { |
|
/* ==== load data ==== */ |
|
load : function (p) { |
|
window.addEventListener('load', function () { |
|
init(p); |
|
}, false); |
|
} |
|
} |
|
})().load({ |
|
points: [ |
|
[-80,-80,80],[80,-80,80],[80,80,80],[-80,80,80],[-80,-80,-80],[80,-80,-80],[80,80,-80],[-80,80,-80], |
|
[-15,-15,15],[15,-15,15],[15,15,15],[-15,15,15],[-15,-15,-15],[15,-15,-15],[15,15,-15],[-15,15,-15] |
|
], |
|
poly: [ |
|
[[0, 1, 2, 3], "i1"],[[1, 5, 6, 2], "i2"],[[4, 0, 3, 7], "i3"],[[5, 4, 7, 6], "i4"],[[7, 3, 2, 6], "i5"],[[5, 1, 0, 4], "i6"], |
|
[[9, 8, 11, 10], "i7"],[[13, 9, 10, 14], "i8"],[[8, 12, 15, 11], "i9"],[[12, 13, 14, 15], "i10"],[[14, 10, 11, 15], "i11"],[[12, 8, 9, 13], "i12"] |
|
] |
|
}); |