Basic GL Texture Loader

Haggis McHaggis
Unregistered
 
Post: #1
Hey!

I'm trying to get basic GL texturing on the go in Project Builder.

I'm using GLUT at the minute because the majority of what I'm doing is in Visual Studio and I'd like some compatibility to allow me to work at home in Project Builder. The thing is all the texturing examples I seem to come across are in Cocoa and my knowledge of C/C++/Java aren't helping me decipher it.

There's no glaux.h so I tried rewriting the standard AUX_RGBImageRec but came to a bit of a dead end.

I'm assuming I need to use NSImageRep or something but I'm having difficulty even using it.

Help? :sorry:
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #2
For simple texture loading, few things beat the Targa format. There's a great tutorial on loading TGA:s over at Nehe on loading them. They support the alpha channel (which BMP doesn't), and there is no compression to worry about. (there's a RLE-encoded version, too, if you feel daring. Smile
The only quirk is that they are loaded up-side down, but that's rarely a problem. Just invert them in your image editor, or specify your UV:s upside down.

In short, TGA loading is done like this:

  • Parse the header to see if it's a compressed or uncompressed TGA file (a simple memcmp)
  • Read the internal header, and extract image size and bit depth (very simple)
  • Calculate buffer size and allocate a memory buffer (a multiplication and a malloc)
  • Read the memory into the buffer (a memcpy/fread/whatever)
  • Swap the red and blue bytes (or use GL_BGRA), this is a loop and a temporary variable.


This is how I do it:

Code:
bmErrCode LoadTGA (bmLoader *LOADER)
{
    char uTGACompare[12] = {0,0,02,0,0,0,0,0,0,0,0,0};
    char cTGACompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};
    char header [12];
    GLubyte internalHeader [6], temp;
    int i, bpp = 0;
    long imageSize;
    bmErrCode err;
    
    // Attempt To Read The File Header
    err = LOADER->ReadBytes(header, sizeof(header)); if (err)
    {
        return err;
    }
    
    // Check to see if this is compressed:
    if (!memcmp (cTGACompare, header, sizeof (cTGACompare)))
    {
        return;     // I don't handle compressed TGA:s in this version
    }
    // Read the internal header
    if (err = LOADER->ReadBytes ((char *)internalHeader, sizeof(internalHeader)))
    {
        return err;
    }
    // Extract the image size, and make sure it is valid
    this->image.w = internalHeader[1] * 256 + internalHeader[0];
    this->image.h = internalHeader[3] * 256 + internalHeader[2];
    if (this->image.w < 1 || this->image.h < 1 || (internalHeader[4] != 24 && internalHeader[4] != 32))
    {
        return kErrIllegalSize;
    }
    // Check the bit depth, and check for alpha channel (a 32-bit is always considered as alpha-savvy)
    bpp = internalHeader[4];
    if ((bpp/8) == 4)    // This is 32-bit TGA, thus it has alpha
        this->image.hasAlpha = true;
    else
        this->image.hasAlpha = false;
    
    // Allocate memory for the pixels
    imageSize = sizeof (GLubyte) * this->image.w * this->image.h * (bpp/8);
    this->image.data = (GLubyte *) malloc (imageSize);
    if (!image.data) GIVE_ERROR (kErrMemAllocFail);
    if (!this->image.data) return kErrMemAllocFail;
    
    // Read the pixels
    LOADER->ReadBytes ((char *)this->image.data, imageSize);
    
    // Swap red and blue components
    for(i = 0; i < imageSize; i += (bpp/8))            // Loop Through The Image Data
    {                            // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
        temp = this->image.data[i];                // Temporarily Store The Value At Image Data 'i'
        this->image.data[i] = this->image.data[i+2];    // Set The 1st Byte To The Value Of The 3rd Byte
        this->image.data[i+2] = temp;            // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
    }
    
    return kOK;

This is heavily based on the Nehe example, but with my own error checking and file reading systems. In short, LOADER->ReadBytes is just a wrapper for fread/memcpy/FSReadFork or whatever is below it.

[EDIT: Oh, this is also entirely cross-platform. No need to worry about endian-ness.]

Hope this helps,
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Texture Basic Question(s)... WhatMeWorry 2 3,296 Feb 27, 2007 10:06 AM
Last Post: arekkusu
  problem with basic texture mapping class wyrmmage 8 4,280 Dec 22, 2006 02:25 PM
Last Post: wyrmmage
  ImageIO texture loader crashing - Cocoa mahalis 4 3,130 Aug 16, 2006 07:33 AM
Last Post: djork
  Basic Texture Mapping hangt5 5 3,589 Dec 14, 2004 12:29 PM
Last Post: hangt5