how to reset system - c++

When I do as below, the coordinate of the pointer is changed. Now how can I reset my coordinate system in order to be 0,0,0 before sketching another object?
glPushMatrix();
glTranslatef(0.0f, -500.0f, 1200.0f);
glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
glPushMatrix();
glColor3f(0.0f, 1.0f, 1.0f);
gluCylinder(quadric,10.0f,10.0f,1000.0f,32,32);
glPopMatrix();
I will sketch another object, but current origin system is not 0,0,0. I think the point is in the cylinder which is already sketched.
And also, If I sketch another object after the first one, it is also rotated. Why?

glPushMatrix() pushes a matrix onto the currently active matrix stack (probably modelview in your case). glTranslate(), glRotate() etc. work with the top modelview matrix, as does rendering. glPopMatrix() removes the top matrix from the stack.
So once you balance out glPushMatrix() and glPopMatrix() calls, the stack will be in the same state as when you started.

glPushMatrix () ;
glTranslatef(0.0f, -500.0f, 1200.0f ) ;
glRotatef ( 270.0f, 1.0f, 0.0f, 0.0f );
glColor3f ( 0.0f, 1.0f, 1.0f );
gluCylinder(quadric,10.0f,10.0f,1000.0f,32,32);
glPopMatrix();
glPushMatrix () ;
glTranslatef(0.0f, -500.0f, 1200.0f ) ;
glRotatef ( 270.0f, 0.0f, 1.0f, 0.0f );
glColor3f ( 0.0f, 1.0f, 1.0f );
gluCylinder(quadric,10.0f,10.0f,1000.0f,32,32);
glPopMatrix();
(This code draws 2 independent objects: one with rotated x-axis, the other one with rotated y-axis)
Every glPushMatrix() call needs an correspondending glPopMatrix() call. If you want to make 'local' transformations for one object (i.e. translate, rotate) you can simply call glPushMatrix(), do your transformation, draw your object and call glPopMatrix(). Then your coordinate system is finally untransformed again, and you can draw your next object.
If you don't get that, you could also use glLoadIdentity() on your Modelview Matrix after you applied some transformations (to reset all transformations again) - but if you're using transformation related code (i.e. gluLookAt) on your ModelviewMatrix you have to do that again, after every glLoadIdentity() call.
glLoadIdentity();
glTranslatef(0.0f, -500.0f, 1200.0f ) ;
glRotatef ( 270.0f, 1.0f, 0.0f, 0.0f );
glColor3f ( 0.0f, 1.0f, 1.0f );
gluCylinder(quadric,10.0f,10.0f,1000.0f,32,32);
glLoadIdentity();
glTranslatef(0.0f, -500.0f, 1200.0f ) ;
glRotatef ( 270.0f, 0.0f, 1.0f, 0.0f );
glColor3f ( 0.0f, 1.0f, 1.0f );
gluCylinder(quadric,10.0f,10.0f,1000.0f,32,32);

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

How to handle OpenGL additive blending and depth test with particles and deeper objects

