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

创建窗口 - 构建 3D 引擎

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (4投票s)

2009 年 2 月 7 日

CPOL

4分钟阅读

viewsIcon

51913

downloadIcon

1983

本文介绍了使用 C# 和 Tao Framework 创建 OpenGL 窗口或 OpenGL 控件

Dancing Triangles

目录

引言

本文旨在成为描述 3D 引擎的机制和元素的系列文章的第一篇。我并非专业的计算机程序员,因此我期望本系列文章中提出的想法和算法能够被“真正的”程序员重写并改编到您的应用程序中。本系列的目的是整合 C# 中写成的一系列主题,让非游戏程序员能够将 3D 图形的强大功能集成到他们的应用程序中。虽然绝大多数 3D 引擎都用于游戏开发,但这类工具对于视觉反馈和图形数据输入也非常有用。我开始编写这个工具时,重点关注的是模拟建模,但我希望保持一定的性能水平,以便能够实现实时图形。

要讨论的主题

基础
  • 创建 OpenGL 窗口(本文)
  • 空间和矩阵变换
  • 四元数用于旋转
  • 导航缩放、平移和环绕(ArcBall)
绘图
  • 绘制点、线和三角形
  • 纹理和纹理坐标
  • 加载静态网格文件(*.obj)
  • 场景图
标准 3D 对象和包含
  • 球体和定向框
  • 胶囊体和圆柱体
  • 菱形体和椭球体
排序树及其应用
  • 八叉树排序
  • BSP 树排序
  • 对象拾取和剔除
杂项
  • 灯光和特殊效果
  • 距离方法
  • 相交方法

背景

我目前正在重写我公司的一个软件模型,并提出了改进我们的 GUI 界面,为用户提供绘图界面。本系列文章是我最初概念验证应用程序重写的一部分。

我是 Lea+Elliott 的电气工程师,我的职责包括开发和维护我们公司的内部模型。也就是说,我不是专业程序员,所以在您查看我的代码时请记住这一点。

使用代码之前

在使用此代码之前,您需要下载 Tao Framework 来访问 Tao 命名空间。您还需要引用 AGE_Engine3D.dll,将 AGE_Engine3D 添加到您的项目中,或者复制适用的 *.cs 文件并将其添加到您的项目中。

提供了两个类来创建 OpenGL 窗口:OpenGLViewWindowOpenGLControlOpenGLViewWindow 类继承自 System.Windows.Forms.Form 类,用作传统的游戏窗口。OpenGLControl 类继承自 Tao.Platform.Windows.SimpleOpenGlControl 类,用作嵌入传统 System.Windows.Forms.Form 的控件。

OpenGLViewWindow

OpenGLViewWindowTao Framework 中包含的 NeHe 教程中的 LessonXX 类的修改版本,由 Jeff Molofee 编写。我需要一个标准的、可重用的类来创建一个标准的 OpenGL 窗口。对他代码唯一的真正修改是包含 SimulationApplicationmouseControl 字段。SimulationApplication 是一个实现了 BaseSimulation 接口的对象引用。这是应用程序逻辑的接口。

创建 OpenGL 窗口非常简单。以下代码创建一个分辨率为 800x600、16 位色、全屏的窗口。

OpenGLViewWindow.Run("AGE Engine3D - Dancing Triangles", 
			800, 600, 16, true, new DancingTriangles());

最后一个参数是一个名为 DanceTriangles 的类,它继承自 BaseSimulation。稍后我将详细介绍 BaseSimulation

OpenGLControl

OpenGLControl 继承自 SimpleOpenGlControl 类。我添加了 SimulationApplicationmouseControl 字段。SimulationApplication 是一个继承自 BaseSimulation 类的对象的引用。这是应用程序逻辑的接口。mouseControl 用于映射鼠标输入并将其传递给 SimulationApplication。要触发控件的重绘,我们需要调用 OpenGLControlInvalidate() 方法。

使用 OpenGLControl 类也相对容易。只需将控件拖到您的窗体上。您需要通过 LoadSimulation 方法加载一个 BaseSimulation。在提供的示例中,我将以下接口添加到我的 TestForm 中,以便轻松访问 OpenGLControl 方法。

public BaseSimulation TheSimulation
{
    set { this.openGLControl1.LoadSimulation(value); }
}
...
//This is the trigger that forces the scene to be redrawn
this.openGLControl1.Invalidate();

BaseSimulation 类是什么?

BaseSimulation 是一个实现了 IBaseSimulation 接口的类,这是我试图标准化 OpenGLViewWindowOpenGLControl 类之间接口的尝试。BaseSimulation 类映射鼠标和键盘输入、屏幕大小以及其他各种信息。最重要的接口是 void ProcessStep() 函数。当 OpenGLViewWindowOpenGLControl 类希望重绘场景时,它们都会调用此函数。

如何使用代码

那么,如何使用这段代码呢?首先,您需要继承 BaseSimulation 类。这将要求您覆盖四个 abstract 函数和一个虚拟函数。以下是随附的 DancingTriangles 示例的摘录。

public class DancingTriangles : BaseSimulation
{
    ...
    #region Methods
    override public void UpdateScene()
    {
        //This is where you update your Scene and perform the application logic
        ...
    }

    override public void UpdateInput()
    {
        //This is where you deal with user input
        ...
    }

    override public void DrawGLScene()
    {
        //This is where you draw your scene.
        ...
        //This is the flag that tells the calling ViewWindow update the display
        this.SwapBuffer = true;
    }

    //This is method that the OpenGLViewWindow and the OpenGLControl call.
    override public void ProcessStep()
    {
        if (!this.IsInitialize)  //Check to see if your Simulation is initialized
        {
            //Initialize the Simulation - A derived function
            this.InitializeSimulation();
        }
        if (this.Active && this.IsInitialize)
        {
            /*---------------------------------------------------------------------------
             * This is how I am currently structuring the each call to the 
	    * ProcessStep method.
             *   1.    I update the application with user inputs//this.UpdateInput();
             *   2.    Then, I update the Scene info.           //this.UpdateScene();
             *   3.    Finally,  Draw the scene.                //this.DrawGLScene();
             *-------------------------------------------------------------------------*/
            this.UpdateInput();
            this.UpdateScene();
            this.SwapBuffer = false;
            if (this.OpenGLFlag)
            {
                this.DrawGLScene();
            }
        }
    }

    override public void InitalizeSimulation()
    {
        base.InitalizeSimulation();
        //Load Resources Here
        //Setup the Camera View Matrix
    }
    #endregion
}

*.zip 文件中包含更多内容,此处未讨论,但我将在其他文章中介绍其他类和概念。

进一步阅读

历史

  • 2009-01-30 - 初始发布
© . All rights reserved.