Saturday, April 30, 2011

Creating a more object-oriented OpenGL Window with Freeglut in C++

As per my previous post where I described how to build an OpenGL window, it was basically a c-to-c++ code transition with explainations of what different methods did.

In this post, I will be posting my code where the window preferences and display information is inside a class and only the main() method is not part of the object.

There are two parts to the following code: the cpp file and the header file. You need them in two separate files and in the same directory for things to compile properly without modifications.

Please feel free to rate and critique the code I post. Also, the method names and filenames are part of a project I'm working on, so feel free to change them. They make sense to me.

Also, I am licensing the following code under the GPL 2. Feel free to distribute and modify the source as you like.

rwindow.cpp

#include <stdlib.h>

#include <stdio.h>

#include <GL/glew.h>

#include <GL/freeglut.h>

#include <GL/gl.h>

#include "rwindow.h"

RWindow::RWindow()

{

str_window_title = "Hello World";

usi_hwindow = 250;

usi_vwindow = 250;

usi_windowx = 100;

usi_windowy = 100;

}

RWindow::RWindow(string newtitle)

{

str_window_title = newtitle;

usi_hwindow = 250;

usi_vwindow = 250;

usi_windowx = 100;

usi_windowy = 100;

}

void RWindow::SetWindowTitle(string newtitle)

{

str_window_title = newtitle;

}

string RWindow::GetWindowTitle() const

{

return str_window_title;

}

void RWindow::SetWindowHorizontal(unsigned short int newsize)

{

usi_hwindow = newsize;

}

unsigned short int RWindow::GetWindowHorizontal() const

{

return usi_hwindow;

}

void RWindow::SetWindowVertical(unsigned short int newsize)

{

usi_vwindow = newsize;

}

unsigned short int RWindow::GetWindowVertical() const

{

return usi_vwindow;

}

unsigned short int RWindow::GetWindowX() const

{

return usi_windowx;

}

void RWindow::SetWindowX(unsigned short int newsize)

{

usi_windowx = newsize;

}

unsigned short int RWindow::GetWindowY() const

{

return usi_windowy;

}

void RWindow::SetWindowY(unsigned short int newsize)

{

usi_windowy = newsize;

}

RWindow::~RWindow()

{

// remove new variables if any

// remove self

delete this; // Make sure pointer is null

}

void RWindow::display_contents()

{

/* clear all pixels */

glClear (GL_COLOR_BUFFER_BIT);

/* draw white polygon (rectangle) with corners at

* (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0)

*/

glColor3f (1.0, 1.0, 1.0);

glBegin(GL_POLYGON);

glVertex3f (0.25, 0.25, 0.0);

glVertex3f (0.75, 0.25, 0.0);

glVertex3f (0.75, 0.75, 0.0);

glVertex3f (0.45, 0.45, 0.0);

glEnd();

/* don't wait!

* start processing buffered OpenGL routines

*/

glFlush ();

};

void RWindow::init ()

{

/* select clearing (background) color */

glClearColor (0.0, 0.0, 0.0, 0.0);

/* initialize viewing values */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, 1.0, 0.0, 1.0, 1.0, -1.0);

};

/*

* Declare initial window size, position, and display mode

* (single buffer and RGBA). Open window with "hello"

* in its title bar. Call initialization routines.

* Register callback function to display graphics.

* Enter main loop and process events.

*/

int main(int argc, char** argv)

{

// Code to initialize window. Normally this would be in another class

RWindow *testWindow = new RWindow();

glutInit(&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGBA);

glutInitWindowSize (testWindow->GetWindowHorizontal(), testWindow->GetWindowVertical());

glutInitWindowPosition (testWindow->GetWindowX(), testWindow->GetWindowY());

// .c_str() converts string to constant char*, which this function needs

glutCreateWindow (testWindow->GetWindowTitle().c_str());

testWindow->init ();

glutDisplayFunc(RWindow::display_contents);

glutMainLoop();

delete testWindow;

return 0; /* ISO C requires main to return int. */

};

rwindow.h

#ifndef R_WINDOW

#define R_WINDOW

#include <string>

using namespace std;

class RWindow

{

public:

RWindow();

RWindow(string);

virtual ~RWindow();

void SetWindowTitle(string);

string GetWindowTitle() const;

void SetWindowHorizontal(unsigned short int);

unsigned short int GetWindowHorizontal() const;

void SetWindowVertical(unsigned short int);

unsigned short int GetWindowVertical() const;

void SetWindowX(unsigned short int);

unsigned short int GetWindowX() const;

void SetWindowY(unsigned short int);

unsigned short int GetWindowY() const;

static void init();

static void display_contents();

private:

string str_window_title;

unsigned short int usi_hwindow;

unsigned short int usi_vwindow;

unsigned short int usi_windowx;

unsigned short int usi_windowy;

};

#endif

In order to compile type this:

g++ -Os rwindow.cpp -lGL -lglut -lX11 -lXext -o ~/example-window

Things you can expand on: adding shape-building methods and including them in display_contents(), random polygon generation, etc. etc.

More to come.

=-=-=-=-=
Powered by Blogilo

