diff options
author | taw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5> | 2008-04-16 16:57:56 +0000 |
---|---|---|
committer | taw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5> | 2008-04-16 16:57:56 +0000 |
commit | f0a0118393a3d121bcb83047b5b9ac95eb0621ba (patch) | |
tree | cfc4f3f7955b4829317fa9b7865e328ccabfb129 /src/texture.c |
Initial import
git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@1 84d2e878-0bd5-11dd-ad15-13eda11d74c5
Diffstat (limited to 'src/texture.c')
-rw-r--r-- | src/texture.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/texture.c b/src/texture.c new file mode 100644 index 0000000..b2aba03 --- /dev/null +++ b/src/texture.c @@ -0,0 +1,180 @@ +/* + * texture.c + * + * Handle textures + * + * (c) 2008 Thomas White <taw27@cam.ac.uk> + * + * thrust3d - a silly game + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <png.h> +#include <stdlib.h> +#include <gl.h> +#include <glu.h> + +#include "render.h" + +void texture_load(RenderContext *ctx, char *name) { + + FILE *fh; + png_bytep header; + png_structp png_ptr; + png_infop info_ptr; + png_infop end_info; + unsigned int width; + unsigned int height; + unsigned int bit_depth; + unsigned int channels; + png_bytep *row_pointers; + unsigned int x; + unsigned int y; + char tmp[64]; + uint8_t *texels; + + /* Open file */ + snprintf(tmp, 63, "%s/textures/%s.png", DATADIR, name); + fh = fopen(tmp, "rb"); + if ( !fh ) { + fprintf(stderr, "Couldn't open texture file '%s'\n", tmp); + return ; + } + + /* Check it's actually a PNG file */ + header = malloc(8); + fread(header, 1, 8, fh); + if ( png_sig_cmp(header, 0, 8)) { + fprintf(stderr, "Texture file '%s' is not a PNG file.\n", tmp); + free(header); + fclose(fh); + return; + } + free(header); + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if ( !png_ptr ) { + fprintf(stderr, "Couldn't create PNG read structure.\n"); + fclose(fh); + return ; + } + + info_ptr = png_create_info_struct(png_ptr); + if ( !info_ptr ) { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + fprintf(stderr, "Couldn't create PNG info structure.\n"); + fclose(fh); + return; + } + + end_info = png_create_info_struct(png_ptr); + if ( !end_info ) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + printf("Couldn't create PNG end info structure.\n"); + fclose(fh); + return; + } + + if ( setjmp(png_jmpbuf(png_ptr)) ) { + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fh); + fprintf(stderr, "PNG read failed.\n"); + return; + } + + png_init_io(png_ptr, fh); + png_set_sig_bytes(png_ptr, 8); + + /* Read! */ + png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + width = png_get_image_width(png_ptr, info_ptr); + height = png_get_image_height(png_ptr, info_ptr); + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + channels = png_get_channels(png_ptr, info_ptr); + if ( bit_depth != 8 ) { + fprintf(stderr, "Texture image '%s' isn't 8 bits per channel per pixel.\n", tmp); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fh); + return; + } + if ( channels != 4 ) { + fprintf(stderr, "Texture image '%s' doesn't have 4 channels.\n", tmp); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fh); + return; + } + + /* Get image data */ + row_pointers = png_get_rows(png_ptr, info_ptr); + + texels = malloc(4*width*height); + for ( y=0; y<height; y++ ) { + for ( x=0; x<width; x++ ) { + + unsigned int r, g, b, a; + + r = row_pointers[y][(channels*x)+0]; + g = row_pointers[y][(channels*x)+1]; + b = row_pointers[y][(channels*x)+2]; + a = row_pointers[y][(channels*x)+3]; + + texels[4*(x + width*(height-1-y)) + 0] = r; + texels[4*(x + width*(height-1-y)) + 1] = g; + texels[4*(x + width*(height-1-y)) + 2] = b; + texels[4*(x + width*(height-1-y)) + 3] = a; + + } + } + + glGenTextures(1, &(ctx->textures[ctx->num_textures].texname)); + glBindTexture(GL_TEXTURE_2D, ctx->textures[ctx->num_textures].texname); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + 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); + //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texels); + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, width, height, GL_RGBA, GL_UNSIGNED_BYTE, texels); + free(texels); + ctx->textures[ctx->num_textures].name = name; + ctx->num_textures++; + + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fh); + +} + +Texture *texture_lookup(RenderContext *ctx, const char *name) { + + int i, found; + + found = 0; + for ( i=0; i<ctx->num_textures; i++ ) { + if ( strcmp(ctx->textures[i].name, name) == 0 ) { + found = 1; + break; + } + } + + if ( found == 0 ) { + return NULL; + } + + return &(ctx->textures[i]); + +} + +void texture_free_all(RenderContext *ctx) { + + int i; + + for ( i=0; i<ctx->num_textures; i++ ) { + glDeleteTextures(1, &(ctx->textures[ctx->num_textures].texname)); + } + +} + |