Changing the rotation point along with object moving in OpenGL? - c++

I'm trying to build a hammer weapon that can move along with the X-axis and rotate around Z-axis. Right now I have a problem with the hammer. The hammer can rotate around Z-axis on a fixed pivot point, but when I move the hammer to a new position then I rotate the hammer, the hammer still rotates around the old pivot point.
I have tried to add the distance I moved to the old pivot point, but it does not work. How could I solve this problem? Thanks for any helping!
Here is my code:
glPushMatrix();
//the rotation angle of Z-axis
glTranslatef(0.5f,1.0f,-1.0f); //Back to original point
glRotatef(zr, 0.0f, 0.0f, 1.0f); //Rotating
glTranslatef(-0.5f,-1.0f,1.0f); //The rotation piovt point
//build weapon base
//the moving distant on X-axis
glPushMatrix();
glColor3f(1, 0, 0);
glTranslatef(0.5f+xr, 1.0f, -1.0f);
glRotatef(-90.0, 1.0, 0.0, 0.0);
quadratic = gluNewQuadric();
gluCylinder(quadratic, 0.2f, 0.2f, 2.0f, 50, 50);
glPopMatrix();
//build hammer
glPushMatrix();
glTranslatef(0.0+xr, 3.0f, -1.0f);
glRotatef(90.0, 0.0, 1.0, 0.0);
glColor3f(0, 1, 0);
quadratic = gluNewQuadric();
gluCylinder(quadratic, 0.2f, 0.2f, 1.0f, 50, 50);
glPopMatrix();
glPopMatrix();

You have to move the pivot, too:
float pivot_x = 0.5f + xr;
glTranslatef(pivot_x, 1.0f, -1.0f); //Back to original point
glRotatef(zr, 0.0f, 0.0f, 1.0f); //Rotating
glTranslatef(-pivot_x, -1.0f, 1.0f); //The rotation piovt point

Related

Why OpenGL cut off polygons (even if this settings is disabled)?

I read similar suggested questions and their solutions, but could not find an answer.
I'm trying to draw a scene with an isometric view in OpenGL.
Draw func:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
glPopMatrix();
In the end, I get this result. The camera does have an isometric projection, but for some reason polygons are clipped.
If I add glTranslatef(-0.8f, 0, -0.8f) before drawing the quad, the result is as follows:
The problem is that I don't apply any optimization to OpenGL render. But why do polygons have to be cut off?
The polygons are clipped by the near or far plane of the viewing volume.
When you do not set a projection matrix, then view space, clip space and normalized device space are the same. The normalized device space is a unique cube with the left, bottom, near of (-1, -1, -1) and right, top, far of (1, 1, 1). All the geometry which is not inside this cube is clipped.
Actually you draw a quad with a side length of 1. One vertex of the quad is at the origin of the view (0, 0, 0). The quad is rotated around the origin by glRotate. Since the length of the diagonal of the quad is sqrt(2.0), one vertex of the rotated quad is clipped by either the near plane or the far plane.
If you construct and rotate a quad whose center is (0, 0 ,0), it will not be clipped, because the length form the center to each vertex is sqrt(2.0)/2.0. That is less than 1 (distance to near and far plane form the center of the viewing volume)
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(-0.5f, 0.0f, -0.5f);
glVertex3f( 0.5f, 0.0f, -0.5f);
glVertex3f( 0.5f, 0.0f, 0.5f);
glVertex3f(-0.5f, 0.0f, 0.5f);
glEnd();
respectively
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
glTranslate(-0.5f, 0.0f, -0.5f);
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
Alternatively you can set an Orthographic projection, which enlarges the viewing volume by glOrtho:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();

OpenGL translation before and after a rotation

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);

OpenGL scene centering problems

I'm trying to make a scene where I am looking at the XY plane with Z coming towards and away from the camera view. I want to see objects that are further away at a different size than objects that are in front of my face so I imagine I am supposed to use gluPerspective for this. I should have some axes on my screen coming from the origin out, however, I don't see anything at all. I had it working with a bunch of translations but I want to make sure I understand how to manipulate this properly because that was all guess and check before.
void resizeWindow(GLint newWidth, GLint newHeight)
{
glViewport(0, 0, newWidth, newHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (GLfloat)newWidth / (GLfloat)newHeight, 0.1f, 100.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
glPushMatrix();
glColor4ub(0, 120, 20, 255);
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(3.0f, 0.0f, 0.0f);
glVertex3f(2.85f, 0.10f, 0.0f);
glVertex3f(2.85f, -0.10f, 0.0f);
glVertex3f(3.0f, 0.0f, 0.0f);
glVertex3f(2.85f, 0.0f, 0.10f);
glVertex3f(2.85f, 0.0f, -0.10f);
glVertex3f(3.0f, 0.0f, 0.0f);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 3.0f, 0.0f);
glVertex3f(0.0f, 2.85f, 0.10f);
glVertex3f(0.0f, 2.85f, -0.10f);
glVertex3f(0.0f, 3.0f, 0.0f);
glVertex3f(0.10f, 2.85f, 0.0f);
glVertex3f(-0.10f, 2.85f, 0.0f);
glVertex3f(0.0f, 3.0f, 0.0f);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 3.0f);
glVertex3f(0.10f, 0.0f, 2.85f);
glVertex3f(-0.10f, 0.0f, 2.85f);
glVertex3f(0.0f, 0.0f, 3.0f);
glVertex3f(0.0f, 0.10f, 2.85f);
glVertex3f(0.0f, -0.10f, 2.85f);
glVertex3f(0.0f, 0.0f, 3.0f);
glEnd();
Didn't try to run the code, but from a quick glance :
Remove the glPushMatrix(). You're not popping it anywhere ... and not modifying them either
Your "eye" coordinates (0.0, 0.0, -1.0) seem to be a bit too close to the original give your axises are 3.0 unit in length. Try (0.0, 0.0, -20.0) or so.

