From: John Tsiombikas Date: Sat, 11 Aug 2018 23:06:36 +0000 (+0300) Subject: doing stuff X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=ld42_outofspace;a=commitdiff_plain;h=b8200afc389ccca3e86463eb48c0563c0e093552 doing stuff --- diff --git a/Makefile b/Makefile index 4189eb2..27fd39b 100644 --- a/Makefile +++ b/Makefile @@ -12,11 +12,16 @@ inc = CFLAGS = $(warn) $(dbg) $(opt) $(inc) CXXFLAGS = $(warn) $(dbg) $(opt) $(inc) -LDFLAGS = $(libgl) $(syslibs) +LDFLAGS = $(syslibs) $(libgl) -lgmath -limago sys := $(shell uname -s | sed 's/MINGW.*/mingw/') ifeq ($(sys), mingw) + obj = $(ccsrc:.cc=.w32.o) $(csrc:.c=.w32.o) + dep = $(obj:.o=.d) + bin = game.exe + libgl = -lopengl32 -lglu32 -lfreeglut -lglew32 + syslibs = -lmingw32 -lwinmm else libgl = -lGL -lGLU -lglut -lGLEW syslibs = -ldl @@ -33,6 +38,12 @@ $(bin): $(obj) %.d: %.cc @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ +%.w32.o: %.c + $(CC) -o $@ $(CFLAGS) -c $< + +%.w32.o: %.cc + $(CC) -o $@ $(CXXFLAGS) -c $< + .PHONY: clean clean: rm -f $(obj) $(bin) @@ -40,3 +51,11 @@ clean: .PHONY: cleandep cleandep: rm -f $(dep) + +.PHONY: cross +cross: + $(MAKE) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ sys=mingw + +.PHONY: cross-clean +cross-clean: + $(MAKE) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ sys=mingw clean diff --git a/src/game.cc b/src/game.cc index cf3f62a..230c619 100644 --- a/src/game.cc +++ b/src/game.cc @@ -50,13 +50,12 @@ void game_keyboard(int key, bool pressed) { if(pressed) { switch(key) { - case 'q': - case 'Q': - if(game_modkeys() & MODKEY_CTRL) { - game_quit(); - return; - } - break; + case 17: + /* for some inexplicable reason freeglut seems to produce key + * 17 for ctrl-q on both X and windows. + */ + game_quit(); + return; default: break; diff --git a/src/gamescr.cc b/src/gamescr.cc index 0ae1672..26afe42 100644 --- a/src/gamescr.cc +++ b/src/gamescr.cc @@ -1,24 +1,147 @@ +#include +#include #include "game.h" #include "screen.h" #include "opengl.h" +#include "texture.h" + +/* NOTES: + * - whistle hhgg music + * - colliding particles merge + * - select objects and center camera on them + */ + +struct Particle { + float mass; + Vec2 pos; + Vec2 vel; +}; + +struct Emitter { + Vec2 pos; + float mass; + float rate, chunk; + float angle, spread; +}; + + +#define SIM_DT 0.016 + +#define GRID_SIZE 4096 +#define GRID_BITS 12 +#define GRID_X(idx) (((idx) >> GRID_BITS) & (GRID_SIZE - 1)) +#define GRID_Y(idx) ((idx) & (GRID_SIZE - 1)) + +#define FIELD_SIZE 2048 +#define MIN_CAM_DIST 1.0f +#define MAX_CAM_DIST 350.0f + +static int pos_to_grid(float x, float y); + +static float grid[GRID_SIZE * GRID_SIZE]; +static Particle grid_part[GRID_SIZE * GRID_SIZE]; + +static std::vector emitters; + +static Texture *grid_tex; + +static float cam_theta; +static float cam_dist = 100.0f; +static Vec2 *targ_pos; +static Mat4 view_matrix, proj_matrix; + bool GameScreen::init() { + grid_tex = new Texture; + if(!grid_tex->load("data/purple_grid.png")) { + return false; + } + grid_tex->set_anisotropy(glcaps.max_aniso); + return true; } void GameScreen::destroy() { + delete grid_tex; +} + +static void simstep() +{ } +static void update() +{ + static float interval; + + interval += frame_dt; + if(interval >= SIM_DT) { + interval -= SIM_DT; + simstep(); + } + + // update projection matrix + proj_matrix.perspective(deg_to_rad(60.0f), win_aspect, 0.5, 5000.0); + + // update view matrix + Vec3 targ; + if(targ_pos) { + targ.x = targ_pos->x; + targ.z = targ_pos->y; + } + + float theta = -deg_to_rad(cam_theta); + Vec3 camdir = Vec3(sin(theta) * cam_dist, pow(cam_dist * 0.1, 2.0) + 0.5, cos(theta) * cam_dist); + Vec3 campos = targ + camdir; + + view_matrix.inv_lookat(campos, targ, Vec3(0, 1, 0)); +} void GameScreen::draw() { - glClearColor(1, 0, 0, 1); + update(); + + glClearColor(0.01, 0.01, 0.01, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(proj_matrix[0]); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(view_matrix[0]); + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + + glEnable(GL_TEXTURE_2D); + bind_texture(grid_tex); + + float maxu = FIELD_SIZE / 32.0f; + float maxv = FIELD_SIZE / 32.0f; + float hsz = FIELD_SIZE * 0.5f; + + glBegin(GL_QUADS); + glColor3f(1, 1, 1); + glTexCoord2f(0, 0); + glVertex3f(-hsz, 0, -hsz); + glTexCoord2f(maxu, 0); + glVertex3f(hsz, 0, -hsz); + glTexCoord2f(maxu, maxv); + glVertex3f(hsz, 0, hsz); + glTexCoord2f(0, maxv); + glVertex3f(-hsz, 0, hsz); + glEnd(); + + glPopAttrib(); +} + +void GameScreen::reshape(int x, int y) +{ } + void GameScreen::keyboard(int key, bool pressed) { if(pressed) { @@ -33,14 +156,29 @@ void GameScreen::keyboard(int key, bool pressed) } } +static int prev_x, prev_y; + void GameScreen::mbutton(int bn, bool pressed, int x, int y) { + prev_x = x; + prev_y = y; } void GameScreen::mmotion(int x, int y) { + int dx = x - prev_x; + int dy = y - prev_y; + prev_x = x; + prev_y = y; + + if(game_bnstate(2)) { + cam_theta += dx * 0.5; + } } void GameScreen::mwheel(int dir, int x, int y) { + cam_dist -= dir * cam_dist * 0.05f; + if(cam_dist <= MIN_CAM_DIST) cam_dist = MIN_CAM_DIST; + if(cam_dist > MAX_CAM_DIST) cam_dist = MAX_CAM_DIST; } diff --git a/src/goatkit/theme.cc b/src/goatkit/theme.cc index 8f46615..65febbc 100644 --- a/src/goatkit/theme.cc +++ b/src/goatkit/theme.cc @@ -27,6 +27,8 @@ along with this program. If not, see . #ifdef WIN32 #include +#define RTLD_LAZY 0 + static void *dlopen(const char *name, int flags); static void dlclose(void *so); static void *dlsym(void *so, const char *symbol); @@ -289,7 +291,7 @@ static void *dlopen(const char *name, int flags) static void dlclose(void *so) { - FreeLibrary(so); + FreeLibrary((HMODULE)so); } static void *dlsym(void *so, const char *symbol) @@ -297,6 +299,6 @@ static void *dlsym(void *so, const char *symbol) if(!so) { so = GetModuleHandle(0); } - return (void*)GetProcAddress(so, symbol); + return (void*)GetProcAddress((HMODULE)so, symbol); } #endif diff --git a/src/image.cc b/src/image.cc new file mode 100644 index 0000000..57817ca --- /dev/null +++ b/src/image.cc @@ -0,0 +1,299 @@ +#include + +#if defined(WIN32) || defined(__WIN32__) +#include +#else +#include +#endif + +#include "imago2.h" +#include "image.h" + +static int pixel_elements(Image::Format fmt); +static int elem_size(Image::Format fmt); +static int pixel_size(Image::Format fmt); + +Image::Image() +{ + fmt = FMT_RGBA; + width = height = 0; + pixels = 0; +} + +Image::~Image() +{ + delete [] (char*)pixels; +} + +int Image::get_width() const +{ + return width; +} + +int Image::get_height() const +{ + return height; +} + +Image::Format Image::get_format() const +{ + return fmt; +} + +bool Image::create(int x, int y, Format fmt) +{ + width = x; + height = y; + this->fmt = fmt; + + try { + pixels = new char[x * y * pixel_size(fmt)]; + } + catch(...) { + return false; + } + return true; +} + +bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt) +{ + if(!create(xsz, ysz, fmt)) { + return false; + } + memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt)); + return true; +} + +bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt) +{ + return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt); +} + +bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt) +{ + if(scan_width <= 0) { + scan_width = xsz; + } + + if(!create(xsz, ysz, fmt)) { + return false; + } + + int pixsz = pixel_size(fmt); + + unsigned char *dest = (unsigned char*)this->pixels; + unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz; + for(int i=0; i dest) { + memcpy(tmppix, src, pixsz); + memcpy(src, dest, pixsz); + memcpy(dest, tmppix, pixsz); + dest += pixsz; + src -= pixsz; + } + + scan += width * pixsz; + } +} + +void Image::flip_vertical() +{ + int pixsz = pixel_size(fmt); + + unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz); + + unsigned char *dest = (unsigned char*)pixels; + unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz; + + while(src > dest) { + memcpy(tmpscan, src, width * pixsz); + memcpy(src, dest, width * pixsz); + memcpy(dest, tmpscan, width * pixsz); + dest += width * pixsz; + src -= width * pixsz; + } +} + +void Image::rotate_180() +{ + flip_vertical(); + flip_horizontal(); +} + +void Image::resize_half() +{ + int pixsz = pixel_size(fmt); + int newxsz = width / 2; + int newysz = height / 2; + + if(!newxsz || !newysz) return; + + unsigned char *newpix = new unsigned char[newxsz * newysz * pixsz]; + + unsigned char *sptr = (unsigned char*)pixels; + unsigned char *dptr = newpix; + + for(int i=0; i + +class Image { +public: + enum Format { + FMT_GREY, + FMT_RGB, + FMT_RGBA, + FMT_GREY_FLOAT, + FMT_RGB_FLOAT, + FMT_RGBA_FLOAT + }; + +private: + Format fmt; + int width, height; + void *pixels; + +public: + std::string name; + + Image(); + ~Image(); + + int get_width() const; + int get_height() const; + + Format get_format() const; + + bool create(int x, int y, Format fmt = FMT_RGBA); + bool set_pixels(int xsz, int ysz, void *pixels, Format fmt = FMT_RGBA); + bool set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt = FMT_RGBA); + bool set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width = -1, Format fmt = FMT_RGBA); + void *get_pixels() const; + + void flip_horizontal(); + void flip_vertical(); + void rotate_180(); + + void resize_half(); + + bool load(const char *fname); + bool save(const char *fname) const; +}; + +#endif // IMAGE_H_ diff --git a/src/menuscr.cc b/src/menuscr.cc index 7e910c4..00b0aa2 100644 --- a/src/menuscr.cc +++ b/src/menuscr.cc @@ -34,14 +34,14 @@ bool MenuScreen::init() bn_start = new goatkit::Button; bn_start->set_position(xpos, ypos += vsep); bn_start->set_size(bnwidth, bnheight); - bn_start->set_text("Start"); + bn_start->set_text("Don't Panic!"); bn_start->set_callback(goatkit::EV_CLICK, bn_handler, (void*)BN_START); ui.add_widget(bn_start); bn_exit = new goatkit::Button; bn_exit->set_position(xpos, ypos += vsep); bn_exit->set_size(bnwidth, bnheight); - bn_exit->set_text("Exit"); + bn_exit->set_text("Panic"); bn_exit->set_callback(goatkit::EV_CLICK, bn_handler, (void*)BN_EXIT); ui.add_widget(bn_exit); @@ -113,6 +113,18 @@ void MenuScreen::reshape(int x, int y) void MenuScreen::keyboard(int key, bool pressed) { + if(pressed) { + switch(key) { + case KEY_ESC: + exit_pending = true; + ui.hide(); + return; + + default: + break; + } + } + ui.sysev_keyboard(key, pressed); } diff --git a/src/opengl.c b/src/opengl.c index 7042514..5c3ff44 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -15,6 +15,10 @@ int init_opengl(void) { glewInit(); + if(GLEW_EXT_texture_filter_anisotropic) { + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glcaps.max_aniso); + } + glcaps.debug = GLEW_ARB_debug_output; #ifndef NDEBUG diff --git a/src/opengl.h b/src/opengl.h index 80e4875..397cd38 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -5,6 +5,7 @@ struct GLCaps { int debug; /* ARB_debug_output */ + int max_aniso; }; extern struct GLCaps glcaps; diff --git a/src/screen.cc b/src/screen.cc index 6b9a274..1870796 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -16,7 +16,8 @@ bool init_screens() return false; } - push_screen(scr_menu); + //push_screen(scr_menu); + push_screen(scr_game); return true; } diff --git a/src/screen.h b/src/screen.h index c5422f9..6978b77 100644 --- a/src/screen.h +++ b/src/screen.h @@ -55,6 +55,7 @@ public: void destroy(); void draw(); + void reshape(int x, int y); void keyboard(int key, bool pressed); void mbutton(int bn, bool pressed, int x, int y); diff --git a/src/texture.cc b/src/texture.cc new file mode 100644 index 0000000..d9e4f29 --- /dev/null +++ b/src/texture.cc @@ -0,0 +1,486 @@ +#include +#include +#include "texture.h" +#include "image.h" +#include "opengl.h" +#include "imago2.h" + +static int glifmt_from_ifmt(unsigned int ifmt); +static int glfmt_from_ifmt(unsigned int ifmt); +static int gltype_from_ifmt(unsigned int ifmt); + +static int glifmt_from_imgfmt(Image::Format fmt); + +static unsigned int type_to_target(TextureType type); +static TextureType target_to_type(unsigned int targ); + +static unsigned int cur_target[8] = { + GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, + GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D +}; + +static unsigned int cube_faces[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z +}; + + +void bind_texture(Texture *tex, int tunit) +{ + if(tex) { + tex->bind(tunit); + } else { + glActiveTexture(GL_TEXTURE0 + tunit); + glBindTexture(cur_target[tunit], 0); + assert(glGetError() == GL_NO_ERROR); + glActiveTexture(GL_TEXTURE0); + } +} + +Image *Texture::default_img; + +Texture::Texture() +{ + target = 0; + sz[0] = sz[1] = sz[2] = 0; + texfmt = 0; + + img = 0; + glGenTextures(1, &id); +} + +Texture::~Texture() +{ + if(id) { + glDeleteTextures(1, &id); + } + if(img) { + delete img; + } +} + +void Texture::set_wrapping(unsigned int wrap) +{ + if(!target) { + return; + } + + glBindTexture(target, id); + assert(glGetError() == GL_NO_ERROR); + glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap); + glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap); + glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap); +} + +void Texture::set_filtering(unsigned int filt) +{ + unsigned int mag_filter; + + if(!target) { + return; + } + + switch(filt) { + case GL_LINEAR_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_LINEAR: + mag_filter = GL_LINEAR; + break; + + case GL_NEAREST_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + mag_filter = GL_NEAREST; + break; + + default: + mag_filter = filt; + } + + set_filtering(filt, mag_filter); +} + +void Texture::set_filtering(unsigned int min_filt, unsigned int mag_filt) +{ + glBindTexture(target, id); + assert(glGetError() == GL_NO_ERROR); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filt); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filt); +} + +void Texture::set_anisotropy(int aniso) +{ + if(aniso > glcaps.max_aniso) { + aniso = glcaps.max_aniso; + } + + glBindTexture(target, id); + glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso); +} + +unsigned int Texture::get_format() const +{ + return texfmt; +} + +int Texture::get_size(int dim) const +{ + if(dim < 0 || dim >= 3) { + return 0; + } + return sz[dim]; +} + +int Texture::get_width() const +{ + return sz[0]; +} + +int Texture::get_height() const +{ + return sz[1]; +} + +unsigned int Texture::get_id() const +{ + return id; +} + +TextureType Texture::get_type() const +{ + return target_to_type(target); +} + +void Texture::bind(int tex_unit) const +{ + glActiveTexture(GL_TEXTURE0 + tex_unit); + glBindTexture(target, id); + assert(glGetError() == GL_NO_ERROR); + glActiveTexture(GL_TEXTURE0); + + cur_target[tex_unit] = target; +} + + +void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt) +{ + if(textype == TEX_CUBE && xsz != ysz) { + fprintf(stderr, "trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz); + return; + } + + int fmt = glfmt_from_ifmt(ifmt); + int type = gltype_from_ifmt(ifmt); + + target = type_to_target(textype); + + glBindTexture(target, id); + assert(glGetError() == GL_NO_ERROR); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + switch(textype) { + case TEX_2D: + glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0); + break; + + case TEX_CUBE: + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + for(int i=0; i<6; i++) { + glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + } + break; + } + + sz[0] = xsz; + sz[1] = ysz; + texfmt = ifmt; +} + +#define DEF_IMAGE_SIZE 64 +void Texture::create_default(TextureType type) +{ + if(!default_img) { + default_img = new Image; + default_img->create(DEF_IMAGE_SIZE, DEF_IMAGE_SIZE, Image::FMT_RGBA); + + unsigned char *pixels = (unsigned char*)default_img->get_pixels(); + for(int i=0; i> 3) & 1) == ((j >> 3) & 1); + pixels[0] = chess ? 255 : 32; + pixels[1] = 64; + pixels[2] = chess ? 32 : 255; + pixels[3] = 255; + pixels += 4; + } + } + } + + switch(type) { + case TEX_2D: + set_image(*default_img); + break; + + case TEX_CUBE: + for(int i=0; i<6; i++) { + set_image(*default_img, i); + } + break; + } +} + +void Texture::set_image(const Image &img, int idx) +{ + if(idx >= 0 && idx < 6) { + set_image_cube(img, idx); + } else { + if(!set_image_cube(img)) { + set_image_2d(img); + } + } +} + +void Texture::set_image_2d(const Image &img) +{ + texfmt = glifmt_from_imgfmt(img.get_format()); + unsigned int fmt = glfmt_from_ifmt(texfmt); + unsigned int type = gltype_from_ifmt(texfmt); + + sz[0] = img.get_width(); + sz[1] = img.get_height(); + + target = GL_TEXTURE_2D; + glBindTexture(target, id); + assert(glGetError() == GL_NO_ERROR); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + +#ifdef __GLEW_H__ + if(GLEW_SGIS_generate_mipmap) { + glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); +#endif + glTexImage2D(target, 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels()); +#ifdef __GLEW_H__ + } else { + gluBuild2DMipmaps(target, texfmt, sz[0], sz[1], fmt, type, img.get_pixels()); + } +#endif + +#ifdef GL_ES_VERSION_2_0 + glGenerateMipmap(target); +#endif +} + +bool Texture::set_image_cube(const Image &img, int idx) +{ + unsigned int err; + if(idx < 0 || idx >= 6) { + return false; + } + + texfmt = glifmt_from_imgfmt(img.get_format()); + unsigned int fmt = glfmt_from_ifmt(texfmt); + unsigned int type = gltype_from_ifmt(texfmt); + + sz[0] = img.get_width(); + sz[1] = img.get_height(); + + target = GL_TEXTURE_CUBE_MAP; + glBindTexture(target, id); + if((err = glGetError()) == GL_INVALID_OPERATION) { + return false; // probably not a cubemap + } + assert(err == GL_NO_ERROR); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels()); + return true; +} + +bool Texture::set_image_cube(const Image &img) +{ + static const float one_third = 1.0 / 3.0; + static const float two_thirds = 2.0 / 3.0; + static const float hcross[2][6] = { + {0.5, 0.0, 0.25, 0.25, 0.25, 0.75}, {one_third, one_third, 0.0, two_thirds, one_third, one_third} }; + static const float vcross[2][6] = { + {two_thirds, 0.0, one_third, one_third, one_third, one_third}, {0.25, 0.25, 0.0, 0.5, 0.25, 0.75} }; + static const float hsix[2][6] = { + {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} }; + + int xsz = img.get_width(); + int ysz = img.get_height(); + + if((xsz << 8) / 4 == (ysz << 8) / 3) { + // horizontal cross, assume the vertical bit is center-left + return set_cube_multi(img, hcross[0], hcross[1], xsz / 4); + } + if((xsz << 8) / 3 == (ysz << 8) / 4) { + // vertical cross, assume the horizontal bit is center-top (180-rotated image 5) + return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); + } + if((xsz << 8) / 3 == (ysz << 8) / 2) { + // horizontal sixpack + return set_cube_multi(img, hsix[0], hsix[1], ysz / 2); + } + + return false; +} + + +bool Texture::load(const char *fname) +{ + Image img; + if(!img.load(fname)) { + fprintf(stderr, "failed to load 2D texture: %s\n", fname); + return false; + } + set_image(img); + + printf("loaded 2D texture: %s\n", fname); + return true; +} + +bool Texture::load_cube(const char *fname) +{ + Image img; + if(!img.load(fname)) { + return false; + } + return set_image_cube(img); +} + +bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, + unsigned int rotmask) +{ + for(int i=0; i<6; i++) { + Image face; + + int xoffs = xoffsets[i] * img.get_width(); + int yoffs = yoffsets[i] * img.get_height(); + + if(!face.set_pixels(sz, sz, img.get_pixels(), xoffs, yoffs, img.get_width(), img.get_format())) { + return false; + } + + if(rotmask & (1 << i)) { + face.rotate_180(); + } + set_image_cube(face, i); + } + return true; +} + +static int glifmt_from_ifmt(unsigned int ifmt) +{ +#ifdef GL_ES_VERSION_2_0 + switch(ifmt) { + case GL_LUMINANCE16F_ARB: + case GL_LUMINANCE32F_ARB: + ifmt = GL_LUMINANCE; + break; + + case GL_RGB16F: + case GL_RGB32F: + ifmt = GL_RGB; + break; + + case GL_RGBA16F: + case GL_RGBA32F: + ifmt = GL_RGBA; + break; + + default: + break; + } +#endif + return ifmt; // by default just pass it through... +} + +static int glfmt_from_ifmt(unsigned int ifmt) +{ + switch(ifmt) { + case GL_LUMINANCE16F_ARB: + case GL_LUMINANCE32F_ARB: + case GL_SLUMINANCE: + return GL_LUMINANCE; + + case GL_RGB16F: + case GL_RGB32F: + case GL_SRGB: + return GL_RGB; + + case GL_RGBA16F: + case GL_RGBA32F: + case GL_SRGB_ALPHA: + return GL_RGBA; + + default: + break; + } + return ifmt; +} + +static int gltype_from_ifmt(unsigned int ifmt) +{ + switch(ifmt) { + case GL_RGB16F: + case GL_RGBA16F: + case GL_LUMINANCE16F_ARB: +#ifdef GL_ES_VERSION_2_0 + return GL_HALF_FLOAT_OES; +#endif + case GL_RGB32F: + case GL_RGBA32F: + case GL_LUMINANCE32F_ARB: + return GL_FLOAT; + + default: + break; + } + return GL_UNSIGNED_BYTE; +} + +static int glifmt_from_imgfmt(Image::Format fmt) +{ + switch(fmt) { + case Image::FMT_GREY: + return GL_SLUMINANCE; + case Image::FMT_GREY_FLOAT: + return GL_LUMINANCE16F_ARB; + case Image::FMT_RGB: + return GL_SRGB; + case Image::FMT_RGB_FLOAT: + return GL_RGB16F; + case Image::FMT_RGBA: + return GL_SRGB_ALPHA; + case Image::FMT_RGBA_FLOAT: + return GL_RGBA16F; + default: + break; + } + return 0; +} + +static unsigned int type_to_target(TextureType type) +{ + return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; +} + +static TextureType target_to_type(unsigned int targ) +{ + return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D; +} diff --git a/src/texture.h b/src/texture.h new file mode 100644 index 0000000..5f74e98 --- /dev/null +++ b/src/texture.h @@ -0,0 +1,61 @@ +#ifndef TEXTURE_H_ +#define TEXTURE_H_ + +#include "opengl.h" + +class Image; + +enum TextureType { TEX_2D, TEX_CUBE }; + +class Texture { +private: + unsigned int id; + unsigned int target; + unsigned int texfmt; + int sz[3]; + Image *img; + static Image *default_img; + + Texture(const Texture &tex) {} + Texture &operator =(const Texture &tex) { return *this; } + + void set_image_2d(const Image &img); + bool set_image_cube(const Image &img, int idx); + bool set_image_cube(const Image &img); + + bool load_cube(const char *fname); + + /* for loading multiple cubemap faces from a single image */ + bool set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, + unsigned int rotmask = 0); + +public: + Texture(); + ~Texture(); + + void set_wrapping(unsigned int wrap); + void set_filtering(unsigned int filt); + void set_filtering(unsigned int min_filt, unsigned int mag_filt); + void set_anisotropy(int aniso); + + unsigned int get_format() const; + + int get_size(int dim) const; + int get_width() const; + int get_height() const; + + void create(int xsz, int ysz, TextureType type = TEX_2D, unsigned int ifmt = GL_RGBA); + void create_default(TextureType type = TEX_2D); + void set_image(const Image &img, int idx = -1); + + bool load(const char *fname); + + unsigned int get_id() const; + TextureType get_type() const; + + void bind(int tex_unit = 0) const; +}; + +void bind_texture(Texture *tex, int tunit = 0); + +#endif // TEXTURE_H_ diff --git a/src/uitheme.cc b/src/uitheme.cc index 28c497c..9a98ef8 100644 --- a/src/uitheme.cc +++ b/src/uitheme.cc @@ -45,12 +45,12 @@ static bool initialized; static std::map funcmap; /* theme colors */ -static float fgcol[] = {0.8, 0.6, 0.4, 1.0}; -static float fgcol_off[] = {0.65, 0.65, 0.6, 1.0}; +static float fgcol[] = {0.4, 0.5, 0.8, 1.0}; +static float fgcol_off[] = {0.5, 0.6, 0.65, 1.0}; static float fgcol_inact[] = {0.4, 0.4, 0.4, 1.0}; -static float bgcol[] = {0.3, 0.3, 0.3, 1.0}; -static float bgcol_off[] = {0.3, 0.3, 0.3, 1.0}; -static float bgcol_inact[] = {0.3, 0.3, 0.3, 1.0}; +static float bgcol[] = {0.1, 0.1, 0.15, 1.0}; +static float bgcol_off[] = {0.1, 0.1, 0.15, 1.0}; +static float bgcol_inact[] = {0.1, 0.1, 0.15, 1.0}; extern "C" goatkit::WidgetDrawFunc get_widget_func(const char *name) diff --git a/tools/dlldepends b/tools/dlldepends new file mode 100755 index 0000000..7515d35 --- /dev/null +++ b/tools/dlldepends @@ -0,0 +1,25 @@ +#!/bin/dash + +depends() { + dlls=$(strings $1 | grep '\.dll' | grep -v '\(USER32\|KERNEL32\|msvcrt\)') + + gccver=$(i686-w64-mingw32-gcc -dumpversion | awk -F . '{ print $1 "." $2 }') + + libpaths="/usr/i686-w64-mingw32/lib \ + /usr/i686-w64-mingw32/bin \ + /usr/lib/gcc/i686-w64-mingw32/$gccver-win32" + + for i in $dlls; do + for path in $libpaths; do + dllfile=$path/$i + if [ -f $dllfile ]; then + echo $dllfile + if [ ! "$2" = noreq ]; then + depends $dllfile noreq + fi + fi + done + done +} + +depends game.exe | sort | uniq