使用Tao和C#进行OpenGL 3D导航2 Tao.OpenGL, Tao.freeGlut, EP_OpenGL_CS02
这是一个小型程序,演示了如何使用键盘和鼠标在3D空间中导航。它使用Tao.OpenGl和Tao.freeGlut。它还演示了如何绘制一个3D立方体。

引言
此项目基于我之前的项目CS02OpenGL3DNavigationTaoCSharp
,但是我添加了更多功能。我认为对于OpenGL初学者来说,学习如何创建3D空间并在其中导航是最重要的知识领域之一。如果你不知道自己实际上在看哪里,可能会非常混乱。此程序演示了如何在3D空间中导航。这是一个初级程序,演示了如何在3D空间中导航。它使用glRotatef()
、glTranslatef()
和glLookAt()
函数进行导航。它包含键盘事件和鼠标事件的示例。它包含3D立方体和颜色的示例。为了简化操作,我用线条划分了3D空间。x、y、z轴的交点是位置(0,0,0)。线的点划部分是每个轴的负半部分。请注意,z轴不可见,因为我们从(0,0,15)坐标查看空间。
Using the Code
- 绿色代表 x 轴
- 红色代表 y 轴
- 蓝色代表 z 轴
- x 绕x轴旋转 // 使用
glRotatef()
函数 - X 绕x轴反向旋转
- y 绕y轴旋转
- Y 绕y轴反向旋转
- z 绕z轴旋转
- Z 绕z轴反向旋转
left_key
- 向左平移 (x轴) // 使用glTranslatef()
right_key
- 向右平移 (x轴)up_key
- 向上平移 (y轴)down_key
- 向下平移 (y轴)page_up
- 沿z轴平移 (放大)page_down
- 沿z轴平移 (缩小)- j 沿x轴平移 // 使用
glLookAt()
- J 沿x轴反向平移
- k 沿y轴平移
- K 沿y轴反向平移
- l 沿z轴平移
- L 沿z轴反向平移
- b,B 在 x 轴上旋转 (+/-)90 度
- n,N 在 y 轴上旋转 (+/-)90 度
- m,M 在 z 轴上旋转 (+/-)90 度
- o,O 将所有内容重置到起始位置
*********************************************************
新的按键和功能
- F1 显示/隐藏线条
- F2 旋转/停止立方体在x,y,z方向上的旋转
- 鼠标左键按下 在x和y方向平移立方体 (上/下,左/右)
- 鼠标滚轮 在+/- z方向平移立方体 (放大/缩小)
using System;
using System.Collections.Generic;
using System.Text;
using Tao.OpenGl;
using Tao.FreeGlut;
namespace OpenGLNavigation2TaoCSharp
{
sealed class Program
{
// Declared static (no need for object reference
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)
static bool lines = true; // Display x,y,z lines (coordinate lines)
static bool rotation = false; // Rotate if F2 is pressed
static int old_x, old_y; // Used for mouse event
static int mousePressed;
// Draw the lines (x,y,z)
static void drawings()
{
// Clear the Color Buffer and Depth Buffer
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
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
if (rotation) // If F2 is pressed update x,y,z for rotation of the cube
{
rotX += 0.2f;
rotY += 0.2f;
rotZ += 0.2f;
}
Gl.glTranslatef(X, Y, Z); // Translates the screen left or right,
// up or down or zoom in zoom out
if (lines) // If F1 is pressed don't draw the lines
{
// 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 coordinates
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();
}
// I start to draw my 3D cube
Gl.glBegin(Gl.GL_POLYGON);
// I'm setting a new color for each corner, this creates a rainbow effect
Gl.glColor3f(0.0f, 0.0f, 1.0f); // Set color to blue
Gl.glVertex3f(3.0f, 3.0f, 3.0f);
Gl.glColor3f(1.0f, 0.0f, 0.0f); // Set color to red
Gl.glVertex3f(3.0f, -3.0f, 3.0f);
Gl.glColor3f(0.0f, 1.0f, 0.0f); // Set color to green
Gl.glVertex3f(-3.0f, -3.0f, 3.0f);
Gl.glColor3f(1.0f, 0.0f, 1.0f); // Set color to something
//(right now I don't know which color)
Gl.glVertex3f(-3.0f, 3.0f, 3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(0.50f, 0.50f, 1.0f); // Set a new color
Gl.glVertex3f(3.0f, 3.0f, -3.0f);
Gl.glVertex3f(3.0f, -3.0f, -3.0f);
Gl.glVertex3f(-3.0f, -3.0f, -3.0f);
Gl.glVertex3f(-3.0f, 3.0f, -3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(0.0f, 1.0f, 0.0f); // Set a new color (green)
Gl.glVertex3f(3.0f, 3.0f, 3.0f);
Gl.glVertex3f(3.0f, 3.0f, -3.0f);
Gl.glVertex3f(3.0f, -3.0f, -3.0f);
Gl.glVertex3f(3.0f, -3.0f, 3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(0.50f, 1.0f, 0.50f);
Gl.glVertex3f(-3.0f, 3.0f, 3.0f);
Gl.glVertex3f(-3.0f, -3.0f, 3.0f);
Gl.glVertex3f(-3.0f, -3.0f, -3.0f);
Gl.glVertex3f(-3.0f, 3.0f, -3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(1.0f, 0.0f, 0.0f);
Gl.glVertex3f(3.0f, 3.0f, 3.0f);
Gl.glVertex3f(3.0f, 3.0f, -3.0f);
Gl.glVertex3f(-3.0f, 3.0f, -3.0f);
Gl.glVertex3f(-3.0f, 3.0f, 3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(1.0f, 0.50f, 0.50f);
Gl.glVertex3f(3.0f, -3.0f, 3.0f);
Gl.glVertex3f(3.0f, -3.0f, -3.0f);
Gl.glVertex3f(-3.0f, -3.0f, -3.0f);
Gl.glVertex3f(-3.0f, -3.0f, 3.0f);
Gl.glEnd();
Gl.glDisable(Gl.GL_LINE_STIPPLE); // Disable the line stipple
Glut.glutPostRedisplay(); // Redraw the scene
Gl.glPopMatrix(); // Don't forget to pop the Matrix
Glut.glutSwapBuffers();
}
// Initialize the OpenGL window
static void init()
{
Gl.glShadeModel(Gl.GL_SMOOTH); // Set the shading model to smooth
Gl.glClearColor(0, 0, 0, 0.0f); // Clear the Color
// Clear the Color and Depth Buffer
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glClearDepth(1.0f); // Set the Depth buffer value (ranges[0,1])
Gl.glEnable(Gl.GL_DEPTH_TEST); // Enable Depth test
Gl.glDepthFunc(Gl.GL_LEQUAL); // If two objects on the same coordinate
// show the first drawn
Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);
}
// 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, 500.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 -= 2.0f;
break;
case 88: // X // Opposite way
rotX += 2.0f;
break;
case 121: // y // Rotates screen on y axis
rotY -= 2.0f;
break;
case 89: // Y // Opposite way
rotY += 2.0f;
break;
case 122: // z // Rotates screen on z axis
rotZ -= 2.0f;
break;
case 90: // Z // Opposite way
rotZ += 2.0f;
break;
// j,J,k,K,l,L uses the gluLookAt function for navigation
case 106: // j
rotLx -= 2.0f;
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 += 2.0f;
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 -= 2.0f;
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 += 2.0f;
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 becomes
// 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 -= 2.0f;
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 += 2.0f;
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 // Resets all parameters
case 80: // O // Displays the cube in the starting position
rotation = false;
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)
{
// Check which key is pressed
switch (key)
{
case Glut.GLUT_KEY_LEFT: // Rotate on x axis
X -= 2.0f;
break;
case Glut.GLUT_KEY_RIGHT: // Rotate on x axis (opposite)
X += 2.0f;
break;
case Glut.GLUT_KEY_UP: // Rotate on y axis
Y += 2.0f;
break;
case Glut.GLUT_KEY_DOWN: // Rotate on y axis (opposite)
Y -= 2.0f;
break;
case Glut.GLUT_KEY_PAGE_UP: // Rotate on z axis
Z -= 2.0f;
break;
case Glut.GLUT_KEY_PAGE_DOWN:// Rotate on z axis (opposite)
Z += 2.0f;
break;
case Glut.GLUT_KEY_F1: // Enable/Disable coordinate lines
lines = !lines;
break;
case Glut.GLUT_KEY_F2: // Enable/Disable automatic rotation
rotation = !rotation;
break;
default:
break;
}
Glut.glutPostRedisplay(); // Redraw the scene
}
// Capture the mouse click event
static void processMouseActiveMotion(int button, int state, int x, int y)
{
mousePressed = button; // Capture which mouse button is down
old_x = x; // Capture the x value
old_y = y; // Capture the y value
}
// Translate the x,y windows coordinates to OpenGL coordinates
static void processMouse(int x, int y)
{
if ((mousePressed == 0)) // If left mouse button is pressed
{
X = (x - old_x) / 15; // I did divide by 15 to adjust
// for a nice translation
Y = -(y - old_y) / 15;
}
Glut.glutPostRedisplay();
}
// Get the mouse wheel direction
static void processMouseWheel(int wheel, int direction, int x, int y)
{
Z += direction; // Adjust the Z value
Glut.glutPostRedisplay();
}
// Main Starts
static void Main(string[] args)
{
Glut.glutInit(); // Initialize glut
// 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(drawings);
// Set window's key callback
Glut.glutKeyboardFunc(new Glut.KeyboardCallback(keyboard));
// Set window's to specialKey callback
Glut.glutSpecialFunc(new Glut.SpecialCallback(specialKey));
// Set window's to Mouse callback
Glut.glutMouseFunc(new Glut.MouseCallback(processMouseActiveMotion));
// Set window's to motion callback
Glut.glutMotionFunc(new Glut.MotionCallback(processMouse));
// Set window's to mouse motion callback
Glut.glutMouseWheelFunc(new Glut.MouseWheelCallback(processMouseWheel));
Glut.glutMainLoop();
}
}
}
历史
- 2008年2月20日:初始发布