00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00036
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;
00147 float tCoord::*y;
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 }