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.
Related
I have surfed a lot of sources and tried many varieties, but zooming still don't work. I can't change glprojection to gluPerspective, because in this case my prog don't draw anything. Here is approximate code.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "glut.h"
#define windowSize 900.0
double zoomFactor = 1;
void reshape (int w, int h)
{
glViewport (0.0, 0.0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (-(GLdouble) w * zoomFactor, (GLdouble) w* zoomFactor, -(GLdouble) h* zoomFactor, (GLdouble) h* zoomFactor);
}
void mouse(int button, int state, int x, int y)
{
if (button == 3 || button == 4 )
{
if (state == GLUT_UP) zoomFactor += 0.05;
else zoomFactor -= 0.05;
}
else return;
glutReshapeFunc(reshape);
}
Void display(){
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2f ((0),(0));
glVertex2f ((100),(0));
glEnd();
glBegin(GL_LINES);
glVertex2f ((100),(0));
glVertex2f ((100),(100));
glEnd();
glBegin(GL_LINES);
glVertex2f ((0),(0));
glVertex2f ((100),(1000));
glEnd();
glFlush();
}
int main(int argc,char** argv)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(windowSize, windowSize);
glutInitWindowPosition(500,0);
glutCreateWindow("test");
glClearColor(0, 0.1,0.8,0.90);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 200, 200,0);
glutDisplayFunc( display );
glutMouseFunc(mouse);
glutMainLoop(;
return(0);
}
glutReshapeFunc only tells GLUT which function to call, when the window size changes. It makes very little sense to call it in response to an input event as it will not call the reshape function.
Anyway, your problem is, that you placed setting the viewport and the projection in the reshape function. To all the tutorial writers out there: Stop doing that, it just ingrains bad habits into newbies.
Now please speak with me: "Everything drawing related goes into the display function. The viewport is a drawing state and in every OpenGL program just a little bit more complex than 'Hello Triangle' the viewport is going to be changed several times drawing a single frame – for example when using framebuffer objects. I will thereby vow to never place calls to glViewport or projection matrix setup in the window reshape handler. I also vow to slap everyone in the face who writes code like this in my presence."
Move the whole stuff in your reshape function into display (either set global variables, or use glutGet(GLUT_WINDOW_{WIDTH,HEIGHT}) to get the window dimensions in the display function) and call glutPostRedisplay in your mouse wheel function to trigger a redraw.
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.
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.
I have written a simple OpenGL program in C++ that displays a line joining the center of the window to the current position of the mouse pointer.
My code is :
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include<iostream>
using namespace std;
void passive(int,int);
void reshape(int,int);
void init(void);
void display(void);
void camera(void);
int x=3,y=3;
int main (int argc,char **argv) {
glutInit (&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
glutInitWindowSize(1364,689);
glutInitWindowPosition(0,0);
glutCreateWindow("Sample");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutPassiveMotionFunc(passive);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
void display(void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
camera();
glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(x,y,0);
glEnd();
glutSwapBuffers();
}
void camera(void) {
glRotatef(0.0,1.0,0.0,0.0);
glRotatef(0.0,0.0,1.0,0.0);
glTranslated(0,0,-20);
}
void init(void) {
glEnable (GL_DEPTH_TEST);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_COLOR_MATERIAL);
}
void reshape(int w, int h) {
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)w/(GLfloat)h,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
}
void passive(int x1,int y1) {
x=x1; y=y1;
}
The problem I am facing is that the x and y values set in the passive() function is not correctly mapped into the screen which uses perspective projection. So the line drawn is joining the center to some other coordinate outside the screen. Any modifications to the code to get it working properly?
An easy way would be to create an orthographic projection matrix and then render all of your "2D" elements (including this line, using the screen coordinates provided by glutPassiveMotionFunc).
Something like this:
void display() {
// clear
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( ... ) // create 3D perspective projection matrix
glMatrixMode(GL_MODELVIEW);
// Render 3D content here
// Render 2D content
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, height, 0); // create 2D orthographic projection matrix with coordinate system roughly equivalent to window position
glMatrixMode(GL_MODELVIEW);
glBegin(GL_LINES);
glVertex2f( width / 2, height / 2 ); // now we can use "pixel coordinates"
glVertex2f( cursorX, cursorY );
glEnd();
...
}
Compare this to your modification of the perspective projection in your reshape method.
Obviously you'll also want to disable states that don't make sense for a "2D" rendering (like depth buffer checking, etc) but it should be pretty obvious. Take a look at this GDSE post for a discussion of how other people do this same task.
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.