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

使用 Tao 和 C# 进行 OpenGL 3D 导航

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.03/5 (11投票s)

2008年2月19日

CPOL

2分钟阅读

viewsIcon

71074

downloadIcon

5236

使用 Tao 和 C# 的 OpenGL 3D 导航,使用 glRotatef、glTranslatef 和 gluLookAt。

引言

我认为对于初学者来说,最重要的一步是学习如何创建 3D 空间以及如何在其中导航。尤其是如何在 3D 空间中导航非常重要。这对于初学者来说可能会非常令人困惑。这个程序展示了如何在 3D 空间中导航。

背景

我有一个使用 C++ Windows 控制台应用程序的相同项目。如果您有兴趣,请查看我的其他文章。

使用代码

基本代码来自红宝书“OpenGL 编程指南(第三版)”。这是一个初学者级别的程序,用于演示如何在 3D 空间中导航。它使用了 glRotatef()glTranslatef()gluLookAt() 函数。我用线分割了 3D 空间。x、y、z 轴的交点是位置 (0,0,0)。线的点状部分是轴的负向。 z 轴不可见,因为我们从 (0,0,15) 坐标查看空间。 上图被旋转,因此可以看到 z 轴。

  • 绿色代表 x 轴
  • 红色代表 y 轴
  • 蓝色代表 z 轴
  • x,X - 绕 x 轴旋转;使用 glRotatef() 函数
  • y,Y - 绕 y 轴旋转;使用 glRotatef() 函数
  • z,Z - 绕 z 轴旋转;使用 glRotatef() 函数
  • left_key - 向左平移(x 轴);使用 glTranslatef() 函数
  • right_key - 向右平移(x 轴);使用 glTranslatef() 函数
  • up_key - 向上平移(y 轴);使用 glTranslatef() 函数
  • down_key - 向下平移(y 轴);使用 glTranslatef() 函数
  • page_up - 在 z 轴上平移(放大);使用 glTranslatef() 函数
  • page_down - 在 z 轴上平移(缩小);使用 glTranslatef() 函数
  • j,J - 在 x 轴上平移;使用 glLookAt() 函数
  • k,K - 在 y 轴上平移;使用 glLookAt() 函数
  • l,L - 在 z 轴上平移;使用 glLookAt() 函数
  • b,B 在 x 轴上旋转 (+/-)90 度
  • n,N 在 y 轴上旋转 (+/-)90 度
  • m,M 在 z 轴上旋转 (+/-)90 度
  • o,O - 将所有内容恢复为默认值(起始坐标)

请注意,glTranslatefgluLookAt() 的行为相同。但是,它们并不完全相同。您可以通过使用此程序来找出这一点。

using System;
using System.Collections.Generic;
using System.Text;
using Tao.OpenGl;
using Tao.FreeGlut;

namespace OpenGLNavigationWithTaoCSharp
{

    sealed class Program
    {
        static float X = 0.0f;       // Translate screen to x direction (left or right)
        static float Y = 0.0f;       // Translate screen to y direction (up or down)
        static float Z = 0.0f;       // Translate screen to z direction (zoom in or out)
        static float rotX = 0.0f;    // Rotate screen on x axis 
        static float rotY = 0.0f;    // Rotate screen on y axis
        static float rotZ = 0.0f;    // Rotate screen on z axis

        static float rotLx = 0.0f;   // Translate screen by using  the glulookAt
                                     // function (left or right)
        static float rotLy = 0.0f;   // Translate screen by using  the glulookAt
                                     // function (up or down)
        static float rotLz = 0.0f;   // Translate screen by using  the glulookAt
                                     // function (zoom in or out)

        // Initiliaze the OpenGL window
       static void init()
        {           
            Gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);          // Clear the color 
            Gl.glShadeModel (Gl.GL_FLAT);                     // Set the shading model
                                                              // to GL_FLAT
            Gl.glEnable (Gl.GL_LINE_SMOOTH);
            Gl.glHint(Gl.GL_LINE_SMOOTH_HINT, Gl.GL_NICEST);  // Set Line Antialiasing
        }

        // Draw the lines (x,y,z)
        static void display()
        {    
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);             // Clear the Color Buffer 
            Gl.glPushMatrix();                              // It is important to push
                                                            // the Matrix before calling
                                                            // glRotatef and glTranslatef
            Gl.glRotatef(rotX, 1.0f, 0.0f, 0.0f);           // Rotate on x
            Gl.glRotatef(rotY, 0.0f, 1.0f, 0.0f);           // Rotate on y
            Gl.glRotatef(rotZ, 0.0f, 0.0f, 1.0f);           // Rotate on z
            Gl.glTranslatef(X, Y, Z);                       // Translates the screen
                                                            // left or right, up or down
                                                            // or zoom in zoom out

