This simple program was designed to draw 13 even, red and white stripes placed alternately, as in the US flag.
// A Simple OpenGL Project
// Author: Michael Hall
//
// This C++ code and project are provided "as is" without warranty of any kind.
//
// Copyright 2010 XoaX - For personal use only, not for distribution
//
// Elaborated by me :)
#include <glut.h>
void DrawStripes(const int quantity)
{
glBegin(GL_QUADS);
for(int i=1; i <= quantity ; i++)
{
if(i%2)
glColor3f(1.0,0.0,0.0);
else
glColor3f(1.0,1.0,1.0);
glVertex2f(0,static_cast<float>(i-1)/static_cast<float>(quantity));
glVertex2f(1.0,static_cast<float>(i-1)/static_cast<float>(quantity));
glVertex2f(0,static_cast<float>(i)/static_cast<float>(quantity));
glVertex2f(1.0,2*static_cast<float>(i)/static_cast<float>(quantity));
}
}
void Draw()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 1.0);
DrawStripes(13);
glEnd();
glFlush();
}
void Initialize()
{
glClearColor(0.0, 0.0, 102.0/255.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}
int main(int iArgc, char** cppArgv)
{
glutInit(&iArgc, cppArgv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(950,500);
glutInitWindowPosition(200, 200);
glutCreateWindow("Rough draft");
Initialize();
glutDisplayFunc(Draw);
glutMainLoop();
return 0;
}
This is how it looks in practice:
Why there are blue triangles on the foreground? I've specified only "QUADS" inside Draw/DrawStripes functions.
The blue comes from your clear color:
glClearColor(0.0, 0.0, 102.0/255.0, 0.0);
That third parameter is the Blue channel of the clear color. When you call glClear(GL_COLOR_BUFFER_BIT); you initialize the render target with the clear color.
Thus the blue you are seeing is from your vertices not covering up the entire render target, and letting the blue clear color through. To see it, enable wireframe (glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);).
Also you really ought to draw in a counter-clock wise fashion: top left, bottom left, bottom right, top right. That will result in your polygons being drawn front-facing (which generally is what you want to avoid back-face culling).
At the moment your are "folding" the polygon, by doing top left, top right, bottom left, then bottom right you essentially twist the quad. Try in clockwise order (invert bottom right and bottom left) and see if you can still see the polygons (you shouldn't if back face culling is on).
Finally you also multiply only the bottom right Y coordinate by 2, why ? That is what is causing your deformation (on top of the twisting). You should have both bottom vertices with the same Y coordinate to make a rectangle (so bottom right and bottom left Y coordinate must match).
I think you're drawing the quad vertices in the wrong order. They should be counterclockwise, but you're drawing a 'twisted' quad.
Try swapping the 3rd and 4th vertex in your for loop.
Related
I am using C++, OpenGL and glut. I am trying to make 5 houses that are rotated properly like this:
However, whenever I try to implement the glRotatef function, I seem to not be able to either get the proper coordinates or something is off somewhere in my code. Furthermore, I set the background color to white but it's still all black, how come? For now I have the houses set to white to counter this for now. Here is my code:
#include <GL/glut.h>
typedef int vert2D[2];
void initialize()
{
glClearColor(1.0, 1.0, 1.0, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(10.0, 215.0, 0.0, 250.0);
glMatrixMode(GL_MODELVIEW);
}
void drawHouse(vert2D* sq, vert2D* tri)
{
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_LOOP);
glVertex2iv(sq[0]);
glVertex2iv(sq[1]);
glVertex2iv(sq[2]);
glVertex2iv(sq[3]);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2iv(tri[0]);
glVertex2iv(tri[1]);
glVertex2iv(tri[2]);
glEnd();
}
void render()
{
vert2D sqPts[4] = { {115, 150}, {115, 125}, {100,125}, {100,150} };
vert2D triPts[3] = { {120, 150}, {95,150}, {108,160} };
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glMatrixMode(GL_MODELVIEW);
drawHouse(sqPts, triPts);
glPushMatrix();
glTranslatef(1.0, 0.0, 0.0);
glRotatef(-10.0, 0.0, 0.0, 1.0);
drawHouse(sqPts, triPts);
glTranslatef(1.0, 0.0, 0.0);
glRotatef(-10.0, 0.0, 0.0, -1.0);
drawHouse(sqPts, triPts);
glPopMatrix();
glPushMatrix();
glTranslatef(-1.0, 0.0, 0.0);
glRotatef(10.0, 0.0, 0.0, 1.0);
drawHouse(sqPts, triPts);
glTranslatef(-1.0, 0.0, 0.0);
glRotatef(10.0, 0.0, 0.0, 1.0);
drawHouse(sqPts, triPts);
glPopMatrix();
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(100, 100);
glutInitWindowSize(640, 480);
glutCreateWindow("TestMeOut");
initialize();
glutDisplayFunc(render);
glutMainLoop();
}
Let's answer the simpler question of why your background is still black, first:
You simply never glClear(GL_COLOR_BUFFER_BIT) the color buffer. You tell OpenGL "hey, the next time I call glClear with (at least) the GL_COLOR_BUFFER_BIT, I want the color buffer to be cleared to white." but you never actually clear the buffer.
Now, onto how we can draw the houses with their correct locations and orientations:
You should first start by defining your house's vertices in a sensible local coordinate system/frame that is suitable for transforming them in further steps. Currently, with how you define your house's vertices, it is hard to do any transformations on those (mainly because linear transformations like rotation are always relative to the coordinate system's origin).
So, let's change that. Let's define the origin (0, 0) for your house to be the center of the bottom/base line of the house. And let's also define that your house's quad has a side length of 10 "units":
vert2D sqPts[4] = {
{-5, 0}, // <- bottom left
{ 5, 0}, // <- bottom right
{ 5,10}, // <- top right
{-5,10} // <- top left
};
Now, for the roof of the house, we assume the same coordinate system (with (0, 0) being the center of the house's base/bottom line), so we start at Y=10:
vert2D triPts[3] = {
{-6, 10}, // <- left
{ 6, 10}, // <- right
{ 0, 12} // <- top
};
Next, we need to define where (0, 0) should be in our "world", so to speak. One definition could be: (0, 0) should be the center of the bottom of the viewport/screen and the viewport should have a length of 100 "units". Right now, we don't care about a correct aspect ratio when the viewport's width does not equal the viewport's height. This can be added later.
Starting from the clip space coordinate system, we can transform this clip space into our own "world space" by using these transformations:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(0.0, -1.0, 0.0); // <- move the origin down to the bottom of the viewport
glScalef(1.0 / 50.0, 1.0 / 50.0, 1.0); // <- "scale down" the clip space to cover more space in the viewport
Now, the above part is essentially what gluOrtho2D() does as well, but highlighting the actual coordinate system transformation steps is useful here.
Now that we defined our house's local coordinate system and our "world" coordinate system, we can rotate and translate the world coordinate system such that the houses appear at their correct locations and orientations in our world.
In order to draw 5 houses, we just use a for-loop:
glMatrixMode(GL_MODELVIEW);
for (int i = -2; i <= 2; i++) { // <- 5 steps
glPushMatrix();
glRotatef(i * 20.0, 0.0, 0.0, 1.0);
glTranslatef(0.0, 50.0, 0.0);
drawHouse(sqPts, triPts);
glPopMatrix();
}
So, starting from our world coordinate system, we transform it by rotating the appropriate amount around its origin (0, 0) for the house with index i to have the correct rotation, and then translate the coordinate system by 50 units along its (now rotated) Y axis.
These two transformations will now result in a house to be drawn at the desired location. So, repeat that 5 times in total with differing rotation angles, and you're done.
I drew a triangle and i want to rotate it on X-Axis continuously. Below code is rotating it for couple of times.
//Paints the GL scene
void GLobj::paintGL(void)
{
static int angle;
for (angle = 1; angle<=360; angle += 1)
{
glClear (GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glRotatef(angle, 1, 0 , 0);
glBegin(GL_TRIANGLES);
glColor3f (1.0, 0.0,1.0);
glVertex2f(-0.45,0.0);
glVertex2f(-0.65,0.5);
glVertex2f(-0.25,0.5);
glEnd();
usleep(1000);
glFlush ();
}
If i change the above code as below, output is just busy in executing and not displaying anything.
//Paints the GL scene
void GLobj::paintGL(void)
{
static int angle;
for (angle = 1; angle<=360; angle += 1)
{
glClear (GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glRotatef(angle, 1, 0 , 0);
glBegin(GL_TRIANGLES);
glColor3f (1.0, 0.0,1.0);
glVertex2f(-0.45,0.0);
glVertex2f(-0.65,0.5);
glVertex2f(-0.25,0.5);
glEnd();
usleep(1000);
if (angle == 360)
{angle = 1;}
}
glFlush ();
}
Is there any other better way of implementing continuous rotation?
Most graphic APIs like OpenGL and DirectX write all changes into something called back buffer: The operations are only displayed once you have rendered your complete scene. If each rotation step or glEnd() rendered immediately, you would always see your scene building up each time. The result would be flickering which is not nice to see.
You can tell OpenGL when you have finished drawing your scene, so that everything can be displayed at once. You do this with glFlush.
In your second example, you conduct a rotation and another one and yet another one... at the very end you display your final scene once. The nice transition of your triangle through the rotation phases is not rendered.
I am attempting to make a simple drawing using openGL. However, the depth buffer doesn't appear to be working.
Other people with a similar problem are typically doing one of two things wrong:
Not including glEnable(GL_DEPTH_TEST)
Bad clipping values
However, my code does not have either of these problems.
...
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gluPerspective(25.0,1.0,10.0,200.0);
// Set the camera location
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(20.0, 10.0, 50.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Cull backfacing polygons
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE)
drawCoordinateAxis();
drawBox(5.0,2.0,5.0,0.8,0.0,0.0);
glTranslated(1.0,-1.0,1.0); //The box is 5x2x5, it is shifted 1 unit down and 1 in the x and z directions
drawBox(5.0,2.0,5.0,0.0,1.0,1.0);
...
When I execute my code, this is drawn. http://imgur.com/G9y41O1
Note that the blue box and the red box collide, so the red box should be covering part of the blue box.
The functions drawCoordinateAxis() and drawBox() just draw a few primitives, nothing fancy inside.
I am running this on Debian squeeze.
void reshape(GLint width, GLint height)
{
g_Width = width;
g_Height = height;
glViewport(0, 0, g_Width, g_Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, (float)g_Width / g_Height, g_nearPlane, g_farPlane);
glMatrixMode(GL_MODELVIEW);
}
So set Matrix Mode to GL_PROJECTION first, then gluPerspective.... and then back to MODELVIEW mode.
I am trying to simply draw a triangle in a window. I've drawn shapes before in previous code, and have looked up common issues such as failure to flush or not clearing the color buffer.
No matter what I seem to try though, I can't get anything to draw on screen, even after I've simplified my code to basically look exactly like my previous (working!) code. All I have is a main and a render:
// Declarations //
void Render(void); //Call the drawing functions
int main(int argc, char *argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(20,20);
glutCreateWindow("Triangle Test");
//prepare for drawing
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
//now draw
glutDisplayFunc(Render);
glutMainLoop();
}
// ---- Render Function ----
void Render(void)
{
// Draw a triangle
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_LINE_STRIP);
glVertex2f(100.0f, 20.0f);
glVertex2f(0.0f, 20.0f);
glVertex2f(20.0f, 50.0f);
glEnd();
glFlush();
}
On run, it draws a window with the background color I set (in this case black) and nothing else. I'm completely stumped. All of the other questions on stack seem to be resolved by things I have in here (i.e. glFlush) and its virtually identical to my old code, which draws fine. Any ideas?
You're drawing a line strip that's bigger than your window. You need to either set your matrices so you see a larger area, draw a smaller polygon, or draw a filled polygon by drawing a triangle instead of a line strip.
I just started working with OpenGL, but I ran into a problem after implementing a Font system.
My plan is to simply visualize several Pathfinding Algorithms.
Currently OpenGL gets set up like this (OnSize gets called once on window creation manually):
void GLWindow::OnSize(GLsizei width, GLsizei height)
{
// set size
glViewport(0,0,width,height);
// orthographic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,width,height,0.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
m_uiWidth = width;
m_uiHeight = height;
}
void GLWindow::InitGL()
{
// enable 2D texturing
glEnable(GL_TEXTURE_2D);
// choose a smooth shading model
glShadeModel(GL_SMOOTH);
// set the clear color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
}
In theory I don't need blending, because I will only use untextured Quads to visualize obstacles and line etc to draw paths... So everything will be untextured, except the fonts...
The Font Class has a push and pop function, that look like this (if I remember right my Font system is based on a NeHe Tutorial that I was following quite a while ago):
inline void GLFont::pushScreenMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(viewport[0],viewport[2],viewport[1],viewport[3], -1.0, 1.0);
glPopAttrib();
}
inline void GLFont::popProjectionMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
So the Problem:
If I don't draw a Text I can see the Quads I want to draw, but they are quite dark, so there must be something wrong with my general OpenGL Matrix Properties.
If I draw Text (so the font related push and pop functions get called) I can't see any Quads.
The question:
How do I solve this problem and some background information why this happened would also be nice, because I am still a beginner/student, who just started.
If your quads are untextured, you will run into undefined behaviour. What will probably happen is that any previous texture will be used, and the colour at point (0,0) will be used, which could be what is causing them to be invisible.
Really, you need to disable texturing before trying to draw untextured quads using glDisable(GL_TEXTURE_2D). Again, if you don't, it'll just use the previous texture and texture co-ordinates, which without seeing your draw() loop, I'm assuming to be undefined.