您的位置:首页 > 其它

使用鼠标自由旋转三维图形的算法和思路

2007-12-16 16:39 232 查看
转自www.eternity3.com.cn

考虑鼠标移动在一个半球面而不是普通的平面,如图所示。



鼠标移动时,不是简单从屏幕上的A点移动到B点,而是在球O上沿着弧AB移动到了B点。
也就是说,向量OA沿着圆O旋转到了向量OB。我们便可以将我们的图形也按照同样的方式进行旋转。
因此我们需要知道的是旋转的角度和旋转的法向量。
步骤:
1.计算鼠标在半球面上的坐标
我们可以通过鼠标在屏幕的平面坐标计算鼠标在半球面上的坐标
假设鼠标的屏幕坐标为(Xs, Ys),半球面坐标为(Xh, Yh, Zh)。显然有
Xh = Xs
Yh = Ys
Zh^2 = r^2–Xh^2–Yh^2
其中r为半球半径,一般可以设置为窗口高度的一半。
这样便可以求出向量OA和向量OB的坐标。

2.计算旋转角度
有了向量OA和向量OB的坐标,利用余弦定理我们可以求得角AOB的大小,不过这个计算很复杂,开销很大。
我们可以考虑用A到B的球面距离,即 弧AB的长度 / 圆O的周长 * 360度。
不过弧长也不是那么好算,好在每次鼠标移动的间隔都不大,我们可以简单的使用弦AB的距离来近似弧AB的长度。
因此我们的算法变得很简单。
角AOB = 弦AB的长度 / 圆O的周长 * 360度
弦AB的长度可以用两点间距离公式求得,即 d^2 = (Xa-Xb)^2+(Ya-Yb)^2+(Za-Zb)^2。

3.计算旋转法向量
旋转法向量n是垂直于向量OA和向量OB所决定的平面的,所以只需要求得向量OA与向量OB的外积(也就是叉乘),就可求得旋转法向量n。
即 n = OA×OB。

4.OpenGL的矩阵乘法
有了旋转角度和旋转的法向量就可以使用glRotate函数来旋转图形了,不过这里有一点需要注意的地方:
例如我们旋转一个图形:

程序代码
glLoadIdentity();
glRotatef(theta, axis[0], axis[1], axis[2]);
drawCube();

在这里的glRotate函数实际是产生了一个旋转矩阵,并将其右乘到当前矩阵上,所以当前矩阵的变化为:M = E·R。
如果我们绘制的图形的某一点是P,那么它在绘制时候,将被旋转到点P’ = M·P = E·R·P。
当我们第二次旋转的时候,glRotate函数又产生来一新的旋转矩阵R’,它再次被右乘到当前矩阵上,所以当前矩阵的变化为:M = E·R·R’。
那么当我们再次绘制图形时,P点将被旋转到P’ = M·P = E·R·R’·P。
此时我们发现P点实际上是先按照第二次的旋转矩阵旋转,再按照第一次的旋转,与我们想要的结果刚好相反。
因此我们需要将每一次的旋转矩阵左乘到当前矩阵上,所以我们需要下面的步骤:

程序代码
glLoadIdentity();
glRotatef(theta, axis[0], axis[1], axis[2]);
glMultMatrixf(lastMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, lastMatrix);

我们用lastMatrix保存当前矩阵,然后将其右乘到新的旋转矩阵上,实际相当于将新的旋转矩阵左乘到当前矩阵上,这样做了之后才能实现我们想要的目的。

下面这个是编译好的示例程序及源代码:点击下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