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.
Related
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.
I need to translate my wired sphere along z-axis back and forth while also changing camera angle. Whenever my sphere gets translated, it slowly turns into ellipsoid. I really don't understand why. Here you can see pieces of code where I believe is a mistake. Also, shapes shouldn't be changed when resizing the window, only their size.
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
gluLookAt(ex, ey, ez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glTranslatef(0.0,0.0,tra);
glScalef(0.65, 0.65, 0.65);
glColor3f(1.0f, 0.8f, 1.0f);
glutWireSphere(0.65, 10, 15);
glPopMatrix();
glPushMatrix();
glLoadIdentity();
gluLookAt(ex, ey, ez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glColor3f(0.1f, 0.8f, 1.0f);
glutWireTorus(0.25, 1.0, 15, 15);
glPopMatrix();
glFlush();
glFlush();
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70.0, (GLfloat)w / (GLfloat)h, 1.0, 80.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
[...] while also changing camera angle. Whenever my sphere gets translated, it slowly turns into ellipsoid.
That's caused by the Perspective distortion or wide-angle distortion and increases towards the edge of the view. The effect can be decreased by reducing the field of view angle, but the effect will never be canceled completely (except parallel projection).
See als How to fix perspective projection distortion?.
Also, shapes shouldn't be changed when resizing the window, only their size."
At perspective projection the size of the objects is always relative to the size of the viewport rather than the size of your screen.
If you don't want perspective distortion and if you want that the size of the objects has to be relative to the size of the screen (measured in pixel), then you have to use an orthographic projection, relative to the size of the viewport.
For instance:
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluPerspective(70.0, (GLfloat)w / (GLfloat)h, 1.0, 80.0);
float sx = w / 100.0f;
float sy = h / 100.0f;
glOrtho(-sx/2.0f, sx/2.0f, -sy/2.0f, sy/2.0f, 1.0f, 80.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
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.
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 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.