积木

No sub title

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  140 Posts :: 1 Stories :: 11 Comments :: 0 Trackbacks

常用链接

留言簿(1)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

3D游戏开发中,该变换时常发生。下面记录下,以备随时查询用。

说明:
1)
已经向量v就不用说,可以是3维空间中的任意向量。(不论位置在哪都没关系,因为向量是与位置无关的)
2)
绕已知向量n旋转。此处的n向量,最好要规范化成单位向量。为什么需要此要求呢?其实很简单,如果不规范化成单位向量,那么变换后的结果向量(假如称为v'),其模就不会等于原向量v的模。因此就会出错。(当然,如果非要用非规范化的单位向量参与计算的话,我们也是可以通过将v'进行一些处理,而得到最终想要的向量。)

下面,确认一下,变换矩阵以及变化公式所需的参数信息:
v(vx     ,      vy     ,  vz)                                :
为已经向量
n(nx    ,    ny     ,  nz)                                :
v向量绕n旋转的基向量
R(n     ,    angle)                                         : 为旋转所需的变换矩阵。(注释:angle就是角度,本来可以直接用那些希腊字母,结果发现用了,在此,我就输入不了中文与英文字符了。蛋疼)

v'(vx'   ,    vy'     , vz')                                : 为变换后最终要得到的结果向量

根据3D变换基础知识,可得如下公式:
v' = vR(n, angle)
其中,v向量已知。R(n, angle)根据推导,可得如下式子:
                     [ p' ]    [ nx2(1 - cos(angle)) + cos(angle)                            nxny(1 - cos(angle)) + nzsin(angle)                       nxnz(1 - cos(angle)) - nysin(angle) ]
R(n, angle) =  | q' | = | nxny(1 - cos(angle)) - nzsin(angle)                        ny2(1 - cos(angle)) + cos(angle)                           nynz(1 - cos(angle)) + nxsin(angle) |
                     [ r' ]     [ nxnz(1 - cos(angle)) + nysin(angle)                       nynz(1 - cos(angle)) - nxsin(angle)                        nz2(1 - cos(angle)) + cos(angle)    ]

所以,可得最终的v'向量。具体如下:

v' = vR = (vx, vy, vz)R;

vx'   = vx * (nx2(1 - cos(angle)) + cos(angle));
vx' += vy * (nxny(1 - cos(angle)) - nzsin(angle));
vx' += vz * (nxnz(1 - cos(angle)) + nysin(angle));

vy'   = vx * (nxny(1 - cos(angle)) + nzsin(angle));
vy' += vy * (ny2(1 - cos(angle)) + cos(angle));
vy' += vz * (nynz(1 - cos(angle)) - nxsin(angle));

vz'   = vx * (nxnz(1 - cos(angle)) - nysin(angle));
vz' += vy * (nynz(1 - cos(angle)) + nxsin(angle));
vz' += vz * (nz2(1 - cos(angle)) + cos(angle));

-----------------------------------------------------------------
有了上面的知识,现在就可以很容易理解。如下一段旋转摄像机方向的代码了:(注:代码出自徐明亮作者所著《opengl游戏编程》一书中的内容)

/**  旋转摄像机方向  */
void Camera::rotateView(float angle, float x, float y, float z)
{
    Vector3 newView;

    
/** 计算方向向量 */
    Vector3 view 
= m_View - m_Position;        

    
/** 计算 sin 和cos值 */
    
float cosTheta = (float)cos(angle);
    
float sinTheta = (float)sin(angle);

    
/** 计算旋转向量的x值 */
    newView.x  
= (cosTheta + (1 - cosTheta) * x * x)        * view.x;
    newView.x 
+= ((1 - cosTheta) * x * y - z * sinTheta)    * view.y;
    newView.x 
+= ((1 - cosTheta) * x * z + y * sinTheta)    * view.z;

    
/** 计算旋转向量的y值 */
    newView.y  
= ((1 - cosTheta) * x * y + z * sinTheta)    * view.x;
    newView.y 
+= (cosTheta + (1 - cosTheta) * y * y)        * view.y;
    newView.y 
+= ((1 - cosTheta) * y * z - x * sinTheta)    * view.z;

    
/** 计算旋转向量的z值 */
    newView.z  
= ((1 - cosTheta) * x * z - y * sinTheta)    * view.x;
    newView.z 
+= ((1 - cosTheta) * y * z + x * sinTheta)    * view.y;
    newView.z 
+= (cosTheta + (1 - cosTheta) * z * z)        * view.z;

    
/** 更新摄像机的方向 */
    m_View 
= m_Position + newView;
}



posted on 2012-06-12 11:29 Jacc.Kim 阅读(1680) 评论(0)  编辑 收藏 引用 所属分类: VC / C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理