// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_sg_vertices #define tools_sg_vertices #include "node" #include "gstos" #include "sf" #include "mf" #include "render_action" #include "pick_action" #include "bbox_action" #include "visible_action" #include "../vmanip" namespace tools { namespace sg { class vertices : public node, public gstos { TOOLS_NODE(vertices,tools::sg::vertices,node) typedef gstos parent_gstos; public: sf mode; mf xyzs; public: virtual const desc_fields& node_desc_fields() const { TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::vertices) static const desc_fields s_v(parent::node_desc_fields(),2, //WARNING : take care of count. TOOLS_ARG_FIELD_DESC(mode), TOOLS_ARG_FIELD_DESC(xyzs) ); return s_v; } private: void add_fields(){ add_field(&mode); add_field(&xyzs); } protected: //gstos virtual unsigned int create_gsto(std::ostream&,sg::render_manager& a_mgr) { return a_mgr.create_gsto_from_data(xyzs.values()); } public: virtual void render(render_action& a_action) { if(touched()) {clean_gstos();reset_touched();} if(xyzs.empty()) return; const state& state = a_action.state(); if(state.m_use_gsto) { unsigned int _id = get_gsto_id(a_action.out(),a_action.render_manager()); if(_id) { a_action.begin_gsto(_id); size_t npt = xyzs.values().size()/3; bufpos pos = 0; if(gl::is_line(mode.value())) { //Same logic as Inventor SoLightModel.model = BASE_COLOR. a_action.set_lighting(false); a_action.draw_gsto_v(mode.value(),npt,pos); a_action.set_lighting(state.m_GL_LIGHTING); } else { a_action.draw_gsto_v(mode.value(),npt,pos); } a_action.end_gsto(); return; } else { //!_id // use immediate rendering. } } else { clean_gstos(&a_action.render_manager()); } // immediate rendering : if(gl::is_line(mode.value())) { //Same logic as Inventor SoLightModel.model = BASE_COLOR. a_action.set_lighting(false); a_action.draw_vertex_array(mode.value(),xyzs.values()); a_action.set_lighting(state.m_GL_LIGHTING); } else { a_action.draw_vertex_array(mode.value(),xyzs.values()); } } virtual void pick(pick_action& a_action) { if(touched()) {clean_gstos();reset_touched();} a_action.add__primitive(*this,mode.value(),xyzs.values(),true); } virtual void bbox(bbox_action& a_action) { if(touched()) {clean_gstos();reset_touched();} a_action.add_points(xyzs.values()); } virtual void is_visible(visible_action& a_action) { if(touched()) {clean_gstos();reset_touched();} if(_is_visible(a_action)) a_action.increment(); } public: vertices() :parent() ,mode(gl::line_strip()){ add_fields(); } virtual ~vertices(){ } public: vertices(const vertices& a_from) :parent(a_from) ,parent_gstos(a_from) ,mode(a_from.mode) ,xyzs(a_from.xyzs) { add_fields(); } vertices& operator=(const vertices& a_from){ parent::operator=(a_from); parent_gstos::operator=(a_from); mode = a_from.mode; xyzs = a_from.xyzs; return *this; } public: template void add(const VEC& a_v) { xyzs.add(a_v.x()); xyzs.add(a_v.y()); xyzs.add(a_v.z()); } void add(float a_x,float a_y,float a_z) { xyzs.add(a_x); xyzs.add(a_y); xyzs.add(a_z); } void add_allocated(size_t& a_pos,float a_x,float a_y,float a_z) { std::vector& v = xyzs.values(); v[a_pos] = a_x;a_pos++; v[a_pos] = a_y;a_pos++; v[a_pos] = a_z;a_pos++; xyzs.touch(); } bool add(const std::vector& a_v) { std::vector::size_type _number = a_v.size()/3; if(3*_number!=a_v.size()) return false; std::vector::const_iterator it; for(it=a_v.begin();it!=a_v.end();it+=3) { xyzs.add(*(it+0)); xyzs.add(*(it+1)); xyzs.add(*(it+2)); } return true; } size_t number() const {return xyzs.size()/3;} void clear() {xyzs.clear();} bool add_dashed_line(float a_bx,float a_by,float a_bz, float a_ex,float a_ey,float a_ez, unsigned int a_num_dash) { //optimized version. if(!a_num_dash) return false; // there is a dash at beg and end of line. float fac = 1.0f/float(2*a_num_dash-1); float sx = (a_ex-a_bx)*fac; float sy = (a_ey-a_by)*fac; float sz = (a_ez-a_bz)*fac; float two_sx = sx*2.0f; float two_sy = sy*2.0f; float two_sz = sz*2.0f; float px = a_bx; float py = a_by; float pz = a_bz; for(unsigned int idash=0;idash& v = xyzs.values(); std::vector::size_type _number = v.size()/3; if(!_number) return true; if(3*_number!=v.size()) return false; float x_mean = 0; float y_mean = 0; float z_mean = 0; {for(std::vector::const_iterator it=v.begin();it!=v.end();it+=3) { x_mean += *(it+0); y_mean += *(it+1); z_mean += *(it+2); }} x_mean /= float(_number); y_mean /= float(_number); z_mean /= float(_number); {for(std::vector::iterator it=v.begin();it!=v.end();it+=3) { *(it+0) -= x_mean; *(it+1) -= y_mean; *(it+2) -= z_mean; }} return true; } protected: bool _is_visible(const matrix_action& a_action) { if(xyzs.empty()) return false; const state& _state = a_action.state(); pick_action action(a_action.out(),_state.m_ww,_state.m_wh,0,float(_state.m_ww),0,float(_state.m_wh)); action.set_win_size(_state.m_ww,_state.m_wh); action.set_area(0,float(_state.m_ww),0,float(_state.m_wh)); action.set_stop_at_first(true); action.matrix_action::operator=(a_action); //IMPORTANT. int old_cur = action.cur(); //not 0. action.add__primitive(*this,mode.value(),xyzs.values(),true); if(action.cur()!=old_cur) return false; if(!action.node()) return false; return true; } }; }} #endif