I'm trying to draw a blue quad across the bottom of a room.
This is the the code I've been attempting to use, but there is no quad, just the green clear color.
#include <iostream>
#include <vector>
#include <cmath>
#include <GL/glu.h>
#include <GL/freeglut.h>
bool keystates[256];
bool speckeystates[256];
// manage key events
void keys(unsigned char key, int x, int y) {
keystates[key]=true;
}
void keyup(unsigned char key, int x, int y) {
keystates[key]=false;
}
void skeys(int key, int x, int y) {
speckeystates[key]=true;
}
void skeyup(int key, int x, int y) {
speckeystates[key]=false;
}
void draw(void) {
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gluLookAt(0,0,0,640,480,640,0,1,0); // from near-top-left to far-bottom-right, floor should be visible
glBegin(GL_QUADS);
glColor3ub(15,15,255); // visible blue color
glVertex3i(0,480,0); // draw quad across bottom
glVertex3i(640,480,0);
glVertex3i(640,480,640);
glVertex3i(0,480,640);
glEnd();
glFlush(); // flush drawing
glutSwapBuffers(); // swap the buffers
glutPostRedisplay();
}
int main(int argc, char** argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(640,480);
glutInitWindowPosition(0,0);
glutCreateWindow("Window!"); // init window stuff
glutDisplayFunc(draw); // our frame/draw event
glutKeyboardFunc(keys);
glutKeyboardUpFunc(keyup);
glutSpecialFunc(skeys);
glutSpecialUpFunc(skeyup); // init key event stuff
glEnable(GL_DEPTH_TEST); // init opengl stuff
glClearColor(0.2f,0.3f,0.2f,1.0f);
gluPerspective(45.0,640/480,0,640); // x: 0-640 y: 0-480 z: 0-640
glDepthFunc(GL_LEQUAL);
glutMainLoop(); // begin the loop
}
I am going to answer your question, but first I'd advise you to try and forget about the glBegin function as well as glVertex/color etc. This is a very outdated API from the time when a draw call (e.g. a transfer of data from RAM to graphics memory) was less expensive than the rendering itself, so it didn't matter that you were inefficiently sending data because it took the graphics card more time to process whatever you sent it the last frame than it took the CPU and DMA to get the data from one memory to the other.
A few years later, the exact opposite was true, so the standard expanded to include VBOs so you don't need to send each vertex via a separate draw call, but they kept the immediate mode (which is what you are using) for compatibility reasons.
Nowadays the immediate mode is (finally) deprecated, so it's a bad idea to use it, you can find some decent tutorials about the new API here
Anyway your problem is the way you setup your camera, you stand in the point 0,0,0 and look at the 640,480,640 point which means that the vertices will be defined in the wrong order, causing them to get culled, either change the glulookat call and inverse the target and the eye positions, or change the culling mode
Related
I am novice to OpenGL and I read that glutWireCubedraws a wire cube. Now that it is not appearing on when I run my code, I am wondering what does it do? Does it draw a cube or where have I gone wrong in my code?
#include<GL/glut.h>
GLdouble cubeSize= 10.0;
//FUNCTIONS DECLARATIONS - PROTOTYPES
void init(void);
void display(void);
int main(int argc, char ** argv){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE |GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glutCreateWindow("Wire Cube");
init();
glutDisplayFunc(display);
glutMainLoop();
}
//FUNCTIONS IMPLEMENTAION - DEFINITION
void init(void){
glClearColor(0.0,0.0,1.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
void display(void){
glBegin(GL_POLYGON);
glutWireCube(5.0);
glEnd();
glFlush();
}
Calling glutWireCube is not allowed inside a glBegin/glEnd block. Only glVertex to specify vertices and all the functions to set the current values of some vertex attributes (like glNormal, glColor, ...) can be used there.
How glutWireCube internally works is not specified. It might as well use immediate mode, but in this case, it will do its own glBegin/glEnd calls.
Conceptually, trying to put a cube into a GL_POLYGON is also not going to work. GL_POLYGON is for drawing a single, flat, convex polygon, and it is totally impossible to draw a whole cube as one polygon.
Furthermore, you do not set up any of the GL_MODELVIEW or GL_PROJECTION matrices. This means you directly draw in clip space, and glutWireCube with size 5 will draw a cube which completely lies outside of your viewing frustum, so you will see nothing.
here is my code.
#include "stdafx.h"
#include <GL/glut.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <math.h>
#define pi 3.14;
float x=.05; //translation parameter
float angle=3;
void reshape(int w, int h)
{
if(h==0) h=1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,w,0,h,-1,1);
}
void display(void)
{
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT);
glTranslatef(x,0.0f,0.0f);
glBegin(GL_POLYGON);
glVertex2f(10,10);
glVertex2f(30,20);
glVertex2f(30,30);
glVertex2f(10,30);
glEnd();
x=x+.0000005;
if(x>600)
x=0;
glFlush();
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc , argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_RGB|GLUT_DOUBLE);
glutInitWindowSize(640,480);
glutCreateWindow("my window");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(display);
glutMainLoop();
return(0);
}
the problem with this code is, the rectangle is translated to infinity. I want it translated to maximum window size and again return to starting of window.In this code I am checking x>600 (assumes 600 as maximum) ,if so x is changed to 0. But it wont working.
You need to call glPushMatrix before glTranslatef and glPopMatrix after glEnd.
glTranslatef doesn't set the transformation, it appends it to the existing transformation. What you need to do is push the existing matrix on the matrix stack, apply the transformation, then restore the original. That way the translations don't accumulate.
You are not resetting the ModelView matrix. The GL transformation functions multiply the current modelview matrix by the transformation matrix, so that the transformations accumulate. Every time your display function is called, you move the rectanlge by the amout of x - relative to where it was lats frame -. Thus, your logic of changing x is actually only modulating the speed with wich the object moves.
Put a glLoadIdentiy() at the start of display(). It will reset the matrix to identity, undoing all former transformations.
I am having some trouble running a simple program:(code below text)
i would like to print as an output a square with [50,50],[-50,-50],[50,-50],[-50,50] coordinates.
I'm setting up a glOrtho matrix in init() and then in my display func i print the square with the above coordinates as glVertex2f (for example glVertex2f(50.0,-50.0)) Is it the correct way or does glVertex2f not take real coordinates as values?
Anyway here is the code: (it compiles nicely, however it doesnt show anything in graphics window)
#include <iostream>
#include <stdlib.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <windows.h>
#include <GL/glut.h>
#endif
#define SCR_WID 640
#define SCR_HEI 480
#include "imageloader.h"
using namespace std;
//*****************************CUSTOM FUNCS***********************************//
void init()
{
glViewport(0,0,SCR_WID,SCR_HEI);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho((double)SCR_WID,0.0,(double)SCR_HEI,0.0,-5.0,-20.0);
glMatrixMode(GL_MODELVIEW);
}
//*****************************CALLBACKS (win 1)******************************//
void resizeFunc(int w, int h)
{
glutReshapeWindow(SCR_WID,SCR_HEI);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
glVertex2f(1.0,1.0);
glVertex2f(-1.0,1.0);
glVertex2f(1.0,-1.0);
glVertex2f(-1.0,-1.0);
glEnd();
glutSwapBuffers();
}
void key(unsigned char key, int x, int y)
{
if (key == 'q' || key == 27 )
exit(0);
glutPostRedisplay();
}
//**********************************main func*********************************//
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(SCR_WID,SCR_HEI);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("TestGlut");
glutReshapeFunc(resizeFunc);
glutDisplayFunc(display);
glutIdleFunc(display);
glutKeyboardFunc(key);
init();
glutMainLoop();
return EXIT_SUCCESS;
}
Your init function is a little odd
glViewport(0,0,SCR_WID,SCR_HEI);
The default viewport is already the full window, so this is redundant.
glPushMatrix();
You never call glPopMatrix or manipulate the matrix stack in any other way elsewhere, so why are you doing this?
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho((double)SCR_WID,0.0,(double)SCR_HEI,0.0,-5.0,-20.0);
Calling glLoadIdentity immediately before glOrtho is a waste. glOrtho overwrite the current matrix, so it doesn't matter what it was before. Also glLoadIdentity resets the matrix value back to it's default of an identity matrix, which is what it would be anyway at program start, so it's doubly redundant.
Also, the glOrtho params are 'left right bottom top near far'. You've reversed the X and Y axes by putting a larger number for left and bottom than for right and top. At best this will give you a projection that will put the (0,0) coordinate at the lower right of the screen, which is pretty unusual. Finally, your near and far planes lie completely in negative Z space. That means that vertices that are specified with only two values (glVertex2f as you're using) will always be excluded since they have an implicit 0 for their z coordinate.
void resizeFunc(int w, int h)
{
glutReshapeWindow(SCR_WID,SCR_HEI);
}
Why bother with a resize function if you're going to ignore the input width and height?
glBegin(GL_QUADS);
glVertex2f(1.0,1.0);
glVertex2f(-1.0,1.0);
glVertex2f(1.0,-1.0);
glVertex2f(-1.0,-1.0);
glEnd();
Aside from the fact that these coordinates will produce clipped vertices (because their Z value is implicitly 0, and thus outside of your near/far clip region), you're specifying them in what appear to be in normalized clip coordinates. If you corrected the Z shape problem that genpfault mentioned (by swapping vertex 3 and 4) then these would take up the whole screen if you were working with the default projection matrix. By setting an ortho matrix using the screen pixel dimensions, you've created a square that would be 2 pixels wide and two pixels tall, located in the lower right hand corner of the screen.
void key(unsigned char key, int x, int y)
{
...
glutPostRedisplay();
}
Why? If you want your program to render continuously, and not just when someone hits a key, then you should have glutPostRedisplay() in an idle function, not in the keypress function.
int main(int argc, char *argv[])
{
...
glutIdleFunc(display);
...
}
Don't set your idle function to the display function. If you want your program to animate, make an actual idle function that calls glutPostRedisplay.
So far this is my code:
#include <iostream>
#include <cstdlib>
#include <GL/glut.h>
#include <cmath>
void keyboard(unsigned char key, int x, int y);
void display(void);
void timer(int);
static float x=0.0f,y=0.0f;
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowPosition(200,200);
glutInitWindowSize(640,480);
glutCreateWindow("draw a line");
glutKeyboardFunc(&keyboard);
glutDisplayFunc(&display);
glutTimerFunc(10,timer,0);
glutMainLoop();
return EXIT_SUCCESS;
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case '\x1B':
exit(EXIT_SUCCESS);
break;
}
}
void timer(int value){
x+=0.001;
y+=0.0005;
glutPostRedisplay();
glutTimerFunc(10,timer,0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity ();
glColor3f(0.0f, 1.0f, 0.0f);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
glFlush();
}
What this does is that it lights up a pixel every 10 msecs from the point (0,0) to (1,0.5). What I want is that when a pixel lights up it stays in that state, so eventually you will see a line. How can I achieve this?
I am not familiar with glut but I am guessing display is the function that is called on each redraw. This function starts with glClear(GL_COLOR_BUFFER_BIT). This function clears your color buffer on each redraw.
You might find that removing glClear does not entirely fix your problem. This could well be because your graphics context may be double buffered and to make things more efficient, the front buffer is not copied to the back buffer on each animation run.
You best bet to get the desired effect will probably be to draw a line that grows on each animation run.
why do things the hard way? although the older OGL API is deprecated, you can use GL_LINES to do this:
glBegin(GL_LINES);
glVertex2f(x_start,y_start);
glVertex2f(x_end,y_end);
glEnd();
This will draw the line fully in one go, which is easier and a bit more efficient (it also allows you to benefit from the line anti-aliasing hint).
The display function is being called every time you call glutPostRedisplay(). And every time the display function is called, you clear the screen.
You need to write a function that will iterate through all of the points you want to display. Each iteration will call something like a drawPoint() function.
Perhaps something like this:
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0f, 1.0f, 0.0f);
for (int i = 0; i < num_points; i++)
{
drawPoint(points(i));
}
glFlush();
}
Alternatively, you could skip writing a new function and do this:
glBegin(GL_POINTS);
for (int i = 0; i < num_points; i++)
{
glVertex2f(points(i).getX(), points(i).getY());
}
glEnd();
If your using, GL_LINES. A way to do it is to have an array of points you want to draw EG: p[0], p[1], p[2], p[3], p[4], p[5] ... then draw it using some for loop
glBegin(GL_LINES);
for(...) {
glVertex2f(p[i ]->x,p[i ]->y);
glVertex2f(p[i+1]->x,p[i+1]->y);
}
glEnd();
So using this method you can replace p[] with a function allowing you to make pretty shapes
glVertex2f(functionx(i ),functiony(i ));
glVertex2f(functionx(i+1),functiony(i+1));
note: lines work weirdly they dont link up you need to have a start point to end point kind of thing hence the i+1
I guess your trying to draw stuff like cardioid's using polar coordinates?
Maybe I set up GLUT wrong. I want verticies to be relative to their size in pixels. Right now if I create a hexagon, it takes up the whole screen even though the units are 6.
#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include <cmath>
//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
using namespace std;
//Called when a key is pressed
void handleKeypress(unsigned char key, //The key that was pressed
int x, int y) { //The current mouse coordinates
switch (key) {
case 27: //Escape key
exit(0); //Exit the program
}
}
//Initializes 3D rendering
void initRendering() {
//Makes 3D drawing work when something is in front of something else
glEnable(GL_DEPTH_TEST);
}
//Called when the window is resized
void handleResize(int w, int h) {
//Tell OpenGL how to convert from coordinates to pixel values
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective
//Set the camera perspective
glLoadIdentity(); //Reset the camera
gluPerspective(45.0, //The camera angle
(double)w / (double)h, //The width-to-height ratio
1.0, //The near z clipping coordinate
200.0); //The far z clipping coordinate
}
//Draws the 3D scene
void drawScene() {
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //Reset the drawing perspective
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_POLYGON); //Begin quadrilateral coordinates
//Trapezoid
glColor3f(255,0,0);
for(int i = 0; i < 6; ++i) {
glVertex2d(sin(i/6.0*2* 3.1415),
cos(i/6.0*2* 3.1415));
}
glEnd(); //End quadrilateral coordinates
glutSwapBuffers(); //Send the 3D scene to the screen
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400, 400); //Set the window size
//Create the window
glutCreateWindow("Basic Shapes - videotutorialsrock.com");
initRendering(); //Initialize rendering
//Set handler functions for drawing, keypresses, and window resizes
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutReshapeFunc(handleResize);
glutMainLoop(); //Start the main loop. glutMainLoop doesn't return.
return 0; //This line is never reached
}
How can I make it so that the coordinates:
(0,0),
(10,0),
(10,10),
and (0,10) define a polygon starting at the top left of the screen and is a width and height of 10 pixels?
If you want the objects to be scaled that sort of way, you should use an orthographic projection.
Right now, with perspective, things are scaled not only by their size, but by their Z-axis position. So use this function instead of gluPerspective:
gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top);
That function basically defines the space you can see, which is like a big rectangular prism. That makes far things appear the same size as near things.
As for the exact scaling, it will also change relative to the viewport size. To get the pixels exactly right, you would have to constantly change the projection, or keep the viewport size fixed.
For it to work out as 1:1, if your viewport is x pixels wide, the orthographic projection should be x pixels wide as well.
If you're drawing in 2D, you don't want to use perspective projection. If you set up your camera with gluOrtho2D(0, window_width, window_height, 0); then you should get what you're looking for.