openglgraphics.cpp

00001 /*      _______   __   __   __   ______   __   __   _______   __   __
00002  *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
00003  *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
00004  *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
00005  *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
00006  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
00007  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
00008  *
00009  * Copyright (c) 2004, 2005, 2006 Olof Naessén and Per Larsson
00010  *
00011  *                                                         Js_./
00012  * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
00013  * Olof Naessén a.k.a jansem/yakslem                _asww7!uY`>  )\a//
00014  *                                                 _Qhm`] _f "'c  1!5m
00015  * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
00016  *                                               .)j(] .d_/ '-(  P .   S
00017  * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
00018  * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
00019  * binary forms, with or without                 )4d[#7r, .   '     )d`)[
00020  * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
00021  * that the following conditions are met:       j<<WP+k/);.        _W=j f
00022  * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
00023  *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
00024  *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
00025  *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
00026  * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
00027  *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
00028  *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
00029  *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
00030  *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
00031  *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
00032  * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
00033  *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
00034  *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
00035  *    from this software without specific        (js, \[QQW$QWW#?!V"".
00036  *    prior written permission.                    ]y:.<\..          .
00037  *                                                 -]n w/ '         [.
00038  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
00039  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
00040  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
00041  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
00042  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
00043  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
00044  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
00045  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
00046  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
00047  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
00048  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
00049  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
00050  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00051  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00052  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00053  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00054  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00055  */
00056 
00057 /*
00058  * For comments regarding functions please see the header file.
00059  */
00060 
00061 #include "guichan/opengl/openglgraphics.hpp"
00062 
00063 #ifdef _WIN32
00064 #define WIN32_LEAN_AND_MEAN
00065 #include <windows.h>
00066 #endif
00067 
00068 #ifdef __amigaos4__
00069 #include <mgl/gl.h>
00070 #define glVertex3i glVertex3f
00071 #else
00072 #include <GL/gl.h>
00073 #endif
00074 
00075 #include "guichan/exception.hpp"
00076 #include "guichan/image.hpp"
00077 #include "guichan/opengl/openglimage.hpp"
00078 
00079 namespace gcn
00080 {
00081     OpenGLGraphics::OpenGLGraphics()
00082     {
00083         setTargetPlane(640, 480);
00084         mAlpha = false;
00085     }
00086 
00087     OpenGLGraphics::OpenGLGraphics(int width, int height)
00088     {
00089         setTargetPlane(width, height);
00090     }
00091 
00092     OpenGLGraphics::~OpenGLGraphics()
00093     {
00094 
00095     }
00096 
00097     void OpenGLGraphics::_beginDraw()
00098     {
00099         glPushAttrib(
00100             GL_COLOR_BUFFER_BIT |
00101             GL_CURRENT_BIT |
00102             GL_DEPTH_BUFFER_BIT |
00103             GL_ENABLE_BIT |
00104             GL_FOG_BIT |
00105             GL_LIGHTING_BIT |
00106             GL_LINE_BIT |
00107             GL_POINT_BIT |
00108             GL_POLYGON_BIT |
00109             GL_SCISSOR_BIT |
00110             GL_STENCIL_BUFFER_BIT |
00111             GL_TEXTURE_BIT |
00112             GL_TRANSFORM_BIT |
00113             GL_POINT_BIT |
00114             GL_LINE_BIT
00115             );
00116 
00117         glMatrixMode(GL_MODELVIEW);
00118         glPushMatrix();
00119         glLoadIdentity();
00120 
00121         glMatrixMode(GL_TEXTURE);
00122         glPushMatrix();
00123         glLoadIdentity();
00124 
00125         glMatrixMode(GL_PROJECTION);
00126         glPushMatrix();
00127         glLoadIdentity();
00128 
00129         glOrtho(0.0, (double)mWidth, (double)mHeight, 0.0, -1.0, 1.0);
00130 
00131         glDisable(GL_LIGHTING);
00132         glDisable(GL_CULL_FACE);
00133         glDisable(GL_DEPTH_TEST);
00134         glDisable(GL_TEXTURE_2D);
00135 
00136         glEnable(GL_SCISSOR_TEST);
00137         glPointSize(1.0);
00138         glLineWidth(1.0);
00139 
00140         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00141 
00142         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00143         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00144         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00145         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00146 
00147         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00148 
00149         pushClipArea(Rectangle(0, 0, mWidth, mHeight));
00150     }
00151 
00152     void OpenGLGraphics::_endDraw()
00153     {
00154         glMatrixMode(GL_MODELVIEW);
00155         glPopMatrix();
00156 
00157         glMatrixMode(GL_TEXTURE);
00158         glPopMatrix();
00159 
00160         glMatrixMode(GL_PROJECTION);
00161         glPopMatrix();
00162 
00163         glPopAttrib();
00164 
00165         popClipArea();
00166     }
00167 
00168     bool OpenGLGraphics::pushClipArea(Rectangle area)
00169     {
00170         bool result = Graphics::pushClipArea(area);
00171 
00172         glScissor(mClipStack.top().x,
00173                   mHeight - mClipStack.top().y - mClipStack.top().height,
00174                   mClipStack.top().width,
00175                   mClipStack.top().height);
00176 
00177         return result;
00178     }
00179 
00180     void OpenGLGraphics::popClipArea()
00181     {
00182         Graphics::popClipArea();
00183 
00184         if (mClipStack.empty())
00185         {
00186             return;
00187         }
00188 
00189         glScissor(mClipStack.top().x,
00190                   mHeight - mClipStack.top().y - mClipStack.top().height,
00191                   mClipStack.top().width,
00192                   mClipStack.top().height);
00193     }
00194 
00195     void OpenGLGraphics::setTargetPlane(int width, int height)
00196     {
00197         mWidth = width;
00198         mHeight = height;
00199     }
00200 
00201     void OpenGLGraphics::drawImage(const Image* image, int srcX, int srcY,
00202                                    int dstX, int dstY, int width,
00203                                    int height)
00204     {
00205         const OpenGLImage* srcImage = dynamic_cast<const OpenGLImage*>(image);
00206 
00207         if (srcImage == NULL)
00208         {
00209             throw GCN_EXCEPTION("Trying to draw an image of unknown format, must be an OpenGLImage.");
00210         }
00211 
00212         dstX += mClipStack.top().xOffset;
00213         dstY += mClipStack.top().yOffset;
00214 
00215         // Find OpenGL texture coordinates
00216         float texX1 = srcX / (float)srcImage->getTextureWidth();
00217         float texY1 = srcY / (float)srcImage->getTextureHeight();
00218         float texX2 = (srcX+width) / (float)srcImage->getTextureWidth();
00219         float texY2 = (srcY+height) / (float)srcImage->getTextureHeight();
00220 
00221         glBindTexture(GL_TEXTURE_2D, srcImage->getTextureHandle());
00222 
00223         glEnable(GL_TEXTURE_2D);
00224 
00225         // Check if blending already is enabled
00226         if (!mAlpha)
00227         {
00228             glEnable(GL_BLEND);
00229         }
00230 
00231         // Draw a textured quad -- the image
00232         glBegin(GL_QUADS);
00233         glTexCoord2f(texX1, texY1);
00234         glVertex3i(dstX, dstY, 0);
00235 
00236         glTexCoord2f(texX1, texY2);
00237         glVertex3i(dstX, dstY + height, 0);
00238 
00239         glTexCoord2f(texX2, texY2);
00240         glVertex3i(dstX + width, dstY + height, 0);
00241 
00242         glTexCoord2f(texX2, texY1);
00243         glVertex3i(dstX + width, dstY, 0);
00244         glEnd();
00245         glDisable(GL_TEXTURE_2D);
00246 
00247         // Don't disable blending if the color has alpha
00248         if (!mAlpha)
00249         {
00250             glDisable(GL_BLEND);
00251         }
00252     }
00253 
00254     void OpenGLGraphics::drawPoint(int x, int y)
00255     {
00256         x += mClipStack.top().xOffset;
00257         y += mClipStack.top().yOffset;
00258 
00259         glBegin(GL_POINTS);
00260         glVertex3i(x, y, 0);
00261         glEnd();
00262     }
00263 
00264     void OpenGLGraphics::drawLine(int x1, int y1, int x2, int y2)
00265     {
00266         x1 += mClipStack.top().xOffset;
00267         y1 += mClipStack.top().yOffset;
00268         x2 += mClipStack.top().xOffset;
00269         y2 += mClipStack.top().yOffset;
00270 
00271         glBegin(GL_LINES);
00272         glVertex3f(x1+0.5f, y1+0.5f, 0);
00273         glVertex3f(x2+0.5f, y2+0.5f, 0);
00274         glEnd();
00275 
00276         glBegin(GL_POINTS);
00277         glVertex3f(x2+0.5f, y2+0.5f, 0);
00278         glEnd();
00279     }
00280 
00281     void OpenGLGraphics::drawRectangle(const Rectangle& rectangle)
00282     {
00283         glBegin(GL_LINE_LOOP);
00284         glVertex3f(rectangle.x + mClipStack.top().xOffset + 0.5f,
00285                    rectangle.y + mClipStack.top().yOffset + 0.5f, 0);
00286         glVertex3f(rectangle.x + rectangle.width - 0.5f + mClipStack.top().xOffset,
00287                    rectangle.y + mClipStack.top().yOffset + 0.5f, 0);
00288         glVertex3f(rectangle.x + rectangle.width - 0.5f + mClipStack.top().xOffset,
00289                    rectangle.y + rectangle.height + mClipStack.top().yOffset - 0.5f, 0);
00290         glVertex3f(rectangle.x + mClipStack.top().xOffset + 0.5f,
00291                    rectangle.y + rectangle.height + mClipStack.top().yOffset - 0.5f, 0);
00292         glEnd();
00293     }
00294 
00295     void OpenGLGraphics::fillRectangle(const Rectangle& rectangle)
00296     {
00297         glBegin(GL_QUADS);
00298         glVertex3i(rectangle.x + mClipStack.top().xOffset,
00299                    rectangle.y + mClipStack.top().yOffset, 0);
00300         glVertex3i(rectangle.x + rectangle.width + mClipStack.top().xOffset,
00301                    rectangle.y + mClipStack.top().yOffset, 0);
00302         glVertex3i(rectangle.x + rectangle.width + mClipStack.top().xOffset,
00303                    rectangle.y + rectangle.height + mClipStack.top().yOffset, 0);
00304         glVertex3i(rectangle.x + mClipStack.top().xOffset,
00305                    rectangle.y + rectangle.height + mClipStack.top().yOffset, 0);
00306         glEnd();
00307     }
00308 
00309     void OpenGLGraphics::setColor(const Color& color)
00310     {
00311         mColor = color;
00312         glColor4ub(color.r, color.g, color.b, color.a);
00313 
00314         mAlpha = color.a != 255;
00315 
00316         if (mAlpha)
00317         {
00318             glEnable(GL_BLEND);
00319         }
00320     }
00321 
00322     const Color& OpenGLGraphics::getColor()
00323     {
00324         return mColor;
00325     }
00326 }

Generated on Sat Jul 29 19:38:48 2006 for Guichan by  doxygen 1.4.7