I have a little sprites particle system made with OpenGL & glut using textures to draw a basic flame. The flame is reproduced symmetrically to illustrate how it behaves in a little box/scene. And as the pictures below demonstrate, there are two problems:
1- To produce a somewhat good looking flame effect I want to use additive blending with my particles, but the blending also takes the color of the deeper cyan panel into account and produce a white flame.
2.1 - Also, to achieve a correct implementation of the additive blending I have to disable the depth test while drawing the particles, but doing so enable the drawing of particles even if they should be "hidden".
2.2 - If I enable the depth test while drawing the particles, here is what it looks like.
If it is of any help, here is the texture I am applying to the particles.
Here is the relevant code that displays the scene and the particles.
void drawParticles()
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
glBindTexture(GL_TEXTURE_2D,explosionTexture[0]);
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
for (int i = 0; i < particlesNumber; ++i)
{
glPointSize(50.0f);
glBegin(GL_POINTS);
glColor4f(particlesArray[i].color[0],particlesArray[i].color[1],particlesArray[i].color[2],0.5f);
glVertex3f(particlesArray[i].position[0],particlesArray[i].position[1],particlesArray[i].position[2]);
glEnd();
}
glBindTexture(GL_TEXTURE_2D, 0);
glDisable( GL_BLEND );
glEnable( GL_DEPTH_TEST );
glPopAttrib();
}
void drawScene()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60.0f, (GLdouble) g_width / (GLdouble) g_height, 0.1f, 300.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( dist*sin(phi)*sin(theta), dist*cos(phi), dist*sin(phi)*cos(theta), 0, 0, 0, 0, 1, 0 );
glEnable( GL_DEPTH_TEST );
glDisable( GL_BLEND );
glBegin( GL_LINES );
glColor3f( 1.0f, 0.0f, 0.0f );
glVertex3f( 0.0f, 0.0f, 0.0f );
glVertex3f( 0.5f, 0.0f, 0.0f );
glColor3f( 0.0f, 1.0f, 0.0f );
glVertex3f( 0.0f, 0.0f, 0.0f );
glVertex3f( 0.0f, 0.5f, 0.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glVertex3f( 0.0f, 0.0f, 0.0f );
glVertex3f( 0.0f, 0.0f, 0.5f );
glEnd();
glBegin( GL_QUADS );
glColor4f( 1.0f, 1.0f, 1.0f , 0.0f);
glVertex3f( -1.0f, -0.2f, 1.0f );
glVertex3f( 1.0f, -0.2f, 1.0f );
glVertex3f( 1.0f, -0.2f, -1.0f );
glVertex3f( -1.0f, -0.2f, -1.0f );
glColor4f( 1.0f, 1.0f, 0.0f , 0.0f );
glVertex3f( 1.0f, -2.0f, 1.0f );
glVertex3f( 1.0f, -2.0f, -1.0f );
glVertex3f( 1.0f, -0.2f, -1.0f );
glVertex3f( 1.0f, -0.2f, 1.0f );
glColor4f( 1.0f, 0.0f, 1.0f , 0.0f );
glVertex3f( -1.0f, -2.0f, 1.0f );
glVertex3f( -1.0f, -2.0f, -1.0f );
glVertex3f( -1.0f, -0.2f, -1.0f );
glVertex3f( -1.0f, -0.2f, 1.0f );
glColor4f( 0.0f, 1.0f, 1.0f , 1.0f );
glVertex3f( 1.0f, -2.0f, -1.0f );
glVertex3f( -1.0f, -2.0f, -1.0f );
glVertex3f( -1.0f, -0.2f, -1.0f );
glVertex3f( 1.0f, -0.2f, -1.0f );
glEnd();
glPushMatrix();
drawParticles();
glScalef(1.0f, -1.0f, 1.0f);
drawParticles();
glPopMatrix();
glutSwapBuffers();
}
I am open to any kind of suggestions even involving shaders (but I would be interested to know if it is even possible to do with just plain OpenGL).
UPDATE:
Maybe I was unclear, I'm not necessarily interested in a strictly fixed-pipeline solution, I want to know how to manage additive blending in a scene even it means adding shaders code to my project.
Now, as Columbo pointed out, enabling the depth testing and disabling the depth writing solved my second problem. Now concerning the additive blending issue, I still have no clue about how to manage additive blending in a scene. Even though there might not such basic colors in a scene, the problem still remains as the flame will still be white and I'm open to know what I have to do with the pixel shader as suggested.
For the additive blending issue, it may not be a problem. You'll never have a block of cyan in a real scene. However, if you really really need a solution, you could try a premultiplied alpha blend (glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);), then you have a bit more control. In your pixel shader you can multiply the output RGB by the source alpha manually, then you can choose the output alpha. An output alpha of zero produces an additive blend like you have at the moment. Outputting the full alpha value (vertex alpha * texture alpha) gives you a standard modulating alpha blend. You might be able to find some value in-between those two extremes which darkens the background enough to make your flame look yellow even against a cyan background without making it look rubbish. If you're not using pixel shaders, I believe it'd be possible with the fixed function pipeline by manipulating your texture during texture loading. It's all rather fiddly, and I'd suggest it's not worth doing, because you won't have such primary colours in a finished, lit scene. The more correct solution is to use HDR and tone mapping, but that's getting into some quite advanced rendering techniques.
Fixing the depth problem is simple. You need to enable depth testing for your flame, but disable depth writing. glEnable(GL_DEPTH_TEST) and glDepthMask(GL_FALSE) are the relevant commands.

Why are my OpenGL objects drawing relative to the last object drawn?

