I want to draw a cylinder using gluQuadric and gluCylinder.
This cylinder shall be textured.
My draw code is the following:
pTexture->Enable();
pTexture->Bind();
glPushMatrix();
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
gluQuadricOrientation(quadric, GLU_OUTSIDE);
gluQuadricNormals(quadric, true);
gluQuadricTexture(quadric, true);
gluCylinder(quadric, getRadius(), getRadius(), getHeight(), 16, 1);
glPopMatrix();
pTexture->Unbind();
pTexture->Disable();
My problem with this is now, that the texture is rotated 90 degrees. How can I rotate the uv-mapping of the quadric?
The texture is used in other places and thus cannot be edited.
In addition to the more widely used GL_MODELVIEW and GL_PROJECTION matrix stacks, there is also a GL_TEXTURE matrix stack that can be used to apply transformations to texture coordinates. For example, this will rotate the texture coordinates by 90 degrees:
glMatrixMode(GL_TEXTURE);
glRotatef(90.0f, 0.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
Since texture coordinates are normally in a [0.0, 1.0] x [0.0, 1.0] unit square, using only this might have undesired side effects. The rotation is counter-clockwise around the origin, so our unit square will be rotated to a square with an extent of [-1.0, 0.0] x [0.0, 1.0]. So in addition to the rotation, the square was shifted by (0.0, -1.0). This is harmless if the wrap mode is GL_REPEAT, but would bad when using a wrap mode like GL_CLAMP_TO_EDGE. We can correct for this by applying a translation in the opposite direction after the rotation (remember that the transformation specified last is the one applied first):
glMatrixMode(GL_TEXTURE);
glTranslatef(1.0f, 0.0f, 0.0f);
glRotatef(90.0f, 0.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
Also, depending on what orientation your image is, you may have to rotate by -90 degrees instead. In this case, the unit square with extent [0.0, 1.0] x [0.0, 1.0] will be rotated into a square with extent [0.0, 1.0] x [-1.0, 0.0]. Applying the same type of corrective translation for this case, we end up with:
glMatrixMode(GL_TEXTURE);
glTranslatef(0.0f, 1.0f, 0.0f);
glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
Related
The following is code (taken from http://www.glprogramming.com/red/chapter03.html) regarding how to draw a robot's arm and shoulder and rotating them by some user input:
glPushMatrix();
glTranslatef (-1.0, 0.0, 0.0);
glRotatef ((GLfloat) shoulder, 0.0, 0.0, 1.0);
glTranslatef (1.0, 0.0, 0.0);
glPushMatrix();
glScalef (2.0, 0.4, 1.0);
glutWireCube (1.0);
glPopMatrix();
glTranslatef (1.0, 0.0, 0.0);
glRotatef ((GLfloat) elbow, 0.0, 0.0, 1.0);
glTranslatef (1.0, 0.0, 0.0);
glPushMatrix();
glScalef (2.0, 0.4, 1.0);
glutWireCube (1.0);
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
I understand the code for drawing the shoulder and rotating it. For the shoulder: first we translate it one unit back along the x-axis so that when we do the rotation, it rotates along the origin as a pivot. Then we translate it back (forward one unit on the x-axis). This transformation will be applied to the cube that has been scaled.
Now, my question is for the elbow. Why is there a translation forward on the x-axis both before and after the rotate?
Now, my question is for the elbow. Why is there a translation forward on the x-axis both before and after the rotate?
If you want to imagine how the matrix operations change the model, then you need to "read" the operations in the reverse order.
This is, because the current matrix of the matrix stack is multiplied by the matrix which is specified by the new operation and the matrices are stored in column-major order (fixed function pipeline).
Start with the elbow cube
glutWireCube(1.0f);
Scale the elbow
glPushMatrix();
glScalef(2.0f, 0.4f, 1.0f);
glutWireCube(1.0f);
glPopMatrix();
Move it to the right
glTranslatef(1.0f, 0.0f, 0.0f);
Rotate the elbow
glRotatef(45.0f, 0.0f, 0.0f, 1.0f);
Move the rotated elbow to the right
glTranslatef(1.0f, 0.0f, 0.0f);
Draw the shoulder cube
glutWireCube(1.0f);
Scale the shoulder
glPushMatrix();
glScalef(2.0f, 0.4f, 1.0f);
glutWireCube(1.0f);
glPopMatrix();
Move the arm (elbow and shoulder) to the right
glTranslatef(1.0f, 0.0f, 0.0f);
Rotate the arm
glRotatef(-15.0f, 0.0f, 0.0f, 1.0f);
Move the arm to its final position (to the left)
glTranslatef(-1.0f, 0.0f, 0.0f);
My openGL application draws the circle as an oval instead of a circle. My code is:
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, 800, 0.0f, 400, 0.0f, 1.0f);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glColor3f(255.0, 255.0, 255.0);
drawRect(racket_left_x, racket_left_y, racket_width, racket_height);
drawRect(racket_right_x, racket_right_y, racket_width,
racket_height);
glPopMatrix();
// drawBall();
//drawBall2();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
drawBall();
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
How can I fix this?
I've tried changing the glMatrixModes but that doesn't seems to work. Thanks.
The projection matrix transforms all vertex data from the eye coordinates to the clip coordinates.
Then, these clip coordinates are also transformed to the normalized device coordinates (NDC) by dividing with w component of the clip coordinates.
The normalized device coordinates is in range (-1, -1, -1) to (1, 1, 1).
With the orthographic projection, the eye space coordinates are linearly mapped to the NDC.
The orthographic projection can be set up by glOrtho. If you want to set up a projection that allows you to draw in window size scales, then you have to do it like this:
int wndWidth = 800;
int wndHeight = 400;
glOrtho( 0.0, (float)wndWidth, 0.0, (float)wndHeight, -1.0, 1.0 );
If the viewport is rectangular this has to be considerd by mapping the coordinates.
float aspect = (float)widht/height;
glOrtho(-aspect, aspect, -1.0f, 1.0f, -1.0f, 1.0f);
You set up a proper window size projection matrix before you draw the rectangles (drawRect)
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, 800, 0.0f, 400, 0.0f, 1.0f);
.....
drawRect( ..... );
But you "clear" the projection matrix and do not care about the aspect of the view before you draw the circle (drawBall).
Change your code somehow like this:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float aspect = 800.0f/400.0f;
glOrtho(-aspect, aspect, -1.0f, 1.0f, -1.0f, 1.0f);
drawBall();
By the way, while glPushMatrix push an element to the matrix stack, glPopMatrix pop an element from the matrix stack. In OpenGL there is one matrix stack for each matrix mode (See glMatrixMode). The matrix modes are GL_MODELVIEW, GL_PROJECTION, and GL_TEXTURE and all matrix operations, are applied to the matrix stack you have specified by glMatrixMode.
This means the both glPopMatrix instructions at the end of your code snippet should not be there.
This is my source If I build this source without the function I can see only 2 lines. But I want to see the 'z'axis.
So I added the gluLookAt() function but I can see just black screen.
What's wrong with my code? Is the camera's point of view is wrong?
It is created on the MFC dialog box. Please help me.
void CopglDlg::OnTimer(UINT_PTR nIDEvent)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(3.f, 3.f, 3.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
glBegin(GL_LINE_LOOP);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(-1.0, 0.0, 0.0);
glEnd();
glBegin(GL_LINE_LOOP);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glVertex3f(0.0, -1.0, 0.0);
glEnd();
glBegin(GL_LINE_LOOP);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, -1.0);
glEnd();
glFlush();
When in OpenGL a vertex (point) is processed, it gets transformed by the modelview matrix and the projection matrix.
The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The projection matrix transforms from view space to the clip space, and the coordinates in the clip space are transformed to the normalized device coordinates (NDC) in the range (-1, -1, -1) to (1, 1, 1) by dividing with the w component of the clip coordinates. All the geometry which is out of the clip space is clipped and unvisible.
The modelview matrix is a combination of the model matrix and the view matrix.
The view matrix describes the direction and position from which the scene is looked at. The view matrix transforms from the wolrd space to the view (eye) space.
The model matrix defines the location, oriantation and the relative size of a mesh in the scene.
In OpenGL all matrix operations, are applied to the matrix stack you have specified by glMatrixMode.
In your case you did not set up a projection matrix, so the projection matrix is by default the identity matrix. This means the far plane is by default at 1 and every thing what is farer away from your eye position (3.0, 3.0, 3.0) than 1, gets clipped by the far plane and is not visible.
You can either change the view matrix, so that you can see out from the center (Note, if the projection matrix is the identity matrix, then the projection is an orthographic projection, the near plane is at -1 and the far plane at +1, so the area around the eye position is in the clip space):
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f);
Or you set up a projection matrix with a far plane, that is far enough away to include the area where your lines are in (see glOrtho):
glMatrixMode(GL_PROJECTION);
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 10.0 );
glMatrixMode(GL_MODELVIEW);
gluLookAt(3.0f, 3.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
OpenGL only shows you what is inside an unitary cube. Once you moved your camera 3 steps on each direction, your lines does not fit inside this new cube.
In order to see it, I sugest to move your camera near your orign point:
gluLookAt(.5f, .5f, .5f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
Or create a new visualization volume, by stablishing an orthographic projection
I am trying to understand some parts of OpenGL. I have to create a robot, which is made from a few part. At start I want to draw 3 cubes in a row. At first I want to draw a cube in the middle, and after that the rest two.
Can you tell me what I did wrong?
void drawScene(GLFWwindow* window) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
mat4 P=perspective(50.0f*PI/180.0f,aspect,1.0f,50.0f);
mat4 V=lookAt(
vec3(0.0f,0.0f,-15.0f),
vec3(0.0f,0.0f,0.0f),
vec3(0.0f,1.0f,0.0f));
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(value_ptr(P));
glMatrixMode(GL_MODELVIEW);
mat4 M=mat4(1.0f);
glLoadMatrixf(value_ptr(V*M));
glPushMatrix(); //create matrix 1 on the top
Models::cube.drawSolid(); //draw cube on 0,0,0 coords
glTranslatef(3.0, 0.0, 0.0); //apply translation to matrix 1
Models::cube.drawSolid(); //draw cube on 3,0,0 coords
glPopMatrix();
glRotatef(180*PI/180, 1.0, 0.0, 0.0);
glTranslatef(3.0, 0.0, 0.0);
Models::cube.drawSolid();
glfwSwapBuffers(window);
}
And another example which is giving me the same wrong results:
void drawScene(GLFWwindow* window) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
mat4 P=perspective(50.0f*PI/180.0f,aspect,1.0f,50.0f);
mat4 V=lookAt(
vec3(0.0f,0.0f,-15.0f),
vec3(0.0f,0.0f,0.0f),
vec3(0.0f,1.0f,0.0f));
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(value_ptr(P));
glMatrixMode(GL_MODELVIEW);
mat4 M=mat4(1.0f);
glLoadMatrixf(value_ptr(V*M));
glPushMatrix(); //Matrix 1 on the top
glPushMatrix(); //Matrix 2 on the top
Models::cube.drawSolid(); //Draw cube on matrix 2
glTranslatef(3.0, 0.0, 0.0); //Apply translation on matrix 2
glPushMatrix(); //Matrix 3 on the top
Models::cube.drawSolid(); //Draw cube on matrix 3
glPopMatrix(); //Matrix 2 on the top
glPopMatrix(); //Matrix 1 on the top
glRotatef(180*PI/180, 1.0, 0.0, 0.0); //Apply translation on matrix 1
glTranslatef(3.0, 0.0, 0.0); //Apply translation on matrix 1
Models::cube.drawSolid(); //Draw cube on matrix 1
glfwSwapBuffers(window);
}
In both cases I have to translate last cube for 6.0 instead of 3.0. I dont really understand why. It seems to me that after backing to matrix 1 I apply effect on them.
To be clear, I want to do something like this:
Draw Cube in 0,0,0
[]
go to 3,0,0
Draw Cube
[] []
Go back to 0,0,0
Rotate in 180 degrees
Go to -3,0,0
Draw Cube
[] [] []
You want to draw a cube in the center, a second cube translated to the right and a third cube translated to the left (along the X-axis).
This can be done in different ways:
You can draw the cube in the center, go one step to the right and draw the next cube and finally go two steps to the left an draw the third cube:
float step = 3.0f;
Models::cube.drawSolid();
glTranslatef( 1.0f * step, 0.0f, 0.0f );
Models::cube.drawSolid();
glTranslatef( -2.0f * step, 0.0f, 0.0f );
Models::cube.drawSolid();
You can draw the cube in the center and save (push) the model matirx, go one step to the right and draw the next cube and finally restore (pop) the model matrix, go one steps to the left an draw the third cube:
glPushMatrix();
Models::cube.drawSolid();
glTranslatef( 1.0f * step, 0.0f, 0.0f );
Models::cube.drawSolid();
glPopMatrix();
glTranslatef( -1.0f * step, 0.0f, 0.0f );
Models::cube.drawSolid();
Finally what you desided to do.
Draw the cube in the center and save (push) the model matirx, go one step to the right and draw the next cube and finally restore (pop) the model matrix, turn around 180° degrees, go one steps to the right an draw the third cube. But you have to rotate around the up vector, which is (0, 1, 0) in your case, and not around the X-axis:
glPushMatrix();
Models::cube.drawSolid();
glTranslatef( 1.0f * step, 0.0f, 0.0f );
Models::cube.drawSolid();
glPopMatrix();
glRotatef( 180*PI/180, 0.0, 1.0f, 0.0f ); // rotate around the up vector
glTranslatef( 1.0f * step, 0.0f, 0.0f );
Models::cube.drawSolid();
By the way, in your 2nd example you push 3 matrices onto the stack, but you pop only 2 matrices. Each matrix which is put on the stack should also be taken down again. This means the number of glPushMatrix and glPopMatrixshould always be equal. Else you would either stack up without an end, or you would try to take something from the empty stack.
I'm trying to rotate an object (an arrow) which has it's default position as pointing to the right. I've been looking around and I'm using the glLoadIdentity() and glPushMatrix() and glPopMatrix() as a way to only rotate the object in my glBegin function and not the whole scene:
glLoadIdentity();
glPushMatrix();
glRotatef(5, 0.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex2f(xx2-0.01, yy2);
glVertex2f(xx2-0.06, yy2+0.03);
glVertex2f(xx2-0.06, yy2-0.03);
glEnd();
glPopMatrix();
However, it also translates my arrow, instead of only rotating it. Do I need to translate the offset back to it's original position? Or am I doing something wrong?
SOLVED:
glLoadIdentity();
glPushMatrix();
glTranslatef(xx2, yy2, 0);
glRotatef(45, 0.0f, 0.0f, 1.0f);
glTranslatef(-xx2, -yy2, 0);
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex2f(xx2-0.01, yy2);
glVertex2f(xx2-0.06, yy2+0.03);
glVertex2f(xx2-0.06, yy2-0.03);
glEnd();
glPopMatrix();
Need to translate back to center (0, 0, 0), apply the rotation and then back to it's original position (xx2, yy2, 0)
All rotations are around the origin.
So yes, if you want to rotate around some other point, you must translate from that point to the origin, rotate, and then translate back again.
Your code is correct, but you are applying your operations out of order. Specifically, you need to apply the rotation first, then apply the translation.