src/render/rGradient.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023   
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #include "rGradient.h"
00029 #include "tError.h"
00030 
00031 #include <deque>
00032 #include <utility>
00033 
00034 rGradient::rGradient() : m_dir(value), m_texScale(1,1), m_tex() {
00035     //(*this)[0.]=rColor(); //make sure the beginning and end are defined
00036     //(*this)[1.]=rColor();
00037 }
00038 rGradient::~rGradient() {
00039 }
00040 
00043 void rGradient::SetGradientEdges(tCoord const &edge1, tCoord const edge2) {
00044     if(edge1.x < edge2.x) {
00045         m_origin.x = edge1.x;
00046         m_dimensions.x = edge2.x - edge1.x;
00047     } else {
00048         m_origin.x = edge2.x;
00049         m_dimensions.x = edge1.x - edge2.x;
00050     }
00051     if(edge1.y < edge2.y) {
00052         m_origin.y = edge1.y;
00053         m_dimensions.y = edge2.y - edge1.y;
00054     } else {
00055         m_origin.y = edge2.y;
00056         m_dimensions.y = edge1.y - edge2.y;
00057     }
00058 }
00059 
00060 float rGradient::GetGradientPt(tCoord const &where) {
00061     float ret = 0;
00062     switch (m_dir) {
00063     case horizontal:
00064         ret=(where.x-m_origin.x)/m_dimensions.x;
00065         break;
00066     case vertical:
00067         ret=(where.y-m_origin.y)/m_dimensions.y;
00068         break;
00069     case value:
00070         ret=m_at;
00071         break;
00072     default: tASSERT(0);
00073     }
00074     if(ret<0.) ret=0.;
00075     if(ret>1.) ret=1.;
00076     return ret;
00077 }
00078 
00079 rColor rGradient::GetColor(float where) {
00080 #ifndef DEDICATED
00081     if(empty()) return rColor();
00082     if(begin()->first >= where) return begin()->second;
00083     iterator upper, lower;
00084     iterator i=begin();
00085     iterator j=begin();
00086     ++j;
00087     bool finished = false;
00088     for(; j!=end(); ++i, ++j) {
00089         if(j->first >= where) {
00090             lower = i;
00091             upper = j;
00092             finished = true;
00093             break;
00094         }
00095     }
00096     if (!finished) return rbegin()->second;
00097     float diff = upper->first - lower->first;
00098     float pos = where - lower->first;
00099     rColor &c1 = lower->second;
00100     rColor &c2 = upper->second;
00101     float r = c1.r_*(diff-pos)/diff + c2.r_*pos/diff;
00102     float g = c1.g_*(diff-pos)/diff + c2.g_*pos/diff;
00103     float b = c1.b_*(diff-pos)/diff + c2.b_*pos/diff;
00104     float a = c1.a_*(diff-pos)/diff + c2.a_*pos/diff;
00105     return rColor(r,g,b,a);
00106 #else
00107     return rColor(0.,0.,0.,0.);
00108 #endif
00109 }
00110 
00111 void rGradient::SetValues(tCoord const &where, float *position, float *color, float *texcoords) {
00112     position[0] = where.x;
00113     position[1] = where.y;
00114     rColor c = GetColor(GetGradientPt(where));
00115     color[0] = c.r_;
00116     color[1] = c.g_;
00117     color[2] = c.b_;
00118     texcoords[0] = (where.x-m_origin.x)/m_dimensions.x/m_texScale.x,
00119     texcoords[1] = (where.y-m_origin.y)/m_dimensions.y/m_texScale.y;
00120 }
00121 
00122 void rGradient::DrawAt(tCoord const &where) {
00123 #ifndef DEDICATED
00124     GetColor(GetGradientPt(where)).Apply();
00125     if(m_tex.Valid()) {
00126         glTexCoord2f((where.x-m_origin.x)/m_dimensions.x/m_texScale.x, (m_origin.y-where.y)/m_dimensions.y/m_texScale.y);
00127     }
00128 #endif
00129 }
00130 
00133 void rGradient::DrawAtomicRect(tCoord const &edge1, tCoord const &edge2) {
00134 #ifndef DEDICATED
00135     DrawPoint(edge1);
00136     DrawPoint(tCoord(edge1.x, edge2.y));
00137     DrawPoint(edge2);
00138     DrawPoint(tCoord(edge2.x, edge1.y));
00139 #endif
00140 }
00141 
00144 void rGradient::DrawRect(tCoord const &edge1, tCoord const &edge2) {
00145 #ifndef DEDICATED
00146     float tCoord::*x; //those are correct for horizontal gradients,
00147     float tCoord::*y; //vertical ones just get turned around
00148     BeginDraw();
00149     BeginQuads();
00150     switch(m_dir) {
00151     case horizontal:
00152         x = &tCoord::x;
00153         y = &tCoord::y;
00154         break;
00155     case vertical:
00156         x = &tCoord::y;
00157         y = &tCoord::x;
00158         break;
00159     default:
00160         DrawAtomicRect(edge1, edge2);
00161         RenderEnd();
00162         return;
00163     }
00164     tCoord const &left = (edge1.*x < edge2.*x) ? edge1 : edge2;
00165     tCoord const &right = (edge1.*x < edge2.*x) ? edge2 : edge1;
00166     float min = GetGradientPt(left);
00167     float max = GetGradientPt(right);
00168     iterator i = upper_bound(min);
00169     float last = left.*x;
00170     for(; i != end() && i->first < max; ++i) {
00171         float newpt=i->first - min;
00172         float newx=newpt*m_dimensions.*x+m_origin.*x;
00173         tCoord todraw1;
00174         tCoord todraw2;
00175         todraw1.*x = last;
00176         todraw2.*x = newx;
00177         todraw1.*y = left.*y;
00178         todraw2.*y = right.*y;
00179         DrawAtomicRect(todraw1, todraw2);
00180         last = newx;
00181     }
00182     tCoord todraw;
00183     todraw.*x = last;
00184     todraw.*y = left.*y;
00185     DrawAtomicRect(todraw, right);
00186     RenderEnd();
00187 #endif
00188 }
00189 
00190 void rGradient::BeginDraw() {
00191 #ifndef DEDICATED
00192     if(m_tex.Valid()) {
00193         m_tex.Select();
00194     } else {
00195         glDisable(GL_TEXTURE_2D);
00196     }
00197 #endif
00198 }
00199 
00201 void rGradient::DrawPoint(tCoord const &where) {
00202 #ifndef DEDICATED
00203     DrawAt(where);
00204     Vertex(where.x, where.y);
00205 #endif
00206 }

Generated on Sat Mar 15 22:55:52 2008 for Armagetron Advanced by  doxygen 1.5.4