正文

绕不动点旋转2010-05-21 18:26:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/yuqiexing/51169.html

分享到:

 

玩过Google Earth操作的人都知道,其中键操作非常方便。以中键按下的点为不动点,鼠标操作的方向进行旋转,与仅仅绕场景中心旋转的方式要灵活许多。

 

 

 

 

本文主要介绍了简单的几何实现。

 


 

如图所示,E为视点,C为场景中心,P为中键按下点。此时如果鼠标沿屏幕X方向移动,表示,场景沿水平方向转动;若沿屏幕Y方向移动,场景在CEE’竖直平面内转动。

 

1场景沿水平方向转动比较简单,EC分别以旋转轴为Z轴,以P为旋转中心,转动的角度按照屏幕X方向移动的距离比例计算出来,通过四元数计算新视点和新的场景中心。

 

2、场景在CEE’竖直平面内的转动要复杂一点。首先我们要计算P在这个平面内的投影P’。此时EC分别以P’为旋转中心,PP’为旋转轴,转动的角度按照屏幕Y方向移动的距离比例计算出来,通过四元数计算新视点和新的场景中心。

 

  

 

相关代码如下:

 

void CCamera::RotateScene(double alpha_add, double beta_add,Vertex3d NonMovePoint)

{

       // 绕不动点旋转

       // 用四元数来实现modified by XWP

 

       Vertex3d vZAxis(0,0,1);

       Quaternion qq(-alpha_add*3.1415926,vZAxis);

 

       // 先绕平面上的角度转动

       Vertex3d curOrient = NonMovePoint - m_Eye;

       Vertex3d curOrient2 = m_Cen - NonMovePoint;

 

       Vertex3d newOrient = qq * curOrient;

       Vertex3d newOrient2 = qq * curOrient2;

 

       newOrient.Normailize();

       newOrient = newOrient * curOrient.Length();

 

       newOrient2.Normailize();

       newOrient2 = newOrient2 * curOrient2.Length();

 

       // 得到新的视点和中心

       Vertex3d newEye = NonMovePoint - newOrient;

       Vertex3d newCen = NonMovePoint + newOrient2;

       Vertex3d vAxis = (newEye - newCen) ^ vZAxis;

       vAxis.Normailize();

 

       // 再次在竖直平面内旋转

 

       // 首先求出不动点在竖直平面的垂足

       PLANE3D plane;

       GetPlaneEquation(vAxis,newEye,plane);

       Vertex3d tempFootPt;

       IsPointInPlane(NonMovePoint,plane,&tempFootPt); 

 

       // 连接垂足与视点、垂足与中心,绕竖直平面的法向量进行旋转

       newOrient = tempFootPt - newEye;

       double length = newOrient.Length();

       vAxis = newOrient ^ vZAxis;

       vAxis.Normailize();

 

       Quaternion qq1(-beta_add*3.1415926,vAxis);

       newOrient = qq1 * newOrient;

       newOrient.Normailize();

       newOrient = newOrient * length;

       newEye = tempFootPt - newOrient;

 

       newOrient2 = newCen - tempFootPt;

       length = newOrient2.Length();

 

       vAxis = newOrient2 ^ vZAxis;

       vAxis.Normailize();

 

       Quaternion qq2(-beta_add*3.1415926,vAxis);

       newOrient2 = qq2 * newOrient2;

       newOrient2.Normailize();

       newOrient2 = newOrient2 * length;

       newCen = tempFootPt + newOrient2;

 

       //下面是用来限制不超过度的旋转

       Vertex3d newLine = newCen - newEye;

       newLine.Normailize();

       Vertex3d up = GetUp();

       double dtheta = newLine*up;

       if (fabs(dtheta) -0.98 < 0.000001 && dtheta <0)

       {

              SetEye(newEye);

              SetCenter(newCen);

       }

       if (dtheta >0 && dtheta < 0.98)

       {

              SetEye(newEye);

              SetCenter(newCen);

       }

}

 

实现效果如下:

 


阅读(2456) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册