ここまでやったなら、「俺流」といえるかもしれない。
<!DOCTYPE html>
<meta charset="UTF-8">
<title>3D</title>
<style>
canvas { background : #ddd; }
</style>
<body>
<canvas width="1024" height="512"></canvas>
<script>
function prism (r, h, n, n1) {
var i, j, k, x, y, yn, z;
var rst = [], top = [], btm = [], b = [0], c = [r];
var sin = -Math.sin (k = 2 * Math.PI / n), cos = Math.cos (k);
var h1 = h / n1, h2 = h / 2;
for (i = 0; i < n; ) {
top[i] = [x = b[i], h2, z = c[i]];
btm[i] = [z, -h2, x];
b[++i] = x * cos - z * sin;
c[i] = x * sin + z * cos;
}
for (y = h2, i = 0; i < n1; i++, y = yn)
for (x = b[0], z = c[0], yn = y - h1, j = 1; j <= n; j++)
rst.push ([[x, y, z], [x, yn, z],
[x = b[j], yn, z = c[j]], [x, y, z]]);
return [top].concat (rst, [btm]);
}
function ball (r, n, n1) {
var rst = [], a = [], b = [], c = [];
var pi = Math.PI, sin = Math.sin, cos = Math.cos;
var k = 2 * pi / n1, k2 = pi / n;
var i, i_, j, s, r2, yb;
var r2 = sin (k2) * r, h2 = cos (k2) * r, yr = r2, yt = h2;
for (i = 0; i <= n1; i++) {
s = k * i;
a[i] = sin (s);
b[i] = cos (s);
}
for (i = 0; i < n1; i++) {
rst[i] = [
[0, r, 0],
[a[i] * r2, h2, b[i] * r2],
[a[i_= i +1 ] * r2, h2, b[i_] * r2]
];
c[i] = [
[a[i_ = i + 1] * r2, -h2, b[i_] * r2],
[a[i] * r2, -h2, b[i] * r2],
[0, -r, 0]
];
}
for (i = 2; i < n -1; i++) {
s = k2 * i;
yr2 = sin (s) * r;
yb = cos (s) * r;
for (j = 0; j < n1; j++) {
rst.push ([
[a[j] * yr, yt, b[j] * yr],
[a[j] * yr2, yb, b[j] * yr2],
[a[j+1] * yr2, yb, b[j+1] * yr2],
[a[j+1] *yr, yt, b[j+1] * yr]
]);
}
yt = yb;
yr = yr2;
}
return rst.concat ([c]);
}
function move3D (m, x, y, z) {
var rst = [], a, b, i, j, s0, s1, buf;
for (i = 0; a = m[i]; rst[i++] = c)
for (j = 0, c = []; b = a[j]; c[j++] = b)
(b[0] += x, b[1] += y, b[2] += z);
return rst;
}
function rotation3D (m, x, y, z) {
var deg = Math.PI / 180, sin = Math.sin, cos = Math.cos;
var xc = cos (x * deg), xs = sin (x * deg);
var yc = cos (y * deg), ys = sin (y * deg);
var zc = cos (z * deg), zs = sin (z * deg);
var x0 = xc * yc, y0 = xc * ys * zs - xs * zc, z0 = xc * ys * zc + xs * zs;
var x1 = xs * yc, y1 = xs * ys * zs + xc * zc, z1 = xs * ys * zc - xc * zs;
var x2 = -xs, y2 = yc * zs, z2 = yc * zc;
var i, j, a, b, c, d, e, s;
var rst = [];
for (i = 0; a = m[i]; rst[i++] = s)
for (j = 0, s = []; b = a[j]; j++)
s[j] = [
x0 * (c = b[0]) + y0 * (d = b[1]) + z0 * (e = b[2]),
x1 * c + y1 * d + z1 * e,
x2 * c + y2 * d + z2 * e
];
return rst;
}
function cov3to2 (m, zz, sc) {
var rst = [], a, b, c, s, i, j, t;
for (i = 0; a = m[i]; rst[i++] = c)
for (c = [], j = 0; b = a[j]; j++)
c[j] = [b[0] / (t = (zz + b[2]) / sc), b[1] / t];
return rst;
}
function draw (c, a, o) {
var ctx = c.getContext ('2d');
var x = c.width / 2 + o[0];
var y = c.height / 2 + o[1];
var i, b, f, p;
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgb(0,0,0)';
for (i = 0; b = a[i++]; )
if (0 >= (b[2][0] - b[1][0]) * (b[0][1] - b[1][1]) -
(b[2][1] - b[1][1]) * (b[0][0] - b[1][0])) {
ctx.beginPath ();
ctx.moveTo (x + b[0][0], y - b[0][1]);
for (j = 1; p = b[j++]; )
ctx.lineTo (x + p[0], y - p[1]);
ctx.lineTo (x + b[0][0], y - b[0][1]);
ctx.stroke();
}
}
draw (
document.querySelector ('canvas'),
cov3to2 (move3D (prism (8, 16, 24, 10), 0, -12, 0), 50, 700),
[200, -150]
);
draw (
document.querySelector ('canvas'),
cov3to2 (rotation3D (ball (15, 18, 36), 0,-20,-40), 50, 600),
[-200, 0]
);
</script>