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