Texture Mapping: Loading a texture from a .bmp file?

Nibbie
Posts: 4
Joined: 2008.12
Post: #1
I'm on OSX 10.4.11
I have a 900 MHz PowerPC G3 (laptop)

I'm trying to create a texture from a .bmp file to slap on a openGL quad in the hopes of moving twords creating a simple game using GLUT, openGL, and my knowledge of c++

I am trying to avoid using Cocoa just because of all the effort I've put into trying to learn c++. I have spent a solid month trying to get image data from a url, load it to memory and slap it onto a quad. I haven't found any documentation on how to get this to work without using Objective-c, so I have been reading "Quartz 2D Graphics for mac developers" and the "Red Book" and going through XCode's documentation files, and developer.apple.com files in hopes of finding the answer, all to no avail.

Here is my most recent attempt. I've been using the code I found on onesadcookie's blog about GLUT, and some of NeHe's bits of code smashed with random quartz code trying to get an image reference from a file. I've made no attempt at making clean organized well commented code because I just wanted to slap together a quick project so I could just understand the syntax of loading textures.


Code:
#include <Carbon/Carbon.h>
#include <stdlib.h>
#include <GLUT/glut.h>
#include <ApplicationServices/ApplicationServices.h>

GLuint myTextureName;


void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);
    glEnable(GL_DEPTH_TEST);
    
    CFStringRef url = "MGspriteszed.bmp";

    CFURLRef imageurl = CFURLCreateWithString (NULL, url, NULL);    

    CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(imageurl, NULL);
    CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL);

    size_t width = CGImageGetWidth(myImageRef);
    size_t height = CGImageGetHeight(myImageRef);
    CGRect rect = {{0, 0}, {width, height}};
    void * myData = calloc(width * 4, height);
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGContextRef myBitmapContext = CGBitmapContextCreate (myData,
                            width, height, 8,
                            width*4, space,
                            kCGBitmapByteOrder32Host |
                            kCGImageAlphaPremultipliedFirst);
                            
    CGContextDrawImage(myBitmapContext, rect, myImageRef);
    
    CGContextRelease(myBitmapContext);
    
    glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    
    glGenTextures(1, &myTextureName);
    
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
                        GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, width, height,
                        0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, myData);
    free(myData);

}



void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glBindTexture(GL_TEXTURE_2D, myTextureName);
    
    glTranslatef(0.0, 0.0, 0.0);
    glColor3f(0.0, 0.0, 0.0);
    
    
    
    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVector3f(0.0, 0.0, 0.0);
    glTexCoord2f(1.0, 0.0);    glVector3f(0.25, 0.0, 0.0);
    glTexCoord2f(1.0, 1.0);    glVector3f(0.25, 0.25, 0.0);
    glTexCoord2f(0.0, 1.0);    glVector3f(0.0, 0.25, 0.0);
    glEnd();
    
    glFlush();
    glDisable(GL_TEXTURE_2D);
    
}

void spinDisplay(void)
{

}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-50.0, 50.0, -50.0, 50.0, -1, -1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(200, 180);
    glutInitWindowSize(640, 480);
    
    glutCreateWindow("New Window");
    init();
glutReshapeFunc(reshape);
    glutDisplayFunc(display);

    
    glutMainLoop();
    
return EXIT_SUCCESS;
}

XCode gives me a warning "Initialization from incompatible pointer type when I try to call CFStringRef url = "MGspriteszed.bmp";

I was wondering if there is no way to do this with out resorting to Objective-C if I there is a universal imageIO framework I could use with out needing learn obj-c.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #2
ishrock Wrote:XCode gives me a warning "Initialization from incompatible pointer type when I try to call CFStringRef url = "MGspriteszed.bmp";

"MGspriteszed.bmp" is of type char *. You can use CFSTR("MGspriteszed.bmp") to get a compile-time CFStringRef constant.

ishrock Wrote:I was wondering if there is no way to do this with out resorting to Objective-C if I there is a universal imageIO framework I could use with out needing learn obj-c.

