3

次のリンクにアクセスすると、マウスの位置に基づいて回転する立方体の非常に優れた Javascript シミュレーションが表示されます。

シミュレーション:こちら。

代替テキスト

キューブ回転スクリプトのソースを表示すると、次のように表示されます。

<script type="text/javascript">

/* I wrote this script in a few minutes just for fun. It's not made to win any
   competition. */

var dimension = 1, a = 0, b = 0, i = 27;
while (i--) document.write('<b id="l' + i + '">+</b>');

function f()
{
 i = 0;
 for (x = -dimension; x <= dimension; x += dimension)
  for (y = -dimension; y <= dimension; y += dimension)
   for (z = -dimension; z <= dimension; z += dimension)
   {
    u = x;
    v = y;
    w = z;
    u2 = u * Math.cos(a) - v * Math.sin(a);
    v2 = u * Math.sin(a) + v * Math.cos(a);
    w2 = w;
    u = u2; v = v2; w = w2;
    u2 = u;
    v2 = v * Math.cos(b) - w * Math.sin(b);
    w2 = v * Math.sin(b) + w * Math.cos(b);
    u = u2; v = v2; w = w2;
    var c = Math.round((w + 2) * 70);
    if (c < 0) c = 0;
    if (c > 255) c = 255;
    s = document.getElementById('l' + i).style;
    s.left = 300 + u * (w + 2) * 50;
    s.top  = 300 + v * (w + 2) * 50;
    s.color = 'rgb(' + c + ', ' + c + ', 0)';
    s.fontSize = (w + 2) * 16 + 'px';
    /* The Digg users missed depth sort, so here it is. */
    s.zIndex = Math.round((w + 2) * 10);
    i++;
   }
}

/* Using a timer instead of the onmousemove handler wastes CPU time but makes
   the animation much smoother. */
setInterval('f()', 17);

</script>

何度か見直しましたが、立方体のポイントがどのように計算されるのかまだわかりません。これは「オイラー回転」を​​使用していますか?私が経験した大きな問題の 1 つは、私にとって何の意味もない 1 文字の変数名を使用していることです。

必要な数学の知識を持っている人なら、このシミュレーションで立方体を回転させる背後で数学がどのように機能するかを説明できますか? 似たようなものを作りたいのですが、点数の計算となるとちょっと迷います。

4

2 に答える 2

7
  1. 彼は 27 (3x3x3) + (太字の html ノードで)と書いています。
  2. 彼は、x、y、z 軸をそれぞれ -1->0->1 から反復します (したがって、この立方体の 27 (3x3x3) ポイントすべてに到達します)。
  3. したがって、各ポイントについて、彼は次のことを行います。
  4. a (単純な 2d 回転) による z 軸周りの回転
  5. b による x 軸周りの回転 (単純な 2 次元回転)
  6. 値 c (単にスケーリングされた z 座標) を [0..255] にクランプします (これを色 [深度キューイング] として使用)
  7. HTMLノードを取得し、単純なパースペクティブアプローチで(300/300)に配置します
  8. 深度に応じた色とサイズの設定

あなたが言及するのを忘れている重要なことは、グローバルな a と b が body タグに設定されているということです:

<body onmousemove="a = event.clientX / 99; b = event.clientY / 99;"

変数リスト:

  • i は単なるカウンター (機能なし) a
  • a は z 軸周りの角度
  • b は x 軸周りの角度
  • c は色の強さ
  • x,y,z は [-1,-1,-1]-[1,1,1] の間の空間の座標です。
  • u、v、w は z 軸を中心に回転した点です。
  • u2、v2、w2 は x 軸を中心に回転した点です。
  • s は html ノードです

彼はオイラー角と同様のアプローチを使用しましたが、使用する軸は 2 つだけであるため、オイラー角の使用に関する暗黙の制限はありません。

3 次元での回転の詳細については、ウィキペディアを参照してください。

http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three

また、彼の投影は実際の 3 次元ではないことに注意してください。2 次元空間に投影するために z 座標で割ることはありません。したがって、深さは「歪んでいます」(説明が難しいですが、十字を接続すると、立方体ではなく、歪んだ立方体になります)。実際の 2D 投影では、直線が再び直線になります。 代替テキスト

正しい透視図法については、この記事を参照してください (行列の話に惑わされないでください。必要なのは図と単純な切片定理だけです):

http://en.wikipedia.org/wiki/Perspective_projection#Perspective_projection

x' = x * (eye_dist / eye_dist + z)
y' = y * (eye_dist / eye_dist + z)

このような単純なアプローチでは問題ありませんが、本格的な 3D は同次座標で機能します。

于 2009-09-09T18:47:44.607 に答える
2

アイデアは、標準の回転行列を使用することです。2D では次のようになります。

--     --   --             -- --     --
| x_new |   | cos(a) -sin(a) | | x_old |
|       | = |               | |       |
| y_new |   | sin(a)  cos(a) | | y_old |
---    --   --             -- --     --

a回転している角度はどこですか。

アイデアは、この変換を使用して、すべてのポイントを新しいポイントに変換することです。これをよりよく理解するには、単位円 (アスキー アートでの描画方法がわかりません) を考えて、点 (0,1) を(sqrt(2)/2,sqrt(2)/2)(45 度の回転) に移動する方法を自問してみてください。

x_new = x_old * cos(45) - y_old * sin(45) = 1 * sqrt(2)/2 - 0 * sqrt(2)/2 = sqrt(2)/2
y_new = x_old * sin(45) + y_old * cos(45) = 1 * sqrt(2)/2 + 0 * sqrt(2)/2 = sqrt(2)/2

これを に変換すると(1,0)、さらに 45 度回転します。

x_new = x_old * cos(45) - y_old * sin(45) = sqrt(2)/2 * sqrt(2)/2 - sqrt(2)/2 * sqrt(2)/2 = 0
y_new = x_old * sin(45) + y_old * cos(45) = sqrt(2)/2 * sqrt(2)/2 + sqrt(2)/2 * sqrt(2)/2 = 1

これを 3D に拡張するのは非常に簡単です。必要なのは、XZ 平面に沿った回転に別の乗算を使用することだけです。

于 2009-09-09T18:40:32.407 に答える