Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

gouraud_mesh.cpp

Go to the documentation of this file.
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         //  4---3
00172         //  |t2/|
00173         //  | / |
00174         //  |/t1|
00175         //  1---2
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) // Last column
00207                 {
00208                     m_edges.add(mesh_edge(p2, p3, curr_t1, -1));
00209                 }
00210 
00211                 if(i == m_rows - 2) // Last row
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 //        m_gamma.gamma(2.0);
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         //rasc.clip_box(40, 40, width() - 40, height() - 40);
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))//agg::window_resize))
00488     {
00489         app.wait_mode(false);
00490         return app.run();
00491     }
00492     return 1;
00493 }
00494 
00495 
00496 
00497 
00498 

© sourcejam.com 2005-2008