Indeed there is: http://developer.apple.com/graphicsimagi...ageio.html

As an aside, learning Objective-C is highly beneficial for developing software on the Mac or iPhone. I'd recommend giving it a try sooner rather than later; it only takes a day or two to get up and running with it.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #3
ObjC is absolutely worth it, even if you're focused on C++ ( as I am, for 3d stuff at least ). By learning ObjC + Cocoa, you can work with the good stuff OSX provides so much easier. So much easier.
Quote this message in a reply
Nibbie
Posts: 4
Joined: 2008.12
Post: #4
Thank you for the help and the references. I can now sleep soundly at night. I got it to pass the texture and load the program with out error (the code I posted had glVector3f instead of glVertex3f) but I still haven't got quad to show up on the screen with the texture. i think the quad is off the screen or flipped around, or some gl rendering thing is active when it shouldn't be. I'll post my code when I hunt down the issue.

My concern when it comes with Objective-C is that all my friends run on Microsoft windows. I would love to be able to port my simple games over to windows eventually (or write a game that would work on both systems in the first place). I fear that by using Obj-c that it might make that more painful in the long run. Is there any validity to this concern?

I like GLUT because it seems straight forward and to the point, but I have heard people on the forum talking about it's limited abilities (Though not saying what those limits are). As a hobbiest I think GLUT will probably be a fine starting point (is it?).

I looked into SDL and it seemed daunting. To me at this point in my programing life, daunting means it's probably awesome and I should learn SDL instead of GLUT.... Should I?
Quote this message in a reply
Nibbie
Posts: 4
Joined: 2008.12
Post: #5
So i have cleaned up my code a little and added the suggestions ThemsAllTook gave, minus the obj-c. It all compiles fine... except that my quad still has not texture. I just see a white box on a black background. I added a line of code to check it the texture was ever loaded in the first place and it looks like it hasn't.

I have imported the image file, and copied it to my project folder. In XCode I put it in a group named "Resources". I thought I would only need to put the name of the file ("MGspriteszed.bmp") for my program to be able to find it, but it didn't. I also tried ("/Resources/MGspriteszed.bmp"), ("/GL_Test/MGspriteszed.bmp"), ("Desktop/GL_Test/MGspriteszed.bmp")... so on and so forth.

Would any one be able to look at my code and help me out? Maybe i've done something horrible stupid... well... I'm sure I have, but thats why i need the help Grin

Code:
#include <Carbon/Carbon.h>
#include <stdlib.h>
#include <GLUT/glut.h>
#include <ApplicationServices/ApplicationServices.h>

GLuint myTextureName[1];

CFStringRef GetTextureURL(void) //My function to create a CFStringRef of a URL to a BMP file
{  
    CFStringRef url = CFSTR("MGspriteszed.bmp");    
    return url;
}

void LoadTextures( CFStringRef url) // my function to load a BMP for a url into
{                                    // global GLuint myTextureName[1]

    CFURLRef imageurl = CFURLCreateWithString (NULL, url, NULL);    //creates URL from a string that was passed into the function

    CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(imageurl, NULL);  // makes a refrence to the bmp file the url point to
        if (myImageSourceRef == NULL) {
            exit(TRUE);
            };
    CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL); // load the bmp data from file and create a refrence to where it is in memory

    size_t width = CGImageGetWidth(myImageRef);
    size_t height = CGImageGetHeight(myImageRef);
    CGRect rect = {{0, 0}, {width, height}};
    void * myData = calloc(width * 4, height); // makes sure there is exact space in momory to store bmp data
    
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGContextRef myBitmapContext = CGBitmapContextCreate (myData, // makes off screen bmp context
                            width, height, 8,
                            width*4, space,
                            kCGBitmapByteOrder32Host |
                            kCGImageAlphaPremultipliedFirst);
                            
    CGContextDrawImage(myBitmapContext, rect, myImageRef); // draws my image to somewhere
    
    CGContextRelease(myBitmapContext); //frees memory
    
    glPixelStorei(GL_UNPACK_ROW_LENGTH, width); // does this read the bmp data and prepair to store it
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);        // as something openGL can read?
    
    glGenTextures(1, &myTextureName[0]);        // Tells open gl myTextureName[0] is a place in memory where textures are stored
    
    glBindTexture(GL_TEXTURE_2D, myTextureName[0]);    // puts the data from GL_UNPACK into myTextureName[0]

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,    //voodoo
                        0, GL_RGB, GL_UNSIGNED_BYTE, myData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    

    free(myData); //frees memory from pointer myData
}

