1 #include <math.h>
2 #include <stdio.h>
3 #include <time.h>
4 #include "agg_rendering_buffer.h"
5 #include "agg_conv_transform.h"
6 #include "agg_conv_stroke.h"
7 #include "agg_conv_clip_polyline.h"
8 #include "agg_scanline_u.h"
9 #include "agg_scanline_bin.h"
10 #include "agg_renderer_scanline.h"
11 #include "agg_rasterizer_outline_aa.h"
12 #include "agg_rasterizer_scanline_aa.h"
13 #include "agg_span_allocator.h"
14 #include "agg_span_gouraud_rgba.h"
15 #include "agg_gamma_lut.h"
16 #include "agg_arc.h"
17 #include "agg_bezier_arc.h"
18 #include "agg_pixfmt_rgb.h"
19 #include "agg_pixfmt_rgba.h"
20 #include "agg_bounding_rect.h"
21 #include "agg_vpgen_clip_polygon.h"
22 #include "ctrl/agg_slider_ctrl.h"
23 #include "ctrl/agg_bezier_ctrl.h"
24 #include "ctrl/agg_rbox_ctrl.h"
25 #include "ctrl/agg_cbox_ctrl.h"
26 #include "platform/agg_platform_support.h"
27 
28 #include "agg_rasterizer_compound_aa.h"
29 
30 
31 enum { flip_y = true };
32 
33 typedef agg::pixfmt_bgra32_pre pixfmt;
34 
35 
36 namespace agg
37 {
38 
39     struct mesh_point
40     {
41         double x,y;
42         double dx,dy;
43         rgba8 color;
44         rgba8 dc;
45 
mesh_pointagg::mesh_point46         mesh_point() {}
mesh_pointagg::mesh_point47         mesh_point(double x_, double y_,
48                    double dx_, double dy_,
49                    rgba8 c, rgba8 dc_) :
50             x(x_), y(y_),
51             dx(dx_), dy(dy_),
52             color(c), dc(dc_)
53         {}
54     };
55 
56     struct mesh_triangle
57     {
58         unsigned p1, p2, p3;
59 
mesh_triangleagg::mesh_triangle60         mesh_triangle() {}
mesh_triangleagg::mesh_triangle61         mesh_triangle(unsigned i, unsigned j, unsigned k) :
62             p1(i), p2(j), p3(k)
63         {}
64     };
65 
66     struct mesh_edge
67     {
68         unsigned p1, p2;
69         int      tl, tr;
70 
mesh_edgeagg::mesh_edge71         mesh_edge() {}
mesh_edgeagg::mesh_edge72         mesh_edge(unsigned p1_, unsigned p2_, int tl_, int tr_) :
73             p1(p1_), p2(p2_), tl(tl_), tr(tr_)
74         {}
75     };
76 
77 
random(double v1,double v2)78     static double random(double v1, double v2)
79     {
80         return (v2 - v1) * (rand() % 1000) / 999.0 + v1;
81     }
82 
83 
84     class mesh_ctrl
85     {
86     public:
87         mesh_ctrl();
88 
89         void generate(unsigned cols, unsigned rows,
90                       double cell_w, double cell_h,
91                       double start_x, double start_y);
92 
93         void randomize_points(double delta);
94         void rotate_colors();
95 
96 
97         bool on_mouse_button_down(double x, double y, unsigned flags);
98         bool on_mouse_move(double x, double y, unsigned flags);
99         bool on_mouse_button_up(double x, double y, unsigned flags);
100 
num_vertices() const101         unsigned num_vertices() const { return m_vertices.size(); }
vertex(unsigned i) const102         const mesh_point& vertex(unsigned i) const { return m_vertices[i]; }
vertex(unsigned i)103               mesh_point& vertex(unsigned i)       { return m_vertices[i]; }
104 
vertex(unsigned x,unsigned y) const105         const mesh_point& vertex(unsigned x, unsigned y) const { return m_vertices[y * m_rows + x]; }
vertex(unsigned x,unsigned y)106               mesh_point& vertex(unsigned x, unsigned y)       { return m_vertices[y * m_rows + x]; }
107 
num_triangles() const108         unsigned num_triangles() const { return m_triangles.size(); }
triangle(unsigned i) const109         const mesh_triangle& triangle(unsigned i) const { return m_triangles[i]; }
triangle(unsigned i)110               mesh_triangle& triangle(unsigned i)       { return m_triangles[i]; }
111 
num_edges() const112         unsigned num_edges() const { return m_edges.size(); }
edge(unsigned i) const113         const mesh_edge& edge(unsigned i) const { return m_edges[i]; }
edge(unsigned i)114               mesh_edge& edge(unsigned i)       { return m_edges[i]; }
115 
116     private:
117         unsigned m_cols;
118         unsigned m_rows;
119         int      m_drag_idx;
120         double   m_drag_dx;
121         double   m_drag_dy;
122         double   m_cell_w;
123         double   m_cell_h;
124         double   m_start_x;
125         double   m_start_y;
126         pod_bvector<mesh_point>    m_vertices;
127         pod_bvector<mesh_triangle> m_triangles;
128         pod_bvector<mesh_edge>     m_edges;
129     };
130 
131 
mesh_ctrl()132     mesh_ctrl::mesh_ctrl() :
133         m_cols(0),
134         m_rows(0),
135         m_drag_idx(-1),
136         m_drag_dx(0),
137         m_drag_dy(0)
138     {}
139 
140 
generate(unsigned cols,unsigned rows,double cell_w,double cell_h,double start_x,double start_y)141     void mesh_ctrl::generate(unsigned cols, unsigned rows,
142                              double cell_w, double cell_h,
143                              double start_x, double start_y)
144     {
145         m_cols = cols;
146         m_rows = rows;
147         m_cell_w = cell_w;
148         m_cell_h = cell_h;
149         m_start_x = start_x;
150         m_start_y = start_y;
151 
152         m_vertices.remove_all();
153         unsigned i, j;
154         for(i = 0; i < m_rows; i++)
155         {
156             double x = start_x;
157             for(j = 0; j < m_cols; j++)
158             {
159                 double dx = random(-0.5, 0.5);
160                 double dy = random(-0.5, 0.5);
161                 rgba8 c(rand() & 0xFF, rand() & 0xFF, rand() & 0xFF);
162                 rgba8 dc(rand() & 1, rand() & 1, rand() & 1);
163                 m_vertices.add(mesh_point(x, start_y, dx, dy, c, dc));
164                 x += cell_w;
165             }
166             start_y += cell_h;
167         }
168 
169 
170 
171         //  4---3
172         //  |t2/|
173         //  | / |
174         //  |/t1|
175         //  1---2
176         m_triangles.remove_all();
177         m_edges.remove_all();
178         for(i = 0; i < m_rows - 1; i++)
179         {
180             for(j = 0; j < m_cols - 1; j++)
181             {
182                 int p1 = i * m_cols + j;
183                 int p2 = p1 + 1;
184                 int p3 = p2 + m_cols;
185                 int p4 = p1 + m_cols;
186                 m_triangles.add(mesh_triangle(p1, p2, p3));
187                 m_triangles.add(mesh_triangle(p3, p4, p1));
188 
189                 int curr_cell = i * (m_cols - 1) + j;
190                 int left_cell = j ? int(curr_cell - 1) : -1;
191                 int bott_cell = i ? int(curr_cell - (m_cols - 1)) : -1;
192 
193                 int curr_t1 = curr_cell * 2;
194                 int curr_t2 = curr_t1 + 1;
195 
196                 int left_t1 = (left_cell >= 0) ? left_cell * 2 : -1;
197                 int left_t2 = (left_cell >= 0) ? left_t1 + 1   : -1;
198 
199                 int bott_t1 = (bott_cell >= 0) ? bott_cell * 2 : -1;
200                 int bott_t2 = (bott_cell >= 0) ? bott_t1 + 1   : -1;
201 
202                 m_edges.add(mesh_edge(p1, p2, curr_t1, bott_t2));
203                 m_edges.add(mesh_edge(p1, p3, curr_t2, curr_t1));
204                 m_edges.add(mesh_edge(p1, p4, left_t1, curr_t2));
205 
206                 if(j == m_cols - 2) // Last column
207                 {
208                     m_edges.add(mesh_edge(p2, p3, curr_t1, -1));
209                 }
210 
211                 if(i == m_rows - 2) // Last row
212                 {
213                     m_edges.add(mesh_edge(p3, p4, curr_t2, -1));
214                 }
215             }
216         }
217     }
218 
randomize_points(double delta)219     void mesh_ctrl::randomize_points(double delta)
220     {
221         unsigned i, j;
222         for(i = 0; i < m_rows; i++)
223         {
224             for(j = 0; j < m_cols; j++)
225             {
226                 double xc = j * m_cell_w + m_start_x;
227                 double yc = i * m_cell_h + m_start_y;
228                 double x1 = xc - m_cell_w / 4;
229                 double y1 = yc - m_cell_h / 4;
230                 double x2 = xc + m_cell_w / 4;
231                 double y2 = yc + m_cell_h / 4;
232                 mesh_point& p = vertex(j, i);
233                 p.x += p.dx;
234                 p.y += p.dy;
235                 if(p.x < x1) { p.x = x1; p.dx = -p.dx; }
236                 if(p.y < y1) { p.y = y1; p.dy = -p.dy; }
237                 if(p.x > x2) { p.x = x2; p.dx = -p.dx; }
238                 if(p.y > y2) { p.y = y2; p.dy = -p.dy; }
239             }
240         }
241     }
242 
243 
rotate_colors()244     void mesh_ctrl::rotate_colors()
245     {
246         unsigned i;
247         for(i = 1; i < m_vertices.size(); i++)
248         {
249             rgba8& c = m_vertices[i].color;
250             rgba8& dc = m_vertices[i].dc;
251             int r = c.r + (dc.r ? 5 : -5);
252             int g = c.g + (dc.g ? 5 : -5);
253             int b = c.b + (dc.b ? 5 : -5);
254             if(r < 0) { r = 0; dc.r ^= 1; } if(r > 255) { r = 255; dc.r ^= 1; }
255             if(g < 0) { g = 0; dc.g ^= 1; } if(g > 255) { g = 255; dc.g ^= 1; }
256             if(b < 0) { b = 0; dc.b ^= 1; } if(b > 255) { b = 255; dc.b ^= 1; }
257             c.r = r;
258             c.g = g;
259             c.b = b;
260         }
261     }
262 
263 
on_mouse_button_down(double x,double y,unsigned flags)264     bool mesh_ctrl::on_mouse_button_down(double x, double y, unsigned flags)
265     {
266         if(flags & 1)
267         {
268             unsigned i;
269             for(i = 0; i < m_vertices.size(); i++)
270             {
271                 if(calc_distance(x, y, m_vertices[i].x, m_vertices[i].y) < 5)
272                 {
273                     m_drag_idx = i;
274                     m_drag_dx = x - m_vertices[i].x;
275                     m_drag_dy = y - m_vertices[i].y;
276                     return true;
277                 }
278             }
279         }
280         return false;
281     }
282 
on_mouse_move(double x,double y,unsigned flags)283     bool mesh_ctrl::on_mouse_move(double x, double y, unsigned flags)
284     {
285         if(flags & 1)
286         {
287             if(m_drag_idx >= 0)
288             {
289                 m_vertices[m_drag_idx].x = x - m_drag_dx;
290                 m_vertices[m_drag_idx].y = y - m_drag_dy;
291                 return true;
292             }
293         }
294         else
295         {
296             return on_mouse_button_up(x, y, flags);
297         }
298         return false;
299     }
300 
on_mouse_button_up(double x,double y,unsigned flags)301     bool mesh_ctrl::on_mouse_button_up(double x, double y, unsigned flags)
302     {
303         bool ret = m_drag_idx >= 0;
304         m_drag_idx = -1;
305         return ret;
306     }
307 
308 
309 
310     class styles_gouraud
311     {
312     public:
313         typedef span_gouraud_rgba<rgba8> gouraud_type;
314 
315         template<class Gamma>
styles_gouraud(const mesh_ctrl & mesh,const Gamma & gamma)316         styles_gouraud(const mesh_ctrl& mesh, const Gamma& gamma)
317         {
318             unsigned i;
319             for(i = 0; i < mesh.num_triangles(); i++)
320             {
321                 const agg::mesh_triangle& t = mesh.triangle(i);
322                 const agg::mesh_point& p1 = mesh.vertex(t.p1);
323                 const agg::mesh_point& p2 = mesh.vertex(t.p2);
324                 const agg::mesh_point& p3 = mesh.vertex(t.p3);
325 
326                 agg::rgba8 c1 = p1.color;
327                 agg::rgba8 c2 = p2.color;
328                 agg::rgba8 c3 = p3.color;
329                 c1.apply_gamma_dir(gamma);
330                 c2.apply_gamma_dir(gamma);
331                 c3.apply_gamma_dir(gamma);
332                 gouraud_type gouraud(c1, c2, c3,
333                                      p1.x, p1.y,
334                                      p2.x, p2.y,
335                                      p3.x, p3.y);
336                 gouraud.prepare();
337                 m_triangles.add(gouraud);
338             }
339         }
340 
is_solid(unsigned style) const341         bool is_solid(unsigned style) const { return false; }
342 
color(unsigned style) const343         rgba8 color(unsigned style) const { return rgba8(0,0,0,0); }
344 
generate_span(rgba8 * span,int x,int y,unsigned len,unsigned style)345         void generate_span(rgba8* span, int x, int y, unsigned len, unsigned style)
346         {
347             m_triangles[style].generate(span, x, y, len);
348         }
349 
350     private:
351         pod_bvector<gouraud_type> m_triangles;
352     };
353 }
354 
355 
356 
357 
358 
359 class the_application : public agg::platform_support
360 {
361 
362 public:
363     typedef agg::renderer_base<pixfmt> renderer_base;
364     typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
365     typedef agg::rasterizer_scanline_aa<> rasterizer_scanline;
366     typedef agg::scanline_u8 scanline;
367 
368     agg::mesh_ctrl      m_mesh;
369     agg::gamma_lut<>    m_gamma;
370 
371 
the_application(agg::pix_format_e format,bool flip_y)372     the_application(agg::pix_format_e format, bool flip_y) :
373         agg::platform_support(format, flip_y)
374     {
375 //        m_gamma.gamma(2.0);
376     }
377 
on_init()378     virtual void on_init()
379     {
380         m_mesh.generate(20, 20, 17, 17, 40, 40);
381     }
382 
383 
on_draw()384     virtual void on_draw()
385     {
386         pixfmt pf(rbuf_window());
387         renderer_base ren_base(pf);
388         ren_base.clear(agg::rgba(0, 0, 0));
389         renderer_scanline ren(ren_base);
390 
391         rasterizer_scanline ras;
392         agg::scanline_u8 sl;
393         agg::scanline_bin sl_bin;
394 
395         agg::rasterizer_compound_aa<> rasc;
396         agg::span_allocator<agg::rgba8> alloc;
397 
398         unsigned i;
399         agg::styles_gouraud styles(m_mesh, m_gamma);
400         start_timer();
401         rasc.reset();
402         //rasc.clip_box(40, 40, width() - 40, height() - 40);
403         for(i = 0; i < m_mesh.num_edges(); i++)
404         {
405             const agg::mesh_edge& e = m_mesh.edge(i);
406             const agg::mesh_point& p1 = m_mesh.vertex(e.p1);
407             const agg::mesh_point& p2 = m_mesh.vertex(e.p2);
408             rasc.styles(e.tl, e.tr);
409             rasc.move_to_d(p1.x, p1.y);
410             rasc.line_to_d(p2.x, p2.y);
411         }
412         agg::render_scanlines_compound(rasc, sl, sl_bin, ren_base, alloc, styles);
413         double tm = elapsed_time();
414 
415         char buf[256];
416         agg::gsv_text t;
417         t.size(10.0);
418 
419         agg::conv_stroke<agg::gsv_text> pt(t);
420         pt.width(1.5);
421         pt.line_cap(agg::round_cap);
422         pt.line_join(agg::round_join);
423 
424         sprintf(buf, "%3.2f ms, %d triangles, %.0f tri/sec",
425             tm,
426             m_mesh.num_triangles(),
427             m_mesh.num_triangles() / tm * 1000.0);
428         t.start_point(10.0, 10.0);
429         t.text(buf);
430 
431         ras.add_path(pt);
432         agg::render_scanlines_aa_solid(ras, sl, ren_base, agg::rgba(1,1,1));
433 
434 
435         if(m_gamma.gamma() != 1.0)
436         {
437             pf.apply_gamma_inv(m_gamma);
438         }
439     }
440 
on_mouse_move(int x,int y,unsigned flags)441     virtual void on_mouse_move(int x, int y, unsigned flags)
442     {
443         if(m_mesh.on_mouse_move(x, y, flags))
444         {
445             force_redraw();
446         }
447     }
448 
on_mouse_button_down(int x,int y,unsigned flags)449     virtual void on_mouse_button_down(int x, int y, unsigned flags)
450     {
451         if(m_mesh.on_mouse_button_down(x, y, flags))
452         {
453             force_redraw();
454         }
455     }
456 
on_mouse_button_up(int x,int y,unsigned flags)457     virtual void on_mouse_button_up(int x, int y, unsigned flags)
458     {
459         if(m_mesh.on_mouse_button_up(x, y, flags))
460         {
461             force_redraw();
462         }
463     }
464 
on_key(int x,int y,unsigned key,unsigned flags)465     virtual void on_key(int x, int y, unsigned key, unsigned flags)
466     {
467     }
468 
on_idle()469     void on_idle()
470     {
471         m_mesh.randomize_points(1.0);
472         m_mesh.rotate_colors();
473         force_redraw();
474     }
475 
on_ctrl_change()476     virtual void on_ctrl_change()
477     {
478     }
479 };
480 
481 
agg_main(int argc,char * argv[])482 int agg_main(int argc, char* argv[])
483 {
484     the_application app(agg::pix_format_bgra32, flip_y);
485     app.caption("AGG Example");
486 
487     if(app.init(400, 400, 0))//agg::window_resize))
488     {
489         app.wait_mode(false);
490         return app.run();
491     }
492     return 1;
493 }
494 
495 
496 
497 
498 
499