![]() |
are you ready for a mindfuck? |
|
....::::Menu::::.... ---------------------------...::About::... ...::Articles::... ...::Contact::... ...::Home & News::... ...::Links & Credits::... --------------------------- --------------------------- |
Axisby Elie De BrauwerGoal of this fileThis file is a first step into the third dimension. We create a X, Y and Z axis (both in a different color). We put the command to draw the coordinate system in a separate procedure so it can be included in future projects. This can be usefull for people with few 3d experience in order not to loose their orientation. History of this file
The concept and a first piece of codeNow how will we create such an axis ? Well we will first create three lines (or vectors):
In code this will look like this:
#include <GL/glut.h>
#include <iostream>
using namespace std;
void disp(void);
void drawAxis(void);
int main(int argc,char **argv){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("Axis1");
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(disp);
glutMainLoop();
}
void disp(void){
glClear(GL_COLOR_BUFFER_BIT);
drawAxis();
glutSwapBuffers();
}
void drawAxis(){
glBegin(GL_LINES);
glColor3f(1.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.80,0.0,0.0);
glColor3f(0.0,1.0,0.0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.80,0.0);
glColor3f(0.0,0.0,1.0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.0,0.80);
glEnd();
}
In essence this is nothing but drawing three colored lines in a double buffered window. In this program resize and keyboard handling are not implemented but I assume that if you need them you can find out how to do that by yourself. You can get this piece of code here. The result is shown in the following image:
What a fraud is this, we are expecting three lines and we only got two. Yes I know this is because the blue line is perpendicular on the red and the green line thus also perpendicular on your screen. We might make things a bit more visual by defining a glutIdleFunc() that makes our object rotate around the (1,1,0) vector.
#include <GL/glut.h>
#include <iostream>
#include <cstdlib>
using namespace std;
typedef unsigned char uchar;
void disp(void);
void idle(void);
void drawAxis(void);
void keyb(uchar key, int x, int y);
static float angle=0;
int main(int argc,char **argv){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("Axis2");
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(disp);
glutIdleFunc(idle);
glutKeyboardFunc(keyb);
glutMainLoop();
}
void disp(void){
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glRotatef(angle,1.0,1.0,0.0);
drawAxis();
glutSwapBuffers();
}
void drawAxis(){
/* unmodified */
}
void idle(void){
angle++;
while(angle>360){
angle-=360;
}
glutPostRedisplay();
}
void keyb(uchar k, int x, int y){
if(k == 's'){
glutIdleFunc(NULL);
}else if(k == 'S'){
glutIdleFunc(idle);
}else if(k == 'q'){
exit(0);
}
}
The code is also vailable here. Also some keyboard bindings were added to start and pause
the rotation.
And now the magic (introducing matrix stacks) The length of our vectors is 0.8 this means we still have a space of 0.2 to add
some eye candy. If we add a glutSolidCone with a height of 0.1 we can create an arrow alike look and it does not
only look nice it also introduces some nice new topics like matrix stacks.
void disp(void){
glClear(GL_COLOR_BUFFER_BIT);
drawAxis();
// store the position
glPushMatrix();
// rotate 45 degrees around the Z axis
glRotatef(45,0.0,0.0,1.0);
// move 0.5 in the positive X direction
glTranslatef(0.5,0.0,0.0);
// draw the white teapot.
glColor3f(1.0,1.0,1.0);
glutSolidTeapot(0.1);
// return to the original position
glPopMatrix();
// save the original position
glPushMatrix();
// move 0.5 in the positive X direction
glTranslatef(0.5,0.0,0.0);
// rotate 45 degrees around the Z axis
glRotatef(45,0.0,0.0,1.0);
// make it a yellow one
glColor3f(1.0,1.0,0.0);
// this is a teapot which is FIRST rotated
// and AFTER that translated.
glutSolidTeapot(0.1);
glPopMatrix();
glutSwapBuffers();
}
You can also get the source here and like we all know a picture sometimes says more than a thousand words:
In the previous example you also saw the usage of glPopMatrix() and glPushMatrix(). glPushMatrix saves the current location in the matrix stack and glPopMatrix() pops it from the matrix stack and returns to the last location. For example: (current center is (0,0)) glPushMatrix(); glRotatef(45,0.0,0.0,1.0); glTranslatef(1.0,0.0,0.0); // we are currently at (cos(45),sin(45)) // we draw something here glPopMatrix(); // current center is (0,0) // we store it again glPushMatrix(); glRotatef(45,0.0,0.0,1.0); glTranslatef(-1.0,0.0,0.0); // we are currently at (-cos(45),-sin(45)) // we draw something here glPopMatrix(); // and now we are back at (0,0). glPushMatrix(); glRotatef(45,0.0,0.0,1.0); // everything you draw here will be 45 degrees rotated // around the Z axis glPopMatrix(); // everything you draw here will not be rotated. Putting it all togetherIn the code below you and on the first snapshot you can see how the cones are transformed to their place. You can also see that the first call to glRotatef() is carried the entire program, so the cones stay on their place. To undo this we could do a call to glLoadIdentity(), this is illustrated in the second snapshot if we do a glLoadIdentity() before we draw the cones we can let all the axis rotate but the cones will remain in place. Since this is done before the glPushMatrix() all of the cones remain in place if it were done after the glPushMatrix() only the red cone would remain where it was first drawn (see snapshot 6). ![]()
#include <GL/glut.h>
#include <iostream>
#include <cstdlib>
using namespace std;
typedef unsigned char uchar;
void disp(void);
void idle(void);
void drawAxis(void);
void keyb(uchar key, int x, int y);
static float angle=0;
int main(int argc,char **argv){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("Axis4");
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(disp);
glutIdleFunc(idle);
glutKeyboardFunc(keyb);
glutMainLoop();
}
void disp(void){
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glRotatef(angle,1.0,1.0,0.0);
drawAxis();
glutSwapBuffers();
}
void drawAxis(){
glBegin(GL_LINES);
glColor3f(1.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.80,0.0,0.0);
glColor3f(0.0,1.0,0.0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.80,0.0);
glColor3f(0.0,0.0,1.0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.0,0.80);
glEnd();
//---------> glLoadIdentity(); for snapshot 5
glPushMatrix();
//---------> glLoadIdentity(); for snapshot 6
glColor3f(1.0,0.0,0.0);
glTranslatef(0.80,0.0,0.0);
glRotatef(90,0.0,1.0,0.0);
glutSolidCone(0.05,0.1,10,10);
glPopMatrix();
glPushMatrix();
glColor3f(0.0,1.0,0.0);
glTranslatef(0.0,0.80,0.0);
glRotatef(-90,1.0,0.0,0.0);
glutSolidCone(0.05,0.1,10,10);
glPopMatrix();
glPushMatrix();
glColor3f(0.0,0.0,1.0);
glTranslatef(0.0,0.0,0.80);
glutSolidCone(0.05,0.1,10,10);
glPopMatrix();
}
void idle(void){
angle++;
while(angle>360){
angle-=360;
}
glutPostRedisplay();
}
void keyb(uchar k, int x, int y){
if(k == 's'){
glutIdleFunc(NULL);
}else if(k == 'S'){
glutIdleFunc(idle);
}else if(k == 'q'){
exit(0);
}
}
You can download the code here |