C# 中的 Arcball 模块 - Tao.OpenGL
使用 Tao.OpenGL 在 C# 中实现的 Arcball 模块。
引言
本文是 C# Arcball 模块的延续。 之前,我发布了一个使用 CsGL 的代码。 在这个版本中,我使用了 Tao.OpenGL 封装器,并添加了旋转/缩放/平移功能。 我还使用了显示列表来加速绘图渲染。 这里编写的 Arcball 模块是通用的,不限于 OpenGL,也可以用于 GDI+ 和 DirectX。 请注意,我的教程主要关注 Arcball 模块,而不是 OpenGL 应用程序。
背景
Arcball(也称为 RollerBall)可能是查看三维对象的最佳直观方法。 Arcball 的原理是围绕对象创建一个球体,并让用户单击球体上的一个点并将其拖动到另一个位置。 其中涉及一些数学运算,您可以在 Google 上搜索到相关信息。 这里有一些不错的链接供您学习:
这里的代码是使用 OpenGL (Tap.OpenGL) 实现 Arcball 的 C# 源代码。
这是同一个对象,但使用鼠标中键进行了缩放
这是平移到左侧的效果,使用鼠标右键
使用代码
在这个版本中,我使用了显示列表、光照和混合函数。 我不会详细介绍 OpenGL 编程,以求简洁。 创建一个新的窗体,创建 Arcball
类的一个实例,并使其填充窗体矩形。 所有绘图都应该在 Form1.cs 中的公共函数 PlotGL
中进行。 在这个例子中,我绘制了一个环面和一个反向环面。
public void PlotGL()
{
try
{
lock (matrixLock)
{
ThisTransformation.get_Renamed(matrix);
}
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glLoadIdentity();
Gl.glPushMatrix(); // NEW: Prepare Dynamic Transform
Gl.glMultMatrixf(matrix); // NEW: Apply Dynamic Transform
#region plot something
Gl.glPolygonMode(Gl.GL_FRONT, Gl.GL_FILL);
Gl.glColor3f(0.8f, 0.3f, 0.1f);
Gl.glCallList(plot_glList1); // plot using display list
//Gl.glPolygonMode(Gl.GL_FRONT, Gl.GL_LINE);
Gl.glColor3f(0.5f, 0.5f, 0.9f);
Gl.glCallList(plot_glList2); // plot using display list
#endregion plot something
Gl.glPopMatrix(); // NEW: Unapply Dynamic Transform
Gl.glFlush(); // Flush the GL Rendering Pipeline
this.simpleOpenGlControl1.Invalidate();
}
catch
{
return;
}
}
我在这里定义了变换矩阵(Arcball.cs)
public class Matrix4f
{
...
public Quat4f Rotation
{
set
{
float n, s;
float xs, ys, zs;
float wx, wy, wz;
float xx, xy, xz;
float yy, yz, zz;
M = new float[4, 4];
n = (value.x * value.x) + (value.y * value.y) +
(value.z * value.z) + (value.w * value.w);
s = (n > 0.0f) ? 2.0f / n : 0.0f;
xs = value.x * s;
ys = value.y * s;
zs = value.z * s;
wx = value.w * xs;
wy = value.w * ys;
wz = value.w * zs;
xx = value.x * xs;
xy = value.x * ys;
xz = value.x * zs;
yy = value.y * ys;
yz = value.y * zs;
zz = value.z * zs;
// rotation
M[0, 0] = 1.0f - (yy + zz);
M[0, 1] = xy - wz;
M[0, 2] = xz + wy;
M[1, 0] = xy + wz;
M[1, 1] = 1.0f - (xx + zz);
M[1, 2] = yz - wx;
M[2, 0] = xz - wy;
M[2, 1] = yz + wx;
M[2, 2] = 1.0f - (xx + yy);
M[3, 3] = 1.0f;
// translation (pan)
M[0, 3] = pan.x;
M[1, 3] = pan.y;
// scale (zoom)
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
M[i, j] *= scl;
}
}
public float Scale
{
set { scl = value; }
}
public Vector3f Pan
{
set { pan = value; }
}
}
您不需要更改其他任何内容,代码应该可以正常工作。 我尽可能地添加了注释,但如果您有任何问题,请随时与我联系。
注意:对于几乎任何代码,您都不需要修改 Arcball
类。
历史
- 这是 1.01 版本。 如果您发现任何错误,请告诉我。