Regarding glutReshapeFunc() - c

I have small code drawing a square initially but when I maximize the window it changes to rectangle. I know this has do with aspect ratio and when I add glutReshapeFunc(Reshape); call it works perfectly, I mean after maximizing the window, it remains square only. ReshapFunc is called every time display is modified and before the first display as well.
I am not getting just by adding reshapefunc, how it maintains aspect ratio. Please help me understanding this. I am copying my code here:
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.5, 0.5, 1.0);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(0.5, -0.5);
glVertex2f(0.5, 0.5);
glVertex2f(-0.5, 0.5);
glEnd();
glutSwapBuffers();
glFlush();
}
void Reshape(int w, int h) {
glutPostRedisplay();
}
void init()
{
glClearColor(1.0, 0.0, 1.0, 0.0);
glColor3f(1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(200, 200);
glutCreateWindow("basics");
glutDisplayFunc(display);
// If I comment this, it will become rectangle.
glutReshapeFunc(Reshape);
init();
glutMainLoop();
}

Your problem is related to the use of gluOrtho2D (...). If you want to preserve aspect ratio, your projection matrix needs to be defined based on the dimensions of your window.
I suggest you do this in your reshape function:
GLdouble aspect = (GLdouble)w / (GLdouble)h;
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (-1.0 * aspect, 1.0 * aspect, -1.0, 1.0);
glMatrixMode (GL_MODELVIEW);
glViewport (0, 0, w, h);

Related

Where is my display function being called in GLUT?

I do not understand how this main function works. I have a display function, which uses glDrawArrays, but I do not see it being called. I only see it being used as a parameter for glutDisplayFunction.
Here is my main:
int main(int argc, char** argv){
// Set up the window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize(800, 600);
glutCreateWindow("Hello Triangle");
// Tell glut where the display function is
glutDisplayFunc(display);
// A call to glewInit() must be done after glut is initialized!
GLenum res = glewInit();
// Check for any errors
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
// Set up your objects and shaders
init();
// Begin infinite event loop
glutMainLoop();
return 0;
}
The problem is, I need to create two different triangles, on the same window, using seperate VAOs and VBOs. I've created the seperate VAO and VBO for my second triangle. However, I do not see how I am meant to generate and link my buffers, draw my arrays, switch to my second buffer, and draw those arrays, when I do not even know when my display function is being called.
My display function looks like this:
void display(){
glClear(GL_COLOR_BUFFER_BIT);
// NB: Make the call to draw the geometry in the currently activated vertex buffer. This is where the GPU starts to work!
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
All operations could be done in separate function named asyouwant called from main
example:
#include <GL/glut.h>
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutInitWindowSize(300, 300);
glutInitWindowPosition(100, 100);
glutCreateWindow("Hello world :D");
glutDisplayFunc(displayMe); // = > draw in displayme function
glutMainLoop();
return 0;
}
void displayMe(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.5, 0.0, 0.0);
glVertex3f(0.5, 0.5, 0.0);
glVertex3f(0.0, 0.5, 0.0);
glEnd();
// a second geoform
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(-0.5, 0.0, 0.0);
glVertex3f(-0.5, -0.5, 0.0);
glVertex3f(0.0, -0.5, 0.0);
glEnd();
glFlush();
}
As complement: for VAO and buffer
1- Init (declare VAO , declare buffer of vertices, ...)
GLuint VaoID;
glGenVertexArrays(1, &VaoID);
glBindVertexArray(VaoID);
// An array of 3 vectors which represents 3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
Once time only
// This will identify our vertex buffer
GLuint vertexbuffer;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
2- Use it (bind and draw in display fucntion)
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0);

Draw 2D and 3D in the same OpenGL window

