2009-09-09 85 views
3

如果您转到以下链接,您会看到一个非常酷的Javascript模拟,该模拟是根据鼠标位置旋转的立方体。有人可以解释这个旋转多维数据集脚本如何工作背后的数学吗?

模拟:here.

alt text

如果您查看立方体旋转脚本的来源,你会看到:

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

我看过了好几遍了,我还是不明白如何计算立方体的点数。这是使用“欧拉旋转”?我遇到的一个重大问题是使用单个字母的变量名,这对我来说毫无意义。

是否有必要的数学知识的人有助于解释在模拟中旋转立方体后的数学运算方式?我想制作类似的东西,但是在计算积分位置时,我有点失落。

+0

难道你只是讨厌人们使用这样的变量名而没有评论。我讨厌混淆代码!这使反编译变得更加困难! ;-) – Kredns

+0

@Lucas Aardvark,说实话,我认为他不认为他是在试图混淆他的代码。我认为他是如何编码的,或者是在试图缩小他的脚本的大小。他与Digg用户对源头进行了大量的讨论,并调整了某些东西。 – KingNestor

+0

我认为它是真正可读的,但是你忘记了onmousemove()事件,所以唯一的问题是:如何设置a和b –

回答

2

这个想法是使用标准的旋转矩阵。在2D是这样的:

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

a是通过你的旋转角度。

这个想法是,你正在翻译每一个点使用这个transformatoin一个新的点。为了更好地了解这一点,考虑一个单位圆(我不知道如何用ASCII艺术绘制),并问自己如何将点(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是非常简单的,你所要做的就是用另一种mutliplication沿XZ平面旋转。

7
  1. 他写道27(3x3x3的)+(在 粗体HTML节点)
  2. 他遍历x,y和z轴的每一个从-1-> 0-> 1(以便达到所有27此立方体的(3x3x3的)分)
  3. 所以对于每一个点,他会做:
  4. 围绕z轴的旋转运动通过一(简单的2D旋转)
  5. 围绕x轴的旋转由b(简单的2D再次旋转)
  6. 夹紧值c(wh ich只是一个缩放的z-coord)分成[0 ..255](使用其作为颜色[深度提示]
  7. 获取HTML节点和用一个简单的透视方法
  8. 根据depht

设定颜色和大小周围(300/300)将它们放置你忘记提到的重要一点是,全球A和b在身体标记设置:

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

变量列表:

  • i是只是一个计数器(没有功能)的
  • 一个是围绕z轴的角
  • b为围绕x轴的角度
  • c是颜色强度的
  • 的x,y,z是坐标在[-1,-1,-1] - [1,1,1]之间的空间中u,v,w是围绕z轴的旋转点
  • u2,v2,w2围绕x轴
  • s是htmlnode

他使用了与欧拉角相似的方法,但他只使用两个坐标轴,所以使用欧拉角时没有含义限制。

有关三维旋转更多信息,看看维基百科:

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

还要注意,他的预测是不是真正的3D:他通过不除法z坐标,伸入2D-空间。所以深度是“扭曲的”(很难解释,但如果连接十字架,它们不会形成立方体,而是形成一个扭曲的立方体)。在实际的2D投影中,直线将再次形成直线。 alt text

正确透视投影看这个文章(不要被矩阵东西..只是图和简单的拦截定理困惑是所有你需要):

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

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

对于这样一个简单的方法是可以的,然而,严重的3d将使用齐次坐标。

+0

@Peter Parker,有趣。你认为在上述脚本中解决这个问题需要做些什么?按照你的建议划分z坐标或? – Mithrax

+0

您需要为每个点进行投影。通常这只是通过截距定理完成的。你需要一个遥远的眼点(你的眼睛和屏幕之间的距离)。公式如下:x'= x *(distant_eyepoint/distant_eyepoint + z)[y相同] –

相关问题