Using the Win32 API with OpenGL and Vertex Buffers

Posted on March 28, 2012

Everyone who has used the Win32 API knows that its not exactly the friendliest thing to work with. It has a lot of defines and macros that can make life difficult, and every time I need to use it, I find myself relearning everything from scratch.

Because of this repeated tedium, I decided to post a complete code file, showing how to use the Win32 API with OpenGL and Vertex Buffers in a nice, class-oriented way. You can find it in the code section of the site, or go straight to it:

Win32, OpenGL, and Drawing Vertex Buffers

Basic LibPNG usage with C++ and OpenGL

Posted on March 4, 2012

I am using LibPNG and Zlib in my game engine. After much frustration, I was finally able to get it to work. The following is my LoadImage function:

 
void Image::LoadImage( const char *filename ) {
	// Open up the file as a binary
	FILE *file_pointer = fopen( filename, "rb");
 
	if( file_pointer == 0 ) {
		Engine::console << "LoadImage failed: file '" << filename << "'does not exist." << std::endl;
		// The file does not exist. Create a false image that is just red.
		GenerateImage( 64, 64, 255, 128, 128, 255 );
		return;
	}
 
	// First we check the header, stored in the first 8 bytes of the file
	char header[8];
	fread(header, 1, 8, file_pointer );
	// png_sig_cmp will return 0 if the file read is not a PNG
	if (png_sig_cmp( (png_const_bytep) header, 0, 8) != 0 ) {
		Engine::console << "LoadImage failed: file '" << filename << "' is not a PNG." << std::endl;
		GenerateImage( 64, 64, 255, 128, 128, 255 );
		fclose( file_pointer );
		return;
	}
 
	// Initialize the two structures that will represent the PNG file.
	png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
	png_infop info_ptr  = png_create_info_struct( png_ptr );
 
	// This is an old C way to handle errors, and franky is not very good because it
	// can jump over class destructors if you're not careful.
	if ( setjmp( png_jmpbuf(png_ptr) ) ) {
		Engine::console << "LoadImage failed: file '" << filename << "' caused LibPNG to trigger an error response." << std::endl;
		GenerateImage( 64, 64, 255, 128, 128, 255 );
		// This block is called if there was an error reading the file
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		if ( file_pointer ) { fclose( file_pointer); }
		return;
	}
 
	// Initialize the reading of the file, skip the 8 signature bytes, and then read the file information
	png_init_io( png_ptr, file_pointer );
	png_set_sig_bytes( png_ptr, 8 );
	png_read_info( png_ptr, info_ptr );
 
	// Get the information, including image width, height, bit depth and color type.
	// Bit depth is the number of bits per channel, a channel being red, green, blue, or alpha.
	// Typically bit depth will be 8, meaning each channel gets 1 byte.
	image_width    = png_get_image_width ( png_ptr, info_ptr );
	image_height   = png_get_image_height( png_ptr, info_ptr );
	int bit_depth  = png_get_bit_depth( png_ptr, info_ptr );
	int color_type = png_get_color_type( png_ptr, info_ptr );
	int channels   = png_get_channels(png_ptr, info_ptr);
 
	// Allocate the data for the texture using its width and height. Reserve 4 bytes for RGBA pixels.
	image_data = new unsigned char[ image_width * image_height * 4 ];
 
	// Read the pixel data from the PNG into an array of rows.
	// First allocate memory for row structure.
	png_bytepp  row_pointers = new png_bytep[image_height];
 
	// Then go through each row, and allocate space for that row.
	for ( int i = 0; i < image_height; i++) {
		row_pointers[i] = new png_byte[ image_width * channels ];
	}
	// Finally, read the image into the row structure we just made.
	png_read_image(png_ptr, row_pointers);
 
	// Copy the image data into the image class's image_data, which
	// must be an array of RGBA pixels.
	for( int y = 0; y < image_height; y++ ) {
		// Get one row of pixels for the row structure
		png_bytep row = row_pointers[y];
		for( int x = 0; x < image_width; x++ ) {
			// Our data is stored in image_data, and the PNG pixels are stored in row
			image_data[ y * image_width * 4 + x*4 + 0 ] = row[ x * channels + 0 ];
			image_data[ y * image_width * 4 + x*4 + 1 ] = row[ x * channels + 1 ];
			image_data[ y * image_width * 4 + x*4 + 2 ] = row[ x * channels + 2 ];
 
			// If there is an alpha channel, be sure to copy it
			if( channels == 4 ) {
				image_data[ y * image_width + x*4 + 3 ] = row[ x * channels + 3 ];
			} else {
				image_data[ y * image_width + x*4 + 3 ] = 255;
			}
		}
	}
 
	// Free all memory that we used to avoid leaks, starting with each individual row
	for ( int i = 0; i < image_height; i++) {
		delete [] row_pointers[i];
	}
	// And finally, delete the row structure
	delete [] row_pointers;
 
	// Final PNG closing things
	png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
 
	// Close our file pointer
	fclose( file_pointer );
}
 



There are some premade things in this snippet. For one, the GenerateImage function just creates a blank, solid color image instead of a loaded PNG, in the case of an error. Engine::console is just a singleton that outputs to some error stream, usually a file. Finally, image_data is an unsigned char array. I allocated 4 bytes per pixel so that the buffer is always RGB.

If you're getting crashes with LibPNG, make sure you are linking the right library: compile LibPNG with the same compiler options as your project. This is due to the fact that LibPNG uses some internal functions to read from a file pointer.

Next time I might just use stb_image.

Python Decorators are Functions that Return Functions

Posted on September 13, 2011

If you've ever seen this kind of syntax and been bewildered:

 
@decorator
def function( x ):
    return x
 


Then you are not alone. This is an example of using decorators in python. The @ indicates that the function will be "decorated" with "decorator." What is decorator exactly?

It's a function that takes a function as an argument and returns a function.

 
def decorator( your_function ):
    return math.sin
 
@decorator
def function( x ):
    return x
 


You have just made a decorator. The function "function" is now whatever "decorator" returns, which is in this case math.sin. Now when you run:

 
print function( 5 )
 


You will really be calling math.sin( 5 ), because that's what your decorator returned. Of course, this is a silly example because it does not make use of your function. Let's make one that does.

 
def decorator( your_function ):
    def new_function( x ):
        return 5 + your_function( x )
    return new_function
 
@decorator
def function( x ):
    return x
 


Don't be thrown off by the fact that I defined a function within a function. This is just fine by the Python compiler.
What's happening here is that I defined a function called new_function that takes a single argument. It calls your function, giving it the value x, and then adds 5 to it and returns it. At the end of the decorator function, new_function is returned. Now when you call

 
print function( 10 )
 


You will see 15. What you really called was the function new_function, with an argument 10. That's because the function decorator returned new_function, which runs your old function and adds 5 to it. So the entire code would be this:

 
def decorator( your_function ):
	def new_function( x ):
		return 5 + your_function( x )
	return new_function
 
@decorator
def function( x ):
	return x
 
print function(5)
 


I hope that was a good explanation for some tricky Python stuff.