I'm creating a 3D game with OpenGL and I would like to make a toolbar in the top of the window. For that, I tried to use SDL to draw the buttons and OpenGL to draw the actual game. Here is the relevant part of my code:
void openMainWindow(){
SDL_Surface *screen;
SDL_Event event;
SDL_Rect position;
SDL_Init(SDL_INIT_VIDEO);
putenv("SDL_VIDEO_CENTERED=center");
SDL_WM_SetCaption("Example",NULL);
SDL_WM_SetIcon(IMG_Load("icon.png"),NULL);
screen = SDL_SetVideoMode(832,487,32,SDL_HWSURFACE | SDL_OPENGL);
glLoadIdentity();
gluPerspective(70,(double)832/487,1,1000);
//Some things to initialize the window
int continue = 1;
while(continue){
SDL_PollEvent(&event);
switch(event.type){
//Events
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
//Draw a square
glEnd();
//Draw more things the same way
glFlush();
SDL_GL_SwapBuffers();
SDL_Surface *button1 = SDL_CreateRGBSurface(SDL_HWSURFACE,50,50,32,0,0,0,0);
SDL_FillRect(button1,NULL,SDL_MapRGB(screen->format,50,50,50);
position.x = 8;
position.y = 8;
SDL_BlitSurface(button1,NULL,screen,&position);
SDL_Flip(screen);
}
SDL_Quit();
}
The problem with this is that when this function is called, the process ends and returns 3 (which means that there is an error). So I tried to draw the buttons with OpenGL like this:
void openMainWindow(){
//Everything before the while loop is the same as in the other code
int continue = 1;
while(continue){
SDL_PollEvent(&event);
switch(event.type){
//Events
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
//Draw a square
glEnd();
//Draw more things the same way
glDisable(GL_DEPTH_TEST);
glLoadIdentity();
glBegin(GL_QUADS); //Draw the button
glColor3ub(50,50,50);
glVertex2d(-0.5,-0.5);
glVertex2d(-0.5,0.5);
glVertex2d(0.5,0.5);
glVertex2d(0.5,-0.5);
glEnd();
glEnable(GL_DEPTH_TEST);
glFlush();
SDL_GL_SwapBuffers();
}
SDL_Quit();
}
I know that the second code should center the button in the window, but I use this code just to test if it works (and it doesn't, that's why I'm posting this question).
With the second code, the 3D things appear in the window as they should, but I can't see any button. How do I put 2D buttons in a 3D OpenGL window?
The second code works by adding the following right before drawing the 2D button:
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glDisable(GL_DEPTH_TEST);
glLoadIdentity();
and the following code right after drawing the 2D button:
glEnable(GL_DEPTH_TEST);
gluPerspective(70,(double)640/480,0.5,INFINITE); //These parameters have to be the same as the ones used for gluPerspective when initializing the 3D
gluLookAt(0,0,3,1,0,3,0,0,0.01); //Where you want to position the camera and where you want to look at
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Here is the complete code that works:
void openMainWindow(){
//Everything before the while loop is the same as in the other code
int continue = 1;
while(continue){
SDL_PollEvent(&event);
switch(event.type){
//Events
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
//Draw a square
glEnd();
//Draw more things the same way
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glDisable(GL_DEPTH_TEST);
glLoadIdentity();
glBegin(GL_QUADS); //Draw the button
glColor3ub(50,50,50);
glVertex2d(-0.5,-0.5);
glVertex2d(-0.5,0.5);
glVertex2d(0.5,0.5);
glVertex2d(0.5,-0.5);
glEnd();
glEnable(GL_DEPTH_TEST);
gluPerspective(70,(double)640/480,0.5,INFINITE); //These parameters have to be the same as the ones used for gluPerspective when initializing the 3D
gluLookAt(0,0,3,1,0,3,0,0,0.01); //Where you want to position the camera and where you want to look at
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glFlush();
SDL_GL_SwapBuffers();
}
SDL_Quit();
}

How to setup gluLookat() and glOrtho() in openGL?

I am new to openGL and have a hard time to understand how to actually parametrize the function gluLookat. I what it does but don't know how to know which parameters I should pass to that function and what consequences it will have.
This is my current code and strangely enough I don't even see the axis I drew... I think it is due to the parameters I pass to the function gluLookAt();
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
void init(void)
{
glClearColor(0.8, 0.8, 0.8, 0.0); /* window color white */
glEnable(GL_DEPTH_TEST);
}
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(3.0,3.0,3.0, 0.0,0.0,0.0, 0.0,1.0,0.0);
//used some random parameters...
gluLookAt(0.0, 0.0, 0.0, 5.0, 5.0, 5.0, 0, 1, 0);
//axis
//x
glColor3f(1.0,0.0,0.0);
glLineWidth(1.0);
glBegin(GL_LINES);
glVertex3d(0.0,0.0,0.0);
glVertex3d(1.0,0.0,0.0);
glEnd();
//y
glColor3f(0.0,1.0,0.0);
glLineWidth(1.0);
glBegin(GL_LINES);
glVertex3d(0.0,0.0,0.0);
glVertex3d(1.0,0.0,0.0);
glEnd();
//z
glColor3f(0.0,0.0,1.0);
glLineWidth(1.0);
glBegin(GL_LINES);
glVertex3d(0.0,0.0,0.0);
glVertex3d(1.0,0.0,0.0);
glEnd();
glFlush();
}
void herschaal(){
glViewport(0,0,500,500);
glMatrixMode(GL_PROJECTION);
glOrtho(-10, 10, 10, -10, 10, -10);
glLoadIdentity();
}
int main( int argc, char * argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowPosition(50, 100);
glutInitWindowSize(500, 500);
glutCreateWindow("mijn test");
glutReshapeFunc(herschaal);
init();
glutDisplayFunc(drawScene);
glutMainLoop();
return 0;
}

Drawing a polygon when the mouse is clicked

Consider this code:
#include <stdlib.h>
#include <stdarg.h>
#include <GLUT/GLUT.h>
#include <OpenGL/OpenGL.h>
double width=600;
double height=600;
void processMouse(int button, int state, int x, int y)
{
glColor4f(1.0,0.0,0.0,0.0);
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glFlush();
}
static void render()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
glutMouseFunc(processMouse);
}
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutCreateWindow("Board");
glutDisplayFunc(render);
glutMainLoop();
}
The render function is executed, and every time a click is performed, it should start the function processMouse.
So if the mouse is clicked, all the window should become red with the instructions:
glColor4f(1.0,0.0,0.0,0.0);
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glFlush();
But when I click the mouse I notice a strange behaviour: only a part of the window gets colored, the part at bottom left (instead of all the screen).
The window remains in this state, until I open a google chrome window.If I open a google chrome (or another graphical application), all the window become colored of red.
Why this? I also have problems with more complex programs, it seems like sometime the glVertex instructions are ignored.If I try debugging the program with fprintf it appears that everything is ok, and everything seems to go like expected (for example I tried to print mouse coordinates in the processMouse function, they were ok), except for the fact that what I draw is ignored.
Edit:
I have modified this code but it still has the same problem:
#include <stdlib.h>
#include <stdarg.h>
#include <GLUT/GLUT.h>
#include <OpenGL/OpenGL.h>
double width=600;
double height=600;
bool down=false;;
// http://elleestcrimi.me/2010/10/06/mouseevents-opengl/
static void render()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
if(down)
{
glColor4f(1.0,0.0,0.0,0.0);
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glFlush();
}
}
void processMouse(int button, int state, int x, int y)
{
if(state==GLUT_DOWN)
{
down=true;
glutPostRedisplay();
}
}
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutCreateWindow("Board");
glutMouseFunc(processMouse);
glutDisplayFunc(render);
glutMainLoop();
}
Still getting only a part of the screen red.
PS: Solved using glutSwapBuffers(), thanks.
When you are using double buffering with GLUT, you need to call glutSwapBuffers() to see the result of the draw.
Add this to the end of your render() function and it will work fine.

