taisei/src/texture.c
laochailan 3f2885e185 fix: memleaks
there were some memleaks I left out of laziness. fixed.
2011-04-26 22:39:50 +02:00

185 lines
No EOL
4.3 KiB
C

/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
*/
#include "texture.h"
#include "global.h"
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "audio.h"
#include "shader.h"
#include "list.h"
void recurse_dir(char *path) {
DIR *dir = opendir(path);
if(dir == NULL)
err(-1, "Couldn't open directory '%s'", path);
struct dirent *dp;
char buf[512];
while((dp = readdir(dir)) != NULL) {
strncpy(buf, path, sizeof(buf));
strncat(buf, "/", sizeof(buf));
strncat(buf, dp->d_name, sizeof(buf));
struct stat statbuf;
stat(buf, &statbuf);
if(S_ISDIR(statbuf.st_mode) && dp->d_name[0] != '.') {
recurse_dir(buf);
} else if(strcmp(dp->d_name + strlen(dp->d_name)-4, ".png") == 0) {
if(strncmp(dp->d_name, "ani_", 4) == 0)
init_animation(buf);
else
load_texture(buf);
} else if(strcmp(dp->d_name + strlen(dp->d_name)-4, ".wav") == 0) {
load_sound(buf);
} else if(strcmp(dp->d_name + strlen(dp->d_name)-4, ".sha") == 0) {
load_shader(buf);
}
}
}
void load_resources() {
printf("load_resources():\n");
char *path = malloc(sizeof(FILE_PREFIX)+4);
printf("- textures:\n");
strcpy(path, FILE_PREFIX);
strncat(path, "gfx", sizeof(FILE_PREFIX)+4);
recurse_dir(path);
printf("- sounds:\n");
strcpy(path, FILE_PREFIX);
strncat(path, "sfx", sizeof(FILE_PREFIX)+4);
recurse_dir(path);
printf("- shader:\n");
strcpy(path, FILE_PREFIX);
strncat(path, "shader", sizeof(FILE_PREFIX)+4);
recurse_dir(path);
}
Texture *get_tex(char *name) {
Texture *t, *res = NULL;
for(t = global.textures; t; t = t->next) {
if(strcmp(t->name, name) == 0)
res = t;
}
if(res == NULL)
errx(-1,"get_tex():\n!- cannot load texture '%s'", name);
return res;
}
void delete_texture(void **texs, void *tex) {
Texture *t = (Texture *)tex;
free(t->name);
glDeleteTextures(1, &t->gltex);
delete_element((void **)texs, tex);
}
void delete_textures() {
delete_all_elements((void **)&global.textures, delete_texture);
}
Texture *load_texture(const char *filename) {
SDL_Surface *surface = IMG_Load(filename);
if(surface == NULL)
err(-1,"load_texture():\n!- cannot load '%s'", filename);
Texture *texture = create_element((void **)&global.textures, sizeof(Texture));
load_sdl_surf(surface, texture);
SDL_FreeSurface(surface);
char *beg = strstr(filename, "gfx/") + 4;
char *end = strrchr(filename, '.');
texture->name = malloc(end - beg + 1);
memset(texture->name, 0, end-beg + 1);
strncpy(texture->name, beg, end-beg);
printf("-- loaded '%s' as '%s'\n", filename, texture->name);
return texture;
}
void load_sdl_surf(SDL_Surface *surface, Texture *texture) {
glGenTextures(1, &texture->gltex);
glBindTexture(GL_TEXTURE_2D, texture->gltex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int nw = 2;
int nh = 2;
while(nw < surface->w) nw *= 2;
while(nh < surface->h) nh *= 2;
Uint32 *tex = calloc(sizeof(Uint32), nw*nh);
int x, y;
for(y = 0; y < nh; y++) {
for(x = 0; x < nw; x++) {
if(y < surface->h && x < surface->w)
tex[y*nw+x] = ((Uint32*)surface->pixels)[y*surface->w+x];
else
tex[y*nw+x] = '\0';
}
}
texture->w = surface->w;
texture->h = surface->h;
texture->truew = nw;
texture->trueh = nh;
glTexImage2D(GL_TEXTURE_2D, 0, 4, nw, nh, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex);
free(tex);
}
void free_texture(Texture *tex) {
glDeleteTextures(1, &tex->gltex);
free(tex);
}
void draw_texture(int x, int y, char *name) {
draw_texture_p(x, y, get_tex(name));
}
void draw_texture_p(int x, int y, Texture *tex) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex->gltex);
glPushMatrix();
float wq = ((float)tex->w)/tex->truew;
float hq = ((float)tex->h)/tex->trueh;
glTranslatef(x,y,0);
glScalef(tex->w/2,tex->h/2,1);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(-1, -1, 0);
glTexCoord2f(0,hq); glVertex3f(-1, 1, 0);
glTexCoord2f(wq,hq); glVertex3f(1, 1, 0);
glTexCoord2f(wq,0); glVertex3f(1, -1, 0);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}