Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

graphics.cpp

Go to the documentation of this file.
00001 #include <SDL/SDL.h>
00002 #include <SDL/SDL_image.h>
00003 #include <string.h>
00004 #include <iostream>
00005 
00006 #include "application.h"
00007 #include "graphics.h"
00008 #include "util.h"
00009 
00010 Graphics::Graphics(string title, int w, int h, bool opengl)
00011 {
00012 #ifdef DEBUG
00013         cerr << "Window title: " << title << " (" << w << ", " << h << ")" << endl;
00014 #endif
00015         if(w < 320)
00016                 width = 320;
00017         else
00018                 width = w;
00019 
00020         if(h < 240)
00021                 height = 240;
00022         else
00023                 height = h;
00024 
00025         int flags = SDL_HWSURFACE | SDL_DOUBLEBUF;
00026         if (opengl)
00027                 flags |= SDL_OPENGL;
00028                 
00029         hwSurface = new Surface;
00030         
00031         SDL_InitSubSystem(SDL_INIT_VIDEO);
00032 
00033         if (opengl)
00034                 PreOpenGLInit();
00035 
00036         hwSurface->surface = SDL_SetVideoMode(width, height, 16, flags);
00037 
00038         hwSurface->w = hwSurface->surface->w;
00039         hwSurface->h = hwSurface->surface->h;
00040 
00041         SDL_WM_SetCaption (title.c_str(), title.c_str());
00042 
00043         if (opengl)
00044                 PostOpenGLInit();
00045 }
00046 
00047 Graphics::~Graphics()
00048 {
00049         SDL_FreeSurface(hwSurface->surface);
00050         delete hwSurface;
00051         
00052         SDL_QuitSubSystem(SDL_INIT_VIDEO);
00053 }
00054 
00055 void Graphics::PreOpenGLInit()
00056 {
00057         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
00058         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
00059         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
00060         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
00061 
00062         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, SDL_DOUBLEBUF);
00063 }
00064         
00065                 
00066 void Graphics::PostOpenGLInit()
00067 {
00068         GLint maxtexsize;
00069         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize);
00070 
00071         cout << "Maximum texture size is " << maxtexsize << 'x' << maxtexsize << endl;
00072 
00073         glDisable(GL_DEPTH_TEST);
00074         glDisable(GL_CULL_FACE);
00075 
00076         glViewport (0, 0, hwSurface->w, hwSurface->h);
00077         glMatrixMode(GL_PROJECTION);
00078         glLoadIdentity();
00079         glOrtho (0, hwSurface->w, hwSurface->h, 0, -10.0, 10.0);
00080         glMatrixMode(GL_MODELVIEW);
00081         glLoadIdentity();
00082         glTranslatef(0.0f, 0.0f, 0.0f);
00083 
00084         glEnable (GL_BLEND);
00085         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00086         glEnable (GL_TEXTURE_2D);
00087         
00088         return;
00089 }
00090 
00091                                                         
00092 void
00093 Graphics::update(int x, int y, int w, int h)
00094 {
00096         if (hwSurface->surface->flags & SDL_OPENGL)
00097                 return;
00098         
00099         if(hwSurface && hwSurface->surface) {
00100                 // If the x coord is offscreen, adjust
00101                 if(x < 0) {
00102                         w += x;
00103                         x = 0;
00104                 }
00105 
00106                 // If the x coord is offscreen to the right, return
00107                 if(x >= width) 
00108                         return;
00109 
00110                 // If the y coord is offscreen...
00111                 if(y < 0) {
00112                         h += y;
00113                         y = 0;
00114                 }
00115 
00116                 if(y >= height) 
00117                         return;
00118 
00119                 // If the width goes offscreen, clip it.
00120                 if((x+w) >= width) 
00121                         w = (width - x);
00122 
00123                 // Same for height
00124                 if((y+h) >= height) 
00125                         h = (height - y);
00126 
00127                 // If the total width/height is <= 0, don't draw
00128                 if(w <= 0 || h <= 0) 
00129                         return;
00130 
00131                 SDL_UpdateRect(hwSurface->surface, x, y, w, h); 
00132         }
00133 }
00134 
00135 void Graphics::update(Rect &r)
00136 {
00137         // -9999 is a special value for rects
00139         if(r.x == r.y && r.y == -9999) 
00140                 return;
00141         
00142         update(r.x, r.y, r.w, r.h);
00143 }
00144 
00145 void Graphics::blitGLtexture (Surface *src, int srx, int sry, int srw, int srh,
00146                 int drx, int dry, int drw, int drh)
00147 {
00148         float width = (float)src->w / (float)src->ts;
00149         float height = (float)src->h / (float)src->ts;
00150 
00151         glBindTexture (GL_TEXTURE_2D, src->tex);
00152         glBegin(GL_QUADS);
00153         glTexCoord2f (0, 0);            glVertex2i (drx, dry);
00154         glTexCoord2f (width, 0);        glVertex2i (drx + srw, dry);
00155         glTexCoord2f (width, height);   glVertex2i (drx + srw, dry + srh);
00156         glTexCoord2f (0, height);       glVertex2i (drx, dry + srh);
00157         glEnd();
00158 }
00159 
00160 
00161 // The following function blits src (0,0)-(src->w,src->h) onto
00162 // the video framebuffer with clipping.
00163 // This function assumes dest and src valid pointers.
00164 void Graphics::blitclip(Surface *dest, int drx, int dry, int drw, int drh,
00165                      Surface *src,  int srx, int sry, int srw, int srh)
00166 {
00168         if (dest && dest->surface && (dest->surface->flags & SDL_OPENGL)) {
00169                 blitGLtexture(src, srx, sry, srw, srh, drx, dry, drw, drh);
00170                 return;
00171         }
00172 
00173         // If we end up drawing off screen to the right or bottom
00174         if ( (drx + drw) >= dest->w ) {
00175                 int offs = (drx + drw) - dest->w;       // count how far off
00176                 drw -= offs;                            // reduce draw
00177                 srw -= offs;
00178         }
00179 
00180         // Same as above if statement for Y values
00181         if ( (dry + drh) >= dest->h ) {
00182                 int offs = (dry + drh) - dest->h;
00183                 drh -= offs;
00184                 srh -= offs;
00185         }
00186 
00187         if ( drx < 0 ) {
00188                 int offs = -drx;        // store how far left
00189                 drx = 0;                // draw at 0
00190                 drw -= offs;            // reduce width by offset
00191                 if (drw <= 0)           // if width is still <= 0, return
00192                         return;
00193 
00194                 srx += offs;            // draw more to the right.
00195                 srw -= offs;            // reduce width.
00196         }
00197 
00198         if ( dry < 0 ) {                // see above comments.
00199                 int offs = -dry;
00200                 dry = 0;
00201                 drh -= offs;
00202                 if (drh <= 0)
00203                         return;
00204 
00205                 sry += offs;
00206                 srh -= offs;
00207         }
00208 
00209         if ( (srx >= src->w) || (sry >= src->h) )
00210                 return;
00211 
00212         // If we end up shrinking width and height to below/= 0
00213         if ( (srw <= 0) || (srh <= 0) || (drw <= 0) || (drh <= 0) )
00214                 return;
00215 
00216         Rect srcrect = Util_BuildRect(srx, sry, srw, srh);
00217         Rect dstrect = Util_BuildRect(drx, dry, drw, drh);
00218 
00219         SDL_LowerBlit(src->surface, &srcrect, dest->surface, &dstrect);
00220 }
00221 
00222 void 
00223 Graphics::blit(Surface *src, int dx, int dy)
00224 {
00225         blit(hwSurface, dx, dy, src);
00226         return;
00227 }
00228 
00229 void 
00230 Graphics::blit(Surface *target, int tx, int ty, Surface *src)
00231 {
00232         // If either tx or ty are offscreen, or src or hwSurface is null,
00233         // return.
00234         if (!target || !src || tx >= (signed int)target->w || ty >= (signed int)target->h) 
00235                 return;
00236         
00237 
00238         blitclip (target,  tx,  ty, src->w, src->h,
00239                      src,   0,   0, src->w, src->h);
00240 }
00241 
00242 void 
00243 Graphics::blit(Surface *target, Rect &t, Surface *src, Rect &s)
00244 {
00245         if(t.x == t.y && t.y == -9999)
00246                 return;
00247         
00248         if(target && src) {
00249                 blitclip (target, t.x, t.y, t.w, t.h,
00250                           src,    s.x, s.y, s.w, s.h);
00251         }
00252 }
00253 
00254 Surface *
00255 Graphics::newSurface(int w, int h)
00256 {
00257         if(w < 1 || h < 1) return (Surface *) NULL;
00258 
00259         Surface *n = new Surface;
00260         n->surface = SDL_CreateRGBSurface (SDL_SWSURFACE, w, h, 32,
00261                 hwSurface->surface->format->Rmask,
00262                 hwSurface->surface->format->Gmask,
00263                 hwSurface->surface->format->Bmask,
00264                 hwSurface->surface->format->Amask);
00265 
00266         if(n) {
00267                 n->w = w;
00268                 n->h = h;
00269                 return n;
00270         }
00271         
00272         cout << SDL_GetError() << endl;
00273 
00274         return (Surface *) NULL;
00275 }
00276 
00277 Surface *
00278 Graphics::CreateSurfaceFrom(Surface *s)
00279 {
00280         if (!s)
00281                 return (Surface *) NULL;
00282         
00283         Surface *n = new Surface;
00284         n->surface = SDL_CreateRGBSurfaceFrom(s->surface->pixels, s->surface->w,
00285                                 s->surface->h, s->surface->format->BitsPerPixel, 
00286                                 s->surface->pitch, s->surface->format->Rmask,
00287                                 s->surface->format->Gmask, s->surface->format->Bmask,
00288                                 s->surface->format->Amask);
00289 
00290         if(n) {
00291                 n->w = n->surface->w;
00292                 n->h = n->surface->h;
00293                 return n;
00294         }
00295 
00296         cout << __LINE__ << ": " << SDL_GetError() << endl;
00297         return (Surface *) NULL;
00298 }
00299 
00300 Surface *
00301 Graphics::CreateSurfaceFrom(Surface *s, int nw, int nh)
00302 {
00303         if (!s)
00304                 return (Surface *) NULL;
00305 
00306         Surface *n = new Surface;
00307         n->surface = SDL_CreateRGBSurface(s->surface->flags, nw, nh,
00308                                 s->surface->format->BitsPerPixel,
00309                                 s->surface->format->Rmask,
00310                                 s->surface->format->Gmask,
00311                                 s->surface->format->Bmask,
00312                                 s->surface->format->Amask);
00313         if(n) {
00314                 n->w = n->surface->w;
00315                 n->h = n->surface->h;
00316                 return n;
00317         }
00318 
00319         cout << __LINE__ << ": " << SDL_GetError() << endl;
00320         return (Surface *) NULL;
00321 }
00322 
00323 void Graphics::deleteSurface(Surface *n)
00324 {
00325         SDL_FreeSurface(n->surface);
00326         delete n;
00327 }
00328 
00329 void Graphics::fillSurface(Surface *n, int color)
00330 {
00331         SDL_FillRect(n->surface, NULL, color);
00332 }
00333 
00334 int Graphics::color(int r, int g, int b, Surface * n)
00335 {
00336         if(n) {
00337                 return SDL_MapRGB(n->surface->format, r, g, b);
00338         } else {
00339                 return SDL_MapRGB(hwSurface->surface->format, r, g, b);
00340         }
00341 }
00342 
00343 Surface *
00344 Graphics::loadImage(const char *fname)
00345 {
00346         if(!fname) return (Surface *)NULL;
00347 
00348         Surface *n = new Surface;
00349         n->surface = IMG_Load(fname);
00350         if (!n) cout << SDL_GetError() << endl;
00351         n->w = n->surface->w;
00352         n->h = n->surface->h;
00353         return n;
00354 }
00355 
00356 Surface *
00357 Graphics::loadImage(string fname) 
00358 { 
00359         return Graphics::loadImage(fname.c_str()); 
00360 }
00361 
00362 Surface *
00363 Graphics::freeImage(Surface *surf)
00364 {
00365         if(surf) {
00366                 SDL_FreeSurface (surf->surface);
00367                 delete surf;
00368         }
00369         return NULL;
00370 }
00371 
00372 Surface *Graphics::displayFormat(Surface *surf, bool alpha)
00373 {
00374         if (alpha) {
00375                 Surface *n = new Surface;
00376                 n->surface = SDL_DisplayFormatAlpha(surf->surface);
00377                 n->w = surf->w;
00378                 n->h = surf->h;
00379                 return n;
00380         }
00381         
00382         Surface *n = new Surface;
00383         n->surface = SDL_DisplayFormat(surf->surface);
00384         n->w = surf->w;
00385         n->h = surf->h;
00386         return n;
00387 }
00388 
00389 bool Graphics::lockMouse(bool lock)
00390 {
00391         return (SDL_WM_GrabInput( (lock) ? SDL_GRAB_ON : SDL_GRAB_OFF ) == SDL_GRAB_ON);
00392 }
00393 
00394 void Graphics::flip()
00395 {
00396         if (!hwSurface || !hwSurface->surface)
00397                 return;
00398         
00399         if (hwSurface->surface->flags & SDL_OPENGL) {
00400                 GLint err = glGetError();
00401                 if (err != GL_NO_ERROR) {
00402                         cerr << "OpenGL error " << err << endl;
00403                         err = glGetError();
00404                 }
00405         
00406                 SDL_GL_SwapBuffers();
00407                 glClear (GL_COLOR_BUFFER_BIT);
00408         } else {
00409                 SDL_Flip(hwSurface->surface);
00410         }
00411 }
00412 
00413 void Graphics::TexturizeSurface (Surface *s)
00414 {
00415         int size = Util_FindBestSurfaceSize (s->w, s->h);
00416 
00417         Surface temp;
00418 
00419         SDL_SetAlpha (s->surface, 0, 0);
00420         
00421         temp.surface = SDL_AllocSurface (SDL_SWSURFACE, size, size, 32, 
00422                                 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
00423         
00424         SDL_BlitSurface (s->surface, NULL, temp.surface, NULL);
00425         SDL_FreeSurface (s->surface);
00426         s->surface = (SDL_Surface *) NULL;
00427 
00428         glGenTextures (1, &(s->tex));
00429         glBindTexture(GL_TEXTURE_2D, s->tex);
00430         glPixelStorei(GL_UNPACK_ROW_LENGTH, temp.surface->pitch / temp.surface->format->BytesPerPixel);
00431         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00432         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00433         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, temp.surface->w, temp.surface->h, 0, GL_RGBA,
00434                         GL_UNSIGNED_BYTE, temp.surface->pixels);
00435         glFlush();
00436 
00437         SDL_FreeSurface (temp.surface);
00438 
00439         s->tx = s->ty = 0;
00440         s->ts = size;
00441 }
00442 
00443 void Graphics::UntexturizeSurface (Surface *s)
00444 {
00445         if (!s || !(s->tex >= 0))
00446                 return;
00447 
00448         glDeleteTextures(1, &s->tex);
00449 }
00450 
00451 void Graphics::RotateZ (float degrees)
00452 {
00453         glLoadIdentity();
00454         glTranslatef (getWidth()/2, getHeight()/2, 0);
00455         glRotatef (degrees, 0.0, 0.0, 1.0);
00456         glTranslatef (getWidth()/-2, getHeight()/-2, 0);
00457 }
00458 

Generated on Sun Dec 8 12:02:19 2002 for nnc by doxygen1.3-rc1