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

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     setModuleIdentifierString();
00062 }
00063 
00064 
00065 OpenGLRenderer::OpenGLRenderer(uint max_quads,int width, int height) :
00066         d_queueing(true),
00067         d_currTexture(0),
00068         d_bufferPos(0)
00069 {
00070         GLint vp[4];   
00071 
00072         // initialise renderer size
00073         glGetIntegerv(GL_VIEWPORT, vp);
00074         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &d_maxTextureSize);
00075         d_display_area.d_left   = 0;
00076         d_display_area.d_top    = 0;
00077         d_display_area.d_right  = static_cast<float>(width);
00078         d_display_area.d_bottom = static_cast<float>(height);
00079 
00080     setModuleIdentifierString();
00081 }
00082 
00083 
00084 /*************************************************************************
00085         Destructor
00086 *************************************************************************/
00087 OpenGLRenderer::~OpenGLRenderer(void)
00088 {
00089         destroyAllTextures();
00090 }
00091 
00092 
00093 /*************************************************************************
00094         add's a quad to the list to be rendered
00095 *************************************************************************/
00096 void OpenGLRenderer::addQuad(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
00097 {
00098         // if not queuing, render directly (as in, right now!)
00099         if (!d_queueing)
00100         {
00101                 renderQuadDirect(dest_rect, z, tex, texture_rect, colours, quad_split_mode);
00102         }
00103         else
00104         {
00105                 QuadInfo quad;
00106                 quad.position                   = dest_rect;
00107                 quad.position.d_bottom  = d_display_area.d_bottom - dest_rect.d_bottom;
00108                 quad.position.d_top             = d_display_area.d_bottom - dest_rect.d_top;
00109                 quad.z                                  = z;
00110                 quad.texid                              = ((OpenGLTexture*)tex)->getOGLTexid();
00111                 quad.texPosition                = texture_rect;
00112                 quad.topLeftCol         = colourToOGL(colours.d_top_left);
00113                 quad.topRightCol        = colourToOGL(colours.d_top_right);
00114                 quad.bottomLeftCol      = colourToOGL(colours.d_bottom_left);
00115                 quad.bottomRightCol     = colourToOGL(colours.d_bottom_right);
00116 
00117         // set quad split mode
00118         quad.splitMode = quad_split_mode;
00119 
00120                 d_quadlist.insert(quad);
00121         }
00122 
00123 }
00124 
00125 
00126 
00127 /*************************************************************************
00128         perform final rendering for all queued renderable quads.
00129 *************************************************************************/
00130 void OpenGLRenderer::doRender(void)
00131 {
00132         d_currTexture = 0;
00133 
00134         initPerFrameStates();
00135         glInterleavedArrays(GL_T2F_C4UB_V3F , 0, myBuff);
00136 
00137         // iterate over each quad in the list
00138         for (QuadList::iterator i = d_quadlist.begin(); i != d_quadlist.end(); ++i)
00139         {
00140                 const QuadInfo& quad = (*i);
00141 
00142                 if(d_currTexture != quad.texid)
00143                 {            
00144                         renderVBuffer();           
00145                         glBindTexture(GL_TEXTURE_2D, quad.texid);
00146                         d_currTexture = quad.texid;          
00147                 }
00148 
00149                 //vert0       
00150                 myBuff[d_bufferPos].vertex[0]   = quad.position.d_left;
00151                 myBuff[d_bufferPos].vertex[1]   = quad.position.d_top;
00152                 myBuff[d_bufferPos].vertex[2]   = quad.z;
00153                 myBuff[d_bufferPos].color               = quad.topLeftCol;
00154                 myBuff[d_bufferPos].tex[0]              = quad.texPosition.d_left;
00155                 myBuff[d_bufferPos].tex[1]              = quad.texPosition.d_top;         
00156                 ++d_bufferPos;
00157 
00158                 //vert1
00159                 myBuff[d_bufferPos].vertex[0]   = quad.position.d_left;
00160                 myBuff[d_bufferPos].vertex[1]   = quad.position.d_bottom;
00161                 myBuff[d_bufferPos].vertex[2]   = quad.z;
00162                 myBuff[d_bufferPos].color               = quad.bottomLeftCol;
00163                 myBuff[d_bufferPos].tex[0]              = quad.texPosition.d_left;
00164                 myBuff[d_bufferPos].tex[1]              = quad.texPosition.d_bottom;
00165                 ++d_bufferPos;
00166 
00167                 //vert2
00168 
00169         // top-left to bottom-right diagonal
00170         if (quad.splitMode == TopLeftToBottomRight)
00171         {
00172             myBuff[d_bufferPos].vertex[0]       = quad.position.d_right;
00173             myBuff[d_bufferPos].vertex[1]       = quad.position.d_bottom;
00174             myBuff[d_bufferPos].vertex[2]       = quad.z;
00175             myBuff[d_bufferPos].color           = quad.bottomRightCol;
00176             myBuff[d_bufferPos].tex[0]          = quad.texPosition.d_right;
00177             myBuff[d_bufferPos].tex[1]          = quad.texPosition.d_bottom;         
00178         }
00179         // bottom-left to top-right diagonal
00180         else
00181         {
00182             myBuff[d_bufferPos].vertex[0]       = quad.position.d_right;
00183             myBuff[d_bufferPos].vertex[1]       = quad.position.d_top;
00184             myBuff[d_bufferPos].vertex[2]       = quad.z;
00185             myBuff[d_bufferPos].color           = quad.topRightCol;
00186             myBuff[d_bufferPos].tex[0]          = quad.texPosition.d_right;
00187             myBuff[d_bufferPos].tex[1]          = quad.texPosition.d_top;         
00188         }
00189                 ++d_bufferPos;
00190 
00191                 //vert3
00192                 myBuff[d_bufferPos].vertex[0]   = quad.position.d_right;
00193                 myBuff[d_bufferPos].vertex[1]   = quad.position.d_top;
00194                 myBuff[d_bufferPos].vertex[2]   = quad.z;
00195                 myBuff[d_bufferPos].color               = quad.topRightCol;
00196                 myBuff[d_bufferPos].tex[0]              = quad.texPosition.d_right;
00197                 myBuff[d_bufferPos].tex[1]              = quad.texPosition.d_top;
00198                 ++d_bufferPos;
00199 
00200                 //vert4
00201 
00202         // top-left to bottom-right diagonal
00203         if (quad.splitMode == TopLeftToBottomRight)
00204         {
00205             myBuff[d_bufferPos].vertex[0]       = quad.position.d_left;
00206             myBuff[d_bufferPos].vertex[1]       = quad.position.d_top;
00207             myBuff[d_bufferPos].vertex[2]       = quad.z;
00208             myBuff[d_bufferPos].color           = quad.topLeftCol;
00209             myBuff[d_bufferPos].tex[0]          = quad.texPosition.d_left;
00210             myBuff[d_bufferPos].tex[1]          = quad.texPosition.d_top;         
00211         }
00212         // bottom-left to top-right diagonal
00213         else
00214         {
00215             myBuff[d_bufferPos].vertex[0]       = quad.position.d_left;
00216             myBuff[d_bufferPos].vertex[1]       = quad.position.d_bottom;
00217             myBuff[d_bufferPos].vertex[2]       = quad.z;
00218             myBuff[d_bufferPos].color           = quad.bottomLeftCol;
00219             myBuff[d_bufferPos].tex[0]          = quad.texPosition.d_left;
00220             myBuff[d_bufferPos].tex[1]          = quad.texPosition.d_bottom;         
00221         }
00222                 ++d_bufferPos;
00223 
00224                 //vert 5
00225                 myBuff[d_bufferPos].vertex[0]   = quad.position.d_right;
00226                 myBuff[d_bufferPos].vertex[1]   = quad.position.d_bottom;
00227                 myBuff[d_bufferPos].vertex[2]   = quad.z;
00228                 myBuff[d_bufferPos].color               = quad.bottomRightCol;
00229                 myBuff[d_bufferPos].tex[0]              = quad.texPosition.d_right;
00230                 myBuff[d_bufferPos].tex[1]              = quad.texPosition.d_bottom;         
00231                 ++d_bufferPos;
00232 
00233                 if(d_bufferPos > (VERTEXBUFFER_CAPACITY - VERTEX_PER_QUAD))
00234                 {          
00235                         renderVBuffer();
00236                 }
00237 
00238         }
00239 
00240         //Render
00241         renderVBuffer();
00242 
00243         exitPerFrameStates();
00244 }
00245 
00246 
00247 /*************************************************************************
00248         clear the queue
00249 *************************************************************************/
00250 void OpenGLRenderer::clearRenderList(void)
00251 {
00252         d_quadlist.clear();
00253 }
00254 
00255 
00256 /*************************************************************************
00257         create an empty texture
00258 *************************************************************************/
00259 Texture* OpenGLRenderer::createTexture(void)
00260 {
00261         OpenGLTexture* tex = new OpenGLTexture(this);
00262         d_texturelist.push_back(tex);
00263         return tex;
00264 }
00265 
00266 
00267 /*************************************************************************
00268         Create a new Texture object and load a file into it.
00269 *************************************************************************/
00270 Texture* OpenGLRenderer::createTexture(const String& filename, const String& resourceGroup)
00271 {
00272         OpenGLTexture* tex = (OpenGLTexture*)createTexture();
00273         tex->loadFromFile(filename, resourceGroup);
00274 
00275         return tex;
00276 }
00277 
00278 
00279 /*************************************************************************
00280         Create a new texture with the given dimensions
00281 *************************************************************************/
00282 Texture* OpenGLRenderer::createTexture(float size)
00283 {
00284         OpenGLTexture* tex = (OpenGLTexture*)createTexture();
00285         tex->setOGLTextureSize((uint)size);
00286 
00287         return tex;
00288 }
00289 
00290 
00291 /*************************************************************************
00292         Destroy a texture
00293 *************************************************************************/
00294 void OpenGLRenderer::destroyTexture(Texture* texture)
00295 {
00296         if (texture != NULL)
00297         {
00298                 OpenGLTexture* tex = (OpenGLTexture*)texture;
00299                 d_texturelist.remove(tex);
00300                 delete tex;
00301         }
00302 
00303 }
00304 
00305 
00306 /*************************************************************************
00307         destroy all textures still active
00308 *************************************************************************/
00309 void OpenGLRenderer::destroyAllTextures(void)
00310 {
00311         while (!d_texturelist.empty())
00312         {
00313                 destroyTexture(*(d_texturelist.begin()));
00314         }
00315 }
00316 
00317 
00318 /*************************************************************************
00319         setup states etc
00320 *************************************************************************/
00321 void OpenGLRenderer::initPerFrameStates(void)
00322 {
00323         //save current attributes
00324         glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
00325         glPushAttrib(GL_ALL_ATTRIB_BITS);
00326 
00327         glPolygonMode(GL_FRONT, GL_FILL);
00328         glMatrixMode(GL_PROJECTION);
00329         glPushMatrix();
00330         glLoadIdentity();
00331         gluOrtho2D(0.0, d_display_area.d_right, 0.0, d_display_area.d_bottom);
00332 
00333         glMatrixMode(GL_MODELVIEW);
00334         glPushMatrix();
00335         glLoadIdentity();       
00336 
00337         glDisable(GL_LIGHTING);
00338         glDisable(GL_DEPTH_TEST);
00339 
00340         glEnable(GL_BLEND);
00341         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
00342 
00343         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00344         glEnable(GL_TEXTURE_2D);
00345 }
00346 
00347 
00348 void OpenGLRenderer::exitPerFrameStates(void)
00349 {
00350         glDisable(GL_TEXTURE_2D);
00351 
00352         glPopMatrix(); 
00353         glMatrixMode(GL_PROJECTION);
00354         glPopMatrix(); 
00355         glMatrixMode(GL_MODELVIEW);
00356 
00357         //restore former attributes
00358         glPopClientAttrib();
00359         glPopAttrib();
00360 }
00361 
00362 
00363 /*************************************************************************
00364         renders whatever is in the vertex buffer
00365 *************************************************************************/
00366 void OpenGLRenderer::renderVBuffer(void)
00367 {
00368         // if bufferPos is 0 there is no data in the buffer and nothing to render
00369         if (d_bufferPos == 0)
00370         {
00371                 return;
00372         }
00373 
00374         // render the sprites
00375         glDrawArrays(GL_TRIANGLES, 0, d_bufferPos);
00376 
00377         // reset buffer position to 0...
00378         d_bufferPos = 0;
00379 }
00380 
00381 
00382 /*************************************************************************
00383         sort quads list according to texture
00384 *************************************************************************/
00385 void OpenGLRenderer::sortQuads(void)
00386 {
00387         // no need to do anything here.
00388 }
00389 
00390 
00391 /*************************************************************************
00392         render a quad directly to the display
00393 *************************************************************************/
00394 void OpenGLRenderer::renderQuadDirect(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
00395 {
00396         QuadInfo quad;
00397         quad.position.d_left    = dest_rect.d_left;
00398         quad.position.d_right   = dest_rect.d_right;
00399         quad.position.d_bottom  = d_display_area.d_bottom - dest_rect.d_bottom;
00400         quad.position.d_top             = d_display_area.d_bottom - dest_rect.d_top;
00401         quad.texPosition                = texture_rect;
00402 
00403         quad.topLeftCol         = colourToOGL(colours.d_top_left);
00404         quad.topRightCol        = colourToOGL(colours.d_top_right);
00405         quad.bottomLeftCol      = colourToOGL(colours.d_bottom_left);
00406         quad.bottomRightCol     = colourToOGL(colours.d_bottom_right);
00407 
00408         MyQuad myquad[VERTEX_PER_QUAD];
00409 
00410         initPerFrameStates();
00411         glInterleavedArrays(GL_T2F_C4UB_V3F , 0, myquad);
00412         glBindTexture(GL_TEXTURE_2D, ((OpenGLTexture*)tex)->getOGLTexid());
00413 
00414         //vert0
00415         myquad[0].vertex[0] = quad.position.d_left;
00416         myquad[0].vertex[1] = quad.position.d_top;
00417         myquad[0].vertex[2] = z;
00418         myquad[0].color     = quad.topLeftCol;
00419         myquad[0].tex[0]    = quad.texPosition.d_left;
00420         myquad[0].tex[1]    = quad.texPosition.d_top;
00421 
00422         //vert1
00423         myquad[1].vertex[0] = quad.position.d_left;
00424         myquad[1].vertex[1] = quad.position.d_bottom;
00425         myquad[1].vertex[2] = z;
00426         myquad[1].color     = quad.bottomLeftCol;     
00427         myquad[1].tex[0]    = quad.texPosition.d_left;
00428         myquad[1].tex[1]    = quad.texPosition.d_bottom;
00429 
00430         //vert2
00431 
00432     // top-left to bottom-right diagonal
00433     if (quad_split_mode == TopLeftToBottomRight)
00434     {
00435         myquad[2].vertex[0] = quad.position.d_right;
00436         myquad[2].vertex[1] = quad.position.d_bottom;
00437         myquad[2].vertex[2] = z;
00438         myquad[2].color     = quad.bottomRightCol;
00439         myquad[2].tex[0]    = quad.texPosition.d_right;
00440         myquad[2].tex[1]    = quad.texPosition.d_bottom;
00441     }
00442     // bottom-left to top-right diagonal
00443     else
00444     {
00445         myquad[2].vertex[0] = quad.position.d_right;
00446         myquad[2].vertex[1] = quad.position.d_top;
00447         myquad[2].vertex[2] = z;
00448         myquad[2].color     = quad.topRightCol;
00449         myquad[2].tex[0]    = quad.texPosition.d_right;
00450         myquad[2].tex[1]    = quad.texPosition.d_top;
00451     }
00452 
00453         //vert3
00454         myquad[3].vertex[0] = quad.position.d_right;
00455         myquad[3].vertex[1] = quad.position.d_top;
00456         myquad[3].vertex[2] = z;
00457         myquad[3].color     = quad.topRightCol;      
00458         myquad[3].tex[0]    = quad.texPosition.d_right;
00459         myquad[3].tex[1]    = quad.texPosition.d_top;
00460 
00461         //vert4
00462 
00463     // top-left to bottom-right diagonal
00464     if (quad_split_mode == TopLeftToBottomRight)
00465     {
00466         myquad[4].vertex[0] = quad.position.d_left;
00467         myquad[4].vertex[1] = quad.position.d_top;
00468         myquad[4].vertex[2] = z;
00469         myquad[4].color     = quad.topLeftCol;
00470         myquad[4].tex[0]    = quad.texPosition.d_left;
00471         myquad[4].tex[1]    = quad.texPosition.d_top;
00472     }
00473     // bottom-left to top-right diagonal
00474     else
00475     {
00476         myquad[4].vertex[0] = quad.position.d_left;
00477         myquad[4].vertex[1] = quad.position.d_bottom;
00478         myquad[4].vertex[2] = z;
00479         myquad[4].color     = quad.bottomLeftCol;
00480         myquad[4].tex[0]    = quad.texPosition.d_left;
00481         myquad[4].tex[1]    = quad.texPosition.d_bottom;
00482     }
00483 
00484         //vert5
00485         myquad[5].vertex[0] = quad.position.d_right;
00486         myquad[5].vertex[1] = quad.position.d_bottom;
00487         myquad[5].vertex[2] = z;
00488         myquad[5].color     = quad.bottomRightCol;
00489         myquad[5].tex[0]    = quad.texPosition.d_right;
00490         myquad[5].tex[1]    = quad.texPosition.d_bottom;
00491 
00492         glDrawArrays(GL_TRIANGLES, 0, 6);
00493 
00494         exitPerFrameStates();
00495 }
00496 
00497 
00498 /*************************************************************************
00499         convert colour value to whatever the OpenGL system is expecting.
00500 *************************************************************************/
00501 long OpenGLRenderer::colourToOGL(const colour& col) const
00502 {
00503         ulong cval;
00504         cval =  (static_cast<ulong>(255 * col.getAlpha())) << 24;
00505         cval |= (static_cast<ulong>(255 * col.getBlue())) << 16;
00506         cval |= (static_cast<ulong>(255 * col.getGreen())) << 8;
00507         cval |= (static_cast<ulong>(255 * col.getRed()));
00508 
00509         return cval;
00510 }
00511 
00512 
00513 /*************************************************************************
00514         Set the size of the display in pixels.  
00515 *************************************************************************/
00516 void OpenGLRenderer::setDisplaySize(const Size& sz)
00517 {
00518         if (d_display_area.getSize() != sz)
00519         {
00520                 d_display_area.setSize(sz);
00521 
00522                 EventArgs args;
00523                 fireEvent(EventDisplaySizeChanged, args, EventNamespace);
00524         }
00525 
00526 }
00527 
00528 void OpenGLRenderer::setModuleIdentifierString()
00529 {
00530     // set ID string
00531     d_identifierString = "CEGUI::OpenGLRenderer - Official OpenGL based renderer module for CEGUI";
00532 }
00533 
00534 } // End of  CEGUI namespace section
00535 

Generated on Wed Sep 7 09:56:35 2005 for Crazy Eddies GUI System by  doxygen 1.4.3