Bouncing Shape in GLFW

Introduction

I've used FreeGLUT a few times, but after seeing some recommendations of GLFW, I came across a web page referring to the source code for two programs that do the same thing, but one uses GLFW whilst the other uses FreeGLUT. Alas, the GLFW source code wouldn't compile for me, and once I got it compiling, it still wouldn't work. It seems that the code was written for an older version of GLFW.

Having got it compiling and working, I thought I'd return the favour by publishing my working version. I don't know who to credit, since the article is “published by John1015”, whilst the article is hosted on the website of “Sassan Barkeshli”, and the article itself credits the code to “Davina”!

Explanation of Changes

#include <windows.h>

Line 10: The window.h header file has to be included before the glfw.h file. This is a common problem, judging from how many times I've seen it mentioned online.

#include <GL/glu.h>

Line 11: The glu.h header file is needed for the gluPerspective() function call.

void handleKeypress(GLFWwindow* window, int key, int scancode, int action, int mode) //The key that was pressed

Line 28: GLFW has changed considerably the way many functions are called. handleKeyPress is just a void type, and provides more properties for the key event.

if (action == GLFW_PRESS) {

Line 30: By checking the action event property, we can prevent a single press causing more than one response; other responses come from the release of the key, for instance.

case GLFW_KEY_ESCAPE:

Line 44: GLFW_KEY_ESC has been renamed to GLFW_KEY_ESCAPE.

void handleResize( GLFWwindow* window, int width,int height)

Line 51: The return type of the handleResize() function is simplified to just void, and the function now takes the window handle reference as an argument.

int fbwidth, fbheight;
glfwGetFramebufferSize( window, &fbwidth, &fbheight );
//Tell OpenGL how to convert from coordinates to pixel values
glViewport( 0, 0, fbwidth, fbheight );

Lines 53 to 56: GLFW warns that the glViewport() function should be passed the size of the framebuffer, as opposed to the window.

void display(GLFWwindow* window)

Line 66: THe display() function takes the window handle reference in order to pass it to the glfwSwapBuffers(), which now requires it.

glTranslatef(transX,transY,0.0f);
...
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);

Lines 77, and 82 to 85: The depth (Z) value of -5.0 prevents the shape from being visible. Setting it to zero makes it visible.

glfwSwapBuffers(window);

Line 89: glfwSwapBuffers() now takes the window handle reference.

GLFWwindow* window = glfwCreateWindow( 512, 512, NULL, NULL, NULL );
if ( !window )

Line 100 and 101: glfwOpenWindow() has been replaced by glfwCreateWindow(), which takes a different set of arguments, and returns a reference to the window's handle.

glfwSetWindowTitle(window, "codeincodeblock.blogspot.com - basic shape");
glfwSetWindowSizeCallback(window, handleResize); //callback function of GLFW to handle window resize
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, handleKeypress); //callback function to handle keypress

Lines 107 to 110: The callback functions now take the handle to the window. Also, calling glfwMakeContextCurrent() is required????

display(window);

Line 117: The handle to the window must be passed to the display() function.

if (transY<=0.0f)
...
if (transY>=-1.0f)
...
if (transX<=0.0f)
...
if (transX>=-1.0f)

Lines 120, 125, 130, and 135: The original values don't work.

glfwPollEvents();

Line 139: glfwPollEvents() is required for the keyboard events to be handled.

running = !glfwWindowShouldClose(window);

Line 140: glfwGetWindowParam() is replaced by glfwGetWindowAttrib(), but glfwWindowShouldClose() seems more appropriate here.

The Full Working Source Code

Here's the full code, which works for me. It was compiled with Visual Studio 2012, Windows SDK 8.1, and GLFW 3.1.2. The host system was Windows 7, 64 bit (although a 32 bit version was compiled), with a fairly ordinary NVIDIA GeForce card.


