Files
2025-12-05 08:54:02 +01:00

236 lines
6.1 KiB
Plaintext

// 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<gl::mode_t> mode;
mf<float> 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 <class VEC>
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<float>& 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<float>& a_v) {
std::vector<float>::size_type _number = a_v.size()/3;
if(3*_number!=a_v.size()) return false;
std::vector<float>::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<a_num_dash;idash++) {
add(px,py,pz);
add(px+sx,py+sy,pz+sz);
px += two_sx;
py += two_sy;
pz += two_sz;
}
return true;
}
bool center() {
std::vector<float>& v = xyzs.values();
std::vector<float>::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<float>::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<float>::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