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

ここまでやったなら、「俺流」といえるかもしれない。

<!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]);
}


//各x,y,z座標に移動する関数
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;
}


//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 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>