Greetings I'm new to OpenGL and Glut. I made a function that displays the 4 dots that make the corners of a square without uniting the dots. The problem is when I run the project, the function doesn't display anything.
I have a similar function that works with lines and displays some lines in the corners of the window which works perfectly. Please tell me what I'm doing wrong and how to fix it. Here are the two functions:
Using Lines. Works perfectly
void Display2() {
glColor3f(1,0.1,0.1);
glBegin(GL_LINES);
glVertex2f(1.0,1.0);
glVertex2f(0.9,0.9);
glVertex2f(0.8,0.8);
glVertex2f(0.7,0.7);
glVertex2f(0.6,0.6);
glVertex2f(0.5,0.5);
glVertex2f(-0.5,-0.5);
glVertex2f(-1.0,-1.0);
glEnd();
}
The one with dots. Does not display anything.
void Display3() {
glColor3f(1,0.1,0.1);
glBegin(GL_POINTS);
glVertex2f(100, 100);
glVertex2f(200, 100);
glVertex2f(100, 200);
glVertex2f(200, 200);
glEnd();
}
The default visible area in OpenGL ranges from -1 to 1 on each axis (the so-called normalized device coordinates).
In your line example, all the values are in this range and thus are visible. In the point example, the coordinates are simply outside of the screen. You can either change the coordinates to fit in the [-1,1] interval, or add a projection matrix that handles that for you.
Related
I'm using qWidget which inherits QGLWidget and below the widget I have 2 buttons.
button1: +
button2: -
this is my code:
void GLWidget::paintGL() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,_w,0,_h,-1,1);
glViewport(_camera_pos_x,0,_w,_h);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(200,200);
glEnd();
update();
}
I want each time I'm pressing the + button, the screen will move 10 pixels to the right which means the line should move to the left by 10 pixels.
This is the code when im pressing the button:
void right() {_camera_pos_x += 10;}
_camera_pos_X is just a member int which is initialized to 0.
When I'm pressing the button another line is rendered 10 pixels to the right and I see 2 lines
What's wrong with my code?
By the way, I think im using old code of OpenGL, is there a better way to render a line?
First of all note, that drawing with glBegin/glEnd sequences is deprecated since more than 10 years.
Read about Fixed Function Pipeline and see Vertex Specification for a state of the art way of rendering.
glViewport specifies the transformation from normalized device coordinates to window coordinates. If you want to change the position of the line, then you have to draw the line at a different position, but that doesn't change the size of the viewport. Keep your viewport as large as the window:
glViewport(0, 0, _w, _h);
The default frame buffer is never cleared, so the rendering is always drawn on the rendering of the previous frames. Because of that, you can "see 2 lines". Use glClear to clear the framebuffer at the begine of the rendering:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Change the model view matrix to set the positon of the line:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,_w,0,_h,-1,1);
glViewport(0, 0, _w, _h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(_camera_pos_x, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(200,200);
glEnd();
You must clear the old contents of the framebuffer, before drawing the new image. Put a glClear(GL_COLOR_BUFFER_BIT) at the beginning of paintGL().
The below code works perfectly fine with no fatal error but, when i use arguments "w","h" in "gluortho2d" as gluortho2d(0,w,h,0) in reshape function I get text on screen whereas if I put these arguments "0,0" as gluortho2d(0,0,0,0) I get shape of box.
How can I get both of them(box and text) simultaneously on screen?
#include"glut.h"
void drawBitmapText(char *string, float x, float y, float z);
void reshape(int w, int h);
void display(void);
void drawBitmapText(char *string, float x, float y, float z)
{
char *c;
glRasterPos3f(x, y, z);//define position on the screen where to draw text.
for (c = string; *c != '\0'; c++)
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *c);
}
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void display(void)
{
glBegin(GL_POLYGON);//1
glVertex2f(-0.2, 0.6 - 0.3);
glVertex2f(-0.1, 0.6 - 0.3);
glVertex2f(-0.1, 0.5 - 0.3);
glVertex2f(-0.2, 0.5 - 0.3);
glEnd();
glColor3f(0, 1, 0);
drawBitmapText("Usama Ishfaq", 200, 400, 0);//drawBitmapText("Usama Ishfaq", x(how much right), y(how much down), z);
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Usama OGL Window");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
By not following bad tutorials and placing calls to glViewport and projection matrix setup at the only place valid: The display function. Setting the viewport and projection matrix in the reshape handler is an anti-pattern. Don't do it.
Do this
void display(void)
{
int const w = glutGet(GLUT_WINDOW_WIDTH);
int const h = glutGet(GLUT_WINDOW_HEIGHT);
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(-1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_POLYGON);//1
glVertex2f(-0.2, 0.6 - 0.3);
glVertex2f(-0.1, 0.6 - 0.3);
glVertex2f(-0.1, 0.5 - 0.3);
glVertex2f(-0.2, 0.5 - 0.3);
glEnd();
/* viewport doesn't change in this
* application, but it's perfectly
* valid to set a different
* glViewport(...) here */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(0, 1, 0);
drawBitmapText("Usama Ishfaq", 200, 400, 0);//drawBitmapText("Usama Ishfaq", x(how much right), y(how much down), z);
glutSwapBuffers();
}
Update (due to request in coments):
Why is it wrong to set the viewport and projection parameters in the reshape handler? Well, you just experienced the reason yourself: They are not "one size fits all" state and throughout rendering slightly more complex frames that go beyond just a mesh drawn, you're going to want to mix and match different viewports and projections throughout rendering. Here's a (incomplete) list of things that require to have different viewports and projections while rendering a single frame:
render-to-texture (FBO) – needs viewport withing the bounds of the texture, and usually also a different projection (important for shadow mapping, dynamic cubemaps and lots of other advanced, multipass rendering techniques)
minimaps / overview frames or similar in the corner (viewport covering just the corner)
text annotation overlays (different projection; usually a plain identity transform so to draw text rectangles directly in NDC space)
"magnifying glass" overlay
Since changing viewport and projection state happens multiple times in only slightly more complex OpenGL drawing, it makes
a) zero sense to set it in the reshape handler: whatever the handler sets will be set only at the beginning of the drawing of the first frame and thereafter the frame drawing code itself would have to reset to what the reshape handler sets. So why even bother doing it in the reshape handler at all?
b) placing viewport and projection setup code in the reshape handler a burden in the long run, because it might cause other parts of the program getting dependent on that. And if that happens, once you realize your mistake and try to move that viewport and projection setup code to where it belongs other parts of the program that relied on it being called from the reshape handler break and you have to fix those, too.
All in all, there are no reasons to place any drawing related calls (and glViewport and projection setup definitely are drawing related) in the reshape handler. Of course "one time" initialization is perfectly fine there, i.e. if you want to adjust the size of FBO render targets to match the window, or if you want to prepare an overlay image that later on gets applied repeatedly.
You can make this much simpler. For what you're doing, there's no need to bother with setting transformations at all.
It looks like, for the box, you're trying to use coordinates in the range [-1.0, 1.0] for both coordinate directions. This corresponds to the OpenGL NDC (Normalized Device Coordinates) coordinate system, which is the coordinate space vertices are in after both the modelview and projection transformations are applied. If you keep these at their default identity matrix, you can specify coordinates directly in NDC space. In other words, to use coordinates in the range [-1.0, 1.0], do... nothing at all, and just keep everything at its default.
The reason the box rendering works for you when you call:
gluOrtho2D(0.0, 0.0, 0.0, 0.0);
is that this call will result in an error, as documented on the man page:
GL_INVALID_VALUE is generated if left = right, or bottom = top, or near = far.
and will therefore keep the defaults untouched, which is exactly what you need.
Now, for the text, it looks like you want to specify the position in units of pixels. The problem you're having is that glRasterPos*() runs the specified coordinates through the transformation pipeline, meaning that, with the default identity modelview and projection transformations, it expects the input coordinates to be in the range [-1.0, 1.0] just like the coordinates you pass to glVertex2f().
Fortunately, there's a very easy way to avoid that. There's a very similar glWindowPos*() call, with the only difference that the coordinates passed to it are in window coordinates, which are in units of pixels.
So in summary:
Remove all glMatrixMode() calls.
Remove all glLoadIdentity() calls.
Remove all gluOrtho2D() calls.
In drawBitmapText(), replace the glRasterPos3f() call by:
glWindowPos2f(x, y);
The only thing to watch out for is that the origin of window coordinates is in the bottom left corner. So if your text position is given relative to the top left corner, you'll need something like:
glWindowPos2f(x, windowHeight - y);
To address some misleading information in another answer: It's perfectly fine to call glViewport() in the reshape() function, as long as you use the same viewport for all your rendering. In more complex applications, you will often need different viewports for different parts of the rendering (e.g. when you render to FBOs, or to only part of the window), so you will need to call glViewport() at the proper places during rendering. But for a simple example, where you do all your rendering to the entire window, there's nothing wrong with calling it in reshape().
I need to draw case/ spare which are Rectangle.
but the problem is that glTranslated()doesn't work. When I call it my rectangle isn't draw anymore.
my rectangle: glRectf(-0.032f, 0.032f, 0.032f, -0.032f);
(I don't understand values but working)
full code:
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3ub(254,128,1);
//glTranslated(50, 20, 0); when I remove the comment, my rectangle doesn't appear.
glRectf(-0.032f, 0.032f, 0.032f, -0.032f);
glFlush();
SDL_GL_SwapBuffers();
}
glRectf(x1,y1,x2,y2) means draw a rectangle from point (-0.032,0.032) to the diagonally opposite corner at (0.032,-0.032).
glTranslated(50,20,0) is applying a vector to move it. Those are pretty big numbers since you are saying you can see the rectangle (square) of size 0.064 wide. It may be drawing out of your viewport so you can't see it.
Try some small numbers and also glTranslated requires doubles (so I would cast them too).
Read more here...
http://www.cprogramming.com/tutorial/opengl_first_opengl_program.html
I've been studying Computer Graphics and I'm very confused about the role of the viewport, gluortho and when to use GL_MatrixMode and GL_Projection.
Here is a sample code I wrote that confuses me.
void init()
{
glClearColor(1.0,1.0,1.0,1.0);//Background Color of Viewport
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-200,200,-200,200,-50,50);
glMatrixMode(GL_MODELVIEW);
}
void wheel()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,0.2,0.2);
glLoadIdentity();
glViewport(0,0,200,200);
glutSolidCube(100);
glFlush();
}
void main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitWindowSize(400,400);
glutInitWindowPosition(400,400);//Position from the top left corner
glutCreateWindow("Car");
init();
glutDisplayFunc(wheel);//Shape to draw
glutMainLoop();
}
When I change the Cube's size to 200 it disappears, why? Is that because it's larger than the z clipping?
When I remove glMatrixMode(GL_MODELVIEW) the cube disappears why?
If I don't flush at the end of the display function the cube disappears as well,why?
When I make the viewport smaller the object get smaller does that mean the object coordinates are relative to the viewport and not the world coordinates?
When you change the cubes size to 200, its faces extend beyond the near and far clipping planes, which you've set in your glOrtho call to -50 and 50. Technically you'd then be viewing the inside of the cube, but the far side of the cube is also outside of the far clipping plane, so you can't see its backface.
Removing the call to set the matrix mode to GL_MODELVIEW means your glLoadIdentity call operates on the fixed functionality projection matrix (I'm pretty sure), and so the cube is directly translated into Normalized Device Coordinates, and it once again extends beyond all the clipping planes.
Finally, glViewport defines the size of the buffer you should be rendering to, and therefore usually matches your screen size. Making it smaller effectively makes your screen size smaller, but does not change the actual GLUT window size. In mathematical terms, it changes the way fragments are projected from normalized device coordinates into screen coordinates.
I've got a screen-aligned quad, and I'd like to zoom into an arbitrary rectangle within that quad, but I'm not getting my math right.
I think I've got the translate worked out, just not the scaling. Basically, my code is the following:
//
// render once zoomed in
glPushMatrix();
glTranslatef(offX, offY, 0);
glScalef(?wtf?, ?wtf?, 1.0f);
RenderQuad();
glPopMatrix();
//
// render PIP display
glPushMatrix();
glTranslatef(0.7f, 0.7f, 0);
glScalef(0.175f, 0.175f, 1.0f);
RenderQuad();
glPopMatrix();
Anyone have any tips? The user selects a rect area, and then those values are passed to my rendering object as [x, y, w, h], where those values are percentages of the viewport's width and height.
Given that your values are passed as [x, y, w, h] I think you want to first translate in the negative direction to get the upper left hand corner at 0,0, then scale by 1/w and 1/h to fill it to the screen. Like this:
//
// render once zoomed in
glPushMatrix();
glTranslatef(-x, -y, 0);
glScalef(1.0/w, 1.0/h, 1.0f);
RenderQuad();
glPopMatrix();
Does this work?
When I've needed to do this, I've always just changed the parameters I passed to glOrtho, glFrustrum, gluPerspective, or whatever (whichever I was using).
From your comment it looks like you want to draw the same quad (RenderQuad()) as full image and in PIP mode.
Assuming you have widthPIP and heightPIP and startXY position of PIP window then use widthPIP/totalWidth, heightPIP/totalHeight to scale original quad and re-render at given startXY.
Is this what you are looking for?