361 lines
8.4 KiB
Plaintext
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
|