Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

openglrenderer.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002         filename:       openglrenderer.cpp
00003         created:        9/4/2004
00004         author:         Mark Strom
00005                                 mwstrom@gmail.com
00006 
00007         purpose:        Interface to Renderer implemented via Opengl
00008 *************************************************************************/
00009 /*************************************************************************
00010     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00011     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00012 
00013     This library is free software; you can redistribute it and/or
00014     modify it under the terms of the GNU Lesser General Public
00015     License as published by the Free Software Foundation; either
00016     version 2.1 of the License, or (at your option) any later version.
00017 
00018     This library is distributed in the hope that it will be useful,
00019     but WITHOUT ANY WARRANTY; without even the implied warranty of
00020     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021     Lesser General Public License for more details.
00022 
00023     You should have received a copy of the GNU Lesser General Public
00024     License along with this library; if not, write to the Free Software
00025     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026 *************************************************************************/
00027 #include "renderers/OpenGLGUIRenderer/openglrenderer.h"
00028 #include "renderers/OpenGLGUIRenderer/opengltexture.h"
00029 #include "CEGUIExceptions.h"
00030 
00031 
00032 // Start of CEGUI namespace section
00033 namespace CEGUI
00034 {
00035 /*************************************************************************
00036         Constants definitions
00037 *************************************************************************/
00038 const int OpenGLRenderer::VERTEX_PER_QUAD                       = 6;
00039 const int OpenGLRenderer::VERTEX_PER_TRIANGLE           = 3;
00040 const int OpenGLRenderer::VERTEXBUFFER_CAPACITY         = OGLRENDERER_VBUFF_CAPACITY;
00041 
00042 
00043 /*************************************************************************
00044         Constructor
00045 *************************************************************************/
00046 OpenGLRenderer::OpenGLRenderer(uint max_quads) :
00047         d_queueing(true),
00048         d_currTexture(0),
00049         d_bufferPos(0)
00050 {
00051         GLint vp[4];   
00052 
00053         // initialise renderer size
00054         glGetIntegerv(GL_VIEWPORT, vp);
00055         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &d_maxTextureSize);
00056         d_display_area.d_left   = 0;
00057         d_display_area.d_top    = 0;
00058         d_display_area.d_right  = (float)vp[2];
00059         d_display_area.d_bottom = (float)vp[3];
00060 }
00061 
00062 
00063 OpenGLRenderer::OpenGLRenderer(uint max_quads,int width, int height) :
00064         d_queueing(true),
00065         d_currTexture(0),
00066         d_bufferPos(0)
00067 {
00068         GLint vp[4];   
00069 
00070         // initialise renderer size
00071         glGetIntegerv(GL_VIEWPORT, vp);
00072         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &d_maxTextureSize);
00073         d_display_area.d_left   = 0;
00074         d_display_area.d_top    = 0;
00075         d_display_area.d_right  = static_cast<float>(width);
00076         d_display_area.d_bottom = static_cast<float>(height);
00077 }
00078 
00079 
00080 /*************************************************************************
00081         Destructor
00082 *************************************************************************/
00083 OpenGLRenderer::~OpenGLRenderer(void)
00084 {
00085         destroyAllTextures();
00086 }
00087 
00088 
00089 /*************************************************************************
00090         add's a quad to the list to be rendered
00091 *************************************************************************/
00092 void OpenGLRenderer::addQuad(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
00093 {
00094         // if not queuing, render directly (as in, right now!)
00095         if (!d_queueing)
00096         {
00097                 renderQuadDirect(dest_rect, z, tex, texture_rect, colours, quad_split_mode);
00098         }
00099         else
00100         {
00101                 QuadInfo quad;
00102                 quad.position                   = dest_rect;
00103                 quad.position.d_bottom  = d_display_area.d_bottom - dest_rect.d_bottom;
00104                 quad.position.d_top             = d_display_area.d_bottom - dest_rect.d_top;
00105                 quad.z                                  = z;
00106                 quad.texid                              = ((OpenGLTexture*)tex)->getOGLTexid();
00107                 quad.texPosition                = texture_rect;
00108                 quad.topLeftCol         = colourToOGL(colours.d_top_left);
00109                 quad.topRightCol        = colourToOGL(colours.d_top_right);
00110                 quad.bottomLeftCol      = colourToOGL(colours.d_bottom_left);
00111                 quad.bottomRightCol     = colourToOGL(colours.d_bottom_right);
00112 
00113         // set quad split mode
00114         quad.splitMode = quad_split_mode;
00115 
00116                 d_quadlist.insert(quad);
00117         }
00118 
00119 }
00120 
00121 
00122 
00123 /*************************************************************************
00124         perform final rendering for all queued renderable quads.
00125 *************************************************************************/
00126 void OpenGLRenderer::doRender(void)
00127 {
00128         d_currTexture = 0;
00129 
00130         initPerFrameStates();
00131         glInterleavedArrays(GL_T2F_C4UB_V3F , 0, myBuff);
00132 
00133         // iterate over each quad in the list
00134         for (QuadList::iterator i = d_quadlist.begin(); i != d_quadlist.end(); ++i)
00135         {
00136                 const QuadInfo& quad = (*i);
00137 
00138                 if(d_currTexture != quad.texid)
00139                 {            
00140                         renderVBuffer();           
00141                         glBindTexture(GL_TEXTURE_2D, quad.texid);
00142                         d_currTexture = quad.texid;          
00143                 }
00144 
00145                 //vert0       
00146                 myBuff[d_bufferPos].vertex[0]   = quad.position.d_left;
00147                 myBuff[d_bufferPos].vertex[1]   = quad.position.d_top;
00148                 myBuff[d_bufferPos].vertex[2]   = quad.z;
00149                 myBuff[d_bufferPos].color               = quad.topLeftCol;
00150                 myBuff[d_bufferPos].tex[0]              = quad.texPosition.d_left;
00151                 myBuff[d_bufferPos].tex[1]              = quad.texPosition.d_top;         
00152                 ++d_bufferPos;
00153 
00154                 //vert1
00155                 myBuff[d_bufferPos].vertex[0]   = quad.position.d_left;
00156                 myBuff[d_bufferPos].vertex[1]   = quad.position.d_bottom;
00157                 myBuff[d_bufferPos].vertex[2]   = quad.z;
00158                 myBuff[d_bufferPos].color               = quad.bottomLeftCol;
00159                 myBuff[d_bufferPos].tex[0]              = quad.texPosition.d_left;
00160                 myBuff[d_bufferPos].tex[1]              = quad.texPosition.d_bottom;
00161                 ++d_bufferPos;
00162 
00163                 //vert2
00164 
00165         // top-left to bottom-right diagonal
00166         if (quad.splitMode == TopLeftToBottomRight)
00167         {
00168             myBuff[d_bufferPos].vertex[0]       = quad.position.d_right;
00169             myBuff[d_bufferPos].vertex[1]       = quad.position.d_bottom;
00170             myBuff[d_bufferPos].vertex[2]       = quad.z;
00171             myBuff[d_bufferPos].color           = quad.bottomRightCol;
00172             myBuff[d_bufferPos].tex[0]          = quad.texPosition.d_right;
00173             myBuff[d_bufferPos].tex[1]          = quad.texPosition.d_bottom;         
00174         }
00175         // bottom-left to top-right diagonal
00176         else
00177         {
00178             myBuff[d_bufferPos].vertex[0]       = quad.position.d_right;
00179             myBuff[d_bufferPos].vertex[1]       = quad.position.d_top;
00180             myBuff[d_bufferPos].vertex[2]       = quad.z;
00181             myBuff[d_bufferPos].color           = quad.topRightCol;
00182             myBuff[d_bufferPos].tex[0]          = quad.texPosition.d_right;
00183             myBuff[d_bufferPos].tex[1]          = quad.texPosition.d_top;         
00184         }
00185                 ++d_bufferPos;
00186 
00187                 //vert3
00188                 myBuff[d_bufferPos].vertex[0]   = quad.position.d_right;
00189                 myBuff[d_bufferPos].vertex[1]   = quad.position.d_top;
00190                 myBuff[d_bufferPos].vertex[2]   = quad.z;
00191                 myBuff[d_bufferPos].color               = quad.topRightCol;
00192                 myBuff[d_bufferPos].tex[0]              = quad.texPosition.d_right;
00193                 myBuff[d_bufferPos].tex[1]              = quad.texPosition.d_top;
00194                 ++d_bufferPos;
00195 
00196                 //vert4
00197 
00198         // top-left to bottom-right diagonal
00199         if (quad.splitMode == TopLeftToBottomRight)
00200         {
00201             myBuff[d_bufferPos].vertex[0]       = quad.position.d_left;
00202             myBuff[d_bufferPos].vertex[1]       = quad.position.d_top;
00203             myBuff[d_bufferPos].vertex[2]       = quad.z;
00204             myBuff[d_bufferPos].color           = quad.topLeftCol;
00205             myBuff[d_bufferPos].tex[0]          = quad.texPosition.d_left;
00206             myBuff[d_bufferPos].tex[1]          = quad.texPosition.d_top;         
00207         }
00208         // bottom-left to top-right diagonal
00209         else
00210         {
00211             myBuff[d_bufferPos].vertex[0]       = quad.position.d_left;
00212             myBuff[d_bufferPos].vertex[1]       = quad.position.d_bottom;
00213             myBuff[d_bufferPos].vertex[2]       = quad.z;
00214             myBuff[d_bufferPos].color           = quad.bottomLeftCol;
00215             myBuff[d_bufferPos].tex[0]          = quad.texPosition.d_left;
00216             myBuff[d_bufferPos].tex[1]          = quad.texPosition.d_bottom;         
00217         }
00218                 ++d_bufferPos;
00219 
00220                 //vert 5
00221                 myBuff[d_bufferPos].vertex[0]   = quad.position.d_right;
00222                 myBuff[d_bufferPos].vertex[1]   = quad.position.d_bottom;
00223                 myBuff[d_bufferPos].vertex[2]   = quad.z;
00224                 myBuff[d_bufferPos].color               = quad.bottomRightCol;
00225                 myBuff[d_bufferPos].tex[0]              = quad.texPosition.d_right;
00226                 myBuff[d_bufferPos].tex[1]              = quad.texPosition.d_bottom;         
00227                 ++d_bufferPos;
00228 
00229                 if(d_bufferPos > (VERTEXBUFFER_CAPACITY - VERTEX_PER_QUAD))
00230                 {          
00231                         renderVBuffer();
00232                 }
00233 
00234         }
00235 
00236         //Render
00237         renderVBuffer();
00238 
00239         exitPerFrameStates();
00240 }
00241 
00242 
00243 /*************************************************************************
00244         clear the queue
00245 *************************************************************************/
00246 void OpenGLRenderer::clearRenderList(void)
00247 {
00248         d_quadlist.clear();
00249 }
00250 
00251 
00252 /*************************************************************************
00253         create an empty texture
00254 *************************************************************************/
00255 Texture* OpenGLRenderer::createTexture(void)
00256 {
00257         OpenGLTexture* tex = new OpenGLTexture(this);
00258         d_texturelist.push_back(tex);
00259         return tex;
00260 }
00261 
00262 
00263 /*************************************************************************
00264         Create a new Texture object and load a file into it.
00265 *************************************************************************/
00266 Texture* OpenGLRenderer::createTexture(const String& filename, const String& resourceGroup)
00267 {
00268         OpenGLTexture* tex = (OpenGLTexture*)createTexture();
00269         tex->loadFromFile(filename, resourceGroup);
00270 
00271         return tex;
00272 }
00273 
00274 
00275 /*************************************************************************
00276         Create a new texture with the given dimensions
00277 *************************************************************************/
00278 Texture* OpenGLRenderer::createTexture(float size)
00279 {
00280         OpenGLTexture* tex = (OpenGLTexture*)createTexture();
00281         tex->setOGLTextureSize((uint)size);
00282 
00283         return tex;
00284 }
00285 
00286 
00287 /*************************************************************************
00288         Destroy a texture
00289 *************************************************************************/
00290 void OpenGLRenderer::destroyTexture(Texture* texture)
00291 {
00292         if (texture != NULL)
00293         {
00294                 OpenGLTexture* tex = (OpenGLTexture*)texture;
00295                 d_texturelist.remove(tex);
00296                 delete tex;
00297         }
00298 
00299 }
00300 
00301 
00302 /*************************************************************************
00303         destroy all textures still active
00304 *************************************************************************/
00305 void OpenGLRenderer::destroyAllTextures(void)
00306 {
00307         while (!d_texturelist.empty())
00308         {
00309                 destroyTexture(*(d_texturelist.begin()));
00310         }
00311 }
00312 
00313 
00314 /*************************************************************************
00315         setup states etc
00316 *************************************************************************/
00317 void OpenGLRenderer::initPerFrameStates(void)
00318 {
00319         //save current attributes
00320         glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
00321         glPushAttrib(GL_ALL_ATTRIB_BITS);
00322 
00323         glPolygonMode(GL_FRONT, GL_FILL);
00324         glMatrixMode(GL_PROJECTION);
00325         glPushMatrix();
00326         glLoadIdentity();
00327         gluOrtho2D(0.0, d_display_area.d_right, 0.0, d_display_area.d_bottom);
00328 
00329         glMatrixMode(GL_MODELVIEW);
00330         glPushMatrix();
00331         glLoadIdentity();       
00332 
00333         glDisable(GL_LIGHTING);
00334         glDisable(GL_DEPTH_TEST);
00335 
00336         glEnable(GL_BLEND);
00337         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
00338 
00339         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00340         glEnable(GL_TEXTURE_2D);
00341 }
00342 
00343 
00344 void OpenGLRenderer::exitPerFrameStates(void)
00345 {
00346         glDisable(GL_TEXTURE_2D);
00347 
00348         glPopMatrix(); 
00349         glMatrixMode(GL_PROJECTION);
00350         glPopMatrix(); 
00351         glMatrixMode(GL_MODELVIEW);
00352 
00353         //restore former attributes
00354         glPopClientAttrib();
00355         glPopAttrib();
00356 }
00357 
00358 
00359 /*************************************************************************
00360         renders whatever is in the vertex buffer
00361 *************************************************************************/
00362 void OpenGLRenderer::renderVBuffer(void)
00363 {
00364         // if bufferPos is 0 there is no data in the buffer and nothing to render
00365         if (d_bufferPos == 0)
00366         {
00367                 return;
00368         }
00369 
00370         // render the sprites
00371         glDrawArrays(GL_TRIANGLES, 0, d_bufferPos);
00372 
00373         // reset buffer position to 0...
00374         d_bufferPos = 0;
00375 }
00376 
00377 
00378 /*************************************************************************
00379         sort quads list according to texture
00380 *************************************************************************/
00381 void OpenGLRenderer::sortQuads(void)
00382 {
00383         // no need to do anything here.
00384 }
00385 
00386 
00387 /*************************************************************************
00388         render a quad directly to the display
00389 *************************************************************************/
00390 void OpenGLRenderer::renderQuadDirect(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
00391 {
00392         QuadInfo quad;
00393         quad.position.d_left    = dest_rect.d_left;
00394         quad.position.d_right   = dest_rect.d_right;
00395         quad.position.d_bottom  = d_display_area.d_bottom - dest_rect.d_bottom;
00396         quad.position.d_top             = d_display_area.d_bottom - dest_rect.d_top;
00397         quad.texPosition                = texture_rect;
00398 
00399         quad.topLeftCol         = colourToOGL(colours.d_top_left);
00400         quad.topRightCol        = colourToOGL(colours.d_top_right);
00401         quad.bottomLeftCol      = colourToOGL(colours.d_bottom_left);
00402         quad.bottomRightCol     = colourToOGL(colours.d_bottom_right);
00403 
00404         MyQuad myquad[VERTEX_PER_QUAD];
00405 
00406         initPerFrameStates();
00407         glInterleavedArrays(GL_T2F_C4UB_V3F , 0, myquad);
00408         glBindTexture(GL_TEXTURE_2D, ((OpenGLTexture*)tex)->getOGLTexid());
00409 
00410         //vert0
00411         myquad[0].vertex[0] = quad.position.d_left;
00412         myquad[0].vertex[1] = quad.position.d_top;
00413         myquad[0].vertex[2] = z;
00414         myquad[0].color     = quad.topLeftCol;
00415         myquad[0].tex[0]    = quad.texPosition.d_left;
00416         myquad[0].tex[1]    = quad.texPosition.d_top;
00417 
00418         //vert1
00419         myquad[1].vertex[0] = quad.position.d_left;
00420         myquad[1].vertex[1] = quad.position.d_bottom;
00421         myquad[1].vertex[2] = z;
00422         myquad[1].color     = quad.bottomLeftCol;     
00423         myquad[1].tex[0]    = quad.texPosition.d_left;
00424         myquad[1].tex[1]    = quad.texPosition.d_bottom;
00425 
00426         //vert2
00427 
00428     // top-left to bottom-right diagonal
00429     if (quad_split_mode == TopLeftToBottomRight)
00430     {
00431         myquad[2].vertex[0] = quad.position.d_right;
00432         myquad[2].vertex[1] = quad.position.d_bottom;
00433         myquad[2].vertex[2] = z;
00434         myquad[2].color     = quad.bottomRightCol;
00435         myquad[2].tex[0]    = quad.texPosition.d_right;
00436         myquad[2].tex[1]    = quad.texPosition.d_bottom;
00437     }
00438     // bottom-left to top-right diagonal
00439     else
00440     {
00441         myquad[2].vertex[0] = quad.position.d_right;
00442         myquad[2].vertex[1] = quad.position.d_top;
00443         myquad[2].vertex[2] = z;
00444         myquad[2].color     = quad.topRightCol;
00445         myquad[2].tex[0]    = quad.texPosition.d_right;
00446         myquad[2].tex[1]    = quad.texPosition.d_top;
00447     }
00448 
00449         //vert3
00450         myquad[3].vertex[0] = quad.position.d_right;
00451         myquad[3].vertex[1] = quad.position.d_top;
00452         myquad[3].vertex[2] = z;
00453         myquad[3].color     = quad.topRightCol;      
00454         myquad[3].tex[0]    = quad.texPosition.d_right;
00455         myquad[3].tex[1]    = quad.texPosition.d_top;
00456 
00457         //vert4
00458 
00459     // top-left to bottom-right diagonal
00460     if (quad_split_mode == TopLeftToBottomRight)
00461     {
00462         myquad[4].vertex[0] = quad.position.d_left;
00463         myquad[4].vertex[1] = quad.position.d_top;
00464         myquad[4].vertex[2] = z;
00465         myquad[4].color     = quad.topLeftCol;
00466         myquad[4].tex[0]    = quad.texPosition.d_left;
00467         myquad[4].tex[1]    = quad.texPosition.d_top;
00468     }
00469     // bottom-left to top-right diagonal
00470     else
00471     {
00472         myquad[4].vertex[0] = quad.position.d_left;
00473         myquad[4].vertex[1] = quad.position.d_bottom;
00474         myquad[4].vertex[2] = z;
00475         myquad[4].color     = quad.bottomLeftCol;
00476         myquad[4].tex[0]    = quad.texPosition.d_left;
00477         myquad[4].tex[1]    = quad.texPosition.d_bottom;
00478     }
00479 
00480         //vert5
00481         myquad[5].vertex[0] = quad.position.d_right;
00482         myquad[5].vertex[1] = quad.position.d_bottom;
00483         myquad[5].vertex[2] = z;
00484         myquad[5].color     = quad.bottomRightCol;
00485         myquad[5].tex[0]    = quad.texPosition.d_right;
00486         myquad[5].tex[1]    = quad.texPosition.d_bottom;
00487 
00488         glDrawArrays(GL_TRIANGLES, 0, 6);
00489 
00490         exitPerFrameStates();
00491 }
00492 
00493 
00494 /*************************************************************************
00495         convert colour value to whatever the OpenGL system is expecting.
00496 *************************************************************************/
00497 long OpenGLRenderer::colourToOGL(const colour& col) const
00498 {
00499         ulong cval;
00500         cval =  (static_cast<ulong>(255 * col.getAlpha())) << 24;
00501         cval |= (static_cast<ulong>(255 * col.getBlue())) << 16;
00502         cval |= (static_cast<ulong>(255 * col.getGreen())) << 8;
00503         cval |= (static_cast<ulong>(255 * col.getRed()));
00504 
00505         return cval;
00506 }
00507 
00508 } // End of  CEGUI namespace section
00509 

Generated on Wed Feb 16 12:41:08 2005 for Crazy Eddies GUI System by  doxygen 1.3.9.1