g4tools  5.4.0
tex_quadrilateral
Go to the documentation of this file.
1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
3 
4 #ifndef tools_sg_tex_quadrilateral
5 #define tools_sg_tex_quadrilateral
6 
7 #include "node"
8 #include "mf"
9 #include "render_action"
10 #include "pick_action"
11 #include "bbox_action"
12 #include "event_action"
13 #include "render_manager"
14 #include "gstos"
15 #include "base_tex"
16 
17 #include "../pointer"
18 #include "../num2s"
19 
20 namespace tools {
21 namespace sg {
22 
23 class tex_quadrilateral : public node, public gstos, public base_tex {
25 public:
26  virtual void* cast(const std::string& a_class) const {
27  {if(void* p = cmp_cast<tex_quadrilateral>(this,a_class)) return p;}
28  {if(void* p = base_tex::cast(a_class)) return p;}
29  return parent::cast(a_class);
30  }
31 public:
34 public:
35  virtual const desc_fields& node_desc_fields() const {
37  static const desc_fields s_v(parent::node_desc_fields(),6, //WARNING : take care of count.
44  );
45  return s_v;
46  }
47 private:
48  void add_fields(){
49  add_field(&img);
51  add_field(&expand);
52  add_field(&limit);
55  }
56 public:
57  virtual void render(render_action& a_action) {
58  //a_action.out() << "tools::tex_quadrilateral::render : " << std::endl;
59 
60  //NOTE : we draw border (show_border is true) and background even if
61  // gen_texture() failed.
62 
63  if(touched()) {
64  update_sg(a_action.out());
65  reset_touched();
66  }
67  if(m_img.is_empty()) return;
68  if(corners.size()!=4) return;
69 
70  unsigned int _id = get_tex_id(a_action.out(),a_action.render_manager(),m_img,nearest.value());
71 
72  const state& state = a_action.state();
73 
74  //image must be 2^n,2^m in size !
75  // exa : 128x64
76 
77  f12 xyzs,nms;
78 
79  if(show_border.value()) {
80  _front(xyzs,nms/*,0.01f*/); //have to revisit a_epsil.
81 
82  a_action.color4f(1,0,0,1);
83  //a_action.line_width(4);
84  a_action.line_width(1);
85 
86  a_action.draw_vertex_array(gl::line_loop(),12,xyzs);
87 
88  //pushes back the filled polygons to avoid z-fighting with lines
89  a_action.set_polygon_offset(true);
90 
91  a_action.color4f(state.m_color);
92  a_action.line_width(state.m_line_width);
93  }
94 
95  //draw a back face pointing toward negative z :
96  {a_action.color4f(back_color.value());
97  f18 tris,_nms;
98  _tris(tris,_nms);
99  a_action.draw_vertex_normal_array(gl::triangles(),18,tris,_nms);
100  a_action.color4f(state.m_color);}
101 
102  if(_id) {
103  //a_action.color4f(back_color.value()); //do we want that ?
104  _front(xyzs,nms);
105  float tcs[8];
106  set_tcs(tcs);
107  a_action.draw_vertex_normal_array_texture(gl::triangle_fan(),12,xyzs,nms,_id,tcs);
108  //a_action.color4f(state.m_color);
109  }
111  }
112  virtual void pick(pick_action& a_action) {
113  if(touched()) {
114  update_sg(a_action.out());
115  reset_touched();
116  }
117  if(m_pick_bbox_check_image) {if(m_img.is_empty()) return;}
118  if(corners.size()!=4) return;
119  f12 xyzs,nms;
120  _front(xyzs,nms);
121  a_action.add__primitive(*this,gl::triangle_fan(),12,xyzs,true);
122  }
123 
124  virtual void bbox(bbox_action& a_action) {
125  if(touched()) {
126  update_sg(a_action.out());
127  reset_touched();
128  }
129  if(m_pick_bbox_check_image) if(m_img.is_empty()) return;
130  if(corners.size()!=4) return;
131  f12 xyzs,nms;
132  _front(xyzs,nms);
133  a_action.add_points(12,xyzs);
134  }
135 public:
136  virtual bool intersect_value(std::ostream&,intersect_type,const line<vec3f>& a_line,std::string& a_s) const {
137  // a_line is in local world coordinate.
138  float x,y;
139  if(!line_2_img_ndc(a_line,x,y)) {a_s.clear();return false;}
140  return img_ndc_value(x,y,a_s);
141  }
142 public:
144  :parent()
145  ,base_tex()
146  ,show_border(false)
147  ,corners()
149  {
150  add_fields();
151  corners.add(vec3f(-1,-1,0));
152  corners.add(vec3f( 1,-1,0));
153  corners.add(vec3f( 1, 1,0));
154  corners.add(vec3f(-1, 1,0));
155  }
156  virtual ~tex_quadrilateral(){}
157 public:
159  :parent(a_from)
160  ,gstos(a_from)
161  ,base_tex(a_from)
162  ,show_border(a_from.show_border)
163  ,corners(a_from.corners)
165  {
166  add_fields();
167  }
169  parent::operator=(a_from);
170  gstos::operator=(a_from);
171  base_tex::operator=(a_from);
172  if(&a_from==this) return *this;
173  show_border = a_from.show_border;
174  corners = a_from.corners;
176  return *this;
177  }
178 public:
179 
180  //const img_byte& rendered_img() const {return m_img;}
181 
182 protected:
183  void update_sg(std::ostream& a_out) {
185  m_normal = plane.normal();
186  clean_gstos(); //must reset for all render_manager.
187  base_tex::_update_sg_(a_out);
188  }
189 protected:
190  bool img_ndc_value(float a_x,float a_y,std::string& a_s) const {
191  const img_byte& _img = img.value();
192  if(_img.is_empty()) {a_s.clear();return false;}
193 
194  int ix = int(float(_img.width())*a_x);
195  int iy = int(float(_img.height())*a_y);
196 
197  //rgb of pixel :
198  std::vector<unsigned char> pixel;
199  if((ix<0)||(iy<0)||!_img.pixel(ix,iy,pixel)) {a_s.clear();return false;}
200 
201  a_s.clear();
202  for(unsigned int ipix=0;ipix<pixel.size();ipix++) {
203  if(ipix) a_s += " ";
204  if(!numas<float>(float(pixel[ipix])/255.0f,a_s)){}
205  }
206 
207  return true;
208  }
209 
210  bool point_2_img_ndc(const vec3f& a_point,float& a_x,float& a_y) const {
211  // a_point is assumed to be in the corners[0,1,3] plane.
212 
213  if(corners.size()!=4) {a_x = 0;a_y = 0;return false;}
214  // In fact, in the below corners[2] is not used.
215 
216  // we assume that :
217  // corners[0] is the bottom-left of image
218  // corners[1] is the bottom-right of image
219  // corners[2] is the top-right of image
220  // corners[3] is the top-left of image
221  vec3f x_axis = corners[1]-corners[0];
222  float l_01 = x_axis.normalize();
223  if(l_01==0.0f) {a_x = 0;a_y = 0;return false;}
224  vec3f y_axis = corners[3]-corners[0];
225  float l_03 = y_axis.normalize();
226  if(l_03==0.0f) {a_x = 0;a_y = 0;return false;}
227 
228  float alpha = x_axis.dot(y_axis);
229  float alpha_sq = alpha*alpha;
230  if(alpha_sq==1.0f) {a_x = 0;a_y = 0;return false;}
231 
232  vec3f Op = a_point-corners[0];
233 
234  float px = Op.dot(x_axis);
235  float py = Op.dot(y_axis);
236 
237  float lambda = (px-alpha*py)/(1.0f-alpha_sq);
238  float mu = (py-alpha*px)/(1-alpha_sq);
239 
240  // We must have : Op = lambda*x_axis+mu*y_axis;
241 
242  a_x = lambda/l_01;
243  a_y = mu/l_03;
244 
245  return true;
246  }
247 
248  bool line_2_img_ndc(const line<vec3f>& a_line,float& a_x,float& a_y) const {
249  // a_line is in local world coordinate.
250  if(corners.size()!=4) {a_x = 0;a_y = 0;return false;}
251  // In fact corners[2] is not used, only [0,1,3].
253  vec3f p;
254  if(!plane.intersect(a_line,p)) {a_x = 0;a_y = 0;return false;}
255  return point_2_img_ndc(p,a_x,a_y);
256  }
257 
258  bool img_ndc_2_point(float a_x,float a_y,vec3f& a_point) const {
259  if(corners.size()!=4) {a_point.set_value(0,0,0);return false;}
260  // In fact, in the below corners[2] is not used.
261 
262  // we assume that :
263  // corners[0] is the bottom-left of image
264  // corners[1] is the bottom-right of image
265  // corners[2] is the top-right of image
266  // corners[3] is the top-left of image
267  vec3f x_axis = corners[1]-corners[0];
268  float l_01 = x_axis.normalize();
269  if(l_01==0.0f) {a_point.set_value(0,0,0);return false;}
270  vec3f y_axis = corners[3]-corners[0];
271  float l_03 = y_axis.normalize();
272  if(l_03==0.0f) {a_point.set_value(0,0,0);return false;}
273 
274  float alpha = x_axis.dot(y_axis);
275  //float alpha_sq = alpha*alpha;
276  //if(alpha_sq==1.0f) {a_point.set_value(0,0,0);return false;}
277 
278  float lambda = a_x*l_01;
279  float mu = a_y*l_03;
280 
281  // px-alpha*py = lambda*(1.0f-alpha_sq);
282  // py-alpha*px = mu*(1-alpha_sq);
283 
284  // px-alpha*(alpha*px+mu*(1-alpha_sq)) = lambda*(1-alpha_sq)
285  // px*(1-alpha_sq)-mu*alpha*(1-alpha_sq)) = lambda*(1-alpha_sq)
286  // px*(1-alpha_sq) = lambda*(1-alpha_sq)+mu*alpha*(1-alpha_sq));
287  // px = lambda+mu*alpha;
288 
289  // py = lambda*alpha+mu;
290 
291  float px = lambda+mu*alpha;
292  float py = lambda*alpha+mu;
293 
294  vec3f Op = px*x_axis+py*y_axis;
295 
296  a_point = Op+corners[0];
297 
298  return true;
299  }
300 
301 /*
302  float max_height() const {
303  const std::vector<vec3f>& cs = corners.values();
304  float _mn = cs[0].y();
305  _mn = mn<float>(_mn,cs[1].y());
306  _mn = mn<float>(_mn,cs[2].y());
307  _mn = mn<float>(_mn,cs[3].y());
308  float _mx = cs[0].y();
309  _mx = mx<float>(_mx,cs[1].y());
310  _mx = mx<float>(_mx,cs[2].y());
311  _mx = mx<float>(_mx,cs[3].y());
312  return (_mx-_mn);
313  }
314 
315  float max_width() const {
316  const std::vector<vec3f>& cs = corners.values();
317  float _mn = cs[0].x();
318  _mn = mn<float>(_mn,cs[1].x());
319  _mn = mn<float>(_mn,cs[2].x());
320  _mn = mn<float>(_mn,cs[3].x());
321  float _mx = cs[0].x();
322  _mx = mx<float>(_mx,cs[1].x());
323  _mx = mx<float>(_mx,cs[2].x());
324  _mx = mx<float>(_mx,cs[3].x());
325  return (_mx-_mn);
326  }
327 */
328 
329  typedef float f12[12];
330  void _front(f12& a_front,f12& a_nms,float a_epsil = 0.0f) {
331  const std::vector<vec3f>& cs = corners.values();
332 
333  a_front[0] = cs[0].x()-a_epsil;
334  a_front[1] = cs[0].y()-a_epsil;
335  a_front[2] = cs[0].z();
336 
337  a_front[3] = cs[1].x()+a_epsil;
338  a_front[4] = cs[1].y()-a_epsil;
339  a_front[5] = cs[1].z();
340 
341  a_front[6] = cs[2].x()+a_epsil;
342  a_front[7] = cs[2].y()+a_epsil;
343  a_front[8] = cs[2].z();
344 
345  a_front[ 9] = cs[3].x()-a_epsil;
346  a_front[10] = cs[3].y()+a_epsil;
347  a_front[11] = cs[3].z();
348 
349  a_nms[0] = m_normal.x();
350  a_nms[1] = m_normal.y();
351  a_nms[2] = m_normal.z();
352 
353  a_nms[3] = m_normal.x();
354  a_nms[4] = m_normal.y();
355  a_nms[5] = m_normal.z();
356 
357  a_nms[6] = m_normal.x();
358  a_nms[7] = m_normal.y();
359  a_nms[8] = m_normal.z();
360 
361  a_nms[9] = m_normal.x();
362  a_nms[10] = m_normal.y();
363  a_nms[11] = m_normal.z();
364  }
365 
366  void _back(f12& a_back) {
367  const std::vector<vec3f>& cs = corners.values();
368 
369  a_back[0] = cs[1].x();
370  a_back[1] = cs[1].y();
371  a_back[2] = cs[1].z();
372 
373  a_back[3] = cs[0].x();
374  a_back[4] = cs[0].y();
375  a_back[5] = cs[0].z();
376 
377  a_back[6] = cs[3].x();
378  a_back[7] = cs[3].y();
379  a_back[8] = cs[3].z();
380 
381  a_back[ 9] = cs[2].x();
382  a_back[10] = cs[2].y();
383  a_back[11] = cs[2].z();
384  }
385 
386  typedef float f18[18];
387  void _tris(f18& a_tris,f18& a_nms){
388  f12 back;
389  _back(back);
390 
391  a_tris[0] = back[0];
392  a_tris[1] = back[1];
393  a_tris[2] = back[2];
394 
395  a_tris[3] = back[3];
396  a_tris[4] = back[4];
397  a_tris[5] = back[5];
398 
399  a_tris[6] = back[6];
400  a_tris[7] = back[7];
401  a_tris[8] = back[8];
402  //
403  a_tris[9] = back[6];
404  a_tris[10] = back[7];
405  a_tris[11] = back[8];
406 
407  a_tris[12] = back[9];
408  a_tris[13] = back[10];
409  a_tris[14] = back[11];
410 
411  a_tris[15] = back[0];
412  a_tris[16] = back[1];
413  a_tris[17] = back[2];
414 
416  a_nms[0] = -m_normal.x();
417  a_nms[1] = -m_normal.y();
418  a_nms[2] = -m_normal.z();
419 
420  a_nms[3] = -m_normal.x();
421  a_nms[4] = -m_normal.y();
422  a_nms[5] = -m_normal.z();
423 
424  a_nms[6] = -m_normal.x();
425  a_nms[7] = -m_normal.y();
426  a_nms[8] = -m_normal.z();
427  //
428  a_nms[9] = -m_normal.x();
429  a_nms[10] = -m_normal.y();
430  a_nms[11] = -m_normal.z();
431 
432  a_nms[12] = -m_normal.x();
433  a_nms[13] = -m_normal.y();
434  a_nms[14] = -m_normal.z();
435 
436  a_nms[15] = -m_normal.x();
437  a_nms[16] = -m_normal.y();
438  a_nms[17] = -m_normal.z();
439  }
440 protected:
442  bool m_pick_bbox_check_image; //for SDSS_image.
443 };
444 
445 }}
446 
447 #endif
base_tex
tools::sg::tex_quadrilateral::operator=
tex_quadrilateral & operator=(const tex_quadrilateral &a_from)
Definition: tex_quadrilateral:168
tools::sg::gstos
Definition: gstos:16
node
tools::sg::base_tex::_update_sg_
void _update_sg_(std::ostream &a_out)
Definition: base_tex:69
tools::img
Definition: img:21
tools::sg::tex_quadrilateral::tex_quadrilateral
tex_quadrilateral()
Definition: tex_quadrilateral:143
tools::sg::render_action::draw_vertex_array
virtual void draw_vertex_array(gl::mode_t, size_t, const float *)=0
tools::sg::base_tex::operator=
base_tex & operator=(const base_tex &a_from)
Definition: base_tex:59
tools::sg::state
Definition: state:25
tools::sg::tex_quadrilateral::node_desc_fields
virtual const desc_fields & node_desc_fields() const
Definition: tex_quadrilateral:35
tools::sg::base_tex::intersect_type
intersect_type
Definition: base_tex:34
tools::gl::triangles
mode_t triangles()
Definition: glprims:20
tools::sg::tex_quadrilateral::f18
float f18[18]
Definition: tex_quadrilateral:386
tools::sg::base_tex::set_tcs
void set_tcs(float a_tcs[8])
Definition: base_tex:204
tools::sg::base_tex::cast
virtual void * cast(const std::string &a_class) const
Definition: base_tex:23
tools::sg::mf_vec
Definition: mf:200
tools::sg::tex_quadrilateral::update_sg
void update_sg(std::ostream &a_out)
Definition: tex_quadrilateral:183
pick_action
tools::sg::tex_quadrilateral
Definition: tex_quadrilateral:23
tools::vec3::set_value
void set_value(const T &a0, const T &a1, const T &a2)
Definition: vec3:92
tools::plane
Definition: plane:12
TOOLS_NODE_NO_CAST
#define TOOLS_NODE_NO_CAST(a__class, a__sclass, a__parent)
Definition: node:328
render_action
tools::sg::tex_quadrilateral::corners
mf_vec< vec3f, float > corners
Definition: tex_quadrilateral:33
tools::sg::state::m_GL_POLYGON_OFFSET_FILL
bool m_GL_POLYGON_OFFSET_FILL
Definition: state:250
tools::gl::triangle_fan
mode_t triangle_fan()
Definition: glprims:22
tools::plane::intersect
bool intersect(const line< VEC3 > &a_line, VEC3 &a_intersection) const
Definition: plane:63
tools::sg::gstos::clean_gstos
void clean_gstos()
Definition: gstos:89
tools::sg::node
Definition: node:28
tools::sg::tex_quadrilateral::_tris
void _tris(f18 &a_tris, f18 &a_nms)
Definition: tex_quadrilateral:387
tools::sg::bbox_action
Definition: bbox_action:15
mf
event_action
tools::sg::gstos::get_tex_id
unsigned int get_tex_id(std::ostream &a_out, render_manager &a_mgr, const img_byte &a_img, bool a_NEAREST)
Definition: gstos:30
tools::sg::base_tex::back_color
sf_vec< colorf, float > back_color
Definition: base_tex:29
tools::img::width
unsigned int width() const
Definition: img:214
tools::sg::tex_quadrilateral::img_ndc_2_point
bool img_ndc_2_point(float a_x, float a_y, vec3f &a_point) const
Definition: tex_quadrilateral:258
tools::sg::base_tex::limit
sf< unsigned int > limit
Definition: base_tex:31
tools::sg::desc_fields
Definition: field_desc:148
tools::vec3::y
const T & y() const
Definition: vec3:85
tools::sg::render_action::color4f
virtual void color4f(float, float, float, float)=0
tools::sg::gstos::operator=
gstos & operator=(const gstos &a_from)
Definition: gstos:22
tools::sg::tex_quadrilateral::img_ndc_value
bool img_ndc_value(float a_x, float a_y, std::string &a_s) const
Definition: tex_quadrilateral:190
tools::sg::tex_quadrilateral::cast
virtual void * cast(const std::string &a_class) const
Definition: tex_quadrilateral:26
tools::sg::pick_action
Definition: pick_action:59
tools::plane::normal
const VEC3 & normal() const
Definition: plane:88
tools::sg::pick_action::add__primitive
bool add__primitive(sg::node &a_node, gl::mode_t a_mode, size_t a_floatn, const float *a_xyzs, bool a_stop=false)
Definition: pick_action:431
tools::vec3::x
const T & x() const
Definition: vec3:84
render_manager
tools::img::pixel
bool pixel(unsigned int a_i, unsigned a_j, std::vector< T > &a_pixel) const
Definition: img:223
tools::sg::tex_quadrilateral::m_normal
vec3f m_normal
Definition: tex_quadrilateral:441
tools::sg::tex_quadrilateral::bbox
virtual void bbox(bbox_action &a_action)
Definition: tex_quadrilateral:124
tools::img::is_empty
bool is_empty() const
Definition: img:194
tools::sg::render_action::set_polygon_offset
virtual void set_polygon_offset(bool)=0
tools::sg::tex_quadrilateral::_front
void _front(f12 &a_front, f12 &a_nms, float a_epsil=0.0f)
Definition: tex_quadrilateral:330
tools::sg::render_action::render_manager
virtual sg::render_manager & render_manager()=0
tools::sg::primitive_visitor::add_points
bool add_points(size_t a_floatn, const float *a_xyzs, bool a_stop=false)
Definition: primitive_visitor:1405
tools::sg::tex_quadrilateral::f12
float f12[12]
Definition: tex_quadrilateral:329
gstos
tools::vec3f
Definition: vec3f:13
tools::sg::render_action
Definition: render_action:24
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::sg::node::add_field
void add_field(field *a_field)
Definition: node:128
tools::sg::tex_quadrilateral::pick
virtual void pick(pick_action &a_action)
Definition: tex_quadrilateral:112
tools::gl::line_loop
mode_t line_loop()
Definition: glprims:18
TOOLS_FIELD_DESC_NODE_CLASS
#define TOOLS_FIELD_DESC_NODE_CLASS(a__class)
Definition: field:68
tools::sg::tex_quadrilateral::~tex_quadrilateral
virtual ~tex_quadrilateral()
Definition: tex_quadrilateral:156
tools::sg::tex_quadrilateral::render
virtual void render(render_action &a_action)
Definition: tex_quadrilateral:57
tools::sg::base_tex
Definition: base_tex:19
tools::sg::tex_quadrilateral::m_pick_bbox_check_image
bool m_pick_bbox_check_image
Definition: tex_quadrilateral:442
tools::sg::tex_quadrilateral::point_2_img_ndc
bool point_2_img_ndc(const vec3f &a_point, float &a_x, float &a_y) const
Definition: tex_quadrilateral:210
tools::sg::render_action::draw_vertex_normal_array
virtual void draw_vertex_normal_array(gl::mode_t, size_t, const float *, const float *)=0
tools::sg::bsf::value
T & value()
Definition: bsf:98
tools::sg::action::out
std::ostream & out() const
Definition: action:51
tools::img::height
unsigned int height() const
Definition: img:215
tools::vec3::z
const T & z() const
Definition: vec3:86
tools::sg::tex_quadrilateral::show_border
sf< bool > show_border
Definition: tex_quadrilateral:32
tools::sg::tex_quadrilateral::_back
void _back(f12 &a_back)
Definition: tex_quadrilateral:366
tools::line
Definition: line:13
tools::sg::tex_quadrilateral::line_2_img_ndc
bool line_2_img_ndc(const line< vec3f > &a_line, float &a_x, float &a_y) const
Definition: tex_quadrilateral:248
tools::sg::state::m_line_width
float m_line_width
Definition: state:267
tools::sg::render_action::draw_vertex_normal_array_texture
virtual void draw_vertex_normal_array_texture(gl::mode_t, size_t, const float *, const float *, gstoid, const float *)=0
tools::sg::state::m_color
colorf m_color
Definition: state:259
tools::vec3f::normalize
float normalize()
Definition: vec3f:74
tools::sg::base_tex::expand
sf< bool > expand
Definition: base_tex:30
tools::sg::render_action::line_width
virtual void line_width(float)=0
tools::sg::base_tex::m_img
img_byte m_img
Definition: base_tex:239
tools::sg::states::state
const sg::state & state() const
Definition: states:76
tools::sg::node::touched
virtual bool touched()
Definition: node:96
tools::sg::tex_quadrilateral::intersect_value
virtual bool intersect_value(std::ostream &, intersect_type, const line< vec3f > &a_line, std::string &a_s) const
Definition: tex_quadrilateral:136
tools::sg::tex_quadrilateral::tex_quadrilateral
tex_quadrilateral(const tex_quadrilateral &a_from)
Definition: tex_quadrilateral:158
tools::img::clear
void clear()
Definition: img:111
tools::sg::sf< bool >
TOOLS_ARG_FIELD_DESC
#define TOOLS_ARG_FIELD_DESC(a__field)
Definition: field:71
tools::sg::base_tex::nearest
sf< bool > nearest
Definition: base_tex:32
tools::sg::node::reset_touched
virtual void reset_touched()
Definition: node:102
bbox_action
tools::vec3::dot
T dot(const vec3 &aV) const
Definition: vec3:125