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 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'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.
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();
}