/* * texture.c * * Handle textures * * Copyright (c) 2008 Thomas White * * This file is part of Thrust3D - a silly game * * Thrust3D is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Thrust3D is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Thrust3D. If not, see . * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "render.h" static int texture_load_png(char *filename, GLuint *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; uint8_t *texels; /* Open file */ fh = fopen(filename, "rb"); if ( !fh ) { return 1; } /* 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", filename); free(header); fclose(fh); return 1; } 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 1; } 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 1; } 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 1; } 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 1; } 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' doesn't have 8 bits per channel per pixel.\n", filename); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fh); return 1; } if ( channels != 4 ) { fprintf(stderr, "Texture image '%s' doesn't have 4 channels.\n", filename); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fh); return 1; } /* Get image data */ row_pointers = png_get_rows(png_ptr, info_ptr); texels = malloc(4*width*height); for ( y=0; ytextures[ctx->num_textures].texname = colourmap; if ( texture_load_png(normalmap_filename, &normalmap) == 0 ) { ctx->textures[ctx->num_textures].normalmap = normalmap; ctx->textures[ctx->num_textures].has_normals = 1; } else { ctx->textures[ctx->num_textures].has_normals = 0; } ctx->textures[ctx->num_textures].name = strdup(name); ctx->num_textures++; } Texture *texture_lookup(RenderContext *ctx, const char *name) { int i, found; found = 0; for ( i=0; inum_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; inum_textures; i++ ) { glDeleteTextures(1, &(ctx->textures[ctx->num_textures].texname)); } }