CANVASで網目模様を描く方法を教えて下さい.その3

動かしてみたら、球体と回転にミスがあることが判明。
OKWave にも投稿したし、これで安眠できる。めでたし、めでたし。

<!DOCTYPE html>
  <meta charset="UTF-8">
  <title>3D</title>
  <style>
    canvas { background : #fff; }
  </style>
<body>
<canvas width="1024" height="512"></canvas>

<script>

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; 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 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 = -ys, 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;
}



//3Dの物体を2Dの座標へと変換する
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 canvas_draw_create (c, o) {
  var ctx = c.getContext ('2d');
  var x = c.width / 2 + o[0];
  var y = c.height / 2 + o[1];

  ctx.lineWidth = 1;
  ctx.strokeStyle = 'rgb(0,0,0)';

  return {
    draw:
      function (a) {//面を描く
        ctx.beginPath ();
        ctx.moveTo (x + a[0][0], y - a[0][1]);

        for (i = 1; b = a[i++]; )
          ctx.lineTo (x + b[0], y - b[1]);

        ctx.lineTo (x + a[0][0], y - a[0][1]);
        ctx.stroke();
      },
    cls:
      function () {
        ctx.fillRect (0,0, c.width, c.height);
        ctx.fillStyle = 'RGB(255,255,255)';
      }
    };
}


function draw (a, dw) {
  dw.cls ();
  for (var i = 0, b; b = a[i++]; ) {//面の3点だけでベクトルの外積の向きで判断
    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]))
    )
      dw.draw (b);
  }
}


var hoge = (function _ (f, a, b, c) {
  var z = ball (15, 18, 36);
  var v = canvas_draw_create (document.querySelector ('canvas'), [0,0]);
  
  return function () {
    z = f (z, a, b, c);
    draw (cov3to2 (z, 50, 600), v);
  };
}) (rotation3D, .7, 1, .5);

setInterval (hoge, 20);

</script>