FIFE
2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2008 by the FIFE team * 00003 * http://www.fifengine.de * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 #include <cassert> 00024 #include <iostream> 00025 // 3rd party library includes 00026 00027 // FIFE includes 00028 // These includes are split up in two parts, separated by one empty line 00029 // First block: files included from the FIFE root src directory 00030 // Second block: files included from the same folder 00031 #include "util/structures/rect.h" 00032 #include "video/sdl/sdlimage.h" 00033 #include "video/renderbackend.h" 00034 00035 #include "glimage.h" 00036 00037 namespace FIFE { 00038 GLImage::GLImage(SDL_Surface* surface): 00039 Image(surface) { 00040 m_sdlimage = new SDLImage(surface); 00041 00042 m_textureids = NULL; 00043 00044 resetGlimage(); 00045 } 00046 00047 GLImage::GLImage(const uint8_t* data, unsigned int width, unsigned int height): 00048 Image(data, width, height) { 00049 assert(m_surface); 00050 m_sdlimage = new SDLImage(m_surface); 00051 00052 m_textureids = NULL; 00053 00054 resetGlimage(); 00055 } 00056 00057 GLImage::~GLImage() { 00058 // remove surface so that deletion happens correctly (by base class destructor) 00059 m_sdlimage->detachSurface(); 00060 delete m_sdlimage; 00061 00062 cleanup(); 00063 } 00064 00065 void GLImage::invalidate() { 00066 resetGlimage(); 00067 } 00068 00069 void GLImage::resetGlimage() { 00070 cleanup(); 00071 00072 m_chunk_size_w = 0; 00073 m_chunk_size_h = 0; 00074 00075 m_colorkey = RenderBackend::instance()->getColorKey(); 00076 } 00077 00078 void GLImage::cleanup() { 00079 if (m_textureids) { 00080 glDeleteTextures(1, &m_textureids[0]); 00081 00082 delete[] m_textureids; 00083 m_textureids = NULL; 00084 } 00085 00086 m_col_tex_coord = 0; 00087 m_row_tex_coord = 0; 00088 } 00089 00090 void GLImage::render(const Rect& rect, SDL_Surface* screen, unsigned char alpha) { 00091 if (!m_textureids) { 00092 generateGLTexture(); 00093 } 00094 00095 //not on the screen. dont render 00096 if (rect.right() < 0 || rect.x > static_cast<int>(screen->w) || rect.bottom() < 0 || rect.y > static_cast<int>(screen->h)) { 00097 return; 00098 } 00099 00100 //completely transparent so dont bother rendering 00101 if (0 == alpha) { 00102 return; 00103 } 00104 00105 // the amount of "zooming" for the image 00106 float scale_x = static_cast<float>(rect.w) / static_cast<float>(m_surface->w); 00107 float scale_y = static_cast<float>(rect.h) / static_cast<float>(m_surface->h); 00108 00109 // apply the scale to the width and height of the image 00110 uint16_t w = static_cast<int>(round(scale_x*m_surface->w)); 00111 uint16_t h = static_cast<int>(round(scale_y*m_surface->h)); 00112 00113 // setting transparency for the whole primitive: 00114 glColor4ub( 255, 255, 255, alpha ); 00115 00116 glEnable(GL_TEXTURE_2D); 00117 glBindTexture(GL_TEXTURE_2D, m_textureids[0]); 00118 00119 glBegin(GL_QUADS); 00120 glTexCoord2f(0.0f, 0.0f); 00121 glVertex2i(rect.x, rect.y); 00122 00123 glTexCoord2f(0.0f, m_row_tex_coord); 00124 glVertex2i(rect.x, rect.y + h); 00125 00126 glTexCoord2f(m_col_tex_coord, m_row_tex_coord); 00127 glVertex2i(rect.x + w, rect.y + h); 00128 00129 glTexCoord2f(m_col_tex_coord, 0.0f); 00130 glVertex2i(rect.x + w, rect.y); 00131 glEnd(); 00132 glDisable(GL_TEXTURE_2D); 00133 00134 } 00135 00136 void GLImage::generateGLTexture() { 00137 const unsigned int width = m_surface->w; 00138 const unsigned int height = m_surface->h; 00139 00140 //calculate the nearest larger power of 2 00141 m_chunk_size_w = nextPow2(width); 00142 m_chunk_size_h = nextPow2(height); 00143 00144 // used to calculate the fill ratio for given chunk 00145 m_col_tex_coord = static_cast<float>(m_surface->w%m_chunk_size_w) / static_cast<float>(m_chunk_size_w); 00146 m_row_tex_coord = static_cast<float>(m_surface->h%m_chunk_size_h) / static_cast<float>(m_chunk_size_h); 00147 00148 if (m_col_tex_coord == 0.0f){ 00149 m_col_tex_coord = 1.0f; 00150 } 00151 00152 if (m_row_tex_coord == 0.0f){ 00153 m_row_tex_coord = 1.0f; 00154 } 00155 00156 uint8_t* data = static_cast<uint8_t*>(m_surface->pixels); 00157 int pitch = m_surface->pitch; 00158 00159 00160 assert(!m_textureids); 00161 00162 m_textureids = new GLuint[1]; 00163 memset(m_textureids, 0x00, 1*sizeof(GLuint)); 00164 00165 00166 uint32_t* oglbuffer = new uint32_t[m_chunk_size_w * m_chunk_size_h]; 00167 memset(oglbuffer, 0x00, m_chunk_size_w*m_chunk_size_h*sizeof(uint32_t)); 00168 00169 for (unsigned int y = 0; y < height; ++y) { 00170 for (unsigned int x = 0; x < width; ++x) { 00171 unsigned int pos = (y * pitch) + (x * 4); 00172 00173 uint8_t r = data[pos + 3]; 00174 uint8_t g = data[pos + 2]; 00175 uint8_t b = data[pos + 1]; 00176 uint8_t a = data[pos + 0]; 00177 00178 if (RenderBackend::instance()->isColorKeyEnabled()) { 00179 // only set alpha to zero if colorkey feature is enabled 00180 if (r == m_colorkey.r && g == m_colorkey.g && b == m_colorkey.b) { 00181 a = 0; 00182 } 00183 } 00184 00185 oglbuffer[(y*m_chunk_size_w) + x] = r | (g << 8) | (b << 16) | (a<<24); 00186 } 00187 } 00188 00189 // get texture id from opengl 00190 glGenTextures(1, &m_textureids[0]); 00191 // set focus on that texture 00192 glBindTexture(GL_TEXTURE_2D, m_textureids[0]); 00193 // set filters for texture 00194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00195 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00196 // transfer data from sdl buffer 00197 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_chunk_size_w, m_chunk_size_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLvoid*>(oglbuffer)); 00198 00199 delete[] oglbuffer; 00200 } 00201 00202 void GLImage::saveImage(const std::string& filename) { 00203 const unsigned int swidth = getWidth(); 00204 const unsigned int sheight = getHeight(); 00205 SDL_Surface *surface = NULL; 00206 uint8_t *pixels; 00207 00208 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, 00209 sheight, 24, 00210 RMASK,GMASK,BMASK, NULLMASK); 00211 00212 if(surface == NULL) { 00213 return; 00214 } 00215 00216 SDL_LockSurface(surface); 00217 pixels = new uint8_t[swidth * sheight * 3]; 00218 glReadPixels(0, 0, swidth, sheight, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels)); 00219 00220 uint8_t *imagepixels = reinterpret_cast<uint8_t*>(surface->pixels); 00221 // Copy the "reversed_image" memory to the "image" memory 00222 for (int y = (sheight - 1); y >= 0; --y) { 00223 uint8_t *rowbegin = pixels + y * swidth * 3; 00224 uint8_t *rowend = rowbegin + swidth * 3; 00225 00226 std::copy(rowbegin, rowend, imagepixels); 00227 00228 // Advance a row in the output surface. 00229 imagepixels += surface->pitch; 00230 } 00231 00232 SDL_UnlockSurface(surface); 00233 saveAsPng(filename, *surface); 00234 SDL_FreeSurface(surface); 00235 delete [] pixels; 00236 } 00237 00238 void GLImage::setClipArea(const Rect& cliparea, bool clear) { 00239 glScissor(cliparea.x, getHeight() - cliparea.y - cliparea.h, cliparea.w, cliparea.h); 00240 00241 if (clear) { 00242 glClear(GL_COLOR_BUFFER_BIT); 00243 } 00244 } 00245 00246 bool GLImage::putPixel(int x, int y, int r, int g, int b, int a) { 00247 cleanup(); 00248 return m_sdlimage->putPixel(x, y, r, g, b, a); 00249 } 00250 00251 void GLImage::drawLine(const Point& p1, const Point& p2, int r, int g, int b, int a) { 00252 cleanup(); 00253 m_sdlimage->drawLine(p1, p2, r, g, b, a); 00254 } 00255 00256 void GLImage::drawTriangle(const Point& p1, const Point& p2, const Point& p3, int r, int g, int b, int a) { 00257 cleanup(); 00258 m_sdlimage->drawTriangle(p1, p2, p3, r, g, b, a); 00259 } 00260 00261 void GLImage::drawRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { 00262 cleanup(); 00263 m_sdlimage->drawRectangle(p, w, h, r, g, b, a); 00264 } 00265 00266 void GLImage::fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { 00267 cleanup(); 00268 m_sdlimage->fillRectangle(p, w, h, r, g, b, a); 00269 } 00270 00271 void GLImage::drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a) { 00272 cleanup(); 00273 m_sdlimage->drawQuad(p1, p2, p3, p4, r, g, b, a); 00274 } 00275 00276 void GLImage::drawVertex(const Point& p, const uint8_t size, int r, int g, int b, int a) { 00277 cleanup(); 00278 m_sdlimage->drawVertex(p, size, r, g, b, a); 00279 } 00280 00281 void GLImage::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) { 00282 cleanup(); 00283 m_sdlimage->drawLightPrimitive(p, intensity, radius, subdivisions, xstretch, ystretch, red, green, blue); 00284 } 00285 }