void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);
    glEnable(GL_DEPTH_TEST);
    
    CFStringRef url = GetTextureURL(); // get a CFStringRef to file name to pass to LoadTextures
    LoadTextures(url); // call to my function to load bmp data with quartz
        
}



void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glEnable(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, myTextureName[0]); // get ready to use my texture
    
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0,  0.0);    //bottom left
        glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 0.0,  0.0);//top left
        glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  0.0);//top right
        glTexCoord2f(0.0, 1.0); glVertex3f(0.0,  1.0,  0.0); //bottom right
    glEnd();

    glFlush();
    glDisable(GL_TEXTURE_2D);
    
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-50.0, 50.0, -50.0, 50.0, -1, -1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(200, 180);
    glutInitWindowSize(640, 480);
    glutCreateWindow("New Window");
    init();
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutMainLoop();
    
return EXIT_SUCCESS;
}
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
ishrock Wrote:My concern when it comes with Objective-C is that all my friends run on Microsoft windows. I would love to be able to port my simple games over to windows eventually (or write a game that would work on both systems in the first place). I fear that by using Obj-c that it might make that more painful in the long run. Is there any validity to this concern?

There is validity, but using Objective-C isn't mutually exclusive with compiling for Windows. There are ways to compile Objective-C code on other platforms, and although I've never personally been able to get them to work, other iDevGames members have. Another approach, which I'm currently using, is to write the vast majority of your game in C or C++ using only platform-independent APIs, and link it to a small platform-specific shell which is implemented separately for each platform you compile for. This way, all of your Objective-C code would be isolated in a "Mac-only" section, and you'd be able to implement an equivalent "Windows-only" (and "Linux-only", etc.) section in another language.

ishrock Wrote:I like GLUT because it seems straight forward and to the point, but I have heard people on the forum talking about it's limited abilities (Though not saying what those limits are). As a hobbiest I think GLUT will probably be a fine starting point (is it?).

I looked into SDL and it seemed daunting. To me at this point in my programing life, daunting means it's probably awesome and I should learn SDL instead of GLUT.... Should I?

GLUT is a fine place to start, though you may find that you outgrow it. Its event handling API isn't exactly full-featured, and I remember one of our members being unable to get full screen mode working reliably. On the plus side, it's completely cross-platform and very easy to use. If nothing else, it's an excellent starting point to get something up and running quickly, that you can potentially swap out later for something more full-featured.

I haven't used SDL myself, but many other members here swear by it. One caveat to be aware of is that you'll need to bundle the appropriate SDL frameworks with your application when you distribute it, which has historically been the source of many headaches. It also increases the size of your distribution by a few megabytes.

As for the file loading problem, you were barking up the right tree. Here's an explanation from another one of our members: http://blog.onesadcookie.com/2007/12/fin...files.html
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL ES Texture Masking airfire 6 14,950 Mar 17, 2014 07:07 PM
Last Post: baioses
  Mapping 2D texture to multiple GL_TRIANGLES ardowz 2 1,111 Mar 12, 2014 08:56 AM
Last Post: ardowz
  Rendering Heightmap using texture data ardowz 3 1,142 Feb 25, 2014 10:25 AM
Last Post: SethWillits
  Render to Texture behaves weirdly ardowz 2 1,461 Feb 17, 2014 04:50 PM
Last Post: ardowz
  Preventing texture from creating transparent gaps on edges ardowz 3 1,554 Jan 21, 2014 11:28 AM
Last Post: SethWillits