Loading embedded textures with SOIL

I am using this answer to embed my image in the .exe:

http ://stackoverflow.com/questions/4158900/embedding-resources-in-exe-using-gcc
Remove the space after http, it’s only there because I am not allowed to post links.

Here are the relevant bits of my code:

GLuint grass_DTexture;

extern char binary_grass_D_bmp_start[];
extern char binary_grass_D_bmp_size[];
short loadTexture(char *imageData[], GLuint *texture, int width, int height) {
    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, texture);
    glBindTexture(GL_TEXTURE_2D, *texture);

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    *texture = SOIL_load_OGL_texture_from_memory(imageData, sizeof(*imageData), SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_MIPMAPS);

    //gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, imageData);

    //glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, width, height);
    //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
    //glGenerateMipmap(GL_TEXTURE_2D);

    glDisable(GL_TEXTURE_2D);
    return 1;
}
loadTexture(&binary_grass_D_bmp_start, &grass_DTexture, 512, 512);

However the exe crashes as soon as it is run. I am also greeted with the following warning, which could be the cause of this (probably missing an * or an & somewhere):

init.c:76:2: warning: passing argument 1 of ‘loadTexture’ from incompatible poin
ter type [enabled by default]
loadTexture.h:1:7: note: expected ‘char **’ but argument is of type ‘char (*)[]’

I have managed to narrow the crash to the SOIL_load_OGL_texture_from_memory call.

Also note that simply loading the texture from an external file using only this one line works fine:

*texture = SOIL_load_OGL_texture("image.bmp", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);

So it’s not a problem with lighting or anything else specific to my project.

Thanks.

This declares imageData as an array of pointers (which is actually the same as pointer-to-pointer, i.e. “char **imageData”, as C doesn’t support passing arrays by value). It should just be a “char *”. Also, the length needs to be passed in as a parameter (unless you can compute it from width and height, or get SOIL to deduce it from the data stream). In general, you can’t determine the size of an array from just a pointer.

So this should probably be:


int loadTexture(char *imageData, size_t length, GLuint *texture, int width, int height)

sizeof(*imageData) will be the size of a pointer, i.e. probably 4 on a 32-bit system or 8 on a 64-bit system. The length should be passed in as a parameter (see above), so:


    *texture = SOIL_load_OGL_texture_from_memory(imageData, length, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_MIPMAPS);

This passes a pointer to an array, whereas the corresponding argument is declared as a pointer-to-pointer (see above). Passing the array by name will pass a pointer to its first element, which is normally what you want. With the changes I suggested above, this should be:


loadTexture(binary_grass_D_bmp_start, (size_t) (binary_grass_D_bmp_end - binary_grass_D_bmp_start), &grass_DTexture, 512, 512);

Thanks so much, it’s working perfectly now!

I feel pretty nooby though; I’m off to read some more pointer tutorials as I don’t think I fully grasped the concept when I first learnt about them.