00001 #include <math.h>
00002 #include <stdio.h>
00003 #include <time.h>
00004 #include "agg_rendering_buffer.h"
00005 #include "agg_conv_transform.h"
00006 #include "agg_conv_stroke.h"
00007 #include "agg_conv_clip_polyline.h"
00008 #include "agg_scanline_u.h"
00009 #include "agg_scanline_bin.h"
00010 #include "agg_renderer_scanline.h"
00011 #include "agg_rasterizer_outline_aa.h"
00012 #include "agg_rasterizer_scanline_aa.h"
00013 #include "agg_span_allocator.h"
00014 #include "agg_span_gouraud_rgba.h"
00015 #include "agg_gamma_lut.h"
00016 #include "agg_arc.h"
00017 #include "agg_bezier_arc.h"
00018 #include "agg_pixfmt_rgb.h"
00019 #include "agg_pixfmt_rgba.h"
00020 #include "agg_bounding_rect.h"
00021 #include "agg_vpgen_clip_polygon.h"
00022 #include "ctrl/agg_slider_ctrl.h"
00023 #include "ctrl/agg_bezier_ctrl.h"
00024 #include "ctrl/agg_rbox_ctrl.h"
00025 #include "ctrl/agg_cbox_ctrl.h"
00026 #include "platform/agg_platform_support.h"
00027
00028 #include "agg_rasterizer_compound_aa.h"
00029
00030
00031 enum { flip_y = true };
00032
00033 typedef agg::pixfmt_bgra32_pre pixfmt;
00034
00035
00036 namespace agg
00037 {
00038
00039 struct mesh_point
00040 {
00041 double x,y;
00042 double dx,dy;
00043 rgba8 color;
00044 rgba8 dc;
00045
00046 mesh_point() {}
00047 mesh_point(double x_, double y_,
00048 double dx_, double dy_,
00049 rgba8 c, rgba8 dc_) :
00050 x(x_), y(y_),
00051 dx(dx_), dy(dy_),
00052 color(c), dc(dc_)
00053 {}
00054 };
00055
00056 struct mesh_triangle
00057 {
00058 unsigned p1, p2, p3;
00059
00060 mesh_triangle() {}
00061 mesh_triangle(unsigned i, unsigned j, unsigned k) :
00062 p1(i), p2(j), p3(k)
00063 {}
00064 };
00065
00066 struct mesh_edge
00067 {
00068 unsigned p1, p2;
00069 int tl, tr;
00070
00071 mesh_edge() {}
00072 mesh_edge(unsigned p1_, unsigned p2_, int tl_, int tr_) :
00073 p1(p1_), p2(p2_), tl(tl_), tr(tr_)
00074 {}
00075 };
00076
00077
00078 static double random(double v1, double v2)
00079 {
00080 return (v2 - v1) * (rand() % 1000) / 999.0 + v1;
00081 }
00082
00083
00084 class mesh_ctrl
00085 {
00086 public:
00087 mesh_ctrl();
00088
00089 void generate(unsigned cols, unsigned rows,
00090 double cell_w, double cell_h,
00091 double start_x, double start_y);
00092
00093 void randomize_points(double delta);
00094 void rotate_colors();
00095
00096
00097 bool on_mouse_button_down(double x, double y, unsigned flags);
00098 bool on_mouse_move(double x, double y, unsigned flags);
00099 bool on_mouse_button_up(double x, double y, unsigned flags);
00100
00101 unsigned num_vertices() const { return m_vertices.size(); }
00102 const mesh_point& vertex(unsigned i) const { return m_vertices[i]; }
00103 mesh_point& vertex(unsigned i) { return m_vertices[i]; }
00104
00105 const mesh_point& vertex(unsigned x, unsigned y) const { return m_vertices[y * m_rows + x]; }
00106 mesh_point& vertex(unsigned x, unsigned y) { return m_vertices[y * m_rows + x]; }
00107
00108 unsigned num_triangles() const { return m_triangles.size(); }
00109 const mesh_triangle& triangle(unsigned i) const { return m_triangles[i]; }
00110 mesh_triangle& triangle(unsigned i) { return m_triangles[i]; }
00111
00112 unsigned num_edges() const { return m_edges.size(); }
00113 const mesh_edge& edge(unsigned i) const { return m_edges[i]; }
00114 mesh_edge& edge(unsigned i) { return m_edges[i]; }
00115
00116 private:
00117 unsigned m_cols;
00118 unsigned m_rows;
00119 int m_drag_idx;
00120 double m_drag_dx;
00121 double m_drag_dy;
00122 double m_cell_w;
00123 double m_cell_h;
00124 double m_start_x;
00125 double m_start_y;
00126 pod_bvector<mesh_point> m_vertices;
00127 pod_bvector<mesh_triangle> m_triangles;
00128 pod_bvector<mesh_edge> m_edges;
00129 };
00130
00131
00132 mesh_ctrl::mesh_ctrl() :
00133 m_cols(0),
00134 m_rows(0),
00135 m_drag_idx(-1),
00136 m_drag_dx(0),
00137 m_drag_dy(0)
00138 {}
00139
00140
00141 void mesh_ctrl::generate(unsigned cols, unsigned rows,
00142 double cell_w, double cell_h,
00143 double start_x, double start_y)
00144 {
00145 m_cols = cols;
00146 m_rows = rows;
00147 m_cell_w = cell_w;
00148 m_cell_h = cell_h;
00149 m_start_x = start_x;
00150 m_start_y = start_y;
00151
00152 m_vertices.remove_all();
00153 unsigned i, j;
00154 for(i = 0; i < m_rows; i++)
00155 {
00156 double x = start_x;
00157 for(j = 0; j < m_cols; j++)
00158 {
00159 double dx = random(-0.5, 0.5);
00160 double dy = random(-0.5, 0.5);
00161 rgba8 c(rand() & 0xFF, rand() & 0xFF, rand() & 0xFF);
00162 rgba8 dc(rand() & 1, rand() & 1, rand() & 1);
00163 m_vertices.add(mesh_point(x, start_y, dx, dy, c, dc));
00164 x += cell_w;
00165 }
00166 start_y += cell_h;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 m_triangles.remove_all();
00177 m_edges.remove_all();
00178 for(i = 0; i < m_rows - 1; i++)
00179 {
00180 for(j = 0; j < m_cols - 1; j++)
00181 {
00182 int p1 = i * m_cols + j;
00183 int p2 = p1 + 1;
00184 int p3 = p2 + m_cols;
00185 int p4 = p1 + m_cols;
00186 m_triangles.add(mesh_triangle(p1, p2, p3));
00187 m_triangles.add(mesh_triangle(p3, p4, p1));
00188
00189 int curr_cell = i * (m_cols - 1) + j;
00190 int left_cell = j ? int(curr_cell - 1) : -1;
00191 int bott_cell = i ? int(curr_cell - (m_cols - 1)) : -1;
00192
00193 int curr_t1 = curr_cell * 2;
00194 int curr_t2 = curr_t1 + 1;
00195
00196 int left_t1 = (left_cell >= 0) ? left_cell * 2 : -1;
00197 int left_t2 = (left_cell >= 0) ? left_t1 + 1 : -1;
00198
00199 int bott_t1 = (bott_cell >= 0) ? bott_cell * 2 : -1;
00200 int bott_t2 = (bott_cell >= 0) ? bott_t1 + 1 : -1;
00201
00202 m_edges.add(mesh_edge(p1, p2, curr_t1, bott_t2));
00203 m_edges.add(mesh_edge(p1, p3, curr_t2, curr_t1));
00204 m_edges.add(mesh_edge(p1, p4, left_t1, curr_t2));
00205
00206 if(j == m_cols - 2)
00207 {
00208 m_edges.add(mesh_edge(p2, p3, curr_t1, -1));
00209 }
00210
00211 if(i == m_rows - 2)
00212 {
00213 m_edges.add(mesh_edge(p3, p4, curr_t2, -1));
00214 }
00215 }
00216 }
00217 }
00218
00219 void mesh_ctrl::randomize_points(double delta)
00220 {
00221 unsigned i, j;
00222 for(i = 0; i < m_rows; i++)
00223 {
00224 for(j = 0; j < m_cols; j++)
00225 {
00226 double xc = j * m_cell_w + m_start_x;
00227 double yc = i * m_cell_h + m_start_y;
00228 double x1 = xc - m_cell_w / 4;
00229 double y1 = yc - m_cell_h / 4;
00230 double x2 = xc + m_cell_w / 4;
00231 double y2 = yc + m_cell_h / 4;
00232 mesh_point& p = vertex(j, i);
00233 p.x += p.dx;
00234 p.y += p.dy;
00235 if(p.x < x1) { p.x = x1; p.dx = -p.dx; }
00236 if(p.y < y1) { p.y = y1; p.dy = -p.dy; }
00237 if(p.x > x2) { p.x = x2; p.dx = -p.dx; }
00238 if(p.y > y2) { p.y = y2; p.dy = -p.dy; }
00239 }
00240 }
00241 }
00242
00243
00244 void mesh_ctrl::rotate_colors()
00245 {
00246 unsigned i;
00247 for(i = 1; i < m_vertices.size(); i++)
00248 {
00249 rgba8& c = m_vertices[i].color;
00250 rgba8& dc = m_vertices[i].dc;
00251 int r = c.r + (dc.r ? 5 : -5);
00252 int g = c.g + (dc.g ? 5 : -5);
00253 int b = c.b + (dc.b ? 5 : -5);
00254 if(r < 0) { r = 0; dc.r ^= 1; } if(r > 255) { r = 255; dc.r ^= 1; }
00255 if(g < 0) { g = 0; dc.g ^= 1; } if(g > 255) { g = 255; dc.g ^= 1; }
00256 if(b < 0) { b = 0; dc.b ^= 1; } if(b > 255) { b = 255; dc.b ^= 1; }
00257 c.r = r;
00258 c.g = g;
00259 c.b = b;
00260 }
00261 }
00262
00263
00264 bool mesh_ctrl::on_mouse_button_down(double x, double y, unsigned flags)
00265 {
00266 if(flags & 1)
00267 {
00268 unsigned i;
00269 for(i = 0; i < m_vertices.size(); i++)
00270 {
00271 if(calc_distance(x, y, m_vertices[i].x, m_vertices[i].y) < 5)
00272 {
00273 m_drag_idx = i;
00274 m_drag_dx = x - m_vertices[i].x;
00275 m_drag_dy = y - m_vertices[i].y;
00276 return true;
00277 }
00278 }
00279 }
00280 return false;
00281 }
00282
00283 bool mesh_ctrl::on_mouse_move(double x, double y, unsigned flags)
00284 {
00285 if(flags & 1)
00286 {
00287 if(m_drag_idx >= 0)
00288 {
00289 m_vertices[m_drag_idx].x = x - m_drag_dx;
00290 m_vertices[m_drag_idx].y = y - m_drag_dy;
00291 return true;
00292 }
00293 }
00294 else
00295 {
00296 return on_mouse_button_up(x, y, flags);
00297 }
00298 return false;
00299 }
00300
00301 bool mesh_ctrl::on_mouse_button_up(double x, double y, unsigned flags)
00302 {
00303 bool ret = m_drag_idx >= 0;
00304 m_drag_idx = -1;
00305 return ret;
00306 }
00307
00308
00309
00310 class styles_gouraud
00311 {
00312 public:
00313 typedef span_gouraud_rgba<rgba8> gouraud_type;
00314
00315 template<class Gamma>
00316 styles_gouraud(const mesh_ctrl& mesh, const Gamma& gamma)
00317 {
00318 unsigned i;
00319 for(i = 0; i < mesh.num_triangles(); i++)
00320 {
00321 const agg::mesh_triangle& t = mesh.triangle(i);
00322 const agg::mesh_point& p1 = mesh.vertex(t.p1);
00323 const agg::mesh_point& p2 = mesh.vertex(t.p2);
00324 const agg::mesh_point& p3 = mesh.vertex(t.p3);
00325
00326 agg::rgba8 c1 = p1.color;
00327 agg::rgba8 c2 = p2.color;
00328 agg::rgba8 c3 = p3.color;
00329 c1.apply_gamma_dir(gamma);
00330 c2.apply_gamma_dir(gamma);
00331 c3.apply_gamma_dir(gamma);
00332 gouraud_type gouraud(c1, c2, c3,
00333 p1.x, p1.y,
00334 p2.x, p2.y,
00335 p3.x, p3.y);
00336 gouraud.prepare();
00337 m_triangles.add(gouraud);
00338 }
00339 }
00340
00341 bool is_solid(unsigned style) const { return false; }
00342
00343 rgba8 color(unsigned style) const { return rgba8(0,0,0,0); }
00344
00345 void generate_span(rgba8* span, int x, int y, unsigned len, unsigned style)
00346 {
00347 m_triangles[style].generate(span, x, y, len);
00348 }
00349
00350 private:
00351 pod_bvector<gouraud_type> m_triangles;
00352 };
00353 }
00354
00355
00356
00357
00358
00359 class the_application : public agg::platform_support
00360 {
00361
00362 public:
00363 typedef agg::renderer_base<pixfmt> renderer_base;
00364 typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
00365 typedef agg::rasterizer_scanline_aa<> rasterizer_scanline;
00366 typedef agg::scanline_u8 scanline;
00367
00368 agg::mesh_ctrl m_mesh;
00369 agg::gamma_lut<> m_gamma;
00370
00371
00372 the_application(agg::pix_format_e format, bool flip_y) :
00373 agg::platform_support(format, flip_y)
00374 {
00375
00376 }
00377
00378 virtual void on_init()
00379 {
00380 m_mesh.generate(20, 20, 17, 17, 40, 40);
00381 }
00382
00383
00384 virtual void on_draw()
00385 {
00386 pixfmt pf(rbuf_window());
00387 renderer_base ren_base(pf);
00388 ren_base.clear(agg::rgba(0, 0, 0));
00389 renderer_scanline ren(ren_base);
00390
00391 rasterizer_scanline ras;
00392 agg::scanline_u8 sl;
00393 agg::scanline_bin sl_bin;
00394
00395 agg::rasterizer_compound_aa<> rasc;
00396 agg::span_allocator<agg::rgba8> alloc;
00397
00398 unsigned i;
00399 agg::styles_gouraud styles(m_mesh, m_gamma);
00400 start_timer();
00401 rasc.reset();
00402
00403 for(i = 0; i < m_mesh.num_edges(); i++)
00404 {
00405 const agg::mesh_edge& e = m_mesh.edge(i);
00406 const agg::mesh_point& p1 = m_mesh.vertex(e.p1);
00407 const agg::mesh_point& p2 = m_mesh.vertex(e.p2);
00408 rasc.styles(e.tl, e.tr);
00409 rasc.move_to_d(p1.x, p1.y);
00410 rasc.line_to_d(p2.x, p2.y);
00411 }
00412 agg::render_scanlines_compound(rasc, sl, sl_bin, ren_base, alloc, styles);
00413 double tm = elapsed_time();
00414
00415 char buf[256];
00416 agg::gsv_text t;
00417 t.size(10.0);
00418
00419 agg::conv_stroke<agg::gsv_text> pt(t);
00420 pt.width(1.5);
00421 pt.line_cap(agg::round_cap);
00422 pt.line_join(agg::round_join);
00423
00424 sprintf(buf, "%3.2f ms, %d triangles, %.0f tri/sec",
00425 tm,
00426 m_mesh.num_triangles(),
00427 m_mesh.num_triangles() / tm * 1000.0);
00428 t.start_point(10.0, 10.0);
00429 t.text(buf);
00430
00431 ras.add_path(pt);
00432 agg::render_scanlines_aa_solid(ras, sl, ren_base, agg::rgba(1,1,1));
00433
00434
00435 if(m_gamma.gamma() != 1.0)
00436 {
00437 pf.apply_gamma_inv(m_gamma);
00438 }
00439 }
00440
00441 virtual void on_mouse_move(int x, int y, unsigned flags)
00442 {
00443 if(m_mesh.on_mouse_move(x, y, flags))
00444 {
00445 force_redraw();
00446 }
00447 }
00448
00449 virtual void on_mouse_button_down(int x, int y, unsigned flags)
00450 {
00451 if(m_mesh.on_mouse_button_down(x, y, flags))
00452 {
00453 force_redraw();
00454 }
00455 }
00456
00457 virtual void on_mouse_button_up(int x, int y, unsigned flags)
00458 {
00459 if(m_mesh.on_mouse_button_up(x, y, flags))
00460 {
00461 force_redraw();
00462 }
00463 }
00464
00465 virtual void on_key(int x, int y, unsigned key, unsigned flags)
00466 {
00467 }
00468
00469 void on_idle()
00470 {
00471 m_mesh.randomize_points(1.0);
00472 m_mesh.rotate_colors();
00473 force_redraw();
00474 }
00475
00476 virtual void on_ctrl_change()
00477 {
00478 }
00479 };
00480
00481
00482 int agg_main(int argc, char* argv[])
00483 {
00484 the_application app(agg::pix_format_bgra32, flip_y);
00485 app.caption("AGG Example");
00486
00487 if(app.init(400, 400, 0))
00488 {
00489 app.wait_mode(false);
00490 return app.run();
00491 }
00492 return 1;
00493 }
00494
00495
00496
00497
00498