Introduction
This article is the continuation on my Arcball module for C#. Previously, I had posted a code using CsGL. In this version, I have utilized the Tao.OpenGL wrapper and I have added Rotation/Zoom/Pan functions. I have also made use of Display Lists to speed up plot rendering. The Arcball module written here is general and not limited to OpenGL, and can be used in GDI+ and DirectX as well. Please note that my main focus in this tutorial is on the Arcball module, not on OpenGL application.
Background
Arcball (also know as RollerBall) is probably the most intuitive method to view three dimensional objects. The principle of the Arcball is based on creating a sphere around the object and letting users to click a point on the sphere and drag it to a different location. There is a bit of math involved and you can Google for it. Here are few good links to educate yourself:
The code here is a C# source code implementing an Arcball in OpenGL (Tap.OpenGL).
Here is the same object but zoomed using the mouse middle button:
And, here is when it is panned to the left using the mouse right button:
Using the code
In this version, I am using Display List, Lighting, and Blending functions. I am not going to go into the details of OpenGL programming for the sake of brevity. Create a new form, create an instance of the Arcball
class, and make if fill the form rectangle. All plots should go in the public function PlotGL
in Form1.cs. I am plotting a torus and a backward torus in this example.
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();
Gl.glMultMatrixf(matrix);
#region plot something
Gl.glPolygonMode(Gl.GL_FRONT, Gl.GL_FILL);
Gl.glColor3f(0.8f, 0.3f, 0.1f);
Gl.glCallList(plot_glList1);
Gl.glColor3f(0.5f, 0.5f, 0.9f);
Gl.glCallList(plot_glList2);
#endregion plot something
Gl.glPopMatrix();
Gl.glFlush();
this.simpleOpenGlControl1.Invalidate();
}
catch
{
return;
}
}
I have defined the transformation matrices in here (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;
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;
M[0, 3] = pan.x;
M[1, 3] = pan.y;
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; }
}
}
You don't need to change anything else and the code should work. I have included comments as much as possible, but feel free to contact me if you have questions.
Note: For almost any code, you do not need to modify the Arcball
class at all.
History
- This is release 1.01. Please let me know if you find any bugs.