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.
Related
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 making a simple GLUT program which tracks the mouse and put points on the path.
Well This is my code:
void init()
{
glClearColor( 0.0, 0.0, 1.0, 1.0);
glMatrixMode( GL_PROJECTION);
gluOrtho2D( 0.0, 400.0, 0.0, 400.0);
for(int i=0;i<5000;i++)
{
arr[i][0]=0;
arr[i][1]=0;
}
glPointSize(10.0);
}
void drawPoints()
{
glBegin( GL_POINTS );
glColor3f( 0.0,0.0,0.0 );
for ( int i = 0; i < z; i++ )
{
glVertex2f( arr[i][0], arr[i][1]);
}
glEnd();
}
void myDisplay()
{
glClear( GL_COLOR_BUFFER_BIT);
drawPoints();
glutSwapBuffers();
glutPostRedisplay();
}
void myMouseMove( int x, int y)
{
arr[z][0]=x;
arr[z++][1]=y;
}
int main( int argc, char ** argv)
{
glutInit( &argc, argv);
glutInitDisplayMode( GLUT_DOUBLE| GLUT_RGB);
glutInitWindowPosition( 100, 100);
glutInitWindowSize(600,600);
glutCreateWindow( "Testing");
init();
glutDisplayFunc( myDisplay);
glutPassiveMotionFunc( myMouseMove);
glutMainLoop();
return 0;
}
However I am having few problems:
Y coordinate runs in opposite direction.
Draws point ahead of cursor position(while moving in a direction).
Is there any better way to do this?
The Y coordinate being flipped is actually expected behavior. Simply correct for it in your code and you should be fine.
If you want to make sure that your rendered image and mouse cursor are completely synchronized, simply have glut hide the mouse cursor, and then render it yourself using OpenGL.
You should be aware that when using a traditional projection matrix in OpenGL: (0,0) is the lower-left corner. Most window systems will map (0,0) to the top-left corner.
In some circumstances, you can make them match up simply by swapping the bottom/top fields in your call to glOrtho (...) or gluOrtho2D (...) - this has other consequences like reversing polygon winding, so it is not always the best approach.
As for "drawing points ahead of the cursor," I think you may be describing input latency (particularly if you are using VSYNC).
When you use a software cursor vs. hardware cursor the position of the mouse may be off by one or more frames. There is a somewhat technical discussion here (see: Idiosyncrasies) on the effect of buffer swap intervals (OpenGL's mechanism for VSYNC) on input latency.
To fix the inversion do 600 - y for setting arr element. Also your gluOrtho2D is on a scale of 400 by 400 while your windows is 600 by 600 so change your gluOrtho2D scale to the same as the window size and you'll be fine.
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
I'm trying to load 3D models from .obj format and it draws the object on the scren without any problem but when I resize the screen everything disappear. Here's the code:
Obj* object = new Obj();
GLuint texture[1];
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,(double)w / (double)h,1.0,200.0);
}
void initRendering() {
object->GetObj("cube.obj");
glShadeModel(GL_LINEAR);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glEnable(GL_DEPTH_TEST);
}
void handleKeypress(unsigned char key, int x, int y) {
switch (key) {
case 27:
{
exit(0);
break;
}
}
}
void drawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glRotatef(45.0,0.0,1.0,0.0);
object->DrawObj();
glPopMatrix();
glutSwapBuffers();
glFlush();
}
int _tmain(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("3D");
initRendering();
glutReshapeFunc(handleResize);
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutMainLoop();
return 0;
}
And here's the code for Obj.DrawObj():
glBegin(GL_TRIANGLES);
for(int i = 0;i < faces.capacity()-1;i++)
{
glVertex3f(vertices[faces[i].vertex1].cordinate1,vertices[faces[i].vertex1].cordinate2,vertices[faces[i].vertex1].cordinate3);
glVertex3f(vertices[faces[i].vertex2].cordinate1,vertices[faces[i].vertex2].cordinate2,vertices[faces[i].vertex2].cordinate3);
glVertex3f(vertices[faces[i].vertex3].cordinate1,vertices[faces[i].vertex3].cordinate2,vertices[faces[i].vertex3].cordinate3);
}
glEnd;
In your drawing code you set the projection matrix, which is good. However you set it to identity. In the resize handler you're setting the projection matrix as well, but you shouldn't do it there; yes I know the tutorials have it all there, but this is very bad style. You should move all the code currently in the reshape handler into the drawing handler, replacing the current setting of the projection matrix.
I can see that you're still confused by reading your PasteBin. Let me try to explain:
The reason why you can see your object the first time you draw it is because you have not set a projection matrix. So your object is drawn directly in normalized device coordinates (-1 to 1 range).
When you resize, you're setting the projection matrix for the first time, and this changes what viewing region is drawn to your screen. Your object as it is initially drawn is outside of the viewing region defined by your projection matrix (it is on top of the camera and I guess in front of the near plane. You have to move the object back away from the camera so that it is inside the view frustum. This is what datenwolf was suggesting.
However at the same time you introduced other errors into your code, particularly that you stopped resetting the projection matrix in handleResize. You have to always clear the projection matrix before you call gluPerspective, or else you will get a bogus result.
If you take the exact code from your pastebin, and add a glLoadIdentity to handleResize, I think that should work then:
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); //<--- add
glLoadIdentity(); //<--- add
gluPerspective(45.0,(double)w / (double)h,1.0,200.0);
}
Also, you're still clearing the projection matrix during the drawScene function. When you clear the matrix, you're throwing away the perspective setting that you just set in handleResize, you don't want to do that.
So basically:
Set the Projection matrix in handleResize and on initialization
Don't touch the projection matrix in drawScene
Translate the object so that it fits into the viewing frustum.
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.