/*
 * RETRIEVED: 2015-09-08 09:24
 *
 * FROM: http://pastebin.com/k3dbDKdn
 *
 * VIA: http://barkeshli.org/pcc/node/783
 *
 */

#include <windows.h>
#include <GL/glu.h>
//include header file for glfw library so that we can use OpenGL
#include <GLFW/glfw3.h>
#include <stdlib.h>  //needed for exit function
#include <iostream>
using namespace std;

float transX =0.0f;
float transY =0.0f;

//Initializes 3D rendering
void initializeRendering()
{
	glfwInit();
}

//Called when a key is pressed
void handleKeypress(GLFWwindow* window, int key, int scancode, int action, int mode) //The key that was pressed
{
	if (action == GLFW_PRESS) {
		switch (key) {
			case GLFW_KEY_UP:
				transY += 0.1f;
				break;
			case GLFW_KEY_DOWN:
				transY -= 0.1f;
				break;
			case GLFW_KEY_RIGHT:
				transX += 0.1f;
				break;
			case GLFW_KEY_LEFT:
				transX -= 0.1f;
				break;
			case GLFW_KEY_ESCAPE:
				exit(0);
		}
	}
}

//Called when the window is resized
void handleResize( GLFWwindow* window, int width,int height)
{
	int fbwidth, fbheight;
	glfwGetFramebufferSize( window, &fbwidth, &fbheight );
	//Tell OpenGL how to convert from coordinates to pixel values
	glViewport( 0, 0, fbwidth, fbheight );

	glMatrixMode( GL_PROJECTION ); //Switch to setting the camera perspective
	//Set the camera perspective
	glLoadIdentity(); //reset the camera
	gluPerspective( 45.0f,                      //camera angle
			(GLfloat)width/(GLfloat)height, //The width to height ratio
			1.0f,                          //The near z clipping coordinate
			100.0f );                       //The far z clipping coordinate
}
void display(GLFWwindow* window)
{
	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); //clear background screen to black

	//Clear information from last draw
	glClear( GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
	glLoadIdentity(); //Reset the drawing perspective

	glPushMatrix();
	glTranslatef(transX,transY,0.0f);

	glBegin(GL_QUADS);
	glColor3f(0.6f, 0.1f, 0.6f);
	//square
	glVertex3f(0.0f, 0.0f, 0.0f);
	glVertex3f(1.0f, 0.0f, 0.0f);
	glVertex3f(1.0f, 1.0f, 0.0f);
	glVertex3f(0.0f, 1.0f, 0.0f);
	glEnd();

	glPopMatrix();
	glfwSwapBuffers(window);

}
int main()
{
	// int     width, height;
	//int     frame = 0;
	bool running = true;

	initializeRendering();

	GLFWwindow* window = glfwCreateWindow( 512, 512, NULL, NULL, NULL );
	if ( !window )
	{
		glfwTerminate(); //terminating glfw window
		return 0;
	}

	glfwSetWindowTitle(window, "codeincodeblock.blogspot.com - basic shape");
	glfwSetWindowSizeCallback(window, handleResize); //callback function of GLFW to handle window resize
	glfwMakeContextCurrent(window);
	glfwSetKeyCallback(window, handleKeypress); //callback function to handle keypress
	bool Up= false;
	bool Right=false;

	while(running) // infinite loop to draw object again and again
	{              // because once object is draw then window is terminated
		Sleep(10);
		display(window);

		if(Up){
			if (transY<=0.0f)
				transY+=0.01f;
			else
				Up=false;}
		else{
			if (transY>=-1.0f)
				transY-=0.01f;
			else
				Up=true;}
		if(Right){
			if (transX<=0.0f)
				transX+=0.03f;
			else
				Right=false;}
		else{
			if (transX>=-1.0f)
				transX-=0.03f;
			else
				Right=true;}
		glfwPollEvents();
		running = !glfwWindowShouldClose(window);
		//if should-be-closed then return false
	}
	return 0;
}

	


Home About Me
Copyright © Neil Carter

Last updated: 2016-03-02