![]() |
are you ready for a mindfuck? |
|
....::::Menu::::.... ---------------------------...::About::... ...::Articles::... ...::Contact::... ...::Home & News::... ...::Links & Credits::... --------------------------- --------------------------- |
coilby Elie De BrauwerGoal of this fileIn this file we go another little step further and we will draw some coil alike structures. This can be seen as an extension of the circle and the spiral programs into the third dimension. We will also implement the axis we saw in a a previous article. And we will make some variations on this theme. History of this file
First contactWithin our current project we are starting to do some object oriented C++ programming so I assume you already have some knowledge about it, if that is not the case I strongly suggest some googling but on the otherhand the syntax is not that hard and you should be able to follow this (easy example). Let us first take a look at our main program. This basicly consists of nothing. We open a window, define a Coil object, define an idlefunc and define a displayfunc.The only difficult thing is drawing the axis which is explained in an older text so nothing new appears here. Now I present you the code:
#include <GL/glut.h>
#include <iostream>
#include "coil.h"
using namespace std;
void disp(void);
void idle(void);
void drawAxis(void);
static Coil *coil;
int main(int argc,char **argv){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("Coil");
glClearColor(0.0,0.0,0.0,0.0);
coil = new Coil(0.2,0.1,10,90);
glutDisplayFunc(disp);
glutIdleFunc(idle);
glutMainLoop();
}
void disp(void){
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glColor3f(1.0,1.0,1.0);
coil->draw();
drawAxis();
glPopMatrix();
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();
glPushMatrix();
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){
coil->setAngle(coil->getAngle()+1);
glutPostRedisplay();
}
The code is also available. Now what is missing ? Everything that has anything to do with the coil we are willing to draw. Please note that the glPushMatrix() and glPopMatrix() are here so we don't need to call a glLoadIdentity() in the Coil::draw(); method. Drawing the coil & parametric curves
In the previous code snippet we have seen we need a coil.h file which contains
the definition of the coil. In that file we must have a constructor,
a draw method,a getAngle method and a setAngle method.
Internally some other functions are implemented which are not used from the
main program. Now how do we define, do we draw this coil ?
void Coil::draw(void) const{
double angle;
// create zstart to make it symmetrical around the origin
double zstart = -(rounds*dz)/2.0;
double z;
glRotatef(this->angle,0.0,1.0,0.0);
glBegin(GL_LINE_STRIP);
for(int i = 0; i<rounds;i++){
for(int j =0;j<NUM_LINES_A_LOOP;j++){
// M_PI defined in cmath.h
angle = j*2.0*M_PI/NUM_LINES_A_LOOP;
z = zstart + i*dz + dz*angle/(2.0*M_PI);
// we use vertex3f since we are currently in working in 3d
glVertex3f(radius*cos(angle),radius*sin(angle),z);
}
}
glEnd();
}
The source of coil.h Variation on this themeFor those with an interest in there parametric curves try to modify the code so the following results are shown:
Projection transformationOpenGL support by default 2 projection transformations, the Ortographic projection and the Perspective projection. The first is the default and is used for blueprints and second is used for more realistic visualisation. Ortographic projection
Now take a closer look at the two snapshots of the result. The blue axis is the Z-axis.
You notice that when you look in the direction of the Z-axis (snapshot2) you see no coil, you only
see a circle. If you would try this in real life you would see more than just a circle. This is
because in OpenGL you are by default using Ortographic projection. In if an object is right
behind another object (like our rotated coil) you will only see the front this is because everything is
projected perpendicular on the near clipping plane. The viewing volume is a rectangular parallelepiped.
The size of the object will remains constant and is not dependant on the distance of the camera.
If you see a large tree far far away it appears smaller than a small person standing near to you. In real
life (looking) you don't use ortographic projection. Ortographic projection is used in CAD application like
AutoCAD or QCAD, it is used for creating blueprints and maps.
Perspective projectionThe viewing volume in perspective projection is a piramid with the eye at the top. OpenGL offers two ways of manipulating this viewing plane. The first is a call to glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far). The meaning of these values will become clear if you take a look at the image below. The viewing volume is the volume between the black,red and blue lines.
A second method of defining the perspective projection is by using a calls to gluPespective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far). The fovy parameter is the viewing angle in the YZ plane, aspect is the aspect ration of the frustum, this is the width of the clipping plane divided by the height of the clipping plane. Again for more information look at the image below.
I agree in the beginning these values may look a bit strange and 'how do I know how big that angle has to be ?'.
Don't worry, just play a bit with the parameters until you get them right. It might be a little awkward in the
beginning. A note on errors
Please note that all values for the near and far clipping plane are relative to the eye coordinates. And thus can not be negative
values. If you should supply a negative value for you far or near clipping plane this will result in an error. But OpenGL does not
abort when an error occurs, OpenGL is very stubborn and silently continues hoping everything will go away. That makes it a little
hard debugging at first sight that's why there exists something like GLenum glGetError(void). This function call
returns the value of the error flag. At this point there are three values that might be of any interest to you:
GL_INVALID_VALUE occurs when one of your (near of far) clipping planes are negative, GL_STACK_OVERFLOW and
GL_STACK_UNDERFLOW occur when you overflow or underflow your matrix stacks.
void handleErr(void){
static GLenum errCode;
errCode = glGetError();
if(errCode != GL_NO_ERROR){
cout << gluErrorString(errCode) << endl;;
}
}
It is recommended to check for errors at least once every display. This also happened in the next coil version coil2.cpp which also applies the perspective projection, see further. Applying Perspective projectionSince our project now usese ortographic projection (just like any other project this far) we will give it a try in Perspective mode. To obtain the results below we added a reshape callback, in that callback we modify the GL_PROJECTION matrix, we multiple this matrix with the perspective projection matrix that is created by using the gluPerspective call. After that we switch back to the GL_MODELVIEW matrix and call a gluLookAt to define the eye coordinates. The code we added is the following reshape function:
void reshape(int x,int y){
glViewport(0,0,x,y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50,(x*1.0)/(y*1.0),1,6);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(2.0,0,0,0,0,0,0,1,0);
}
And these are the results:
We don't see a circle anymore but a spiral. Take also a look at the cones. In the orthographic projection they looked like triangles. But if you look at the bottom of the cones now you can see they are more round now.
In the orthographic projection we saw a periodic function new we see a symmetric figure (symmetric around the origin).
This image give a 3 dimensional impression.Here you can actually see that objects close to the eye coordinates are drawn larger than objects that are further away. The final sourcecode can be downloaded here: Coil2.cpp and the class here: coil.h. |