mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-12-02 12:08:16 +08:00
499 lines
14 KiB
C++
499 lines
14 KiB
C++
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include "agg_rendering_buffer.h"
|
|
#include "agg_conv_transform.h"
|
|
#include "agg_conv_stroke.h"
|
|
#include "agg_conv_clip_polyline.h"
|
|
#include "agg_scanline_u.h"
|
|
#include "agg_scanline_bin.h"
|
|
#include "agg_renderer_scanline.h"
|
|
#include "agg_rasterizer_outline_aa.h"
|
|
#include "agg_rasterizer_scanline_aa.h"
|
|
#include "agg_span_allocator.h"
|
|
#include "agg_span_gouraud_rgba.h"
|
|
#include "agg_gamma_lut.h"
|
|
#include "agg_arc.h"
|
|
#include "agg_bezier_arc.h"
|
|
#include "agg_pixfmt_rgb.h"
|
|
#include "agg_pixfmt_rgba.h"
|
|
#include "agg_bounding_rect.h"
|
|
#include "agg_vpgen_clip_polygon.h"
|
|
#include "ctrl/agg_slider_ctrl.h"
|
|
#include "ctrl/agg_bezier_ctrl.h"
|
|
#include "ctrl/agg_rbox_ctrl.h"
|
|
#include "ctrl/agg_cbox_ctrl.h"
|
|
#include "platform/agg_platform_support.h"
|
|
|
|
#include "agg_rasterizer_compound_aa.h"
|
|
|
|
|
|
enum { flip_y = true };
|
|
|
|
typedef agg::pixfmt_bgra32_pre pixfmt;
|
|
|
|
|
|
namespace agg
|
|
{
|
|
|
|
struct mesh_point
|
|
{
|
|
float_t x,y;
|
|
float_t dx,dy;
|
|
rgba8 color;
|
|
rgba8 dc;
|
|
|
|
mesh_point() {}
|
|
mesh_point(float_t x_, float_t y_,
|
|
float_t dx_, float_t dy_,
|
|
rgba8 c, rgba8 dc_) :
|
|
x(x_), y(y_),
|
|
dx(dx_), dy(dy_),
|
|
color(c), dc(dc_)
|
|
{}
|
|
};
|
|
|
|
struct mesh_triangle
|
|
{
|
|
unsigned p1, p2, p3;
|
|
|
|
mesh_triangle() {}
|
|
mesh_triangle(unsigned i, unsigned j, unsigned k) :
|
|
p1(i), p2(j), p3(k)
|
|
{}
|
|
};
|
|
|
|
struct mesh_edge
|
|
{
|
|
unsigned p1, p2;
|
|
int tl, tr;
|
|
|
|
mesh_edge() {}
|
|
mesh_edge(unsigned p1_, unsigned p2_, int tl_, int tr_) :
|
|
p1(p1_), p2(p2_), tl(tl_), tr(tr_)
|
|
{}
|
|
};
|
|
|
|
|
|
static float_t random(float_t v1, float_t v2)
|
|
{
|
|
return (v2 - v1) * (rand() % 1000) / 999.0 + v1;
|
|
}
|
|
|
|
|
|
class mesh_ctrl
|
|
{
|
|
public:
|
|
mesh_ctrl();
|
|
|
|
void generate(unsigned cols, unsigned rows,
|
|
float_t cell_w, float_t cell_h,
|
|
float_t start_x, float_t start_y);
|
|
|
|
void randomize_points(float_t delta);
|
|
void rotate_colors();
|
|
|
|
|
|
bool on_mouse_button_down(float_t x, float_t y, unsigned flags);
|
|
bool on_mouse_move(float_t x, float_t y, unsigned flags);
|
|
bool on_mouse_button_up(float_t x, float_t y, unsigned flags);
|
|
|
|
unsigned num_vertices() const { return m_vertices.size(); }
|
|
const mesh_point& vertex(unsigned i) const { return m_vertices[i]; }
|
|
mesh_point& vertex(unsigned i) { return m_vertices[i]; }
|
|
|
|
const mesh_point& vertex(unsigned x, unsigned y) const { return m_vertices[y * m_rows + x]; }
|
|
mesh_point& vertex(unsigned x, unsigned y) { return m_vertices[y * m_rows + x]; }
|
|
|
|
unsigned num_triangles() const { return m_triangles.size(); }
|
|
const mesh_triangle& triangle(unsigned i) const { return m_triangles[i]; }
|
|
mesh_triangle& triangle(unsigned i) { return m_triangles[i]; }
|
|
|
|
unsigned num_edges() const { return m_edges.size(); }
|
|
const mesh_edge& edge(unsigned i) const { return m_edges[i]; }
|
|
mesh_edge& edge(unsigned i) { return m_edges[i]; }
|
|
|
|
private:
|
|
unsigned m_cols;
|
|
unsigned m_rows;
|
|
int m_drag_idx;
|
|
float_t m_drag_dx;
|
|
float_t m_drag_dy;
|
|
float_t m_cell_w;
|
|
float_t m_cell_h;
|
|
float_t m_start_x;
|
|
float_t m_start_y;
|
|
pod_bvector<mesh_point> m_vertices;
|
|
pod_bvector<mesh_triangle> m_triangles;
|
|
pod_bvector<mesh_edge> m_edges;
|
|
};
|
|
|
|
|
|
mesh_ctrl::mesh_ctrl() :
|
|
m_cols(0),
|
|
m_rows(0),
|
|
m_drag_idx(-1),
|
|
m_drag_dx(0),
|
|
m_drag_dy(0)
|
|
{}
|
|
|
|
|
|
void mesh_ctrl::generate(unsigned cols, unsigned rows,
|
|
float_t cell_w, float_t cell_h,
|
|
float_t start_x, float_t start_y)
|
|
{
|
|
m_cols = cols;
|
|
m_rows = rows;
|
|
m_cell_w = cell_w;
|
|
m_cell_h = cell_h;
|
|
m_start_x = start_x;
|
|
m_start_y = start_y;
|
|
|
|
m_vertices.remove_all();
|
|
unsigned i, j;
|
|
for(i = 0; i < m_rows; i++)
|
|
{
|
|
float_t x = start_x;
|
|
for(j = 0; j < m_cols; j++)
|
|
{
|
|
float_t dx = random(-0.5, 0.5);
|
|
float_t dy = random(-0.5, 0.5);
|
|
rgba8 c(rand() & 0xFF, rand() & 0xFF, rand() & 0xFF);
|
|
rgba8 dc(rand() & 1, rand() & 1, rand() & 1);
|
|
m_vertices.add(mesh_point(x, start_y, dx, dy, c, dc));
|
|
x += cell_w;
|
|
}
|
|
start_y += cell_h;
|
|
}
|
|
|
|
|
|
|
|
// 4---3
|
|
// |t2/|
|
|
// | / |
|
|
// |/t1|
|
|
// 1---2
|
|
m_triangles.remove_all();
|
|
m_edges.remove_all();
|
|
for(i = 0; i < m_rows - 1; i++)
|
|
{
|
|
for(j = 0; j < m_cols - 1; j++)
|
|
{
|
|
int p1 = i * m_cols + j;
|
|
int p2 = p1 + 1;
|
|
int p3 = p2 + m_cols;
|
|
int p4 = p1 + m_cols;
|
|
m_triangles.add(mesh_triangle(p1, p2, p3));
|
|
m_triangles.add(mesh_triangle(p3, p4, p1));
|
|
|
|
int curr_cell = i * (m_cols - 1) + j;
|
|
int left_cell = j ? int(curr_cell - 1) : -1;
|
|
int bott_cell = i ? int(curr_cell - (m_cols - 1)) : -1;
|
|
|
|
int curr_t1 = curr_cell * 2;
|
|
int curr_t2 = curr_t1 + 1;
|
|
|
|
int left_t1 = (left_cell >= 0) ? left_cell * 2 : -1;
|
|
int left_t2 = (left_cell >= 0) ? left_t1 + 1 : -1;
|
|
|
|
int bott_t1 = (bott_cell >= 0) ? bott_cell * 2 : -1;
|
|
int bott_t2 = (bott_cell >= 0) ? bott_t1 + 1 : -1;
|
|
|
|
m_edges.add(mesh_edge(p1, p2, curr_t1, bott_t2));
|
|
m_edges.add(mesh_edge(p1, p3, curr_t2, curr_t1));
|
|
m_edges.add(mesh_edge(p1, p4, left_t1, curr_t2));
|
|
|
|
if(j == m_cols - 2) // Last column
|
|
{
|
|
m_edges.add(mesh_edge(p2, p3, curr_t1, -1));
|
|
}
|
|
|
|
if(i == m_rows - 2) // Last row
|
|
{
|
|
m_edges.add(mesh_edge(p3, p4, curr_t2, -1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void mesh_ctrl::randomize_points(float_t delta)
|
|
{
|
|
unsigned i, j;
|
|
for(i = 0; i < m_rows; i++)
|
|
{
|
|
for(j = 0; j < m_cols; j++)
|
|
{
|
|
float_t xc = j * m_cell_w + m_start_x;
|
|
float_t yc = i * m_cell_h + m_start_y;
|
|
float_t x1 = xc - m_cell_w / 4;
|
|
float_t y1 = yc - m_cell_h / 4;
|
|
float_t x2 = xc + m_cell_w / 4;
|
|
float_t y2 = yc + m_cell_h / 4;
|
|
mesh_point& p = vertex(j, i);
|
|
p.x += p.dx;
|
|
p.y += p.dy;
|
|
if(p.x < x1) { p.x = x1; p.dx = -p.dx; }
|
|
if(p.y < y1) { p.y = y1; p.dy = -p.dy; }
|
|
if(p.x > x2) { p.x = x2; p.dx = -p.dx; }
|
|
if(p.y > y2) { p.y = y2; p.dy = -p.dy; }
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void mesh_ctrl::rotate_colors()
|
|
{
|
|
unsigned i;
|
|
for(i = 1; i < m_vertices.size(); i++)
|
|
{
|
|
rgba8& c = m_vertices[i].color;
|
|
rgba8& dc = m_vertices[i].dc;
|
|
int r = c.r + (dc.r ? 5 : -5);
|
|
int g = c.g + (dc.g ? 5 : -5);
|
|
int b = c.b + (dc.b ? 5 : -5);
|
|
if(r < 0) { r = 0; dc.r ^= 1; } if(r > 255) { r = 255; dc.r ^= 1; }
|
|
if(g < 0) { g = 0; dc.g ^= 1; } if(g > 255) { g = 255; dc.g ^= 1; }
|
|
if(b < 0) { b = 0; dc.b ^= 1; } if(b > 255) { b = 255; dc.b ^= 1; }
|
|
c.r = r;
|
|
c.g = g;
|
|
c.b = b;
|
|
}
|
|
}
|
|
|
|
|
|
bool mesh_ctrl::on_mouse_button_down(float_t x, float_t y, unsigned flags)
|
|
{
|
|
if(flags & 1)
|
|
{
|
|
unsigned i;
|
|
for(i = 0; i < m_vertices.size(); i++)
|
|
{
|
|
if(calc_distance(x, y, m_vertices[i].x, m_vertices[i].y) < 5)
|
|
{
|
|
m_drag_idx = i;
|
|
m_drag_dx = x - m_vertices[i].x;
|
|
m_drag_dy = y - m_vertices[i].y;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool mesh_ctrl::on_mouse_move(float_t x, float_t y, unsigned flags)
|
|
{
|
|
if(flags & 1)
|
|
{
|
|
if(m_drag_idx >= 0)
|
|
{
|
|
m_vertices[m_drag_idx].x = x - m_drag_dx;
|
|
m_vertices[m_drag_idx].y = y - m_drag_dy;
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return on_mouse_button_up(x, y, flags);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool mesh_ctrl::on_mouse_button_up(float_t x, float_t y, unsigned flags)
|
|
{
|
|
bool ret = m_drag_idx >= 0;
|
|
m_drag_idx = -1;
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
class styles_gouraud
|
|
{
|
|
public:
|
|
typedef span_gouraud_rgba<rgba8> gouraud_type;
|
|
|
|
template<class Gamma>
|
|
styles_gouraud(const mesh_ctrl& mesh, const Gamma& gamma)
|
|
{
|
|
unsigned i;
|
|
for(i = 0; i < mesh.num_triangles(); i++)
|
|
{
|
|
const agg::mesh_triangle& t = mesh.triangle(i);
|
|
const agg::mesh_point& p1 = mesh.vertex(t.p1);
|
|
const agg::mesh_point& p2 = mesh.vertex(t.p2);
|
|
const agg::mesh_point& p3 = mesh.vertex(t.p3);
|
|
|
|
agg::rgba8 c1 = p1.color;
|
|
agg::rgba8 c2 = p2.color;
|
|
agg::rgba8 c3 = p3.color;
|
|
c1.apply_gamma_dir(gamma);
|
|
c2.apply_gamma_dir(gamma);
|
|
c3.apply_gamma_dir(gamma);
|
|
gouraud_type gouraud(c1, c2, c3,
|
|
p1.x, p1.y,
|
|
p2.x, p2.y,
|
|
p3.x, p3.y);
|
|
gouraud.prepare();
|
|
m_triangles.add(gouraud);
|
|
}
|
|
}
|
|
|
|
bool is_solid(unsigned style) const { return false; }
|
|
|
|
rgba8 color(unsigned style) const { return rgba8(0,0,0,0); }
|
|
|
|
void generate_span(rgba8* span, int x, int y, unsigned len, unsigned style)
|
|
{
|
|
m_triangles[style].generate(span, x, y, len);
|
|
}
|
|
|
|
private:
|
|
pod_bvector<gouraud_type> m_triangles;
|
|
};
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class the_application : public agg::platform_support
|
|
{
|
|
|
|
public:
|
|
typedef agg::renderer_base<pixfmt> renderer_base;
|
|
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
|
|
typedef agg::rasterizer_scanline_aa<> rasterizer_scanline;
|
|
typedef agg::scanline_u8 scanline;
|
|
|
|
agg::mesh_ctrl m_mesh;
|
|
agg::gamma_lut<> m_gamma;
|
|
|
|
|
|
the_application(agg::pix_format_e format, bool flip_y) :
|
|
agg::platform_support(format, flip_y)
|
|
{
|
|
// m_gamma.gamma(2.0);
|
|
}
|
|
|
|
virtual void on_init()
|
|
{
|
|
m_mesh.generate(20, 20, 17, 17, 40, 40);
|
|
}
|
|
|
|
|
|
virtual void on_draw()
|
|
{
|
|
pixfmt pf(rbuf_window());
|
|
renderer_base ren_base(pf);
|
|
ren_base.clear(agg::rgba(0, 0, 0));
|
|
renderer_scanline ren(ren_base);
|
|
|
|
rasterizer_scanline ras;
|
|
agg::scanline_u8 sl;
|
|
agg::scanline_bin sl_bin;
|
|
|
|
agg::rasterizer_compound_aa<> rasc;
|
|
agg::span_allocator<agg::rgba8> alloc;
|
|
|
|
unsigned i;
|
|
agg::styles_gouraud styles(m_mesh, m_gamma);
|
|
start_timer();
|
|
rasc.reset();
|
|
//rasc.clip_box(40, 40, width() - 40, height() - 40);
|
|
for(i = 0; i < m_mesh.num_edges(); i++)
|
|
{
|
|
const agg::mesh_edge& e = m_mesh.edge(i);
|
|
const agg::mesh_point& p1 = m_mesh.vertex(e.p1);
|
|
const agg::mesh_point& p2 = m_mesh.vertex(e.p2);
|
|
rasc.styles(e.tl, e.tr);
|
|
rasc.move_to_d(p1.x, p1.y);
|
|
rasc.line_to_d(p2.x, p2.y);
|
|
}
|
|
agg::render_scanlines_compound(rasc, sl, sl_bin, ren_base, alloc, styles);
|
|
float_t tm = elapsed_time();
|
|
|
|
char buf[256];
|
|
agg::gsv_text t;
|
|
t.size(10.0);
|
|
|
|
agg::conv_stroke<agg::gsv_text> pt(t);
|
|
pt.width(1.5);
|
|
pt.line_cap(agg::round_cap);
|
|
pt.line_join(agg::round_join);
|
|
|
|
sprintf(buf, "%3.2f ms, %d triangles, %.0f tri/sec",
|
|
tm,
|
|
m_mesh.num_triangles(),
|
|
m_mesh.num_triangles() / tm * 1000.0);
|
|
t.start_point(10.0, 10.0);
|
|
t.text(buf);
|
|
|
|
ras.add_path(pt);
|
|
agg::render_scanlines_aa_solid(ras, sl, ren_base, agg::rgba(1,1,1));
|
|
|
|
|
|
if(m_gamma.gamma() != 1.0)
|
|
{
|
|
pf.apply_gamma_inv(m_gamma);
|
|
}
|
|
}
|
|
|
|
virtual void on_mouse_move(int x, int y, unsigned flags)
|
|
{
|
|
if(m_mesh.on_mouse_move(x, y, flags))
|
|
{
|
|
force_redraw();
|
|
}
|
|
}
|
|
|
|
virtual void on_mouse_button_down(int x, int y, unsigned flags)
|
|
{
|
|
if(m_mesh.on_mouse_button_down(x, y, flags))
|
|
{
|
|
force_redraw();
|
|
}
|
|
}
|
|
|
|
virtual void on_mouse_button_up(int x, int y, unsigned flags)
|
|
{
|
|
if(m_mesh.on_mouse_button_up(x, y, flags))
|
|
{
|
|
force_redraw();
|
|
}
|
|
}
|
|
|
|
virtual void on_key(int x, int y, unsigned key, unsigned flags)
|
|
{
|
|
}
|
|
|
|
void on_idle()
|
|
{
|
|
m_mesh.randomize_points(1.0);
|
|
m_mesh.rotate_colors();
|
|
force_redraw();
|
|
}
|
|
|
|
virtual void on_ctrl_change()
|
|
{
|
|
}
|
|
};
|
|
|
|
|
|
int agg_main(int argc, char* argv[])
|
|
{
|
|
the_application app(agg::pix_format_bgra32, flip_y);
|
|
app.caption("AGG Example");
|
|
|
|
if(app.init(400, 400, 0))//agg::window_resize))
|
|
{
|
|
app.wait_mode(false);
|
|
return app.run();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|