2010-10-12 10:55:23 +02:00
|
|
|
/*
|
2011-03-05 13:44:21 +01:00
|
|
|
* This software is licensed under the terms of the MIT-License
|
|
|
|
* See COPYING for further information.
|
|
|
|
* ---
|
|
|
|
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
|
2010-10-12 10:55:23 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "texture.h"
|
2011-03-19 16:21:48 +01:00
|
|
|
#include "global.h"
|
|
|
|
#include <dirent.h>
|
2011-03-20 09:01:54 +01:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2011-05-06 17:09:43 +02:00
|
|
|
#include <png.h>
|
2011-06-27 08:20:42 +02:00
|
|
|
#include "paths/native.h"
|
2011-06-26 16:10:13 +02:00
|
|
|
#include "taisei_err.h"
|
2011-04-02 12:14:37 +02:00
|
|
|
#include "audio.h"
|
2011-04-25 19:40:21 +02:00
|
|
|
#include "shader.h"
|
2011-04-10 10:23:24 +02:00
|
|
|
#include "list.h"
|
2010-10-12 10:55:23 +02:00
|
|
|
|
2011-03-19 16:21:48 +01:00
|
|
|
void recurse_dir(char *path) {
|
|
|
|
DIR *dir = opendir(path);
|
2011-04-25 19:40:21 +02:00
|
|
|
if(dir == NULL)
|
2011-06-26 16:10:13 +02:00
|
|
|
errx(-1, "Couldn't open directory '%s'", path);
|
2011-03-19 16:21:48 +01:00
|
|
|
struct dirent *dp;
|
|
|
|
|
|
|
|
while((dp = readdir(dir)) != NULL) {
|
2011-06-26 21:15:01 +02:00
|
|
|
char *buf = malloc(strlen(path) + strlen(dp->d_name)+2);
|
|
|
|
strcpy(buf, path);
|
|
|
|
strcat(buf, "/");
|
|
|
|
strcat(buf, dp->d_name);
|
2011-03-19 16:21:48 +01:00
|
|
|
|
2011-03-20 09:01:54 +01:00
|
|
|
struct stat statbuf;
|
|
|
|
stat(buf, &statbuf);
|
|
|
|
|
|
|
|
if(S_ISDIR(statbuf.st_mode) && dp->d_name[0] != '.') {
|
2011-03-19 16:21:48 +01:00
|
|
|
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);
|
2011-04-02 12:14:37 +02:00
|
|
|
} else if(strcmp(dp->d_name + strlen(dp->d_name)-4, ".wav") == 0) {
|
|
|
|
load_sound(buf);
|
2011-04-25 19:40:21 +02:00
|
|
|
} else if(strcmp(dp->d_name + strlen(dp->d_name)-4, ".sha") == 0) {
|
|
|
|
load_shader(buf);
|
2011-03-19 16:21:48 +01:00
|
|
|
}
|
2011-06-27 08:20:42 +02:00
|
|
|
|
|
|
|
free(buf);
|
2011-03-19 16:21:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-02 12:14:37 +02:00
|
|
|
void load_resources() {
|
|
|
|
printf("load_resources():\n");
|
2011-06-26 20:23:28 +02:00
|
|
|
char *path = malloc(strlen(get_prefix())+7);
|
|
|
|
|
2011-04-02 12:14:37 +02:00
|
|
|
printf("- textures:\n");
|
2011-06-26 20:23:28 +02:00
|
|
|
strcpy(path, get_prefix());
|
|
|
|
strcat(path, "gfx");
|
2011-04-02 12:14:37 +02:00
|
|
|
recurse_dir(path);
|
|
|
|
|
2011-06-27 13:36:35 +02:00
|
|
|
if(!tconfig.intval[NO_AUDIO]) {
|
|
|
|
printf("- sounds:\n");
|
|
|
|
alGenSources(SNDSRC_COUNT, global.sndsrc);
|
|
|
|
strcpy(path, get_prefix());
|
|
|
|
strcat(path, "sfx");
|
|
|
|
recurse_dir(path);
|
|
|
|
}
|
2011-04-25 19:40:21 +02:00
|
|
|
|
2011-06-27 13:36:35 +02:00
|
|
|
if(!tconfig.intval[NO_SHADER]) {
|
|
|
|
printf("- shader:\n");
|
|
|
|
strcpy(path, get_prefix());
|
|
|
|
strcat(path, "shader");
|
|
|
|
recurse_dir(path);
|
|
|
|
} else {
|
|
|
|
printf("- shader: disabled.\n");
|
|
|
|
}
|
2011-03-19 16:21:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2011-04-26 22:39:50 +02:00
|
|
|
|
2011-06-26 13:45:27 +02:00
|
|
|
Texture *prefix_get_tex(char *name, char *prefix) {
|
|
|
|
char *src;
|
|
|
|
|
|
|
|
if((src = strrchr(name, '/')))
|
|
|
|
src++;
|
|
|
|
else
|
|
|
|
src = name;
|
|
|
|
|
2011-06-26 16:10:13 +02:00
|
|
|
char *buf = malloc(strlen(src) + strlen(prefix) + 1);
|
2011-06-26 13:45:27 +02:00
|
|
|
strcpy(buf, prefix);
|
|
|
|
strcat(buf, src);
|
|
|
|
|
|
|
|
Texture *tex = get_tex(buf);
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
return tex;
|
|
|
|
}
|
|
|
|
|
2011-04-26 22:39:50 +02:00
|
|
|
void delete_texture(void **texs, void *tex) {
|
|
|
|
Texture *t = (Texture *)tex;
|
|
|
|
free(t->name);
|
|
|
|
glDeleteTextures(1, &t->gltex);
|
2011-03-19 16:21:48 +01:00
|
|
|
|
2011-04-26 22:39:50 +02:00
|
|
|
delete_element((void **)texs, tex);
|
|
|
|
}
|
|
|
|
|
2011-03-19 16:21:48 +01:00
|
|
|
void delete_textures() {
|
2011-04-26 22:39:50 +02:00
|
|
|
delete_all_elements((void **)&global.textures, delete_texture);
|
2011-03-19 16:21:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Texture *load_texture(const char *filename) {
|
2011-05-06 17:09:43 +02:00
|
|
|
SDL_Surface *surface = load_png(filename);
|
2010-10-12 10:55:23 +02:00
|
|
|
|
2010-10-13 12:38:38 +02:00
|
|
|
if(surface == NULL)
|
2011-06-26 16:10:13 +02:00
|
|
|
errx(-1,"load_texture():\n!- cannot load '%s'", filename);
|
2010-10-13 12:38:38 +02:00
|
|
|
|
2011-03-19 16:21:48 +01:00
|
|
|
Texture *texture = create_element((void **)&global.textures, sizeof(Texture));
|
2010-11-14 13:24:56 +01:00
|
|
|
load_sdl_surf(surface, texture);
|
|
|
|
SDL_FreeSurface(surface);
|
2011-03-19 16:21:48 +01:00
|
|
|
|
|
|
|
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;
|
2010-11-14 13:24:56 +01:00
|
|
|
}
|
|
|
|
|
2011-05-06 17:09:43 +02:00
|
|
|
SDL_Surface *load_png(const char *filename) {
|
|
|
|
FILE *fp = fopen(filename, "rb");
|
|
|
|
if(!fp)
|
2011-06-26 16:10:13 +02:00
|
|
|
errx(-1, "Error loading '%s'", filename);
|
2011-05-06 17:09:43 +02:00
|
|
|
|
|
|
|
png_structp png_ptr;
|
|
|
|
if(!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
|
|
|
|
errx(-1,"Error loading '%s'", filename);
|
|
|
|
|
|
|
|
png_infop info_ptr;
|
|
|
|
if(!(info_ptr = png_create_info_struct(png_ptr))) {
|
|
|
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
|
|
|
errx(-1,"Error loading '%s'", filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
png_infop end_info;
|
|
|
|
if(!(end_info = png_create_info_struct(png_ptr))) {
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
|
|
errx(-1,"Error loading '%s'", filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
png_init_io(png_ptr, fp);
|
|
|
|
|
|
|
|
png_read_png(png_ptr, info_ptr, 0, NULL);
|
|
|
|
|
|
|
|
int width = png_get_image_width(png_ptr, info_ptr);
|
|
|
|
int height = png_get_image_height(png_ptr, info_ptr);
|
|
|
|
int depth = png_get_bit_depth(png_ptr, info_ptr);
|
|
|
|
|
|
|
|
png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);
|
|
|
|
|
|
|
|
Uint32 *pixels = malloc(sizeof(Uint32)*width*height);
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < height; i++)
|
|
|
|
memcpy(&pixels[i*width], row_pointers[i], sizeof(Uint32)*width);
|
|
|
|
|
|
|
|
Uint32 rmask, gmask, bmask, amask;
|
|
|
|
|
|
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
|
|
rmask = 0xff000000;
|
|
|
|
gmask = 0x00ff0000;
|
|
|
|
bmask = 0x0000ff00;
|
|
|
|
amask = 0x000000ff;
|
|
|
|
#else
|
|
|
|
rmask = 0x000000ff;
|
|
|
|
gmask = 0x0000ff00;
|
|
|
|
bmask = 0x00ff0000;
|
|
|
|
amask = 0xff000000;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SDL_Surface *res = SDL_CreateRGBSurfaceFrom(pixels, width, height, depth*4, 0, rmask, gmask, bmask, amask);
|
|
|
|
if(!res)
|
|
|
|
errx(-1,"Error loading '%s'", filename);
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2010-11-14 13:24:56 +01:00
|
|
|
void load_sdl_surf(SDL_Surface *surface, Texture *texture) {
|
2010-10-12 10:55:23 +02:00
|
|
|
glGenTextures(1, &texture->gltex);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture->gltex);
|
|
|
|
|
2010-10-13 12:38:38 +02:00
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
2010-10-12 10:55:23 +02:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
2010-10-13 12:38:38 +02:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
2010-10-12 10:55:23 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2010-11-14 13:24:56 +01:00
|
|
|
free(tex);
|
2010-10-12 10:55:23 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 13:41:10 +01:00
|
|
|
void free_texture(Texture *tex) {
|
|
|
|
glDeleteTextures(1, &tex->gltex);
|
|
|
|
free(tex);
|
|
|
|
}
|
|
|
|
|
2011-06-13 18:48:36 +02:00
|
|
|
void draw_texture(float x, float y, char *name) {
|
2011-03-19 16:21:48 +01:00
|
|
|
draw_texture_p(x, y, get_tex(name));
|
|
|
|
}
|
|
|
|
|
2011-06-13 18:48:36 +02:00
|
|
|
void draw_texture_p(float x, float y, Texture *tex) {
|
2010-10-12 10:55:23 +02:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex->gltex);
|
|
|
|
|
2010-10-13 12:38:38 +02:00
|
|
|
glPushMatrix();
|
|
|
|
|
2010-11-14 13:24:56 +01:00
|
|
|
float wq = ((float)tex->w)/tex->truew;
|
2010-10-13 12:38:38 +02:00
|
|
|
float hq = ((float)tex->h)/tex->trueh;
|
|
|
|
|
|
|
|
glTranslatef(x,y,0);
|
2010-10-24 14:44:48 +02:00
|
|
|
glScalef(tex->w/2,tex->h/2,1);
|
2010-10-13 12:38:38 +02:00
|
|
|
|
2010-10-12 10:55:23 +02:00
|
|
|
glBegin(GL_QUADS);
|
2010-10-24 14:44:48 +02:00
|
|
|
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);
|
2010-10-13 12:38:38 +02:00
|
|
|
glEnd();
|
2010-10-12 10:55:23 +02:00
|
|
|
|
2010-10-13 12:38:38 +02:00
|
|
|
glPopMatrix();
|
2010-10-12 10:55:23 +02:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2011-05-09 13:42:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void fill_screen(float xoff, float yoff, float ratio, char *name) {
|
2011-06-13 18:48:36 +02:00
|
|
|
fill_screen_p(xoff, yoff, ratio, get_tex(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fill_screen_p(float xoff, float yoff, float ratio, Texture *tex) {
|
2011-05-09 13:42:02 +02:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex->gltex);
|
|
|
|
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(xoff,yoff, 0);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
|
|
|
|
float rw = ratio;
|
|
|
|
float rh = ratio;
|
|
|
|
|
|
|
|
if(ratio == 0) {
|
|
|
|
rw = ((float)tex->w)/tex->truew;
|
|
|
|
rh = ((float)tex->h)/tex->trueh;
|
|
|
|
}
|
|
|
|
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0,0); glVertex3f(0,0,0);
|
|
|
|
glTexCoord2f(0,rh); glVertex3f(0,VIEWPORT_H,0);
|
|
|
|
glTexCoord2f(rw,rh); glVertex3f(VIEWPORT_W,VIEWPORT_H,0);
|
|
|
|
glTexCoord2f(rw,0); glVertex3f(VIEWPORT_W,0,0);
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
2010-10-12 10:55:23 +02:00
|
|
|
}
|