65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中的 Arcball 模块 - Tao.OpenGL

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.61/5 (13投票s)

2007年12月27日

CPOL

2分钟阅读

viewsIcon

136442

downloadIcon

6965

使用 Tao.OpenGL 在 C# 中实现的 Arcball 模块。

引言

本文是 C# Arcball 模块的延续。 之前,我发布了一个使用 CsGL 的代码。 在这个版本中,我使用了 Tao.OpenGL 封装器,并添加了旋转/缩放/平移功能。 我还使用了显示列表来加速绘图渲染。 这里编写的 Arcball 模块是通用的,不限于 OpenGL,也可以用于 GDI+ 和 DirectX。 请注意,我的教程主要关注 Arcball 模块,而不是 OpenGL 应用程序。

背景

Arcball(也称为 RollerBall)可能是查看三维对象的最佳直观方法。 Arcball 的原理是围绕对象创建一个球体,并让用户单击球体上的一个点并将其拖动到另一个位置。 其中涉及一些数学运算,您可以在 Google 上搜索到相关信息。 这里有一些不错的链接供您学习:

这里的代码是使用 OpenGL (Tap.OpenGL) 实现 Arcball 的 C# 源代码。

Screenshot - pic1.png

这是同一个对象,但使用鼠标中键进行了缩放

Screenshot - pic2.png

这是平移到左侧的效果,使用鼠标右键

Screenshot - pic3.png

使用代码

在这个版本中,我使用了显示列表、光照和混合函数。 我不会详细介绍 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 版本。 如果您发现任何错误,请告诉我。
© . All rights reserved.