Texture mapping in OpenGL (with SOIL)

I'm having trouble getting a texture loaded with SOIL to show up properly on this quad. In case it's not clear, I'm just writing up a little 2D sprite engine, and this is the rendering portion (needs a bit of optimization without a doubt). I haven't done any OpenGL in a couple months, and I'm admittedly quite rusty.
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include "SOIL.h"
#include <stdio.h>
GLuint linktex;
void drawSprite(GLint left, GLint right, GLint bottom, GLint top, GLuint texture){
//Draw clockwise
glColor3f(1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2i(1,1); glVertex2i(right , top);
glTexCoord2i(1,0); glVertex2i(right , bottom);
glTexCoord2i(0,0); glVertex2i(left , bottom);
glTexCoord2i(0,1); glVertex2i(left , top);
glEnd();
}
void display(void){
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho(0.0, 240.0, 0.0, 160.0, -1.0, 1.0);
drawSprite(50, 82, 50, 82, linktex);
glFlush();
}
void reshape(int w, int h){
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
void init(){
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glFrontFace(GL_CW);
GLuint linktex = SOIL_load_OGL_texture(
"link.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
if( 0 == linktex )
{
printf( "SOIL loading error: '%s'\n", SOIL_last_result());
}
}
int main (int argc, char **argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE);
glutInitWindowSize (240, 160);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Test");
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutMainLoop();
init();
return 0;
}
It looks like when you are loading the texture, you are assigning the id to a local variable linktex instead of the global you declared at the beginning of the file.
When you reference linktex in the void display(void); method, the texture is un-initialized.
Try changing your call to load the texture to :
// comment out the type declaration, to assign to the global instead of a local
/*GLuint*/ linktex = SOIL_load_OGL_texture(
"link.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y
);

Resources