Thursday, April 28, 2011

Creating an OpenGL Window with Freeglut in C++

It seems everybody exudes the virtues of OpenGL's 3D capabilities. That's all fine and good, but what about 2D?

While searching for information on creating my own 2D hardware-accelerated platform, I came across this excellent website.

http://nehe.gamedev.net/

- See the opengl tutorials on the left-hand side.

And as always, the official OpenGL website is a great resource.

http://www.opengl.org/resources/libraries/

Making a window using Freeglut to accelerate it through OpenGL isn't too difficult.

I can't remember where I found the code I am using as an example, but the gist of it can be found here:

http://www.codeproject.com/KB/openGL/OpenGLWindowWithGLUT.aspx?display=Mobile

(Credit goes to whomever wrote it)

Differences include:

  • This probably won't run on a Windows box
  • We have to compile it manually (see below)

Alright. Onto the code.

First we have the headers. They are C headers, but Freeglut is a C++ friendly library so there shouldn't be any problems.

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <GL/glew.h>

#include <GL/freeglut.h>

#include <GL/gl.h>

We are importing two main categories of libraries: standard C libraries that handle input/output, library functions and strings as well as the OpenGL libraries.

using namespace std;

Use the standard namespace so you don't have to write out the path of the library functions. It makes reading the code a lot easier.

Now to include a method that will display a static something in the window when we get to that point.

The reason we are writing this function right after the include and namespace statements is because both C and C++ (to name two of many programming languages) cannot call a method that it does not know about at compile time. If this function was at the bottom of our file and we called it at the top, it wouldn't know that function existed yet so it would fail.

void display(void)

{

/* clear all pixels */

glClear (GL_COLOR_BUFFER_BIT);

/* draw white polygon (rectangle) with corners at

* (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0)

*/

glColor3f (1.0, 1.0, 1.0);

glBegin(GL_POLYGON);

glVertex3f (0.25, 0.25, 0.0);

glVertex3f (0.75, 0.25, 0.0);

glVertex3f (0.75, 0.75, 0.0);

glVertex3f (0.25, 0.75, 0.0);

glEnd();

/* don't wait!

* start processing buffered OpenGL routines

*/

glFlush ();

}

The statements are fairly self-explainatory here. glClear clears the window of previous drawings, sets a colour (white), creates a polygon (in this case, a square/rectangle), sets the points and then completes the shape, It then calls the glFlush so that all images that have been declared (have a Begin/End) get displayed.

The reason for having a flush statement is because a) it is faster to store a bunch of shapes in memory and display them after a period of time (aka a flush of the video buffer) than it is to display each and every object right after it gets created, plus b) it makes predicting and controlling frame rates a LOT easier. There are lots of reasons I'm probably not getting to, but it is important.

You could put the flush statement in the main loop after the display() method, but that would be if you want animations or are doing game design, and I recommend keeping the main loop as clean as possible. Plus it would make conditions a lot easier to write. Sometimes the flush() method is skipped because the hardware cannot keep up with the window which causes the dropping of frames to keep framerate acceptible. It will cause 'lag', but won't slow the entire program down to a crawl.

Another point to note: the glVertex3f function. Perhaps you are thinking it should be 'glVertex3d' because we are dealing with 3d graphics libraries here. This is not the case. The '3f' part of the function stands for '3 float parameter' (3f) function. As you can see, the method as 3 values that are floats and must stay as floats. (A float is a number with decimal places, smaller than a double value) If there is no number/letter suffix to the method, it probably has just one type of input parameter.

There could be a glVertex3d method, which would take doubles. Or a glVertex3i, which takes 3 integers. As you can see, the number/letter notation is a great way to know how the method gets used. Of course, you need to know the different C types as a pre-requesite to make good use of this.

void init (void)

{

/* select clearing (background) color */

glClearColor (0.0, 0.0, 0.0, 0.0);

/* initialize viewing values */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);

}

The init method is next. It takes no parameters itself, like the display method above. All this does is set a few values for the window we'll be creating. The window we'll be drawing will need a background colour (otherwise the background of your computer will be seen through it) and some values set.

I'm not an expert in OpenGL by any means, so when I describe the glMatrixMode() method, I could be off.

There are a few different modes that OpenGL can operate in. GL_PROJECTION mode which I'm guessing is a more 2D-oriented mode, GL_MODELVIEW which does 3D, GL_TEXTURE which applies images and other texturey things to a surface (2D or 3D) therefore requires efficient I/O operations, and GL_COLOR which works on colour algorithms such as blending, transparencies and effects than actual objects.

glOrtho is part of the GL_PROJECTION Matrix Mode. It may be 2D only. The first 4 double values determine the four points of the buffer we display. Left, Right, Bottom, Top. The next two values are near and far values, glOrtho seems to deal with inversion and clipping. The OpenGL article seems to depict that it is a matrix transformation that replaces the current matrix (or what has been written to the video buffer).

Anyway, enough math for now. It may be better to experiment with changing values than to explain it with words.

The main() method, not to be mistaken for the main loop I mentioned earlier, sets up the window.

