1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.2 3 // Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 16 #ifndef AGG_SPAN_GOURAUD_INCLUDED 17 #define AGG_SPAN_GOURAUD_INCLUDED 18 19 #include "agg_basics.h" 20 #include "agg_math.h" 21 #include "agg_span_generator.h" 22 23 namespace agg 24 { 25 26 //============================================================span_gouraud 27 template<class ColorT, class Allocator> 28 class span_gouraud : public span_generator<ColorT, Allocator> 29 { 30 public: 31 typedef ColorT color_type; 32 typedef Allocator alloc_type; 33 34 struct coord_type 35 { 36 double x; 37 double y; 38 color_type color; 39 }; 40 41 //-------------------------------------------------------------------- 42 span_gouraud(alloc_type& alloc) : 43 span_generator<color_type, alloc_type>(alloc), 44 m_vertex(0) 45 { 46 m_cmd[0] = path_cmd_stop; 47 } 48 49 //-------------------------------------------------------------------- 50 span_gouraud(alloc_type& alloc, 51 const color_type& c1, 52 const color_type& c2, 53 const color_type& c3, 54 double x1, double y1, 55 double x2, double y2, 56 double x3, double y3, 57 double d) : 58 span_generator<color_type, alloc_type>(alloc) 59 { 60 colors(c1, c2, c3); 61 triangle(x1, y1, x2, y2, x3, y3, d); 62 } 63 64 //-------------------------------------------------------------------- 65 void colors(ColorT c1, ColorT c2, ColorT c3) 66 { 67 m_coord[0].color = c1; 68 m_coord[1].color = c2; 69 m_coord[2].color = c3; 70 } 71 72 //-------------------------------------------------------------------- 73 // Sets the triangle and dilates it if needed. 74 // The trick here is to calculate beveled joins in the vertices of the 75 // triangle and render it as a 6-vertex polygon. 76 // It's necessary to achieve numerical stability. 77 // However, the coordinates to interpolate colors are calculated 78 // as miter joins (calc_intersection). 79 void triangle(double x1, double y1, 80 double x2, double y2, 81 double x3, double y3, 82 double d) 83 { 84 m_coord[0].x = m_x[0] = x1; 85 m_coord[0].y = m_y[0] = y1; 86 m_coord[1].x = m_x[1] = x2; 87 m_coord[1].y = m_y[1] = y2; 88 m_coord[2].x = m_x[2] = x3; 89 m_coord[2].y = m_y[2] = y3; 90 m_cmd[0] = path_cmd_move_to; 91 m_cmd[1] = path_cmd_line_to; 92 m_cmd[2] = path_cmd_line_to; 93 m_cmd[3] = path_cmd_stop; 94 95 if(d != 0.0) 96 { 97 dilate_triangle(m_coord[0].x, m_coord[0].y, 98 m_coord[1].x, m_coord[1].y, 99 m_coord[2].x, m_coord[2].y, 100 m_x, m_y, d); 101 102 calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5], 103 m_x[0], m_y[0], m_x[1], m_y[1], 104 &m_coord[0].x, &m_coord[0].y); 105 106 calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1], 107 m_x[2], m_y[2], m_x[3], m_y[3], 108 &m_coord[1].x, &m_coord[1].y); 109 110 calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3], 111 m_x[4], m_y[4], m_x[5], m_y[5], 112 &m_coord[2].x, &m_coord[2].y); 113 m_cmd[3] = path_cmd_line_to; 114 m_cmd[4] = path_cmd_line_to; 115 m_cmd[5] = path_cmd_line_to; 116 m_cmd[6] = path_cmd_stop; 117 } 118 } 119 120 //-------------------------------------------------------------------- 121 // Vertex Source Interface to feed the coordinates to the rasterizer 122 void rewind(unsigned) 123 { 124 m_vertex = 0; 125 } 126 127 //-------------------------------------------------------------------- 128 unsigned vertex(double* x, double* y) 129 { 130 *x = m_x[m_vertex]; 131 *y = m_y[m_vertex]; 132 return m_cmd[m_vertex++]; 133 } 134 135 136 137 protected: 138 //-------------------------------------------------------------------- 139 void arrange_vertices(coord_type* coord) const 140 { 141 coord[0] = m_coord[0]; 142 coord[1] = m_coord[1]; 143 coord[2] = m_coord[2]; 144 145 if(m_coord[0].y > m_coord[2].y) 146 { 147 coord[0] = m_coord[2]; 148 coord[2] = m_coord[0]; 149 } 150 151 coord_type tmp; 152 if(coord[0].y > coord[1].y) 153 { 154 tmp = coord[1]; 155 coord[1] = coord[0]; 156 coord[0] = tmp; 157 } 158 159 if(coord[1].y > coord[2].y) 160 { 161 tmp = coord[2]; 162 coord[2] = coord[1]; 163 coord[1] = tmp; 164 } 165 } 166 167 168 private: 169 //-------------------------------------------------------------------- 170 coord_type m_coord[3]; 171 double m_x[8]; 172 double m_y[8]; 173 unsigned m_cmd[8]; 174 unsigned m_vertex; 175 }; 176 177 } 178 179 #endif 180 181