I'm pretty sure this is due to my lack of understanding of how the GL_MODELVIEW matrix works. Here is a screen recording of what's happening: http://youtu.be/3F7FLkVI7kA
As you can see, the bottom-most triangle is the first triangle being drawn, and moves as I expect the other 2 triangles to move. The second triangle is moved and rotated relative to the first, and the third is moved and rotated relative to that combination.
What I want is for all three triangles to be stationary in 3D space, but spinning (like the first triangle).
Source:
// Main loop
do {
// Clear Screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Update camera
glfwGetCursorPos(window, &cursorX, &cursorY);
cam.update(0.001f, (int)cursorX, (int)cursorY);
// Reset Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// move camera
glRotatef(cam.rotation.x, 1.0f, 0.0f, 0.0f);
glRotatef(cam.rotation.y, 0.0f, 1.0f, 0.0f);
// translate modelview matrix to position of the camera - everything should now draw relative to camera position
glTranslatef(-cam.position.x, cam.position.y, -cam.position.z);
// Draw ground
drawGroundGrid(-25.0f);
drawSpinningTriangle(0.0f, 0.0f, -5.0f);
drawSpinningTriangle(3.14f, 3.0f, -6.0f);
drawSpinningTriangle(-6.0f, 12.0f, -5.0f);
// Swap buffers - back buffer is now front buffer to be rendered to next frame
glfwSwapBuffers(window);
glfwPollEvents();
calcFPS();
} while (!glfwGetKey(window, GLFW_KEY_ESCAPE) && !glfwWindowShouldClose(window));// Main Loop End
[...]
void drawSpinningTriangle(float x, float y, float z) {
glMatrixMode(GL_MODELVIEW);
glTranslatef(x, y, z);
glRotatef(glfwGetTime() * 50.0f, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLES);
{
// Red vertex
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// Yellow vertex
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
// White vertex
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
}
glEnd();
}
First using the matrix stack is deprecated. It's much better to manage your own matrices
Second you should pushMatrix and popMatrix before the transformations and after drawing:
void drawSpinningTriangle(float x, float y, float z) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(x, y, z);
glRotatef(glfwGetTime() * 50.0f, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLES);
{
// Red vertex
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// Yellow vertex
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
// White vertex
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
}
glEnd();
glPopMatrix();
}
This will save and restore the top most matrix so any changes between the 2 calls are removed.

Using glLoadMatrixf with my own matrix

I have a simple drawing loop where I manipulate the camera, using glRotatef and glTranslatef then I attempt to draw a an object with my own matrix instead of using the gl* commands
e.g.
void GLCore::render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(camera.xRot,1.0,0.0,0.0);
glRotatef(camera.yRot,0.0,1.0,0.0);
glTranslatef(-camera.position.X, -camera.position.Y, -camera.position.Z);
glPushMatrix();
drawScene();
glPopMatrix();
camera.updateCamera();
}
void GLCore::drawScene()
{
glEnableClientState(GL_VERTEX_ARRAY);
glPushMatrix();
glLoadMatrixf(mapObject->matrix.getMatrixPointer());
glVertexPointer(....);
glDrawElements(....);
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY);
}
The Matrix is from mapObject as:
float m[] = { 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, -10.0f, 1.0f };
This draws as expect, with the model 10.0f away, however when I use glLoadMatrix I loose control of the camera, the view is fixed in the initial state. This doesn't happen when I move the object using glTranslate, everything works fine and the camera will still look around. From what I understand the glLoadMatrix call should only be applied to the top matrix in the stack so it shouldn't effect the camera matrix.
Any ideas? :(
Thanks for the help
glLoadMatrix assigns your matrix to the top of the stack. What you want to do is to multiply your matrix with the one on the top of the stack. Use glMultMatrix for that.

OpenGL Color Matrix

How do I get the OpenGL color matrix transforms working?
I've modified a sample program that just draws a triangle, and added some color matrix code to see if I can change the colors of the triangle but it doesn't seem to work.
static float theta = 0.0f;
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glClearDepth(1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef( theta, 0.0f, 0.0f, 1.0f );
glMatrixMode(GL_COLOR);
GLfloat rgbconversion[16] =
{
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f
};
glLoadMatrixf(rgbconversion);
glMatrixMode(GL_MODELVIEW);
glBegin( GL_TRIANGLES );
glColor3f( 1.0f, 0.0f, 0.0f ); glVertex3f( 0.0f, 1.0f , 0.5f);
glColor3f( 0.0f, 1.0f, 0.0f ); glVertex3f( 0.87f, -0.5f, 0.5f );
glColor3f( 0.0f, 0.0f, 1.0f ); glVertex3f( -0.87f, -0.5f, 0.5f );
glEnd();
glPopMatrix();
As far as I can tell, the color matrix I'm loading should change the triangle to black, but it doesn't seem to work. Is there something I'm missing?
The color matrix only applies to pixel transfer operations such as glDrawPixels which aren't hardware accelerated on current hardware. However, implementing a color matrix using a fragment shader is really easy. You can just pass your matrix as a uniform mat4 then mulitply it with gl_FragColor
It looks like you're doing it correctly, but your current color matrix sets the triangle's alpha value to 0 as well, so while it is being drawn, it does not appear on the screen.
"Additionally, if the ARB_imaging extension is supported, GL_COLOR is also accepted."
From the glMatrixMode documentation. Is the extension supported on your machine?
I have found the possible problem.
The color matrix is supported by the "Image Processing Subset". In most HW, it was supported by driver.(software implementation)
Solution:
Add this line after glEnd():
glCopyPixels(0,0, getWidth(), getHeight(),GL_COLOR);
It's very slow....