Rotating an object around a fixed point in opengl

I have a problem with this openGL code:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix(); // put current matrix on stack
//glTranslatef(0.0f, 0.0f, 0.0f);
//glTranslatef(-4*1.5, 0.0, 4*1.5);
glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f); // rotate the robot on its y-axis
glTranslatef(xpos, ypos, zpos);
DrawRobot(xpos, ypos, zpos); // draw the robot
glPopMatrix();
What should I do to make my robot turn around the point at which it is currently situated and not around the origin? I think the problem lies in this snippet.
Example of rotating an object around its centre along the z-axis:
glPushMatrix();
glTranslatef(250,250,0.0); // 3. Translate to the object's position.
glRotatef(angle,0.0,0.0,1.0); // 2. Rotate the object.
glTranslatef(-250,-250,0.0); // 1. Translate to the origin.
// Draw the object
glPopMatrix();
Simply do the rotation after the translation. The order matters.
glTranslatef(xpos, ypos, zpos);
glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f);
try rotating after translation:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix(); // put current matrix on stack
//glTranslatef(0.0f, 0.0f, 0.0f);
//glTranslatef(-4*1.5, 0.0, 4*1.5);
glTranslatef(xpos, ypos, zpos);
glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f); // rotate the robot on its y-axis
DrawRobot(xpos, ypos, zpos); // draw the robot
glPopMatrix();
Use this
house();
glTranslatef(x, y, 0.0); // 3. Translate back to original
glRotatef(theta, 0.0, 0.0, 1.0); // 2. Rotate the object around angle
glTranslatef(-m, -n, 0.0); // 1. Move to origin
house();
where m and n are the point on the object around which you want to rotate and
x and y are the points around which you want to rotate.

Invisible Terrain

I am using GL_TRIANGLE_STRIP to draw my terrain to the screen, however when I compile and run the program I get nothing. When I change GL_TRIANGLE_STRIP to GL_LINES it shows up and works. What can I do to get it working with GL_TRIANGLE_STRIP?
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -10.0f);
glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
glRotatef(-_angle, 0.0f, 1.0f, 0.0f);
GLfloat ambientColor[] = {.5, .5, .5, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
float scale = 5.0f / max(63.0,63.0);
glScalef(scale, scale*10, scale);
glTranslatef(-(float)(63.0) / 2, 0.0f, -(float)(63.0) / 2);
/*GLfloat lightColor0[] = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat lightPos0[] = {-0.5f, 4, 32, 0.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);*/
glColor3f(0.3f, 0.9f, 0.0f);
for(int x = 0;x<64;x++){
glBegin(GL_LINES);
for(int z = 0;z<63;z++){
glNormal3f(0,1,0);
Vertex(x,map[x][z],z);
Vertex(x,map[x][z+1],z+1);
}
glEnd();
}
for(int z = 0;z<64;z++){
glBegin(GL_LINES);
for(int x = 0;x<63;x++){
Vertex(x,map[x][z],z);
Vertex(x+1,map[x+1][z],z);
}
glEnd();
}
I'm not sure this is important but for my terrain I have code that makes it a 3d Gaussian distribution.
An explanation of TRIANGLE_STRIP is found by a Google search. There is an illustration on Wikipedia.
My advice is to print out the first five vertices of your vertex data, and draw it by hand on paper. The fact that GL_LINES work suggest that the right vertices are there, you might just drawing them in the wrong order.
Another piece of advice is to disable backface culling.
glDisable(GL_CULL_FACE);
As a random stab in the dark, do you have culling turned on? It may be that it's not drawing any triangles because the back of the triangles are invisible. Try adding:
glDisable(GL_CULL_FACE);
To you init code, or simply removing:
glEnable(GL_CULL_FACE);
From your init code.