aboutsummaryrefslogtreecommitdiff
path: root/src/texture.c
diff options
context:
space:
mode:
authortaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-04-16 16:57:56 +0000
committertaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-04-16 16:57:56 +0000
commitf0a0118393a3d121bcb83047b5b9ac95eb0621ba (patch)
treecfc4f3f7955b4829317fa9b7865e328ccabfb129 /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.c180
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));
+ }
+
+}
+