Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 00025 #ifndef AGG_SPAN_GOURAUD_INCLUDED 00026 #define AGG_SPAN_GOURAUD_INCLUDED 00027 00028 #include "agg_basics.h" 00029 #include "agg_math.h" 00030 00031 namespace agg 00032 { 00033 00034 //============================================================span_gouraud 00035 template<class ColorT> class span_gouraud 00036 { 00037 public: 00038 typedef ColorT color_type; 00039 00040 struct coord_type 00041 { 00042 double x; 00043 double y; 00044 color_type color; 00045 }; 00046 00047 //-------------------------------------------------------------------- 00048 span_gouraud() : 00049 m_vertex(0) 00050 { 00051 m_cmd[0] = path_cmd_stop; 00052 } 00053 00054 //-------------------------------------------------------------------- 00055 span_gouraud(const color_type& c1, 00056 const color_type& c2, 00057 const color_type& c3, 00058 double x1, double y1, 00059 double x2, double y2, 00060 double x3, double y3, 00061 double d) : 00062 m_vertex(0) 00063 { 00064 colors(c1, c2, c3); 00065 triangle(x1, y1, x2, y2, x3, y3, d); 00066 } 00067 00068 //-------------------------------------------------------------------- 00069 void colors(ColorT c1, ColorT c2, ColorT c3) 00070 { 00071 m_coord[0].color = c1; 00072 m_coord[1].color = c2; 00073 m_coord[2].color = c3; 00074 } 00075 00076 //-------------------------------------------------------------------- 00077 // Sets the triangle and dilates it if needed. 00078 // The trick here is to calculate beveled joins in the vertices of the 00079 // triangle and render it as a 6-vertex polygon. 00080 // It's necessary to achieve numerical stability. 00081 // However, the coordinates to interpolate colors are calculated 00082 // as miter joins (calc_intersection). 00083 void triangle(double x1, double y1, 00084 double x2, double y2, 00085 double x3, double y3, 00086 double d) 00087 { 00088 m_coord[0].x = m_x[0] = x1; 00089 m_coord[0].y = m_y[0] = y1; 00090 m_coord[1].x = m_x[1] = x2; 00091 m_coord[1].y = m_y[1] = y2; 00092 m_coord[2].x = m_x[2] = x3; 00093 m_coord[2].y = m_y[2] = y3; 00094 m_cmd[0] = path_cmd_move_to; 00095 m_cmd[1] = path_cmd_line_to; 00096 m_cmd[2] = path_cmd_line_to; 00097 m_cmd[3] = path_cmd_stop; 00098 00099 if(d != 0.0) 00100 { 00101 dilate_triangle(m_coord[0].x, m_coord[0].y, 00102 m_coord[1].x, m_coord[1].y, 00103 m_coord[2].x, m_coord[2].y, 00104 m_x, m_y, d); 00105 00106 calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5], 00107 m_x[0], m_y[0], m_x[1], m_y[1], 00108 &m_coord[0].x, &m_coord[0].y); 00109 00110 calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1], 00111 m_x[2], m_y[2], m_x[3], m_y[3], 00112 &m_coord[1].x, &m_coord[1].y); 00113 00114 calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3], 00115 m_x[4], m_y[4], m_x[5], m_y[5], 00116 &m_coord[2].x, &m_coord[2].y); 00117 m_cmd[3] = path_cmd_line_to; 00118 m_cmd[4] = path_cmd_line_to; 00119 m_cmd[5] = path_cmd_line_to; 00120 m_cmd[6] = path_cmd_stop; 00121 } 00122 } 00123 00124 //-------------------------------------------------------------------- 00125 // Vertex Source Interface to feed the coordinates to the rasterizer 00126 void rewind(unsigned) 00127 { 00128 m_vertex = 0; 00129 } 00130 00131 //-------------------------------------------------------------------- 00132 unsigned vertex(double* x, double* y) 00133 { 00134 *x = m_x[m_vertex]; 00135 *y = m_y[m_vertex]; 00136 return m_cmd[m_vertex++]; 00137 } 00138 00139 protected: 00140 //-------------------------------------------------------------------- 00141 void arrange_vertices(coord_type* coord) const 00142 { 00143 coord[0] = m_coord[0]; 00144 coord[1] = m_coord[1]; 00145 coord[2] = m_coord[2]; 00146 00147 if(m_coord[0].y > m_coord[2].y) 00148 { 00149 coord[0] = m_coord[2]; 00150 coord[2] = m_coord[0]; 00151 } 00152 00153 coord_type tmp; 00154 if(coord[0].y > coord[1].y) 00155 { 00156 tmp = coord[1]; 00157 coord[1] = coord[0]; 00158 coord[0] = tmp; 00159 } 00160 00161 if(coord[1].y > coord[2].y) 00162 { 00163 tmp = coord[2]; 00164 coord[2] = coord[1]; 00165 coord[1] = tmp; 00166 } 00167 } 00168 00169 private: 00170 //-------------------------------------------------------------------- 00171 coord_type m_coord[3]; 00172 double m_x[8]; 00173 double m_y[8]; 00174 unsigned m_cmd[8]; 00175 unsigned m_vertex; 00176 }; 00177 00178 } 00179 00180 #endif 00181