From fee98162a6a1639a46d5724370bef564c6799a9b Mon Sep 17 00:00:00 2001 From: Allanis Date: Sat, 1 Jun 2013 21:59:08 +0100 Subject: [PATCH] [Fix] OpenGL blitting stuff. --- src/opengl.c | 115 ++++++++++++++++++++++++++++++--------------------- src/opengl.h | 9 +++- 2 files changed, 76 insertions(+), 48 deletions(-) diff --git a/src/opengl.c b/src/opengl.c index 5759c3f..0e9d8dd 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -32,6 +32,9 @@ static uint8_t* SDL_MapTrans(SDL_Surface* s); static int pot(int n); // glTexture. static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh); +static void gl_blitTexture(const glTexture* texture, + const double x, const double y, + const double tx, const double ty, const glColour* c); // PNG. int write_png(const char* file_name, png_bytep* rows, int w, int h, @@ -350,82 +353,102 @@ void gl_getSpriteFromDir(int* x, int* y, const glTexture* t, const double dir) { // BLITTING! // ================ +static void gl_blitTexture(const glTexture* texture, + const double x, const double y, + const double tx, const double ty, const glColour* c) { + + double tw, th; + + // Texture dimensions. + tw = texture->sw / texture->rw; + th = texture->sh / texture->rh; + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texture->texture); + glBegin(GL_QUADS); + // Set colour or default if not set. + if(c == NULL) glColor4d(1., 1., 1., 1.); + else COLOUR(*c); + + glTexCoord2d(tx, ty); + glVertex2d(x, y); + + glTexCoord2d(tx + tw, ty); + glVertex2d(x + texture->sw, y); + + glTexCoord2d(tx + tw, ty + th); + glVertex2d(x + texture->sw, y + texture->sh); + + glTexCoord2d(tx, ty + th); + glVertex2d(x, y + texture->sh); + glEnd(); + glDisable(GL_TEXTURE_2D); + + // Did anything fail? + gl_checkErr(); +} + // Blit the sprite at given position. void gl_blitSprite(const glTexture* sprite, const double bx, const double by, const int sx, const int sy, const glColour* c) { - // Don't bother drawing if offscreen -- waste of cycles. - if(fabs(bx-VX(*gl_camera)+gui_xoff) > SCREEN_W / 2 + sprite->sw / 2 || - fabs(by-VY(*gl_camera)+gui_yoff) > SCREEN_H / 2 + sprite->sh / 2) - return; - double x, y, tx, ty; - glEnable(GL_TEXTURE_2D); - + // Calculate position - we'll use relative coords to player. x = bx - VX(*gl_camera) - sprite->sw/2. + gui_xoff; y = by - VY(*gl_camera) - sprite->sh/2. + gui_yoff; + // Don't draw if offscreen. + if((fabs(x) > SCREEN_W/2 + sprite->sw) || + (fabs(y) > SCREEN_H/2 + sprite->sh)) + return; + + // Texture coords. tx = sprite->sw * (double)(sx)/sprite->rw; ty = sprite->sh * (sprite->sy-(double)sy-1)/sprite->rh; - // Actual blitting.... - glBindTexture(GL_TEXTURE_2D, sprite->texture); - glBegin(GL_QUADS); - if(c == NULL) glColor4d(1., 1., 1., 1.); - else COLOUR(*c); + // Actual blitting. + gl_blitTexture(sprite, x, y, tx, ty, c); +} - glTexCoord2d(tx, ty); - glVertex2d(x, y); +// Like gl_blitSprite but will use the actual direction, for things that +// can just rotate around. +void gl_blitRotate(const glTexture* texture, + const double bx, const double by, + const double dir, const glColour* c) { - glTexCoord2d(tx + sprite->sw/sprite->rw, ty); - glVertex2d(x + sprite->sw, y); + double x, y; - glTexCoord2d(tx + sprite->sw/sprite->rw, ty + sprite->sh/sprite->rh); - glVertex2d(x + sprite->sw, y + sprite->sh); + // Calculate position - we'll use relative coords to player. + x = bx - VX(*gl_camera) - texture->sw/2. + gui_xoff; + y = by - VY(*gl_camera) - texture->sh/2. + gui_yoff; - glTexCoord2d(tx, ty + sprite->sh/sprite->rh); - glVertex2d(x, y + sprite->sh); + // Don't draw if offscreen. + if((fabs(x) > SCREEN_W/2 + texture->sw) || + (fabs(y) > SCREEN_H/2 + texture->sh)) + return; - glEnd(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glRotated(dir, 0., 0., 1.); - glDisable(GL_TEXTURE_2D); + // Blit. + gl_blitTexture(texture, x, y, 0, 0, c); - gl_checkErr(); + glPopMatrix(); // GL_PROJECTION. } // Just straight out blit the thing at position. void gl_blitStatic(const glTexture* texture, const double bx, const double by, const glColour* c) { double x, y; - glEnable(GL_TEXTURE_2D); + // Here we use absolute coords. x = bx - (double)SCREEN_W/2.; y = by - (double)SCREEN_H/2.; // Actual blitting.. - glBindTexture(GL_TEXTURE_2D, texture->texture); - glBegin(GL_QUADS); - if(c == NULL) glColor4d(1., 1., 1., 1.); - else COLOUR(*c); - - glTexCoord2d(0., 0.); - glVertex2d(x, y); - - glTexCoord2d(texture->sw/texture->rw, 0.); - glVertex2d(x + texture->sw, y); - - glTexCoord2d(texture->sw/texture->rw, texture->sh/texture->rh); - glVertex2d(x + texture->sw, y + texture->sh); - - glTexCoord2d(0., texture->sh/texture->rh); - glVertex2d(x, y + texture->sh); - - glEnd(); - - glDisable(GL_TEXTURE_2D); - - gl_checkErr(); + gl_blitTexture(texture, x, y, 0, 0, c); } // Bind our precious camera to a vector. diff --git a/src/opengl.h b/src/opengl.h index d03b41b..1d5b4c6 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -60,11 +60,16 @@ glTexture* gl_newSprite(const char* path, const int sx, const int sy); void gl_freeTexture(glTexture* texture); // Rendering. -// Blits a sprite. +// Blits a sprite, relative pos. void gl_blitSprite(const glTexture* sprite, const double bx, const double by, const int sx, const int sy, const glColour* c); -// Blit the entire image. +// Blits a texture rotated, relative pos. +void gl_blitRotate(const glTexture* texture, + const double bx, const double by, + const double dir, const glColour* c); + +// Blit the entire image, absolute pos. void gl_blitStatic(const glTexture* texture, const double bx, const double by, const glColour* c);