Introduction
This project is based on my previous project "OpenGL 3D Navigation2 With Tao and CSharp".
It shows how to create multiple views on a single window. I did create 6 different views of the same object (cube). It also has an example of Glut fonts and glRasterPos3f()
function.
Background
The goal of this program is to use multiple views in a single window. Therefore I'm going to explain a little bit about this subject. I also displayed fonts for each view. So I'm going to explain how I displayed the fonts. I'm not going to explain anything about how to navigate in 3D space because it is not the subject of this program.
This program (idea) is basically a copy of an existing idea - one window and multiple views. You can probably use multiple views in games with two or multiple players. Also you may use this in simulations where you want the simulation in a different perspective.
Dividing the window in multiple views is very simple. I will show how to do it below. The challenging part is to use this in your program.
Using Scissor
You start by enabling the SCISSOR_TEST
.
Gl.glEnable(Gl.GL_SCISSOR_TEST);
Second you set the ViewPort
, window size and location:
Gl.glViewport(0, height, width, height);
Gl.glScissor(0, height, width, height);
Now you write your code for this window. I have the same code six times with different parameters, because I did divide the window in 6 views.
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Glu.gluPerspective(75f, (float)width / (float)height, 0.10f, 500.0f);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
Glu.gluLookAt(0.0, 0.0, 15.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
drawCube();
Once you are done, make sure to disable the Scissor test.
Gl.glDisable(Gl.GL_SCISSOR_TEST);
Using Font
You need a small method with a for
loop to render a string
(text). The for
loop goes through the string
end sets the Font
type and size for each character. In this case, the font type is Times Roman and size 24.
static void text(string c)
{
for (int i = 0; i < c.Length; i++)
{
Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_TIMES_ROMAN_24, c[i]);
}
}
Then you set the position for the string
(text) that you want to display and call your method with the string
that you want to display.
Gl.glRasterPos3f(-15, 19 , -15);
text("Front");
Using the Code
About the Demo
I did include the Tao.OpenGL.dll and Tao.freeGlut.dll in the Demo folder. Normally it should execute without any problem. However, I did not test the demo on a different Operating System or computers so I don't know if it will work on your machine. You might need Vista and .NET Framework 2.0.
About the Source
I used Visual Studio 2005 (.NET Framework 2.0) C# and Tao (Tao.OpenGL
, Tao.freeGlut
). If you have VS 2005 and .NET Framework 2.0, you should not have any problem running the program from Visual Studio. Once you run the program, you can use the keyboard and mouse to navigate in 3D space.
Help
I did include lines through the x, y and z axis so that it will be easier to visualize. The dotted part is the negative side. The intersection of (x,y,z) is (0,0,0).
Line Colors
- Green for x axis
- Red for y axis
- Blue for z axis
Keys For Rotation (glRotatef())
- x rotates on x axis
- X rotates to opposite direction
- y rotates on y axis
- Y rotates to opposite direction
- z rotates on z axis
- Z rotates to opposite direction
- b,B rotates (+/-)90 degrees on x axis
- n,N rotates (+/-)90 degrees on y axis
- m,M rotates (+/-)90 degrees on z axis
Keys for Translation (glTranslatef())
- left_key - translates to left (x axis)
- right_key - translates to right (x axis)
- up_key - translates up (y axis)
- down_key - translates down (y axis)
- page_up - translates on z axis (zoom in)
- page_down - translates on z axis (zoom out)
Other Keys
- o,O brings everything to starting position
- F1 removes/shows the lines
- F2 rotates/stops the cube in x,y,z direction
Mouse
LeftMouseDown
translates cube in x and y direction (up/down,left/right) - Mouse wheel translates cube in +/- z direction (zoom in / zoom out)
Code
using System;
using System.Collections.Generic;
using System.Text;
using Tao.OpenGl;
using Tao.FreeGlut;
namespace OpenGLOneWindow6Views
{
sealed partial class OpenGLOneWindow6Views
{
static float X = 0.0f;
static float Y = 0.0f;
static float Z = 0.0f;
static float rotX = 0.0f;
static float rotY = 0.0f;
static float rotZ = 0.0f;
static float rotLx = 0.0f;
static float rotLy = 0.0f;
static float rotLz = 0.0f;
static bool lines = true;
static bool rotation = false;
static int old_x, old_y;
static int mousePressed;
static void text(string c)
{
for (int i = 0; i < c.Length; i++)
{
Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_TIMES_ROMAN_24, c[i]);
}
}
static void draw()
{
int width = Glut.glutGet(Glut.GLUT_WINDOW_WIDTH);
int height = Glut.glutGet(Glut.GLUT_WINDOW_HEIGHT);
width = (width + 1) / 3;
height = (height + 1) / 2;
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glEnable(Gl.GL_SCISSOR_TEST);
Gl.glViewport(0, height, width, height);
Gl.glScissor(0, height, width, height);
setWindow(width, height);
Glu.gluLookAt(0.0f , 0.0f , 15.0f , 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f);
drawCube();
Gl.glRasterPos3f(-15, 19, -15);
text("Front");
Gl.glViewport(0, 0, width, height);
Gl.glScissor(0, 0, width, height);
setWindow(width, height);
Glu.gluLookAt(0.0f, 0.0f , -15.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
drawCube();
Gl.glRasterPos3f(15.0f , 19.0f , 15.0f);
text("Back");
Gl.glViewport(width, height, width, height);
Gl.glScissor(width, height, width, height);
setWindow(width, height);
Glu.gluLookAt(15.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
drawCube();
Gl.glRasterPos3f(-15.0f, 19.0f, 15.0f);
text("Right");
Gl.glViewport(width, 0, width, height);
Gl.glScissor(width, 0, width, height);
setWindow(width, height);
Glu.gluLookAt(-15.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
drawCube();
Gl.glRasterPos3f(15.0f, 19.0f, -15.0f);
text("Left");
Gl.glViewport(2 * width, height, width, height);
Gl.glScissor(2 * width, height, width, height);
setWindow(width, height);
Glu.gluLookAt(0.0f , 15.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f);
drawCube();
Gl.glRasterPos3f(-15.0f, -15.0f, -19.0f);
text("Up");
Gl.glViewport(2 * width, 0, width, height);
Gl.glScissor(2 * width, 0, width, height);
setWindow(width, height);
Glu.gluLookAt(0.0f, -15.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f);
drawCube();
Gl.glRasterPos3f(15.0f, 15.0f, -19.0f);
text("Bottom");
Gl.glDisable(Gl.GL_SCISSOR_TEST);
Glut.glutSwapBuffers();
}
static void setWindow(float width, float height)
{
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Glu.gluPerspective(75.0f, (float)width /
(float)height, 0.10f, 500.0f);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
}
static void drawCube()
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glPushMatrix();
Gl.glRotatef(rotX, 1.0f, 0.0f, 0.0f);
Gl.glRotatef(rotY, 0.0f, 1.0f, 0.0f);
Gl.glRotatef(rotZ, 0.0f, 0.0f, 1.0f);
if (rotation)
{
rotX += 0.2f;
rotY += 0.2f;
rotZ += 0.2f;
}
Gl.glTranslatef(X, Y, Z);
if (lines)
{
Gl.glBegin(Gl.GL_LINES);
Gl.glColor3f(0.0f, 1.0f, 0.0f);
Gl.glVertex3f(0f, 0f, 0f);
Gl.glVertex3f(10f, 0f, 0f);
Gl.glColor3f(1.0f, 0.0f, 0.0f);
Gl.glVertex3f(0f, 0f, 0f);
Gl.glVertex3f(0f, 10f, 0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(0f, 0f, 0f);
Gl.glVertex3f(0f, 0f, 10f);
Gl.glEnd();
Gl.glEnable(Gl.GL_LINE_STIPPLE);
Gl.glLineStipple(1, 0x0101);
Gl.glBegin(Gl.GL_LINES);
Gl.glColor3f(0.0f, 1.0f, 0.0f);
Gl.glVertex3f(-10f, 0f, 0f);
Gl.glVertex3f(0f, 0f, 0f);
Gl.glColor3f(1.0f, 0.0f, 0.0f);
Gl.glVertex3f(0f, 0f, 0f);
Gl.glVertex3f(0f, -10f, 0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(0f, 0f, 0f);
Gl.glVertex3f(0f, 0f, -10f);
Gl.glEnd();
Gl.glDisable(Gl.GL_LINE_STIPPLE);
}
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(3.0f, 3.0f, 3.0f);
Gl.glColor3f(1.0f, 0.0f, 0.0f);
Gl.glVertex3f(3.0f, -3.0f, 3.0f);
Gl.glColor3f(0.0f,0.0f, 1.0f);
Gl.glVertex3f(-3.0f, -3.0f, 3.0f);
Gl.glColor3f(1.0f, 0.0f, 0.0f);
Gl.glVertex3f(-3.0f, 3.0f, 3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(0.5f, 0.0f, .0f);
Gl.glVertex3f(3.0f, 3.0f, -3.0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(3.0f, -3.0f, -3.0f);
Gl.glColor3f(0.5f, 0.0f, 0.0f);
Gl.glVertex3f(-3.0f, -3.0f, -3.0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(-3.0f, 3.0f, -3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(0.0f, 1.0f, 0.0f);
Gl.glVertex3f(3.0f, 3.0f, 3.0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(3.0f, 3.0f, -3.0f);
Gl.glColor3f(0.0f, 1.0f, 0.0f);
Gl.glVertex3f(3.0f, -3.0f, -3.0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(3.0f, -3.0f, 3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(-3.0f, 3.0f, 3.0f);
Gl.glColor3f(0.0f, 1.0f, 0.0f);
Gl.glVertex3f(-3.0f, -3.0f, 3.0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(-3.0f, -3.0f, -3.0f);
Gl.glColor3f(0.0f, 1.0f, 0.0f);
Gl.glVertex3f(-3.0f, 3.0f, -3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(3.0f, 3.0f, 3.0f);
Gl.glColor3f(1.0f, 1.0f, 0.0f);
Gl.glVertex3f(3.0f, 3.0f, -3.0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(-3.0f, 3.0f, -3.0f);
Gl.glColor3f(1.0f, 1.0f, 0.0f);
Gl.glVertex3f(-3.0f, 3.0f, 3.0f);
Gl.glEnd();
Gl.glBegin(Gl.GL_POLYGON);
Gl.glColor3f(1.0f, 1.0f, 0.0f);
Gl.glVertex3f(3.0f, -3.0f, 3.0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(3.0f, -3.0f, -3.0f);
Gl.glColor3f(1.0f, 1.0f, 0.0f);
Gl.glVertex3f(-3.0f, -3.0f, -3.0f);
Gl.glColor3f(0.0f, 0.0f, 1.0f);
Gl.glVertex3f(-3.0f, -3.0f, 3.0f);
Gl.glEnd();
Gl.glColor3f(1.0f, 0.5f, 0.5f);
Glut.glutPostRedisplay();
Gl.glPopMatrix();
}
public static void keyboard(byte key, int x, int y)
{
switch (key)
{
case 120:
rotX -= 2.0f;
break;
case 88:
rotX += 2.0f;
break;
case 121:
rotY -= 2.0f;
break;
case 89:
rotY += 2.0f;
break;
case 122:
rotZ -= 2.0f;
break;
case 90:
rotZ += 2.0f;
break;
case 106:
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:
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:
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:
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:
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:
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:
rotX -= 90.0f;
break;
case 66:
rotX += 90.0f;
break;
case 110:
rotY -= 90.0f;
break;
case 78:
rotY += 90.0f;
break;
case 109:
rotZ -= 90.0f;
break;
case 77:
rotZ += 90.0f;
break;
case 111:
case 80:
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();
}
private static void specialKey(int key, int x, int y)
{
switch (key)
{
case Glut.GLUT_KEY_LEFT:
X -= 2.0f;
break;
case Glut.GLUT_KEY_RIGHT:
X += 2.0f;
break;
case Glut.GLUT_KEY_UP:
Y += 2.0f;
break;
case Glut.GLUT_KEY_DOWN:
Y -= 2.0f;
break;
case Glut.GLUT_KEY_PAGE_UP:
Z -= 2.0f;
break;
case Glut.GLUT_KEY_PAGE_DOWN:
Z += 2.0f;
break;
case Glut.GLUT_KEY_F1:
lines = !lines;
break;
case Glut.GLUT_KEY_F2:
rotation = !rotation;
break;
default:
break;
}
Glut.glutPostRedisplay();
}
static void processMouseActiveMotion(int button, int state, int x, int y)
{
mousePressed = button;
old_x = x;
old_y = y;
}
static void processMouse(int x, int y)
{
if ((mousePressed == 0))
{
X = (x - old_x) / 15;
Y = -(y - old_y) / 15;
}
Glut.glutPostRedisplay();
}
static void processMouseWheel(int wheel, int direction, int x, int y)
{
Z += direction;
Glut.glutPostRedisplay();
}
static void init()
{
Gl.glShadeModel(Gl.GL_SMOOTH);
Gl.glClearColor(0, 0, 0, 1.0f);
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glClearDepth(1.0f);
Gl.glEnable(Gl.GL_DEPTH_TEST);
Gl.glDepthFunc(Gl.GL_LEQUAL);
Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);
Gl.glDisable(Gl.GL_CULL_FACE);
}
static void reshape(int w, int h)
{
Gl.glClearColor(0, 0, 0, 0.0f);
Gl.glViewport(0, 0, w, h);
Gl.glMatrixMode(Gl.GL_PROJECTION);
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);
}
static void Main(string[] args)
{
Glut.glutInit();
Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_RGB);
Glut.glutInitWindowSize(600, 600);
Glut.glutCreateWindow("OpenGL Multiple View");
init();
Glut.glutReshapeFunc(reshape);
Glut.glutDisplayFunc(draw);
Glut.glutKeyboardFunc(new Glut.KeyboardCallback(keyboard));
Glut.glutSpecialFunc(new Glut.SpecialCallback(specialKey));
Glut.glutMouseFunc(new Glut.MouseCallback
(processMouseActiveMotion));
Glut.glutMotionFunc(new Glut.MotionCallback
(processMouse));
Glut.glutMouseWheelFunc(new Glut.MouseWheelCallback
(processMouseWheel));
Glut.glutMainLoop();
}
}
}