            // Draw the positive side of the lines x,y,z
            Gl.glBegin(Gl.GL_LINES);
                Gl.glColor3f(0.0f, 1.0f, 0.0f);                // Green for x axis
                Gl.glVertex3f(0f, 0f, 0f);
                Gl.glVertex3f(10f, 0f, 0f);
                Gl.glColor3f(1.0f, 0.0f, 0.0f);                // Red for y axis
                Gl.glVertex3f(0f, 0f, 0f);
                Gl.glVertex3f(0f, 10f, 0f);
                Gl.glColor3f(0.0f, 0.0f, 1.0f);                // Blue for z axis
                Gl.glVertex3f(0f, 0f, 0f);
                Gl.glVertex3f(0f, 0f, 10f);
            Gl.glEnd();
            
            // Dotted lines for the negative sides of x,y,z
            Gl.glEnable(Gl.GL_LINE_STIPPLE);            // Enable line stipple to
                                                        // use a dotted pattern for
                                                        // the lines
            Gl.glLineStipple(1, 0x0101);                // Dotted stipple pattern for
                                                        // the lines
            Gl.glBegin(Gl.GL_LINES);
                Gl.glColor3f(0.0f, 1.0f, 0.0f);         // Green for x axis
                Gl.glVertex3f(-10f, 0f, 0f);
                Gl.glVertex3f(0f, 0f, 0f);
                Gl.glColor3f(1.0f, 0.0f, 0.0f);         // Red for y axis
                Gl.glVertex3f(0f, 0f, 0f);
                Gl.glVertex3f(0f, -10f, 0f);
                Gl.glColor3f(0.0f, 0.0f, 1.0f);         // Blue for z axis
                Gl.glVertex3f(0f, 0f, 0f);
                Gl.glVertex3f(0f, 0f, -10f);
            Gl.glEnd();