/*

* Declare initial window size, position, and display mode

* (single buffer and RGBA). Open window with "hello"

* in its title bar. Call initialization routines.

* Register callback function to display graphics.

* Enter main loop and process events.

*/

int main(int argc, char** argv)

{

glutInit(&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize (250, 250);

glutInitWindowPosition (100, 100);

glutCreateWindow ("hello");

init ();

glutDisplayFunc(display);

glutMainLoop();

return 0; /* ISO C requires main to return int. */

}

The header with the 'int argc, char** argv' is a C and C++ thing for command line parameters. It could probably be void, but would leave the program with little to no options if it wanted it to run a certain way.

Here's where we use glut commands. Init glut using the method parameters GLUT_SINGLE and GLUT_RGB. These are parameters: GLUT_SINGLE should set up a single buffer for the window while GLUT_RGB allows Red/Green/Blue colour values in it. GLUT_RGBA is also a possible option and I assume includes alpha transparency too.

glutWindowSize and glutWindowPosition are self explainatory. glutCreateWindow sets the window title bar text. Size and Position on your desktop. init() sets up the internals to freeglut while glutDisplayFunc() specifies the name of the method to call for displaying things using GL syntax. glutMainLoop() is that main loop I mentioned earlier and should loop through, refreshing the display so when you move the window, it doesn't get corrupted. (Don't quote me on that though).

Return statement exists as an ISO standard. Even if the program never gets to the return statement, it's required.

So that's a window example in freeglut, opengl, and c++. Copy all the code segments into a text file, save as "filename".cpp. (change filename to something else if you wish, change it in your compile statement too though.)

To compile it, you must first have installed the freeglut libraries and opengl libraries AND have a compatible video card.

But that's not all, you must also specify the libraries in the compile statment so it will include them.

g++ -Os filename.cpp -lGL -lglut -lX11 -lXext -o ~/filename

First off, "-Os" is an optimization flag. Good options are -O1, -O2, and -Os. -Os optimizes the program for small size. Can be omitted.

-lGL and -lglut are required, the -l means include library and we are including glut and opengl. (it's not -lfreeglut because freeglut is meant as a replacement for glut, an abandonded library, so requires the same import name.)

You can omit the -lX11 and -lXext, at least, it works on my machine. It still works when I include them, so maybe it's just if you write in C.

Lastly, -o means output and the next parameter is where to put it and what the program is called using a path. ~ means home directory for Unix or GNU/Linux users.

I'm fairly new to OpenGL windows, but I hope this helps other new users to start up their development-fu for hardware accelerated applications.

If learning this low-level stuff isn't for you, check out QT and KDE application libraries. They have this stuff built in already.

Thanks for stopping by and look forward to more.

=-=-=-=-=
Powered by Blogilo

Saturday, April 23, 2011

Installing Adobe Flash "Square" on a 64-bit Linux Distribution, Firefox 4

In the past month I set myself up a beautiful pure 64-bit Gentoo system on my Thinkpad X61. It's not completely ready yet, as I have yet to compile my custom kernel that should allow the wacom screen to be recognized.

Installing 64-bit Flash "Square" should be the exact same procedure on any major GNU/Linux distribution, so there shouldn't be any specific instructions. Also, this instruction set ignores the "proper" distro way of doing things.

Ubuntu has an install-flashplayer deb that does things for the user. Which is preferrable, as the way I am about to describe does not provide automatic updates. And before we continue, I should stress that Flash Square is a PREVIEW and flash is inherantly insecure due to it being a proprietary offering and ubiquitous on the web.

This method installs flash in "userspace", or in a way that does not require admin privileges. This method reduces the consequences if your computer is comprimised through flash by not being able to touch your system.

1. Download Flash Player "Square" from Adobe's web site: http://labs.adobe.com/downloads/flashplayer10_square.html

Check under the heading "64-bit Release Flash Player Downloads" and choose what should be the last option: plugin for 64-bit linux

(I shake my head at Adobe. Flash doesn't run in the kernel; they should change it to "linux-based OS" or the proper "GNU/Linux" label)

2. Extract the .tar.gz download. This can be done via command line by typing "tar -xvf [file]".

3. Make sure that the plugins folder exists. It didn't by default for my system. "mkdir -p ~/.mozilla/plugins/"

My first attempt at this failed because I created the plugins directory in .mozilla/firefox/.

4. Copy the libflashplayer.so file to the user's plugin folder. This command should work: "cp libflashplayer* ~/.mozilla/plugins/"

If you get any errors in the previous commands, you are probably in the wrong directory when typing them, you are typing the double-quotes (don't), or you aren't in the shell/command line. As well, this is for Firefox 4. Theoretically it should work for previous versions of Firefox, but I'm a little lazy to make sure.

And if you haven't checked out Mozilla's newest browser version, you really should. Startup times alone are much improved. Having a default page already cached helps, but the option to load your previously viewed tabs on last exit is convenient.

I have been doing some introductory coding in OpenGL, Freeglut and C++/QT lately. I hope to come out with some tutorials for those as well in the near future.

=-=-=-=-=
Powered by Blogilo