// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_sg_render_action #define tools_sg_render_action #include "matrix_action" #include "../glprims" #include "../colorf" namespace tools { namespace sg { class render_manager; }} namespace tools { namespace sg { typedef size_t bufpos; class render_action : public matrix_action { TOOLS_ACTION_NO_COPY(render_action,tools::sg::render_action,matrix_action) public: typedef unsigned int gstoid; public: virtual void load_proj_matrix(const mat4f&) = 0; virtual void load_model_matrix(const mat4f&) = 0; public: virtual void draw_vertex_array(gl::mode_t,size_t,const float*) = 0; virtual void draw_vertex_array_xy(gl::mode_t,size_t,const float*) = 0; virtual void draw_vertex_color_array(gl::mode_t,size_t,const float*,const float*) = 0; virtual void draw_vertex_normal_array(gl::mode_t,size_t,const float*,const float*) = 0; virtual void draw_vertex_color_normal_array(gl::mode_t,size_t,const float*,const float*,const float*) = 0; ///////////////////////////////////////////////////////////////// /// texture ///////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// virtual void draw_vertex_array_texture(gl::mode_t,size_t,const float*,gstoid,const float*) = 0; virtual void draw_vertex_normal_array_texture(gl::mode_t,size_t,const float*,const float*,gstoid,const float*) = 0; ///////////////////////////////////////////////////////////////// /// VBO ///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// virtual void begin_gsto(gstoid) = 0; virtual void draw_gsto_v(gl::mode_t,size_t,bufpos) = 0; virtual void draw_gsto_vc(gl::mode_t,size_t,bufpos,bufpos) = 0; virtual void draw_gsto_vn(gl::mode_t,size_t,bufpos,bufpos) = 0; virtual void draw_gsto_vcn(gl::mode_t,size_t,bufpos,bufpos,bufpos) = 0; virtual void end_gsto() = 0; ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// virtual void clear_color(float,float,float,float) = 0; virtual void color4f(float,float,float,float) = 0; virtual void line_width(float) = 0; virtual void point_size(float) = 0; virtual void set_polygon_offset(bool) = 0; virtual void set_winding(winding_type) = 0; virtual void set_shade_model(shade_type) = 0; virtual void set_cull_face(bool) = 0; virtual void set_point_smooth(bool) = 0; virtual void set_line_smooth(bool) = 0; virtual void normal(float,float,float) = 0; virtual void set_depth_test(bool) = 0; virtual unsigned int max_lights() = 0; virtual void enable_light(unsigned int, float,float,float, //directrion float,float,float,float, //diffuse RGBA float,float,float,float) = 0; //ambient RGBA virtual void set_lighting(bool) = 0; virtual void set_blend(bool) = 0; virtual void restore_state(unsigned int) = 0; virtual sg::render_manager& render_manager() = 0; //sg:: is needed. public: render_action(std::ostream& a_out,unsigned int a_ww,unsigned int a_wh) :parent(a_out,a_ww,a_wh) ,m_do_transparency(false) ,m_have_to_do_transparency(false) {} virtual ~render_action(){} public: render_action(const render_action& a_from) :parent(a_from) ,m_do_transparency(a_from.m_do_transparency) ,m_have_to_do_transparency(a_from.m_have_to_do_transparency) {} render_action& operator=(const render_action& a_from){ parent::operator=(a_from); m_do_transparency = a_from.m_do_transparency; m_have_to_do_transparency = a_from.m_have_to_do_transparency; return *this; } public: void set_do_transparency(bool a_value) {m_do_transparency = a_value;} bool do_transparency() const {return m_do_transparency;} void set_have_to_do_transparency(bool a_value) {m_have_to_do_transparency = a_value;} bool have_to_do_transparency() const {return m_have_to_do_transparency;} bool have_to_render() { bool transparent = state().m_color.a()!=1.0f?true:false; if(transparent && state().m_GL_BLEND) { if(m_do_transparency) return true; m_have_to_do_transparency = true; return false; } if(m_do_transparency) return false; return true; } void load_matrices_to_identity() { load_proj_matrix(m_identity); load_model_matrix(m_identity); } void load_matrices_from_state() { const sg::state& _state = state(); load_proj_matrix(_state.m_proj); load_model_matrix(_state.m_model); } void clear_color(const colorf& a_color){ clear_color(a_color[0],a_color[1],a_color[2],a_color[3]); } void color4f(const colorf& a_color){ color4f(a_color[0],a_color[1],a_color[2],a_color[3]); } void enable_light(unsigned int a_light, const vec3f& a_dir, const colorf& a_col,const colorf& a_ambient) { enable_light(a_light, a_dir[0],a_dir[1],a_dir[2], a_col[0],a_col[1],a_col[2],a_col[3], a_ambient[0],a_ambient[1],a_ambient[2],a_ambient[3]); } void draw_vertex_array(gl::mode_t a_mode,const std::vector& a_xyzs){ const float* _xyzs = a_xyzs.data(); draw_vertex_array(a_mode,a_xyzs.size(),_xyzs); } void draw_vertex_array_xy(gl::mode_t a_mode,const std::vector& a_xys){ const float* _xys = a_xys.data(); draw_vertex_array_xy(a_mode,a_xys.size(),_xys); } void draw_vertex_color_array(gl::mode_t a_mode, const std::vector& a_xyzs, const std::vector& a_rgbas){ const float* _xyzs = a_xyzs.data(); const float* _rgbas = a_rgbas.data(); draw_vertex_color_array(a_mode,a_xyzs.size(),_xyzs,_rgbas); } void draw_vertex_normal_array(gl::mode_t a_mode, const std::vector& a_xyzs, const std::vector& a_nms){ const float* _xyzs = a_xyzs.data(); const float* _nms = a_nms.data(); draw_vertex_normal_array(a_mode,a_xyzs.size(),_xyzs,_nms); } void draw_vertex_color_normal_array(gl::mode_t a_mode, const std::vector& a_xyzs, const std::vector& a_rgbas, const std::vector& a_nms){ const float* _xyzs = a_xyzs.data(); const float* _rgbas = a_rgbas.data(); const float* _nms = a_nms.data(); draw_vertex_color_normal_array(a_mode,a_xyzs.size(),_xyzs,_rgbas,_nms); } void normal(const vec3f& a_vec) {normal(a_vec[0],a_vec[1],a_vec[2]);} public: // for sphere::visit template. bool add_triangles_normal(size_t a_floatn,const float* a_xyzs,const float* a_nms) { draw_vertex_normal_array(gl::triangles(),a_floatn,a_xyzs,a_nms); return true; } bool add_triangle_fan_normal(size_t a_floatn,const float* a_xyzs,const float* a_nms) { draw_vertex_normal_array(gl::triangle_fan(),a_floatn,a_xyzs,a_nms); return true; } bool add_triangle_fan_normal_rgba(size_t a_floatn,const float* a_xyzs,float* a_nms,const float* a_rgbas) { draw_vertex_color_normal_array(gl::triangle_fan(),a_floatn,a_xyzs,a_rgbas,a_nms); return true; } bool add_triangle_strip_normal(size_t a_floatn,const float* a_xyzs,const float* a_nms) { draw_vertex_normal_array(gl::triangle_strip(),a_floatn,a_xyzs,a_nms); return true; } bool add_triangle_strip_normal_rgba(size_t a_floatn,const float* a_xyzs,const float* a_nms,const float* a_rgbas) { draw_vertex_color_normal_array(gl::triangle_strip(),a_floatn,a_xyzs,a_rgbas,a_nms); return true; } bool add_lines(size_t a_floatn,const float* a_xyzs) { draw_vertex_array(gl::lines(),a_floatn,a_xyzs); return true; } bool add_line_loop(size_t a_floatn,const float* a_xyzs) { draw_vertex_array(gl::line_loop(),a_floatn,a_xyzs); return true; } bool add_line_strip(size_t a_floatn,const float* a_xyzs) { draw_vertex_array(gl::line_strip(),a_floatn,a_xyzs); return true; } bool add_points(size_t a_floatn,const float* a_xyzs) { draw_vertex_array(gl::points(),a_floatn,a_xyzs); return true; } bool add_triangle_fan_texture_normal(size_t a_floatn,const float* a_xyzs,const float* a_nms,gstoid a_tex,const float* a_texs){ draw_vertex_normal_array_texture(gl::triangle_fan(),a_floatn,a_xyzs,a_nms,a_tex,a_texs); return true; } bool add_triangle_strip_texture_normal(size_t a_floatn,const float* a_xyzs,const float* a_nms,gstoid a_tex,const float* a_texs){ draw_vertex_normal_array_texture(gl::triangle_strip(),a_floatn,a_xyzs,a_nms,a_tex,a_texs); return true; } bool add_line_loop(const std::vector& a_xyzs){ const float* _xyzs = a_xyzs.data(); draw_vertex_array(gl::line_loop(),a_xyzs.size(),_xyzs); return true; } bool add_line_strip(const std::vector& a_xyzs){ const float* _xyzs = a_xyzs.data(); draw_vertex_array(gl::line_strip(),a_xyzs.size(),_xyzs); return true; } bool add_triangle_strip_as_triangles(size_t a_floatn,const float* a_xyzs,const float* a_nms) { //used in sg::sphere, icosahedron_sphere. // It appears that if glShadeModel is GL_FLAT, triangle strip does not look the same in "gsto mode" where it is rendered as triangles. // We use this function for immediate rendering, in case we want the same rendering as "gsto mode". size_t num = a_floatn/3; if(num<3) return false; size_t nxyzs = (num-2)*3*3; std::vector m_xyzs(nxyzs); std::vector m_nms(nxyzs); {float* pxyzs = m_xyzs.data(); float* pnms = m_nms.data(); gl::triangle_strip_to_triangles_nms(num,a_xyzs,a_nms,pxyzs,pnms);} return add_triangles_normal(nxyzs,m_xyzs.data(),m_nms.data()); } void dump_vertex_array_xy(std::ostream& a_out,gl::mode_t /*a_mode*/,size_t a_floatn,const float* a_xys) { size_t num = a_floatn/2; if(!num) return; a_out << "dump_vertex_array_xy : begin : " << num << std::endl; for(size_t index=0;index