I'm writing an OpenGl program about a cone rotating in 3D space and I have a txt with datas of the angles and the axes around whom the rotation takes place.
The problem is that OpenGL requires the total rotation angle while in the file I have the increment in angle for every time step.
here my code :
GLdouble matrice1 [] {1.,0,0,0,0,1.,0,0,0,0,1.,0,0,0,0,1.};
GLdouble * matrice = matrice1;
void displayCone(void){
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //
// set matrix mode
glMatrixMode(GL_MODELVIEW);
// clear model view matrix
glLoadIdentity();
//gluLookAt(3.0, 3.0, 3.0-4.5, 0.0, 0.0,-4.5,0,0,1);
gluLookAt(3.0, 3.0, 3.0, 0.0, 0.0,0.0,0,0,1);
glBegin(GL_LINES);
glColor3f (1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(2.0, 0.0, 0.0);
glColor3f (0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 2.0, 0.0);
glColor3f (0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 2.0);
glEnd();
//glLoadMatrixd(matrice);
glColor3f(0.8, 0.2, 0.1);
glMultMatrixd(matrice); // <------ ** me trying to implement the previous rotation before //rotating of the increment angle xRotated
glRotated(xRotated,a1,a2,a3); // <----- **here the rotation**
glGetDoublev(GL_MODELVIEW, matrice); // <----- ** me trying to save the total rotation //matrix **
glTranslatef(0.0, 0.0, height);
glutSolidCone(base,height,slices,stacks);
glPushMatrix();
glTranslatef(0.0, 0.0, height-0.1);
glutSolidCylinder(0.07,height_c,slices,stacks);
glPopMatrix();
glPushMatrix();
glScalef(1.0,1.0,-1.0);
//glTranslatef(0.0, 0.0, 2*height);
//glPopMatrix();
//glPushMatrix();
glutSolidCone(base,height,slices,stacks);
// Flush buffers to screen
glPopMatrix();
glFlush();
}
What I'm trying to do here with glGetDoublevand glMultMatrixdis to save the precedent Rotation Angle but this doesn't work. Does anyone know how to save the precedent rotation matrix in order to get the total rotation and not the RotationAngle of the increment angle ?
For one, that code you have there is using the old and busted fixed function, legacy API that's been out of fashion for well over 15 years.
More to the point, you can use a proper 3D graphics math library (GLM, Eigen, linmath.h) to manage a rotation matrix and apply it to the OpenGL transformation matrix stack using glMultMatrix instead of using multiple calls to glRotate. Or manage the whole transformation matrix yourself and just load it with glLoadMatrix.
And when you do your own matrix management, it's only a small step to ditch the fixed function pipeline and use shaders, where you pass the matrix as so called uniform values.
Related
I am trying to draw the 3D axis. I have also a cone which is rotating around its vertex and I would want the axis starting from there.
Here I have my function to draw the cone and I wrote the functions to draw the axis after gluLookAt:
GLfloat xRotated, yRotated, zRotated;
// Cone
GLdouble base=0.5;
GLdouble height=1.3;
GLint slices =20;
GLint stacks =20;
std::vector<std::array<GLfloat, 3>> data;
void displayCone(void)
{
// set matrix mode
glMatrixMode(GL_MODELVIEW);
// clear model view matrix
glLoadIdentity();
// multiply view matrix to current matrix
gluLookAt(0,2.,0.,0.,0.,-4.5,0,1,0); // <----------------------- add
// ******
glPushMatrix();
glLoadIdentity();
glTranslatef(0.0, 0.0, -4.5);
glBegin(GL_LINES);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(2.0, 0.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 2.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 2.0);
glEnd();
glPopMatrix();
// ******
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT);
// traslate the draw by z = -4.0
// Note this when you decrease z like -8.0 the drawing will looks far , or smaller.
glTranslatef(0.0,0.0,-4.5);
// Red color used to draw.
glColor3f(0.8, 0.2, 0.1);
// changing in transformation matrix.
// rotation about X axis
glRotatef(xRotated,1.0,0.0,0.0);
// rotation about Y axis
glRotatef(yRotated,0.0,1.0,0.0);
// rotation about Z axis
glRotatef(zRotated,0.0,0.0,1.0);
// scaling transfomation
glScalef(1.0,1.0,1.0);
// built-in (glut library) function , draw you a Cone.
// move the peak of the cone to the origin
glTranslatef(0.0, 0.0, -height);
glutSolidCone(base,height,slices,stacks);
// Flush buffers to screen
// gluLookAt(3,3,3,0,0,-4.5,0,1,0); <----------------------- delete
glFlush();
// sawp buffers called because we are using double buffering
// glutSwapBuffers();
}
I thought to draw the 3D axis in this way but I am making some mistakes.
What am I missing?
The lies are cleared immediately after they've been drawn by glClear. Do glClear(GL_COLOR_BUFFER_BIT); at the begin of displayCone:
If you want to draw the lines in view space, then the view matrix has to be set. Remove glLoadIdentity before drawing the lines.
e.g.
void displayCone(void)
{
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT); // <---- add
// set matrix mode
glMatrixMode(GL_MODELVIEW);
// clear model view matrix
glLoadIdentity();
// multiply view matrix to current matrix
gluLookAt(3.0, 3.0, 3.0-4.5, 0.0, 0.0,-4.5,0,1,0);
// ******
glPushMatrix();
// glLoadIdentity(); <---- delete
glTranslatef(0.0, 0.0, -4.5);
glBegin(GL_LINES);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(2.0, 0.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 2.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 2.0);
glEnd();
glPopMatrix();
// clear the drawing buffer.
// glClear(GL_COLOR_BUFFER_BIT); // <---- delete
// traslate the draw by z = -4.0
// Note this when you decrease z like -8.0 the drawing will looks far , or smaller.
glTranslatef(0.0,0.0,-4.5);
// Red color used to draw.
glColor3f(0.8, 0.2, 0.1);
// changing in transformation matrix.
// rotation about X axis
glRotatef(xRotated,1.0,0.0,0.0);
// rotation about Y axis
glRotatef(yRotated,0.0,1.0,0.0);
// rotation about Z axis
glRotatef(zRotated,0.0,0.0,1.0);
// scaling transfomation
glScalef(1.0,1.0,1.0);
// built-in (glut library) function , draw you a Cone.
// move the peak of the cone to the origin
glTranslatef(0.0, 0.0, -height);
glutSolidCone(base,height,slices,stacks);
// Flush buffers to screen
// gluLookAt(3,3,3,0,0,-4.5,0,1,0); <----------------------- delete
glFlush();
// sawp buffers called because we are using double buffering
// glutSwapBuffers();
}
I'm facing a problem in my opengl code
I'm trying to build a house, and rotate it 360°, for simplicity let's assume the house has the front wall with window and dor, and a back wall.
I'm using DEPTH_BUFFER not to see the back wall when viewing the front wall, and the other way around, but when I rotate the house the door and window start to shake and get distorced.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glLoadIdentity();
gluLookAt(0.0, 0.0, 40.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(angle, 0.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST);
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(8.0, 3.0, 0.0);
glVertex3f(8.0, -10.0, 0.0);
glVertex3f(1.0, -10.0, 0.0);
glVertex3f(1.0, 3.0, 0.0);
glEnd();
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(-9.0, -4.0, 0.0);
glVertex3f(-9.0, 3.0, 0.0);
glVertex3f(-2.0, 3.0, 0.0);
glVertex3f(-2.0, -4.0, 0.0);
glEnd();
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(10.0, -10.0, -20.0);
glVertex3f(-10.0, -10.0, -20.0);
glVertex3f(-10.0, 10.0, -20.0);
glVertex3f(10.0, 10.0, -20.0);
glEnd();
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(10.0, -10.0, 0.0);
glVertex3f(10.0, 10.0, 0.0);
glVertex3f(-10.0, 10.0, 0.0);
glVertex3f(-10.0, -10.0, 0.0);
glEnd();
glDisable(GL_DEPTH_TEST);
glutSwapBuffers();
The issue is called Z-fighting. This is caused, because depth of the "door", "window" and "wall" are equal. The vertiex coordinates are transformed by the model view matrix and projection matrix and interpolated for each fragment which is covered by the polygon. This results in inaccuracies of the final z coordinate (depth).
Enable the polygon fill offset (glPolygonOffset) by before drawing the walls, to solve the issue:
glEnable(GL_DEPTH_TEST);
glDisable( GL_POLYGON_OFFSET_FILL );
// draw door and window
// ...
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( 1, 1 );
// draw walls
// ...
Polygon fill offset manipulates the depth of a fragment by a minimum amount. This causes that the depth of the "walls" is different to the depth of the "window" and "door", even after the transformation by the model view and projection matrix.
Since an offset is added to the depth of the "wall", the "wall" is always behind the window and the door, independent of the point of view.
OK, I have made simple rectangular using OpenGL, and it looks pretty simple
glNormal3f(0.0f, 0.0f, 0.0f);
glVertex3f(-0.0, 2.0, 0.0);
glVertex3f(1.0, 2.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
and small as well. So my Q. is how can I make this twice as bigger using one single line of code or how can I make lets say only X axis values to be doubled. I know it's possible, but I have no idea what function to search for. Thanks in advance.
Well, you can move the camera closer by using glTranslate or scale the scene using glScale. But frankly?
x *= 2.0;
y *= 2.0;
glVertex3f(-0.0, y*2.0, 0.0);
glVertex3f(x*1.0, y*2.0, 0.0);
glVertex3f(x*1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
... this is the way to go.
I made a fancy shape with OpenGL and I draw that shape this function:
drawShape(const Point & center, char radius, int points, int rotation)
Inside the function I have code that tells OpenGL where the vertexes are:
glBegin(GL_LINE_LOOP);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(center.getX() + 0.0, center.getY() + 1.0);
// more vertices
glEnd();
Now when I add glRotatef(rotation, 0.0, 0.0, 1.0), I would like just this shape that I have drawn to rotate on the screen. However, if I add it above glBegin() it rotates everything in the window. If I include all the code between glPushMatrix() and glPopMatrix() rotates the object, but around the center of the window. How can I rotate just the object that I have drawn?
You're doing OpenGL's job by having center.getX and such added to the values.
What you want is this:
glPushMatrix();
glTranslatef(center.getX(), center.getY(), 0.0f);
glRotatef(rotation, 0.0, 0.0, 1.0);
glBegin(GL_LINE_LOOP);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(0.0, 1.0);
// more vertices
glEnd();
glPopMatrix();
You can probably apply the radius by using a glScale matrix and assuming a radius of 1.0 in your glVertex calls.
Is there a simple way to have isometric projection?
I mean the true isometric projection, not the general orthogonal projection.
(Isometric projection happens only when projections of unit X, Y and Z vectors are equally long and angles between them are exactly 120 degrees.)
Try using gluLookAt
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
/* use this length so that camera is 1 unit away from origin */
double dist = sqrt(1 / 3.0);
gluLookAt(dist, dist, dist, /* position of camera */
0.0, 0.0, 0.0, /* where camera is pointing at */
0.0, 1.0, 0.0); /* which direction is up */
glMatrixMode(GL_MODELVIEW);
glBegin(GL_LINES);
glColor3d(1.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(1.0, 0.0, 0.0);
glColor3d(0.0, 1.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 1.0, 0.0);
glColor3d(0.0, 0.0, 1.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 1.0);
glEnd();
glFlush();
Results in
We can draw a cube to check that parallel lines are indeed parallel
glPushMatrix();
glTranslated(0.5, 0.5, 0.5);
glColor3d(0.5, 0.5, 0.5);
glutWireCube(1);
glPopMatrix();
An isometric projection is just a matter of using an orthographic projection with a specific rotation angle.
You should be able to choose any of the 8 potential orientations, with a orthographic projection, and get a perfect isometric view of your model. Just follow the math in your referenced Wiki article for setting up the view matrix, and do an orthographic projection for your projection matrix, and you're all set.
Maybe I'm not quite grokking the math correctly, but couldn't you just position your camera as it explains in that Wikipedia link and use a standard orthogonal projection?
Even if it's not the same, the projection stack is entirely up to you.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// your isometric matrix here (see math on Wikipedia)
glMatrixMode(GL_MODELVIEW);
If you do not want to use GLU, here is bare bones using glOrtho
void gl_enter_2_5d_mode (void)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
double scale = 50;
glOrtho(-scale,
scale,
-scale * 0.7,
scale * 0.7,
-scale,
scale);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glRotatef(35.264f, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
}
void gl_leave_2_5d_mode (void)
{
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
then draw a cube in it
void cube (double size)
{
glBegin(GL_QUADS);
glVertex3f(size,size,size);
glVertex3f(-size,size,size);
glVertex3f(-size,-size,size);
glVertex3f(size,-size,size);
glVertex3f(size,size,-size);
glVertex3f(-size,size,-size);
glVertex3f(-size,-size,-size);
glVertex3f(size,-size,-size);
glVertex3f(size,size,size);
glVertex3f(size,-size,size);
glVertex3f(size,-size,-size);
glVertex3f(size,size,-size);
glVertex3f(-size,size,size);
glVertex3f(-size,-size,size);
glVertex3f(-size,-size,-size);
glVertex3f(-size,size,-size);
glVertex3f(size,size,size);
glVertex3f(-size,size,size);
glVertex3f(-size,size,-size);
glVertex3f(size,size,-size);
glVertex3f(size,-size,size);
glVertex3f(-size,-size,size);
glVertex3f(-size,-size,-size);
glVertex3f(size,-size,-size);
glEnd();
}
void test (void)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBindTexture(GL_TEXTURE_2D, 0);
cube(1.0);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
}
and call something like this
gl_enter_2_5d_mode()
test()
gl_leave_2_5d_mode()
should you want to toggle between 2d and 2.5d (so you can draw your UI) then I have similar functions to enter and leave 2d mode e.g.
void gl_init_2d_mode (void)
{
/*
* Enable Texture Mapping
*/
glEnable(GL_TEXTURE_2D);
/*
* Enable alpha blending for sprites
*/
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/*
* Setup our viewport
*/
glViewport(0, 0, game.video_pix_width,
game.video_pix_height);
/*
* Make sure we're changing the model view and not the projection
*/
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
/*
* Reset the view
*/
glLoadIdentity();
gl_init_fbo();
}
void gl_enter_2d_mode (void)
{
/*
* Change to the projection matrix and set our viewing volume.
*/
glMatrixMode(GL_PROJECTION);
glPushMatrix();
/*
* Reset the view
*/
glLoadIdentity();
/*
* 2D projection
*/
glOrtho(0,
game.video_gl_width, game.video_gl_height,
0, -1200.0, 1200.0);
/*
* Make sure we're changing the model view and not the projection
*/
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
/*
* Reset the view
*/
glLoadIdentity();
}