draw.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software 
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00010 #include "utils.h"
00011 #include <cassert>
00012 #include <cstdarg>
00013 #include "video.h"
00014 #include <math.h>
00015 #include "gui.h"
00016 
00017 using namespace std;
00018 using namespace hoa_video::private_video;
00019 
00020 namespace hoa_video 
00021 {
00022 
00023 //-----------------------------------------------------------------------------
00024 // _DrawStillImage: draws an image given the image descriptor, using the scene light
00025 //                   color. Helper function to DrawImage()
00026 //-----------------------------------------------------------------------------
00027 
00028 bool GameVideo::_DrawStillImage(const StillImage &id)
00029 {
00030   // if real lighting is enabled, draw images normally since the light overlay
00031   // will take care of the modulation. If not, (i.e. no overlay is being used)
00032   // then pass the light color so the vertex colors can do the modulation
00033   
00034   if(!_uses_lights && (_light_color != Color::white))
00035     return _DrawStillImage(id, _light_color);
00036   else
00037     return _DrawStillImage(id, Color::white);
00038 }
00039 
00040   
00041 //-----------------------------------------------------------------------------
00042 // _DrawStillImage: draws an image given the image descriptor, colored using the
00043 //                   color passed in.
00044 //-----------------------------------------------------------------------------
00045 
00046 bool GameVideo::_DrawStillImage(const StillImage &id, const Color &color)
00047 {
00048   // Don't do anything if this image is completely transparent (invisible)
00049   if (color[3] == 0.0f) {
00050     return true;
00051   }
00052 
00053   size_t num_elements = id._elements.size();
00054   
00055   float modulation = _fader.GetFadeModulation();
00056   Color fade_color(modulation, modulation, modulation, 1.0f);
00057 
00058   float x_shake = _x_shake * (_coord_sys.GetRight() - _coord_sys.GetLeft()) / 1024.0f;
00059   float y_shake = _y_shake * (_coord_sys.GetTop()   - _coord_sys.GetBottom()) / 768.0f;
00060 
00061   float x_align_offset = ((_x_align+1) * id._width)  * 0.5f * -_coord_sys.GetHorizontalDirection();
00062   float y_align_offset = ((_y_align+1) * id._height) * 0.5f * -_coord_sys.GetVerticalDirection();
00063 
00064   glPushMatrix();
00065   MoveRelative(x_align_offset, y_align_offset); 
00066 
00067   bool skip_modulation = (color == Color::white && modulation == 1.0f);
00068 
00069   // If we're modulating, calculate modulation color now
00070   if (!skip_modulation)
00071     fade_color = color * fade_color;
00072   
00073   Color color_modulated[4];
00074   
00075   for(uint32 iElement = 0; iElement < num_elements; ++iElement)
00076   {   
00077     glPushMatrix();
00078     
00079     float x_off = (float)id._elements[iElement].x_offset;
00080     float y_off = (float)id._elements[iElement].y_offset;
00081 
00082     if(_x_flip)
00083     {
00084       x_off = id._width - x_off - id._elements[iElement].width;
00085     }
00086     
00087     if(_y_flip)
00088     {
00089       y_off = id._height - y_off - id._elements[iElement].height;
00090     }
00091 
00092     x_off += x_shake;
00093     y_off += y_shake;
00094 
00095 //    float x__ = 0.5f * abs(_coord_sys.GetRight()-_coord_sys.GetLeft()) / (float)_width;
00096 //    float y__ = 0.5f * abs(_coord_sys.GetTop()-_coord_sys.GetBottom()) / (float)_height;
00097 
00098 //    MoveRelative(x__ + x_off * _coord_sys.GetHorizontalDirection(), y__ + y_off * _coord_sys.GetVerticalDirection());
00099 
00100     MoveRelative(x_off * _coord_sys.GetHorizontalDirection(), y_off * _coord_sys.GetVerticalDirection());
00101     
00102     float x_scale = id._elements[iElement].width;
00103     float y_scale = id._elements[iElement].height;
00104     
00105     if(_coord_sys.GetHorizontalDirection() < 0.0f)
00106       x_scale = -x_scale;
00107     if(_coord_sys.GetVerticalDirection() < 0.0f)
00108       y_scale = -y_scale;
00109     
00110     glScalef(x_scale, y_scale, 1.0f);
00111 
00112     bool success;
00113     
00114     if(skip_modulation)
00115       success = _DrawElement(id._elements[iElement], id._elements[iElement].color);
00116     else
00117     {
00118       color_modulated[0] = id._elements[iElement].color[0] * fade_color;
00119       color_modulated[1] = id._elements[iElement].color[1] * fade_color;
00120       color_modulated[2] = id._elements[iElement].color[2] * fade_color;
00121       color_modulated[3] = id._elements[iElement].color[3] * fade_color;
00122       success = _DrawElement(id._elements[iElement], color_modulated);
00123     }
00124     
00125     if(!success)
00126     {
00127       if(VIDEO_DEBUG)
00128         cerr << "VIDEO ERROR: _DrawElement() failed in DrawImage()!" << endl;
00129       
00130       glPopMatrix();
00131       return false;
00132     }     
00133     glPopMatrix();
00134   }
00135 
00136   glPopMatrix();
00137   return true;
00138 }
00139 
00140 
00141 //-----------------------------------------------------------------------------
00142 // _DrawElement: draws an image element. This is only used privately.
00143 //-----------------------------------------------------------------------------
00144 
00145 bool GameVideo::_DrawElement(const ImageElement &element, const Color *color_array) {
00146   Image *img = element.image;
00147   
00148   // Set vertex coordinates
00149   static const float xlo = 0.0f;
00150   static const float xhi = 1.0f;
00151   static const float ylo = 0.0f;
00152   static const float yhi = 1.0f;
00153 
00154   // Array of the four vertexes defined on
00155   // the 2D plane for glDrawArrays().
00156   static const float vert_coords[] = 
00157   { 
00158     xlo, ylo,
00159     xhi, ylo,
00160     xhi, yhi,
00161     xlo, yhi,
00162   };
00163 
00164   // Set blending parameters
00165   if(_blend)
00166   {
00167     glEnable(GL_BLEND);
00168     if (_blend == 1)
00169       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00170     else
00171       glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive
00172   }
00173   else
00174   {
00175     // if blending isn't in the draw flags, don't use blending UNLESS
00176     // the given image element has translucent vertex colors
00177     if(!element.blend)
00178       glDisable(GL_BLEND);
00179     else
00180       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00181   }
00182 
00183   // Constant function local values for array rendering
00184   static const int num_vertexes      = 4;
00185   static const int coords_per_vertex = 2;
00186 
00187     
00188   // If we have an image, setup texture coordinates
00189   // and the texture coordinate array for glDrawArrays().
00190   if (img)
00191   {
00192     // set texture coordinates  
00193     float s0,s1,t0,t1;
00194 
00195     s0 = img->u1 + element.u1 * (img->u2 - img->u1);
00196     s1 = img->u1 + element.u2 * (img->u2 - img->u1);
00197     t0 = img->v1 + element.v1 * (img->v2 - img->v1);
00198     t1 = img->v1 + element.v2 * (img->v2 - img->v1);
00199 
00200 
00201     // swap x texture coordinates for x flipping
00202     if (_x_flip) 
00203     { 
00204       float temp = s0;
00205       s0 = s1;
00206       s1 = temp;
00207     } 
00208 
00209     // swap y texture coordinates for y flipping
00210     if (_y_flip) 
00211     { 
00212       float temp = t0;
00213       t0 = t1;
00214       t1 = temp;
00215     }
00216 
00217     // Place texture coordinates in a 4x2 array
00218     // mirroring the structure of the vertex
00219     // array for use in glDrawArrays().
00220     float tex_coords[] = { 
00221       s0, t1,
00222       s1, t1,
00223       s1, t0,
00224       s0, t0,
00225     };
00226 
00227     // Enable texturing and bind texture
00228     glEnable(GL_TEXTURE_2D);
00229     _BindTexture(img->texture_sheet->tex_ID);
00230 
00231     // Enable texture coordinate array
00232     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00233 
00234     // Setup texture coordinate array
00235     glTexCoordPointer(coords_per_vertex, GL_FLOAT, 0, tex_coords);
00236     if (element.one_color)
00237     {
00238       glColor4fv((GLfloat *)&color_array[0]);
00239     }
00240     else
00241     {
00242       glEnableClientState(GL_COLOR_ARRAY);
00243       glColorPointer(4, GL_FLOAT, 0, (GLfloat *)color_array);
00244     }
00245     // Always use a vertex array
00246     glEnableClientState(GL_VERTEX_ARRAY);
00247 
00248     // Setup the vertex array pointer
00249     glVertexPointer(coords_per_vertex, GL_FLOAT, 0, vert_coords);
00250 
00251     // Draw the object using the array pointers we've just setup
00252     glDrawArrays(GL_QUADS, 0, num_vertexes);
00253   }
00254   else
00255   {
00256     // Use a single call to glColor for one_color
00257     // images, or a setup a gl color array for multiple.
00258     if (element.one_color)
00259     {
00260       glColor4fv((GLfloat *)&color_array[0]);
00261       glDisableClientState(GL_COLOR_ARRAY);
00262     }
00263     else
00264     {
00265       glEnableClientState(GL_COLOR_ARRAY);
00266       //glColorPointer(4, GL_FLOAT, 0, (GLfloat *)element.color);
00267       glColorPointer(4, GL_FLOAT, 0, (GLfloat *)color_array);
00268     }
00269     // Always use a vertex array
00270     glEnableClientState(GL_VERTEX_ARRAY);
00271 
00272     // Setup the vertex array pointer
00273     glVertexPointer(coords_per_vertex, GL_FLOAT, 0, vert_coords);
00274 
00275     // Disable the texture array as we're not texturing
00276     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00277 
00278     // Draw the object using the array pointers we've just setup
00279     glDrawArrays(GL_QUADS, 0, num_vertexes);
00280   }
00281 
00282   if (_blend)
00283     glDisable(GL_BLEND);
00284   
00285   if(glGetError())
00286   {
00287     if(VIDEO_DEBUG)
00288       cerr << "VIDEO ERROR: glGetError() returned true in _DrawElement()!" << endl;
00289     return false;
00290   }   
00291     
00292   return true;
00293 }
00294 
00295 
00296 
00297 //-----------------------------------------------------------------------------
00298 // DrawHalo: draws a halo at (x,y) given the halo image
00299 //           This is draws a halo image at the given position and color.
00300 //           If you want to use center alignment, call SetDrawFlags yourself 
00301 //           with VIDEO_X_CENTER and VIDEO_Y_CENTER
00302 //-----------------------------------------------------------------------------
00303 
00304 bool GameVideo::DrawHalo(const StillImage &id, float x, float y, const Color &color)
00305 {
00306   PushMatrix();
00307   Move(x, y);
00308 
00309   char oldBlendMode = _blend;
00310   _blend = VIDEO_BLEND_ADD;
00311   DrawImage(id, color);
00312   _blend = oldBlendMode;
00313   PopMatrix();
00314   
00315   return true;
00316 }
00317 
00318 
00319 //-----------------------------------------------------------------------------
00320 // DrawLight: draws a light at (x,y) given the light mask
00321 //           This is draws a light at the given position and color.
00322 //           If you want to use center alignment, call SetDrawFlags yourself 
00323 //           with VIDEO_X_CENTER and VIDEO_Y_CENTER
00324 //-----------------------------------------------------------------------------
00325 bool GameVideo::DrawLight(const StillImage &id, float x, float y, const Color &color)
00326 {
00327   if(!_uses_lights)
00328   {
00329     if(VIDEO_DEBUG)
00330       cerr << "VIDEO ERROR: called DrawLight() even though real lighting was not enabled!" << endl;
00331     return false;
00332   }
00333 
00334   return DrawHalo(id, x, y, color);
00335 }
00336 
00337 
00338 //-----------------------------------------------------------------------------
00339 // DrawFPS: draws current frames per second
00340 //-----------------------------------------------------------------------------
00341 
00342 void GameVideo::DrawFPS(uint32 frame_time)
00343 {
00344   _PushContext();
00345   GUIManager->DrawFPS(frame_time);
00346   _PopContext();
00347 
00348 }
00349 
00350 
00351 //-----------------------------------------------------------------------------
00352 // DrawImage: draws an image descriptor (can either be a static image or
00353 //            animated image), modulating the colors by the scene lighting
00354 //-----------------------------------------------------------------------------
00355 
00356 bool GameVideo::DrawImage(const ImageDescriptor &id) {
00357   if (id._animated) {
00358     const AnimatedImage &anim = dynamic_cast<const AnimatedImage &>(id);
00359     return _DrawStillImage(*anim.GetFrame(anim.GetCurrentFrameIndex()));
00360   }
00361   else {
00362     return _DrawStillImage(dynamic_cast<const StillImage &>(id));
00363   }
00364 }
00365 
00366 
00367 //-----------------------------------------------------------------------------
00368 // DrawImage: draws an image descriptor (can either be a static image or
00369 //            animated image), modulating the colors by a custom color
00370 //-----------------------------------------------------------------------------
00371 
00372 bool GameVideo::DrawImage(const ImageDescriptor &id, const Color &color)
00373 {
00374   if(id._animated)
00375   {
00376     const AnimatedImage &anim = dynamic_cast<const AnimatedImage &>(id);    
00377     return _DrawStillImage(*anim.GetFrame(anim.GetCurrentFrameIndex()), color);
00378   }
00379   else
00380   {
00381     return _DrawStillImage(dynamic_cast<const StillImage &>(id), color);
00382   }
00383 }
00384 
00385 
00386 }  // namespace hoa_video

Generated on Fri Jul 6 23:11:13 2007 for Hero of Allacrost by  doxygen 1.5.1