Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / multimedia / OpenGL

Creating a Window - Building a 3D Engine

3.67/5 (4 votes)
7 Feb 2009CPOL4 min read 51.1K   2K  
This article describes the creation of an OpenGL window or OpenGL control with C# and Tao Framework
Dancing Triangles

Contents

Introduction

This article is intended to be the first of many articles describing the mechanics and elements of a 3D Engine. I am not a computer programmer by profession and as such I would expect that ideas and algorithms expressed in this series to be rewritten and adapted to your application by “real” programmers. The purpose of the series is intended to consolidate a number of topics written in C# allowing non-game programmers to incorporate the power of 3D drawings in their application. While the vast majority of 3D Engines are used for game development, this type of tool is very useful for visual feedback and graphic data input. I began writing this tool with a focus on simulation modeling but it is my intent to maintain a level of performance that will allow real-time graphics.

Topics To Be Discussed

Basics:
  • Creation of an OpenGL Window (This article)
  • Spaces and Matrix Transforms
  • Quaternion for Rotation
  • Navigation Zooming, Panning and Orbit (ArcBall)
Drawing:
  • Drawing Points, Lines and Triangles
  • Textures and Texture Coordinates
  • Loading a Static Mesh Files (*.obj)
  • SceneGraphs
Standard 3D Objects and Containment:
  • Spheres and Oriented Boxes
  • Capsules and Cylinders
  • Lozenges and Ellipsoids
Sorting Tree and Their Application:
  • Octree Tree Sort
  • BSP Tree Sort
  • Object Picking and Culling
Misc:
  • Lights and Special Effects
  • Distance Methods
  • Intersection Methods

Background

I am currently rewriting one of my company’s software models and have proposed revamping our GUI interface providing users a drawing interface. This series is a product of a rewrite of my original proof of concept application.

I am an Electrical Engineer with Lea+Elliott and as part of my responsibilities, I develop and maintain our company's internal models. That being said, I am not a professional programmer so please keep this in mind if you look through my code.

Prior to Using the Code

Before you can use this code, you need to download the Tao Framework to access the Tao namespaces. You also need to reference the AGE_Engine3D.dll, add the AGE_Engine3D to your project or copy the applicable *.cs file and add them to your project.

There are two classes provided that can be used to create an OpenGL window: OpenGLViewWindow and OpenGLControl. The OpenGLViewWindow class is derived from the System.Windows.Forms.Form class to be used as a traditional game window. The OpenGLControl class is derived from the Tao.Platform.Windows.SimpleOpenGlControl class to be used as a control embedded in a traditional System.Windows.Forms.Form.

The OpenGLViewWindow

The OpenGLViewWindow is a modified version LessonXX class from the NeHe tutorials included with the Tao Framework written by Jeff Molofee. I needed a standard reusable class to create a standard OpenGL Window. The only real modification to his code was the inclusion of the fields SimulationApplication and mouseControl. The SimulationApplication is a reference to an object that implements the interface BaseSimulation. This is the interface to the application logic.

The creation of the OpenGL window is fairly easy. The following code creates a window with a resolution of 800x600, 16 bit color, that is fullscreen.

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

The final argument is a class DanceTriangles that is derived from BaseSimulation. I will go into the BaseSimulation shortly.

The OpenGLControl

The OpenGLControl is derived from the class SimpleOpenGlControl. I added the fields SimulationApplication and mouseControl. The SimulationApplication is a reference to an object that is derived from BaseSimulation class. This is the interface to application logic. The mouseControl is used to map mouse input and pass them to SimulationApplication. To trigger a repaint of the control, we would call the OpenGLControl’s Invalidate() method.

Using the OpenGLControl class is also fairly easy. Just drag the control on to your form. You will need to Load a BaseSimulation via the LoadSimulation method. In the example provided, I add the following interface to my TestForm that allows easy access to the OpenGLControl method.

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

What is this BaseSimulation Class?

The BaseSimulation is a class that implements the IBaseSimulation interface which is my attempt to standardize the interface between both the OpenGLViewWindow and the OpenGLControl classes. The BaseSimulation class maps the mouse and keyboard inputs, screen size, and other various bits of information. The most important interface is the void ProcessStep() function. Both the OpenGLViewWindow and the OpenGLControl classes call this function when they would like the scene redrawn.

How to Use the Code

So how do you use this code? First, you need to derive from the BaseSimulation class. This will require you to override four abstract functions and at least one virtual function. The following is an excerpt from the included example DancingTriangles.

C#
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
}

There is a lot more included in the *.zip file not discussed here, but I will go into the other classes and concepts in other articles.

Further Reading

History

  • 2009-01-30 - Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)