虚拟轨迹球旋转控制器






4.75/5 (9投票s)
1999 年 12 月 2 日
4分钟阅读

176517

3977
引言
这段代码源于我一个(未完成的)项目:一个使用 OpenGL 库的实时 3D 预览的图形曲线编辑器。
起初,为了让用户从不同视角查看 3D 窗口中正在构建的对象,我只是简单地将鼠标移动与绕两个轴(通常是当相机沿 Z 轴时,绕 X 和 Y 轴)的旋转关联起来。
这种方法使用一段时间后就不令人满意了,因为它在对象“颠倒”时会产生一个奇怪的效果:鼠标向右移动会导致明显的向左旋转,反之亦然。
这种奇怪的效果是由于旋转必须相对于局部对象坐标系进行的。在后一种例子中,当对象颠倒时,它实际上是向右转的。
在计算机图形学文献中,有许多关于“直观”旋转控制器的论文;我认为 K. Shoemake 的 arcball 控制器是最好的解决方案之一:其思想是将鼠标移动投影到一个假设的、充满 3D 窗口的球体上,并在按下鼠标按钮时,将由操纵球体产生的旋转应用于对象。
内部
全局旋转在内部使用四元数表示和调整,而不是旋转矩阵,因为这种方法在处理小增量旋转时数值更稳定。
这个轨迹球融合了原始 arcball C 代码(用面向对象风格重写)以及 J. Childs 的虚拟轨迹球控制器(用于他的 GLcube 项目),而后者又源自 M. J. Kilgard 的 GLUT 库中的一些代码。
这两段代码有几个相似之处(例如都使用了四元数),但投影算法不同,因此我决定保留两者:J. Childs 的控制器将鼠标移动投影到球体外的一个抛物面片上,而 K. Shoemake 的控制器将鼠标移动投影到平面上;第一种方法(默认方法)有点更自然,因为它效果是连续的,而第二种方法在鼠标离开/进入虚拟球体时会 abrupt 中断。
在代码中,我(重新)使用了我常用的图形编程工具中的一套数学类,它注释良好,并包含一些可以使用 Doxygen 提取的文档。
用途
轨迹球代码在配套文章 CGLEnabledView - 支持 OpenGL 的 MDI 视图类 中得到了演示。
要在您的程序中使用 CBallController,请按照以下步骤操作:
- 在需要的地方包含
BallController.h
。 - 在应用程序中的某个地方(我建议在视图类中)构造一个
CBallController
,并在构造时指定虚拟球体的半径,半径范围从 0.1 到 1.0(半径为 1.0 表示球体完全填满窗口)。 - [可选] 调用
SetAlternateMethod
或ToggleMethod
成员函数来设置投影到球体的方法。 - 在您的窗口大小调整处理程序例程中调用
ClientAreaResize
方法(也应在首次显示窗口之前调用),并将您的客户区大小作为参数传递。 - [可选但推荐] 在您的键盘按下处理程序中调用
Key
方法,传递字符代码,以通过键盘进行操作(有关按键绑定,请参阅下文)。 - [可选] 通过
UseConstraints
方法设置约束轴,可以通过SetDrawConstraints
方法控制约束的绘制。 - 在您的鼠标处理程序例程中调用
MouseDown
、MouseMove
和MouseMove
方法,传递以本地窗口坐标表示的鼠标坐标(原点在左上角);在鼠标按钮拖动期间捕获窗口外的鼠标移动可能是一个好主意。 - 在(重新)绘制场景之前调用
IssueGLrotation
方法。 - [可选] 在绘制场景后调用
DrawBall
方法,让 BallController 在使用备用方法进行旋转时显示一些反馈。
其他方法
使用 GetDrawConstraints
可以检查约束绘制是否已激活。GetAngleKeyIncrement
和 SetAngleKeyIncrement
分别允许检索和设置键盘交互中使用的角度增量。GetColorV
、GetColor
、SetColor
和 SetColorV
指定或检索 DrawBall 方法使用的颜色,颜色可以以 COLORREF 结构或 [0-1] 范围的浮点数向量形式传递。
密钥
Esc | 中断当前旋转操作(每次按下鼠标按钮都会开始一次旋转操作) |
Canc 或 Numpad 5 | 重置当前旋转(对应于单位旋转矩阵) |
右箭头 或 Numpad 6 | 绕 X 轴旋转 +keyIncrement 度 |
左箭头 或 Numpad 4 | 绕 X 轴旋转 -keyIncrement 度 |
上箭头 或 Numpad 8 | 绕 Y 轴旋转 +keyIncrement 度 |
下箭头 或 Numpad 2 | 绕 Y 轴旋转 -keyIncrement 度 |
Page Up 或 Numpad 9 | 绕 Z 轴旋转 +keyIncrement 度 |
Home 或 Numpad 7 | 绕 Z 轴旋转 -keyIncrement 度 |
TAB | 在约束旋转期间切换约束轴 |
历史
修订 | 描述 |
---|---|
0.2 | 首次公开发布 |
0.1 | 个人开发版本 |