Files
geant4/source/analysis/g4tools/include/tools/sg/tex_rect
T
2019-12-06 15:12:28 +01:00

361 lines
8.4 KiB
Plaintext

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef tools_sg_tex_rect
#define tools_sg_tex_rect
// node to render an RGB tools::img_byte with ::glTexImage2D.
//#define TOOLS_SG_TEX_RECT_DEBUG
#include "node"
#include "render_action"
#include "pick_action"
#include "bbox_action"
#include "event_action"
#include "render_manager"
#include "gstos"
#include "base_tex"
#include "../pointer"
#include "../num2s"
namespace tools {
namespace sg {
class tex_rect : public node, public gstos, public base_tex {
TOOLS_NODE_NO_CAST(tex_rect,tools::sg::tex_rect,node)
public:
virtual void* cast(const std::string& a_class) const {
{if(void* p = cmp_cast<tex_rect>(this,a_class)) return p;}
{if(void* p = base_tex::cast(a_class)) return p;}
return parent::cast(a_class);
}
public:
sf<bool> show_border;
sf<float> height;
public:
virtual const desc_fields& node_desc_fields() const {
TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::tex_rect)
static const desc_fields s_v(parent::node_desc_fields(),6, //WARNING : take care of count.
TOOLS_ARG_FIELD_DESC(img),
TOOLS_ARG_FIELD_DESC(back_color),
TOOLS_ARG_FIELD_DESC(expand),
TOOLS_ARG_FIELD_DESC(limit),
TOOLS_ARG_FIELD_DESC(show_border),
TOOLS_ARG_FIELD_DESC(height)
);
return s_v;
}
private:
void add_fields(){
add_field(&img);
add_field(&back_color);
add_field(&expand);
add_field(&limit);
add_field(&show_border);
add_field(&height);
}
public:
virtual void render(render_action& a_action) {
#ifdef TOOLS_SG_TEX_RECT_DEBUG
a_action.out() << "tools::tex_rect::render : begin : 001 : " << std::endl;
#endif
//NOTE : we draw border (show_border is true) and background even if
// gen_texture() failed.
if(touched()) {
#ifdef TOOLS_SG_TEX_RECT_DEBUG
a_action.out() << "tools::tex_rect::render : touched." << std::endl;
#endif
update_sg(a_action.out());
reset_touched();
}
if(m_img.is_empty()) {
#ifdef TOOLS_SG_TEX_RECT_DEBUG
a_action.out() << "tools::tex_rect::render : m_img is empty." << std::endl;
#endif
return;
}
#ifdef TOOLS_SG_TEX_RECT_DEBUG
a_action.out() << "tools::tex_rect::render : have a m_img. get_tex_id ..." << std::endl;
#endif
unsigned int _id = get_tex_id(a_action.out(),a_action.render_manager(),m_img,nearest.value());
#ifdef TOOLS_SG_TEX_RECT_DEBUG
a_action.out() << "tools::tex_rect::render : get_tex_id : " << _id << "." << std::endl;
#endif
const state& state = a_action.state();
//image must be 2^n,2^m in size !
// exa : 128x64
f12 xyzs;
if(show_border.value()) {
#ifdef TOOLS_SG_TEX_RECT_DEBUG
a_action.out() << "tools::tex_rect::render : show_border." << std::endl;
#endif
f12 nms;
_front(xyzs,nms,0.01f);
a_action.color4f(1,0,0,1);
a_action.line_width(4);
a_action.draw_vertex_array(gl::line_loop(),12,xyzs);
//pushes back the filled polygons to avoid z-fighting with lines
a_action.set_polygon_offset(true);
a_action.color4f(state.m_color);
a_action.line_width(state.m_line_width);
}
#ifdef TOOLS_SG_TEX_RECT_DEBUG
a_action.out() << "tools::tex_rect::render : draw back face." << std::endl;
#endif
//draw a back face pointing toward negative z :
{a_action.color4f(back_color.value());
f18 tris,nms;
_tris(tris,nms);
a_action.draw_vertex_normal_array(gl::triangles(),18,tris,nms);
a_action.color4f(state.m_color);}
if(_id) {
#ifdef TOOLS_SG_TEX_RECT_DEBUG
a_action.out() << "tools::tex_rect::render : draw_vertex_normal_array_texture." << std::endl;
#endif
f12 nms;
_front(xyzs,nms);
float tcs[8];
set_tcs(tcs);
a_action.draw_vertex_normal_array_texture(gl::triangle_fan(),12,xyzs,nms,_id,tcs);
}
a_action.set_polygon_offset(state.m_GL_POLYGON_OFFSET_FILL);
}
virtual void pick(pick_action& a_action) {
if(touched()) {
update_sg(a_action.out());
reset_touched();
}
if(m_img.is_empty()) return;
f12 xyzs,nms;
_front(xyzs,nms);
a_action.add__primitive(*this,gl::triangle_fan(),12,xyzs,true);
}
virtual void bbox(bbox_action& a_action) {
if(touched()) {
update_sg(a_action.out());
reset_touched();
}
if(m_img.is_empty()) return;
f12 xyzs,nms;
_front(xyzs,nms);
a_action.add_points(12,xyzs);
}
public:
virtual bool intersect_value(std::ostream&,intersect_type,const line<vec3f>& a_line,std::string& a_s) const {
// a_line is in local world coordinate.
const img_byte& _img = img.value();
if(_img.is_empty()) {a_s.clear();return false;}
float aspect = float(_img.width())/float(_img.height());
float h2 = height.value()*0.5f;
float w2 = aspect*h2;
plane<vec3f> plane(vec3f(w2,h2,0),vec3f(-w2,h2,0),vec3f(-w2,-h2,0));
vec3f p;
if(!plane.intersect(a_line,p)) {a_s.clear();return false;}
float imw = (float)_img.width();
float imh = (float)_img.height();
//image coordinates :
int ix = int((imw*p.x()/w2+imw)*0.5f);
int iy = int((imh*p.y()/h2+imh)*0.5f);
//rgb of pixel :
std::vector<unsigned char> pixel;
if((ix<0)||(iy<0)||!_img.pixel(ix,iy,pixel)) {a_s.clear();return false;}
a_s.clear();
for(unsigned int ipix=0;ipix<pixel.size();ipix++) {
if(ipix) a_s += " ";
if(!numas<float>(float(pixel[ipix])/255.0f,a_s)){}
}
return true;
}
public:
tex_rect()
:parent()
,base_tex()
,show_border(false)
,height(1)
{
add_fields();
}
virtual ~tex_rect(){}
public:
tex_rect(const tex_rect& a_from)
:parent(a_from)
,gstos(a_from)
,base_tex(a_from)
,show_border(a_from.show_border)
,height(a_from.height)
{
add_fields();
}
tex_rect& operator=(const tex_rect& a_from){
parent::operator=(a_from);
gstos::operator=(a_from);
base_tex::operator=(a_from);
if(&a_from==this) return *this;
show_border = a_from.show_border;
height = a_from.height;
return *this;
}
public:
//const img_byte& rendered_img() const {return m_img;}
void rendered_size(std::ostream& a_out,unsigned int& a_w,unsigned int& a_h) {
update_sg(a_out);
reset_touched();
a_w = m_img.width();
a_h = m_img.height();
}
protected:
//virtual //NOTE : virtual for diaporama node. (but warning with clang -g4flags).
void update_sg(std::ostream& a_out) {
clean_gstos(); //must reset for all render_manager.
if(height.value()<=0) {
m_img.make_empty();
return;
}
base_tex::_update_sg_(a_out);
}
protected:
typedef float f12[12];
void _front(f12& front,f12& nms,float a_epsil = 0.0f) { //[12]
float aspect = float(img.value().width())/float(img.value().height());
float h2 = height*0.5f;
float w2 = aspect*h2;
h2 += a_epsil;
w2 += a_epsil;
front[0] = -w2;
front[1] = -h2;
front[2] = 0;
front[3] = w2;
front[4] = -h2;
front[5] = 0;
front[6] = w2;
front[7] = h2;
front[8] = 0;
front[ 9] = -w2;
front[10] = h2;
front[11] = 0;
nms[0] = 0;
nms[1] = 0;
nms[2] = 1;
nms[3] = 0;
nms[4] = 0;
nms[5] = 1;
nms[6] = 0;
nms[7] = 0;
nms[8] = 1;
nms[9] = 0;
nms[10] = 0;
nms[11] = 1;
}
void _back(f12& back) { //[12]
float aspect = float(img.value().width())/float(img.value().height());
float h2 = height*0.5f;
float w2 = aspect*h2;
float d2 = 0;
back[0] = w2;back[ 1] = -h2;back[ 2] = d2;
back[3] = -w2;back[ 4] = -h2;back[ 5] = d2;
back[6] = -w2;back[ 7] = h2;back[ 8] = d2;
back[9] = w2;back[10] = h2;back[11] = d2;
}
typedef float f18[18];
void _tris(f18& tris,f18& nms){
f12 back;
_back(back);
tris[0] = back[0];
tris[1] = back[1];
tris[2] = back[2];
tris[3] = back[3];
tris[4] = back[4];
tris[5] = back[5];
tris[6] = back[6];
tris[7] = back[7];
tris[8] = back[8];
//
tris[9] = back[6];
tris[10] = back[7];
tris[11] = back[8];
tris[12] = back[9];
tris[13] = back[10];
tris[14] = back[11];
tris[15] = back[0];
tris[16] = back[1];
tris[17] = back[2];
///////////////////// back
nms[0] = 0;
nms[1] = 0;
nms[2] = -1;
nms[3] = 0;
nms[4] = 0;
nms[5] = -1;
nms[6] = 0;
nms[7] = 0;
nms[8] = -1;
//
nms[9] = 0;
nms[10] = 0;
nms[11] = -1;
nms[12] = 0;
nms[13] = 0;
nms[14] = -1;
nms[15] = 0;
nms[16] = 0;
nms[17] = -1;
}
};
}}
#endif