            Gl.glDisable(Gl.GL_LINE_STIPPLE);           // Disable the line stipple
            Gl.glPopMatrix();                           // Don't forget to pop the Matrix
            Glut.glutSwapBuffers();
        }

        // This function is called whenever the window size is changed
       static void reshape (int w, int h)
        {
     
            Gl.glViewport (0, 0, w,  h);                // Set the viewport
            Gl.glMatrixMode (Gl.GL_PROJECTION);         // Set the Matrix mode
            Gl.glLoadIdentity ();                                            
            Glu.gluPerspective(75f, (float) w /(float)h , 0.10f, 100.0f);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity(); 
            Glu.gluLookAt (rotLx, rotLy, 15.0f + rotLz, 0.0f, 0.0f, 0.0f, 0.0f,
                1.0f, 0.0f); 
        }

        // This function is used for the navigation keys
      public static void keyboard(byte key, int x, int y)
        {
            switch (key) {    
            
                // x,X,y,Y,z,Z uses the glRotatef() function
                case 120:    // x           // Rotates screen on x axis 
                    rotX -= 0.5f;
                break;
                case 88:    // X            // Opposite way 
                    rotX += 0.5f;
                break;
                case 121:    // y           // Rotates screen on y axis
                    rotY -= 0.5f;
                break;
                case 89:    // Y            // Opposite way
                    rotY += 0.5f;    
                break;    
                case 122:    // z           // Rotates screen on z axis
                    rotZ -= 0.5f;
                break;
                case 90:    // Z            // Opposite way
                    rotZ += 0.5f;
                break;

                // j,J,k,K,l,L uses the gluLookAt function for navigation
                case 106:   // j
                    rotLx -= 0.2f;  
                    Gl.glMatrixMode(Gl.GL_MODELVIEW);
                    Gl.glLoadIdentity();
                    Glu.gluLookAt (rotLx, rotLy, 15.0 + rotLz, 0.0, 0.0, 0.0, 0.0, 1.0,
                        0.0);
                break;
                case 74:    // J
                    rotLx += 0.2f;
                    Gl.glMatrixMode(Gl.GL_MODELVIEW);
                    Gl.glLoadIdentity();
                    Glu.gluLookAt (rotLx, rotLy, 15.0 + rotLz, 0.0, 0.0, 0.0, 0.0, 1.0,
                        0.0);
                break;    
                case 107:   // k
                    rotLy -= 0.2f;
                    Gl.glMatrixMode(Gl.GL_MODELVIEW);
                    Gl.glLoadIdentity();
                    Glu.gluLookAt (rotLx, rotLy, 15.0 + rotLz, 0.0, 0.0, 0.0, 0.0, 1.0,
                        0.0);
                break;
                case 75:    // K
                    rotLy += 0.2f;
                    Gl.glMatrixMode(Gl.GL_MODELVIEW);
                    Gl.glLoadIdentity();
                    Glu.gluLookAt (rotLx, rotLy, 15.0 + rotLz, 0.0, 0.0, 0.0, 0.0, 1.0,
                        0.0);
                break;
                case 108: // (l) It has a special case when the rotLZ becames less
                          // than -15 the screen is viewed from the opposite side
                          // therefore this if statement below does not allow rotLz
                          // be less than -15
                        if(rotLz + 14 >= 0)
                            rotLz -= 0.2f;
                    Gl.glMatrixMode(Gl.GL_MODELVIEW);
                    Gl.glLoadIdentity();
                    Glu.gluLookAt (rotLx, rotLy, 15.0 + rotLz, 0.0, 0.0, 0.0, 0.0, 1.0,
                        0.0);
                break;
                case 76:    // L
                    rotLz += 0.2f;
                    Gl.glMatrixMode(Gl.GL_MODELVIEW);
                    Gl.glLoadIdentity();
                    Glu.gluLookAt (rotLx, rotLy, 15.0 + rotLz, 0.0, 0.0, 0.0, 0.0,
                        1.0, 0.0);
                break;
                case 98:    // b        // Rotates on x axis by -90 degree
                    rotX -= 90.0f;
                break;
                case 66:    // B        // Rotates on y axis by 90 degree
                    rotX += 90.0f;        
                break;
                case 110:    // n       // Rotates on y axis by -90 degree
                    rotY -= 90.0f;
                break;
                case 78:    // N        // Rotates on y axis by 90 degree
                    rotY += 90.0f;
                break;
                case 109:    // m       // Rotates on z axis by -90 degree
                    rotZ -= 90.0f;            
                break;
                case 77:    // M        // Rotates on z axis by 90 degree
                    rotZ += 90.0f;
                break;
                case 111:    // o       // Default, resets the translations vies from
                                        // starting view
                case 80:    // O        
                    X = Y = 0.0f;
                    Z = 0.0f;
                    rotX = 0.0f;
                    rotY = 0.0f;
                    rotZ = 0.0f;
                    rotLx = 0.0f;
                    rotLy = 0.0f;
                    rotLz = 0.0f;
                    Gl.glMatrixMode(Gl.GL_MODELVIEW);
                    Gl.glLoadIdentity();
                   Glu.gluLookAt(rotLx, rotLy, 15.0f + rotLz, 0.0f, 0.0f, 0.0f, 0.0f,
                       1.0f, 0.0f);
                    
                break;
            }
            Glut.glutPostRedisplay();    // Redraw the scene
        }

        // called on special key pressed
       private static void specialKey(int key, int x, int y) { 
          
            // The keys below are using the gluLookAt() function for navigation
            // Check which key is pressed
            switch(key) {
                case Glut.GLUT_KEY_LEFT :  // Rotate on x axis
                    X -= 0.1f;
                  break;
              case Glut.GLUT_KEY_RIGHT:    // Rotate on x axis (opposite)
                    X +=  0.1f;
                  break;
              case Glut.GLUT_KEY_UP:       // Rotate on y axis 
                    Y += 0.1f;
                  break;
              case Glut.GLUT_KEY_DOWN:     // Rotate on y axis (opposite)
                    Y -= 0.1f;
                  break;
              case Glut.GLUT_KEY_PAGE_UP:  // Roatae on z axis
                    Z -= 0.1f;
                  break;
              case Glut.GLUT_KEY_PAGE_DOWN:// Roatae on z axis (opposite)
                    Z += 0.1f;
                  break;
            }
            Glut.glutPostRedisplay();      // Redraw the scene
        }
        static void Main(string[] args)
        {
           
            Glut.glutInit();
            // Setup display mode to double buffer and RGB color
            Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_RGB); 
            // Set the screen size
            Glut.glutInitWindowSize(600, 600);
            Glut.glutCreateWindow("OpenGL 3D Navigation Program With Tao");
            init();
            Glut.glutReshapeFunc(reshape);
            Glut.glutDisplayFunc(display);
            // set window's key callback     
            Glut.glutKeyboardFunc(new Glut.KeyboardCallback(keyboard));
            // set window's to specialKey callback
            Glut.glutSpecialFunc(new Glut.SpecialCallback(
                                 specialKey));         
            Glut.glutMainLoop();
        }
    }
}
© . All rights reserved.