I am having a problem with my code.
//ball joint
glLoadIdentity();
glTranslatef(0.0,0.0,-12.0);
glRotatef(tippangle, 1,0,0);
glRotatef(viewangle, 0,1,0);
glTranslatef(2.5, .6, 0.0);
glPushMatrix();
gluSphere(quad,.25,15,15);
glPopMatrix();
//right arm
glLoadIdentity();
glTranslatef(0.0,0.0,-12.0);
glRotatef(tippangle, 1,0,0);
glRotatef(viewangle, 0,1,0);
glTranslatef(3.2, .55, 0.0);
glRotatef((GLfloat)rightHandAngle, 0.0, 0.0, 1.0);
glScalef(0.5,.12,0.1);
glPushMatrix();
drawBox();
glPopMatrix();
I am attempting to get the rectangle to rotate around the ball joint (its left side) but instead it is rotating at its center. I think the problem lies in the above code.
The sphere is located at (2.5, 0.6):
glTranslatef(2.5, .6, 0.0);
The box is located at (3.2, 0.55):
glTranslatef(3.2, .55, 0.0);
The center of the sphere is the pivot. The vector form the pivot to the origin of the box is:
(3.2, 0.55) - (2.5, 0.6) = (0.75, -0.05)
If you want to rotate an object around a pivot then you've to:
Translate the object in that way that way, that the pivot is on the origin (0, 0, 0). This is the vector form the pivot to the origin of the box (0.75, -0.05).
glTranslatef(0.75, -0.05f, 0.0f);
Rotate the object.
glRotatef((GLfloat)rightHandAngle, 0.0, 0.0, 1.0);
Translate the rectangle in that way that the pivot is back at its original position. This is the negative vector form the pivot to the origin of the box (-0.75, 0.05).
glTranslatef(-0.7, 0.05f, 0.0f);
See also How to use Pivot Point in Transformations
Since operations like glTranslate and glRotate define an matrix and multiply the current matrix ba the nes matrix, this operations have to be done in the revers order.
//right arm
glLoadIdentity();
glTranslatef(0.0,0.0,-12.0);
glRotatef(tippangle, 1,0,0);
glRotatef(viewangle, 0,1,0);
glTranslatef(3.2, .55, 0.0);
glTranslatef(-0.7, 0.05f, 0.0f);
glRotatef((GLfloat)rightHandAngle, 0.0, 0.0, 1.0);
glTranslatef(0.75, -0.05f, 0.0f);
glScalef(0.5,.12,0.1);
drawBox();
See also OpenGL translation before and after a rotation.
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);
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 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.
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.
I'm trying to understand OpenGL coordinate system. Everywhere I see it's described as right-handed one, but it doesn't correspond with my experience. I tried to draw some shapes and 3-d objects and I see that apparently z-axis points "into the screen" (while x points to right, and y up - which is description of left-handed coordinate system). What am I missing?
edit:
For example:
http://img576.imageshack.us/img576/9234/triangles.jpg
If +Z points viewer, why green triangle, which z-coordinate is larger, is behind red one?
initializeGL:
qglClearColor(Qt::darkGray);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc( GL_LEQUAL );
glEnable(GL_COLOR);
resizeGL:
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50.0f, 50.0f, -50.0f, 50.0f, 50.0, -50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
paintGL:
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef (-30.0, 1.0, 0.0, 0.0);
glRotatef (20.0, 0.0, 1.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex3f(45.0, 0.0, 0.0);
glVertex3f(-45.0, 0.0, 0.0);
glVertex3f(0.0, 45.0, 0.0);
glVertex3f(0.0, -45.0, 0.0);
glVertex3f( 0.0, 0.0, 45.0);
glVertex3f( 0.0, 0.0, -45.0);
glEnd();
glBegin(GL_TRIANGLES);
//Red triangle:
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 20.0, 1.0);
glVertex3f(20.0, 0.0, 1.0);
//Green triangle:
glColor3f(0.0, 1.0, 0.0);
glVertex3f(-15.0, 0.0, 20.0);
glVertex3f(0.0, 25.0, 20.0);
glVertex3f(15.0, 0.0, 20.0);
glEnd();
Okay, the thing that stands out for me is the glOrtho function. You have the near and far clipping planes only 100 units apart. That seems very small. Do you really want it that way? It's represented by the last 2 parameters in that function.
Also your objects are very big in relation to this small frustum. Objects could be sitting directly in front of your camera and it would block other objects from being seen.
I would enlarge all the parameters in the glOrtho call. HTH
In a right-handed system (OpenGL) negative Z (-Z) should point into the screen. Positive Y should be "up," and positive X should be to the right.
This seems to be what you described, and that is a right-handed coordinate system.
Perhaps this can help.
http://www.geometrictools.com/Documentation/LeftHandedToRightHanded.pdf
What am I missing?
In (the viewport of) left-handed system x points right, y points up, z points forward (away from viewer).
In right-handed x points right, y points up, z points backward (towards the viewer).
Picture is taken from wikipedia.
x is thumb, y is index finger and z is middle finger.
Last 2 parameters glOrtho reference:
nearVal, farVal
Specify the distances to the nearer and farther depth clipping planes. These values are negative if the plane is to be behind the viewer.
Your nearer clipping plane is in front of the viewer and farther, behind. It'll flip Z axis.
It depends how you draw.
an Identity for modelview and a regular gluPerspective for projection will expect an input coordinate system that is right-handed (as JustBoo mentioned, -z is into the screen).
if you load a different set of matrices, though, nothing stops you from flipping one of the coordinates in the matrix, resulting in a left-handed system. (or not flip. gluPerspective/glFrustum actually flips z coordinates). There are some practical things to keep in mind when doing this, like the winding order for culling.