g4tools  5.4.0
pick_action
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_pick_action
5 #define tools_sg_pick_action
6 
7 #include "matrix_action"
8 #include "primitive_visitor"
9 
10 #include "../lina/plane"
11 #include "../vmanip"
12 
13 #include "node"
14 
15 namespace tools {
16 namespace sg {
17 
18 class pick_element {
19 public:
20  pick_element(sg::node& a_node,const std::vector<float>& a_zs,const std::vector<float>& a_ws,const sg::state& a_state)
21  :m_node(a_node)
22  ,m_zs(a_zs)
23  ,m_ws(a_ws)
24  ,m_state(a_state)
25  {}
26  virtual ~pick_element(){}
27 public:
28  pick_element(const pick_element& a_from)
29  :m_node(a_from.m_node)
30  ,m_zs(a_from.m_zs)
31  ,m_ws(a_from.m_ws)
32  ,m_state(a_from.m_state)
33  {}
35  m_zs = a_from.m_zs;
36  m_ws = a_from.m_ws;
37  m_state = a_from.m_state;
38  return *this;
39  }
40 public:
41  const sg::node& node() const {return m_node;}
42  sg::node& node() {return m_node;}
43 
44  const std::vector<float>& zs() const {return m_zs;}
45  std::vector<float>& zs() {return m_zs;}
46 
47  const std::vector<float>& ws() const {return m_ws;}
48  std::vector<float>& ws() {return m_ws;}
49 
50  const sg::state& state() const {return m_state;}
51  sg::state& state() {return m_state;}
52 protected:
54  std::vector<float> m_zs;
55  std::vector<float> m_ws;
57 };
58 
61 protected:
62 
63  virtual bool project(float& a_x,float& a_y,float& a_z,float& a_w) {
64  return parent::project_point(a_x,a_y,a_z,a_w);
65  }
66 
67  virtual bool add_point(float a_x,float a_y,float a_z,float a_w) {
68  if(is_inside(a_x,a_y,a_z,a_w)) { //we have a pick.
69  m_done = true;
70  return false; //to stop
71  }
72  return true; //continue.
73  }
74 
75  virtual bool add_point(float a_x,float a_y,float a_z,float a_w,
76  float,float,float,float) {
77  return pick_action::add_point(a_x,a_y,a_z,a_w);
78  }
79 
80  virtual bool add_line(float a_bx,float a_by,float a_bz,float a_bw,
81  float a_ex,float a_ey,float a_ez,float a_ew) {
82  if(is_inside(a_bx,a_by,a_bz,a_bw)) {
83  m_done = true;
84  return false;
85  }
86  if(is_inside(a_ex,a_ey,a_ez,a_ew)) {
87  m_done = true;
88  return false;
89  }
90  if(intersect_line(a_bx,a_by,a_bz,a_bw,
91  a_ex,a_ey,a_ez,a_ew)) {
92  m_done = true;
93  return false;
94  }
95  return true;
96  }
97 
98  virtual bool add_line(float a_bx,float a_by,float a_bz,float a_bw,
99  float,float,float,float,
100  float a_ex,float a_ey,float a_ez,float a_ew,
101  float,float,float,float){
102  return pick_action::add_line(a_bx,a_by,a_bz,a_bw,a_ex,a_ey,a_ez,a_ew);
103  }
104 
105  virtual bool add_triangle(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
106  float a_p2x,float a_p2y,float a_p2z,float a_p2w,
107  float a_p3x,float a_p3y,float a_p3z,float a_p3w){
108  if(intersect_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
109  a_p2x,a_p2y,a_p2z,a_p2w,
110  a_p3x,a_p3y,a_p3z,a_p3w)) {
111  m_done = true;
112  return false;
113  }
114  return true;
115  }
116 
117  virtual bool add_triangle(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
118  float,float,float,float,
119  float a_p2x,float a_p2y,float a_p2z,float a_p2w,
120  float,float,float,float,
121  float a_p3x,float a_p3y,float a_p3z,float a_p3w,
122  float,float,float,float){
123  return pick_action::add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
124  a_p2x,a_p2y,a_p2z,a_p2w,
125  a_p3x,a_p3y,a_p3z,a_p3w);
126  }
127 
128  virtual bool project_normal(float&,float&,float&) {return true;}
129  virtual bool add_point_normal(float a_x,float a_y,float a_z,float a_w,
130  float,float,float) {
131  return pick_action::add_point(a_x,a_y,a_z,a_w);
132  }
133 
134  virtual bool add_point_normal(float a_x,float a_y,float a_z,float a_w,
135  float,float,float,
136  float,float,float,float) {
137  return pick_action::add_point(a_x,a_y,a_z,a_w);
138  }
139 
140  virtual bool add_line_normal(float a_bx,float a_by,float a_bz,float a_bw, float,float,float,
141  float a_ex,float a_ey,float a_ez,float a_ew, float,float,float) {
142  return pick_action::add_line(a_bx,a_by,a_bz,a_bw,a_ex,a_ey,a_ez,a_ew);
143  }
144  virtual bool add_line_normal(float a_bx,float a_by,float a_bz,float a_bw, float,float,float, float,float,float,float,
145  float a_ex,float a_ey,float a_ez,float a_ew, float,float,float, float,float,float,float) {
146  return pick_action::add_line(a_bx,a_by,a_bz,a_bw,a_ex,a_ey,a_ez,a_ew);
147  }
148 
149  virtual bool add_triangle_normal(float a_p1x,float a_p1y,float a_p1z,float a_p1w, float,float,float,
150  float a_p2x,float a_p2y,float a_p2z,float a_p2w, float,float,float,
151  float a_p3x,float a_p3y,float a_p3z,float a_p3w, float,float,float) {
152  return pick_action::add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
153  a_p2x,a_p2y,a_p2z,a_p2w,
154  a_p3x,a_p3y,a_p3z,a_p3w);
155  }
156  virtual bool add_triangle_normal(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
157  float,float,float, float,float,float,float,
158  float a_p2x,float a_p2y,float a_p2z,float a_p2w,
159  float,float,float, float,float,float,float,
160  float a_p3x,float a_p3y,float a_p3z,float a_p3w,
161  float,float,float, float,float,float,float) {
162  return pick_action::add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
163  a_p2x,a_p2y,a_p2z,a_p2w,
164  a_p3x,a_p3y,a_p3z,a_p3w);
165  }
166 public:
167  pick_action(std::ostream& a_out,unsigned int a_ww,unsigned int a_wh,float a_l,float a_r,float a_b,float a_t)
168  :parent(a_out,a_ww,a_wh)
169  ,m_l(a_l)
170  ,m_r(a_r)
171  ,m_b(a_b)
172  ,m_t(a_t)
173  ,m_stop_at_first(false) //same as selection
174  ,m_done(false)
175  ,m_node(0)
176  {
177  set_to_pick_ndc(); //OPTIMIZATION
178  }
179  virtual ~pick_action(){}
180 public:
181  pick_action(const pick_action& a_from)
182  :parent(a_from)
183  ,primitive_visitor(a_from)
184  ,m_l(a_from.m_l)
185  ,m_r(a_from.m_r)
186  ,m_b(a_from.m_b)
187  ,m_t(a_from.m_t)
189  ,m_done(false)
190  ,m_node(0)
191  {
192  set_to_pick_ndc(); //OPTIMIZATION
193  }
195  parent::operator=(a_from);
197  m_l = a_from.m_l;
198  m_r = a_from.m_r;
199  m_b = a_from.m_b;
200  m_t = a_from.m_t;
202  m_done = false;
203  m_node = 0;
204  m_zs.clear();
205  m_ws.clear();
206  m_picks.clear();
207  set_to_pick_ndc(); //OPTIMIZATION
208  return *this;
209  }
210 public:
211  void reset() {
212  parent::reset();
213  m_done = false;
214  m_node = 0;
215  m_zs.clear();
216  m_ws.clear();
217  m_picks.clear();
218  }
219 
220  void set_win_size(unsigned a_ww,unsigned int a_wh) {
221  m_ww = a_ww;
222  m_wh = a_wh;
223  sg::state& _state = state();
224  _state.m_ww = a_ww;
225  _state.m_wh = a_wh;
226  m_states.clear();
227  reset();
228  }
229 
230  void set_area(float a_l,float a_r,float a_b,float a_t) {
231  // a_l,a_r,a_b,a_t are in window coordinates (pixels)
232  // but handled in floats for intersection computation precision.
233  // WARNING : we must have a_t>a_b and a_r>a_l. No check is done for that.
234  m_l = a_l;
235  m_r = a_r;
236  m_b = a_b;
237  m_t = a_t;
238  set_to_pick_ndc(); //OPTIMIZATION
239  }
240 
241  void get_area(float& a_l,float& a_r,float& a_b,float& a_t) const {
242  a_l = m_l;
243  a_r = m_r;
244  a_b = m_b;
245  a_t = m_t;
246  }
247 
251  void set_stop_at_first(bool a_value) {m_stop_at_first = a_value;}
252  bool stop_at_first() const {return m_stop_at_first;}
253 
254  void set_done(bool a_value) {m_done = a_value;}
255  bool done() const {return m_done;}
256 
257  void set_node(sg::node* a_node) {m_node = a_node;}
258  sg::node* node() const {return m_node;}
259 
264 
265  void add_pick(sg::node& a_node,
266  const std::vector<float>& a_zs,
267  const std::vector<float>& a_ws,
268  const sg::state& a_state) {
269  m_picks.push_back(pick_t(a_node,a_zs,a_ws,a_state));
270  }
271  const std::vector<pick_t>& picks() const {return m_picks;}
272 
273  void dump_picks() {
274  m_out << "tools::sg::pick_action :"
275  << " number of picks " << m_picks.size()
276  << std::endl;
277  std::vector<pick_t>::const_iterator it;
278  for(it=m_picks.begin();it!=m_picks.end();++it) {
279  m_out << " " << (*it).node().s_cls();
280 
281  std::vector<float>::const_iterator itz;
282  for(itz=(*it).zs().begin();itz!=(*it).zs().end();++itz) {
283  m_out << " " << *itz;
284  }
285 
286  m_out << std::endl;
287  }
288  }
289 
291  if(m_picks.empty()) return 0;
292  //closest point is minimum z !
293  // near -> -1
294  // far -> 1
295 
296  // find first pick_t with not empty zs :
297  pick_t* pck = 0;
298  float z;
299  std::vector<pick_t>::const_iterator it;
300  for(it=m_picks.begin();it!=m_picks.end();++it) {
301  if(minimum((*it).zs(),z)) {
302  pck = (pick_t*)&(*it);
303  break;
304  }
305  }
306  if(!pck) return 0;
307  it++;
308  for(;it!=m_picks.end();++it) {
309  float zi;
310  if(minimum((*it).zs(),zi)) {
311  if(zi<=z) {
312  pck = (pick_t*)&(*it);
313  z = zi;
314  }
315  }
316  }
317  return pck;
318  }
319 
320  const std::vector<float>& zs() const {return m_zs;}
321  std::vector<float>& zs() {return m_zs;}
322 
323  const std::vector<float>& ws() const {return m_ws;}
324  std::vector<float>& ws() {return m_ws;}
325 
329  }
331  const sg::state& _state = state();
332  projection_matrix() = _state.m_proj;
333  model_matrix() = _state.m_model;
334  }
335 public:
337  gl::mode_t a_mode,
338  size_t a_floatn,const float* a_xys,
339  bool a_stop = false,
340  bool a_triangle_revert = false){
341  if(!a_floatn) return false;
342  if(m_stop_at_first){
343  add_primitive_xy(a_mode,a_floatn,a_xys,a_stop,a_triangle_revert);
344  if(m_done) {
345  m_node = &a_node;
346  return true;
347  }
348  } else {
349  m_done = false;
350  m_zs.clear();
351  add_primitive_xy(a_mode,a_floatn,a_xys,a_stop,a_triangle_revert);
352  if(m_done) {
353  add_pick(a_node,m_zs,m_ws,state());
354  m_done = false;
355  return true;
356  }
357  }
358  return false;
359  }
360 
362  gl::mode_t a_mode,
363  const std::vector<float>& a_xys,
364  bool a_stop = false,
365  bool a_triangle_revert = false){
366  if(a_xys.empty()) return false;
367  if(m_stop_at_first){
368  add_primitive_xy(a_mode,a_xys,a_stop,a_triangle_revert);
369  if(m_done) {
370  m_node = &a_node;
371  return true;
372  }
373  } else {
374  m_done = false;
375  m_zs.clear();
376  add_primitive_xy(a_mode,a_xys,a_stop,a_triangle_revert);
377  if(m_done) {
378  add_pick(a_node,m_zs,m_ws,state());
379  m_done = false;
380  return true;
381  }
382  }
383  return false;
384  }
385 
386  bool add__line_strip_xy(sg::node& a_node,size_t a_floatn,const float* a_xys,bool a_stop = false){
387  if(!a_floatn) return false;
388  if(m_stop_at_first){
389  add_line_strip_xy(a_floatn,a_xys,a_stop);
390  if(m_done) {
391  m_node = &a_node;
392  return true;
393  }
394  } else {
395  m_done = false;
396  m_zs.clear();
397  add_line_strip_xy(a_floatn,a_xys,a_stop);
398  if(m_done) {
399  add_pick(a_node,m_zs,m_ws,state());
400  m_done = false;
401  return true;
402  }
403  }
404  return false;
405  }
406 
407  bool add__lines_xy(sg::node& a_node,
408  const std::vector<float>& a_xys,
409  bool a_stop = false) {
410  if(a_xys.empty()) return false;
411  if(m_stop_at_first){
412  add_lines_xy(a_xys,a_stop);
413  if(m_done) {
414  m_node = &a_node;
415  return true;
416  }
417  } else {
418  m_done = false;
419  m_zs.clear();
420  add_lines_xy(a_xys,a_stop);
421  if(m_done) {
422  add_pick(a_node,m_zs,m_ws,state());
423  m_done = false;
424  return true;
425  }
426  }
427  return false;
428  }
429 
430 public:
431  bool add__primitive(sg::node& a_node,gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs,bool a_stop = false){
432  if(!a_floatn) return false;
433  if(m_stop_at_first){
434  add_primitive(a_mode,a_floatn,a_xyzs,a_stop);
435  if(m_done) {
436  m_node = &a_node;
437  return true;
438  }
439  } else {
440  m_done = false;
441  m_zs.clear();
442  add_primitive(a_mode,a_floatn,a_xyzs,a_stop);
443  if(m_done) {
444  add_pick(a_node,m_zs,m_ws,state());
445  m_done = false;
446  return true;
447  }
448  }
449  return false;
450  }
451 
452  bool add__primitive(sg::node& a_node,gl::mode_t a_mode,const std::vector<float>& a_xyzs,bool a_stop = false) {
453  if(a_xyzs.empty()) return false;
454  if(m_stop_at_first){
455  add_primitive(a_mode,a_xyzs,a_stop);
456  if(m_done) {
457  m_node = &a_node;
458  return true;
459  }
460  } else {
461  m_done = false;
462  m_zs.clear();
463  add_primitive(a_mode,a_xyzs,a_stop);
464  if(m_done) {
465  add_pick(a_node,m_zs,m_ws,state());
466  m_done = false;
467  return true;
468  }
469  }
470  return false;
471  }
472 
473  bool add__line_strip(sg::node& a_node,size_t a_floatn,const float* a_xyzs,bool a_stop = false){
474  if(!a_floatn) return false;
475  if(m_stop_at_first){
476  add_line_strip(a_floatn,a_xyzs,a_stop);
477  if(m_done) {
478  m_node = &a_node;
479  return true;
480  }
481  } else {
482  m_done = false;
483  m_zs.clear();
484  add_line_strip(a_floatn,a_xyzs,a_stop);
485  if(m_done) {
486  add_pick(a_node,m_zs,m_ws,state());
487  m_done = false;
488  return true;
489  }
490  }
491  return false;
492  }
493 
494  bool add__triangles(sg::node& a_node,
495  size_t a_floatn,
496  const float* a_xyzs,
497  bool a_stop = false){
498  if(!a_floatn) return false;
499  if(m_stop_at_first){
500  add_triangles(a_floatn,a_xyzs,a_stop);
501  if(m_done) {
502  m_node = &a_node;
503  return true;
504  }
505  } else {
506  m_done = false;
507  m_zs.clear();
508  add_triangles(a_floatn,a_xyzs,a_stop);
509  if(m_done) {
510  add_pick(a_node,m_zs,m_ws,state());
511  m_done = false;
512  return true;
513  }
514  }
515  return false;
516  }
517 
518  bool add__lines(sg::node& a_node,
519  const std::vector<float>& a_xyzs,
520  bool a_stop = false){
521  if(a_xyzs.empty()) return false;
522  if(m_stop_at_first){
523  add_lines(a_xyzs,a_stop);
524  if(m_done) {
525  m_node = &a_node;
526  return true;
527  }
528  } else {
529  m_done = false;
530  m_zs.clear();
531  add_lines(a_xyzs,a_stop);
532  if(m_done) {
533  add_pick(a_node,m_zs,m_ws,state());
534  m_done = false;
535  return true;
536  }
537  }
538  return false;
539  }
540 
541 public: //for markers
542  bool is_inside(float a_x,float a_y,float a_z,float a_w) {
543  //std::cout << "debug : tools::sg::pick_action::is_inside :"
544  // << " x " << a_x
545  // << " y " << a_y
546  // << std::endl;
547 
548  // In principle we should receive (because of proj x model matrix
549  // mult of world coord points) point in [-1,1]x[-1,1].
550 
551  float x,y;
552  to_pick_ndc(a_x,a_y,x,y);
553 
554  if(x<-1) return false;
555  if(1<x) return false;
556  if(y<-1) return false;
557  if(1<y) return false;
558 
559  //std::cout << "debug : tools::sg::pick_action::is_inside :"
560  // << " inside !"
561  // << std::endl;
562 
563  m_zs.push_back(a_z);
564  m_ws.push_back(a_w);
565 
566  return true;
567  }
568  bool intersect_line(float a_bx,float a_by,float a_bz,float a_bw,
569  float a_ex,float a_ey,float a_ez,float a_ew) {
570 
571  // a_bz, a_ez are used only to compute the intersection point.
572 
573  float bx,by;
574  to_pick_ndc(a_bx,a_by,bx,by);
575  float ex,ey;
576  to_pick_ndc(a_ex,a_ey,ex,ey);
577 
578  //no check on z is done.
579  float bz = a_bz;
580  float bw = a_bw;
581  float ez = a_ez;
582  float ew = a_ew;
583 
584  bool toggle;
585  if(!ortho_clip_line(bx,by,bz,bw, ex,ey,ez,ew, toggle)) return false;
586 
587  m_zs.push_back(bz);
588  m_ws.push_back(bw);
589 
590  return true;
591  }
592 
593 protected:
594  bool intersect_triangle(float a_1x,float a_1y,float a_1z,float a_1w,
595  float a_2x,float a_2y,float a_2z,float a_2w,
596  float a_3x,float a_3y,float a_3z,float a_3w) {
597  //test a triangle.
598 
599  if(is_inside(a_1x,a_1y,a_1z,a_1w)) return true;
600  if(is_inside(a_2x,a_2y,a_2z,a_2w)) return true;
601  if(is_inside(a_3x,a_3y,a_3z,a_3w)) return true;
602 
603  // alll points are outside.
604 
605  float x1,y1;
606  to_pick_ndc(a_1x,a_1y,x1,y1);
607  float x2,y2;
608  to_pick_ndc(a_2x,a_2y,x2,y2);
609 
610  bool toggle;
611  float bx,by,bz,bw,ex,ey,ez,ew;
612 
613  bx = x1;
614  by = y1;
615  bz = a_1z;
616  bw = a_1w;
617 
618  ex = x2;
619  ey = y2;
620  ez = a_2z;
621  ew = a_2w;
622  if(ortho_clip_line(bx,by,bz,bw, ex,ey,ez,ew, toggle)) {
623  m_zs.push_back(bz);
624  m_ws.push_back(bw);
625  return true;
626  }
627 
628  float x3,y3;
629  to_pick_ndc(a_3x,a_3y,x3,y3);
630 
631  bx = x2;
632  by = y2;
633  bz = a_2z;
634  bw = a_2w;
635 
636  ex = x3;
637  ey = y3;
638  ez = a_3z;
639  ew = a_3w;
640  if(ortho_clip_line(bx,by,bz,bw, ex,ey,ez,ew, toggle)) {
641  m_zs.push_back(bz);
642  m_ws.push_back(bw);
643  return true;
644  }
645 
646  bx = x1;
647  by = y1;
648  bz = a_1z;
649  bw = a_1w;
650 
651  ex = x3;
652  ey = y3;
653  ez = a_3z;
654  ew = a_3w;
655  if(ortho_clip_line(bx,by,bz,bw, ex,ey,ez,ew, toggle)) {
656  m_zs.push_back(bz);
657  m_ws.push_back(bw);
658  return true;
659  }
660 
661  // no intersection with edges.
662  // but the triangle may surround [-1,1]x[-1,1] !
663 
664  // test if O=(0,0) is inside the triangle :
665 
666  float xo = 0;
667  float yo = 0;
668  //float zo = 0;
669 
670  {float cp2 = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1); //(2-1).cross(3-1)
671  if(cp2==0) return false; // (1,2,3) aligned points.
672  float cp1 = (x2-x1)*(yo-y1)-(y2-y1)*(xo-x1);
673  if(cp1==0) { // O on (1,2). We can't pass here.
674  //m_out << "pick_action::intersect_triangle : case 0." << std::endl;
675  //m_zs.push_back(???);
676  //m_ws.push_back(???);
677  return false;
678  }
679  if((cp1*cp2)<0) return false;} // O 3 not on same side than (1,2)
680 
681  {float cp2 = (x3-x2)*(y1-y2)-(y3-y2)*(x1-x2); //(3-2).cross(1-2)
682  if(cp2==0) return false; // (1,2,3) aligned points.
683  float cp1 = (x3-x2)*(yo-y2)-(y3-y2)*(xo-x2);
684  if(cp1==0) { // O on (2,3). We can't pass here.
685  //m_out << "pick_action::intersect_triangle : case 1." << std::endl;
686  //m_zs.push_back(???);
687  //m_ws.push_back(???);
688  return false;
689  }
690  if((cp1*cp2)<0) return false;} // O 1 not on same side than (2,3)
691 
692  {float cp2 = (x1-x3)*(y2-y3)-(y1-y3)*(x2-x3); //(1-3).cross(2-3)
693  if(cp2==0) return false; // (1,2,3) aligned points.
694  float cp1 = (x1-x3)*(yo-y3)-(y1-y3)*(xo-x3);
695  if(cp1==0) { // O on (3,1). We can't pass here.
696  //m_out << "pick_action::intersect_triangle : case 2." << std::endl;
697  //m_zs.push_back(???);
698  //m_ws.push_back(???);
699  return false;
700  }
701  if((cp1*cp2)<0) return false;} // O 2 not on same side than (3,1)
702 
703  //std::cout << " (0,0) inside. " << std::endl;
704 
705  //get z of O=(0,0) on the triangle :
706 
707  //NOTE : optimize ?
708 
709  vec3f O(0,0,0);
710  line<vec3f> ln(O,O+vec3f(0,0,1));
711 
712  vec3f pz;
713  {vec3f p1(x1,y1,a_1z);
714  vec3f p2(x2,y2,a_2z);
715  vec3f p3(x3,y3,a_3z);
716  plane<vec3f> pl(p1,p2,p3);
717  if(!pl.intersect(ln,pz)) {
718  m_out << "pick_action::intersect_triangle :"
719  << " z plane/line intersection failed."
720  << std::endl;
721  return false;
722  }}
723 
724  // we can get w by the same plane intersection by changing the zs to ws :
725  // (in the xy plane, 1,2,3 points have same projection, then the
726  // z axis intersection with the triangle hits the same point done with zs
727  // than with ws).
728  vec3f pw;
729  {vec3f p1(x1,y1,a_1w);
730  vec3f p2(x2,y2,a_2w);
731  vec3f p3(x3,y3,a_3w);
732  plane<vec3f> pl(p1,p2,p3);
733  if(!pl.intersect(ln,pw)) {
734  m_out << "pick_action::intersect_triangle :"
735  << " plane/line intersection failed."
736  << std::endl;
737  return false;
738  }}
739  //::printf("debug : w planey %g\n",p[2]);
740 
741  //m_out << "pick_action::intersect_triangle :"
742  // << " p " << p[0] << " " << p[1] << " " << p[2]
743  // << std::endl;
744 
745  m_zs.push_back(pz[2]);
746  m_ws.push_back(pw[2]);
747 
748 /*
749  // check by using interpolation :
750  {vec3f p1(x1,y1,a_1z);
751  vec3f p2(x2,y2,a_2z);
752  vec3f p3(x3,y3,a_3z);
753  line<vec3f> l1p(p1,pz);
754  line<vec3fy> l23(p2,p3);
755  vec3f q; //on 23 side.
756  float prec = 1e10-8;
757  if(!l1p.intersect(l23,q,prec)) {
758  m_out << "pick_action::intersect_triangle :"
759  << " line/line intersection failed."
760  << std::endl;
761  return false;
762  }
763  float dq2 = (q-p2).length();
764  float d32 = (p3-p2).length();
765  if(d32==0) {
766  m_out << "pick_action::intersect_triangle :"
767  << " zero d32."
768  << std::endl;
769  return false;
770  }
771  float dp1 = (pz-p1).length();
772  float dq1 = (q-p1).length();
773  if(dq1==0) {
774  m_out << "pick_action::intersect_triangle :"
775  << " zero dq1."
776  << std::endl;
777  return false;
778  }
779 
780  float wq = a_2w + (a_3w-a_2w)*(dq2/d32);
781  float wp = a_1w + (wq-a_1w)*(dp1/dq1);
782 
783  float zq = a_2z + (a_3z-a_2z)*(dq2/d32);
784  float zp = a_1z + (zq-a_1z)*(dp1/dq1);
785 
786  ::printf("debug : pz[2] %g zp %g\n",pz[2],zp);
787  ::printf("debug : pw[2] %g wp %g\n",pw[2],wp);
788  }
789 */
790 
791  return true;
792  }
793 protected:
794  void set_to_pick_ndc() { //OPTIMIZATION
795  float cx = (m_l+m_r)/2;
796  cx /= float(m_ww);
797  cx *= 2;
798  float cy = (m_b+m_t)/2;
799  cy /= float(m_wh);
800  cy *= 2;
801 
802  float sx = m_r-m_l;
803  sx /= float(m_ww);
804  sx *= 2;
805  float sy = m_t-m_b;
806  sy /= float(m_wh);
807  sy *= 2;
808 
809  //then now cx,cy,sx,sw in [0,2]x[0,2] coords.
810  cx -= 1;
811  cy -= 1;
812  //then now cx,cy,sx,sw in [-1,1]x[-1,1] coords.
813  m_cx = cx;
814  m_cy = cy;
815  m_sx = sx;
816  m_sy = sy;
817  }
818  void to_pick_ndc(const float& a_fx,const float& a_fy,float& a_x,float& a_y) const {
819  a_x = 2*(a_fx-m_cx)/m_sx;
820  a_y = 2*(a_fy-m_cy)/m_sy;
821  }
822 protected:
823  static bool ortho_clip_line(float& a_bx,float& a_by,float& a_bz,float& a_bw,
824  float& a_ex,float& a_ey,float& a_ez,float& a_ew,
825  /*bool a_doz,*/bool& a_toggle) {
826  // it tests against a [-1,1]x[-1,1] box.
827 
828  // toggle means that at return begin contains end and end contains begin).
829  //
830  // begin out, end out
831  // output : a_toggle = false, return false.
832  // begin in, end in
833  // output : a_toggle = false, return true.
834  // begin in, end out
835  // output : a_toggle = true, begin = clipping point, return true.
836  // begin out, end in
837  // output : a_toggle = false, begin = clipping point, return true.
838 
839  a_toggle = false;
840 
841  const unsigned int FILTER__NOZ = 0xf; //4 left right bits set to 1.
842  //const unsigned int FILTER__Z = 0x3f; //6 left right bits set to 1.
843 
844  bool accept = false;
845  bool done = false;
846  do {
847  unsigned int bout = ortho_out(a_bx,a_by/*,a_bz,a_doz*/);
848  unsigned int eout = ortho_out(a_ex,a_ey/*,a_ez,a_doz*/);
849  bool reject = ( (bout & eout & FILTER__NOZ) !=0 ? true : false);
850  if(reject) { //begin and end have a common "outside bit" raised.
851  done = true;
852  } else {
853  accept = !bout && !eout;
854  if(accept) { //begin and end have all outside-bits to zero.
855  done = true;
856  } else {
857  if(!bout) { // begin inside. toggle begin and end.
858  unsigned int tout = eout;
859  float tx = a_ex;
860  float ty = a_ey;
861  float tz = a_ez;
862  float tw = a_ew;
863 
864  eout = bout;
865  a_ex = a_bx;
866  a_ey = a_by;
867  a_ez = a_bz;
868  a_ew = a_bw;
869 
870  bout = tout;
871  a_bx = tx;
872  a_by = ty;
873  a_bz = tz;
874  a_bw = tw;
875 
876  a_toggle = true;
877  }
878  if(bout & (1<<0)) { // by > 1
879  float t = a_ey - a_by;
880  //CHECK_DIV(t,"ClipLineParallel")
881  t = (1 - a_by)/t;
882  a_bx += (a_ex - a_bx) * t;
883  a_by = 1;
884  a_bz += (a_ez - a_bz) * t;
885  a_bw += (a_ew - a_bw) * t;
886  } else if(bout & (1<<1)) { // by < -1
887  float t = a_ey-a_by;
888  //CHECK_DIV(t,"ClipLineParallel")
889  t = (-1 - a_by)/t;
890  a_bx += (a_ex - a_bx) * t;
891  a_by = -1;
892  a_bz += (a_ez - a_bz) * t;
893  a_bw += (a_ew - a_bw) * t;
894  } else if(bout & (1<<2)) { // bx > 1
895  float t = a_ex-a_bx;
896  //CHECK_DIV (t,"ClipLineParallel")
897  t = (1 - a_bx)/t;
898  a_bx = 1;
899  a_by += (a_ey - a_by) * t;
900  a_bz += (a_ez - a_bz) * t;
901  a_bw += (a_ew - a_bw) * t;
902  } else if(bout & (1<<3)) { // bx < -1
903  float t = a_ex-a_bx;
904  //CHECK_DIV (t,"ClipLineParallel")
905  t = (-1 - a_bx)/t;
906  a_bx = -1;
907  a_by += (a_ey - a_by) * t;
908  a_bz += (a_ez - a_bz) * t;
909  a_bw += (a_ew - a_bw) * t;
910  }
911  // z = -1.
912  // z = 0.
913  // G.Barrand : do not do z clipping
914  /* else if(a_doz && (bout & (1<<4)) ) { //bz < -1
915  float t = a_ez-a_bz;
916  //CHECK_DIV (t,"ClipLineParallel")
917  t = (-1 - a_z)/t;
918  a_bx += (a_ex - a_bx) * t;
919  a_by += (a_ey - a_by) * t;
920  a_bz = -1;
921  a_bw += (a_ew - a_bw) * t;
922  } else if(a_doz && (bout & (1<<5)) ) { //bz > 0
923  t = a_ez - a_bz;
924  //CHECK_DIV (t,"ClipLineParallel")
925  t = (- a_bz)/t;
926  a_bx += (a_ex - a_bx) * t;
927  a_by += (a_ey - a_by) * t;
928  a_bz = 0;
929  a_bw += (a_ew - a_bw) * t;
930  } */
931  }
932  }
933  } while (!done);
934  return accept;
935  }
936 
937  static unsigned int ortho_out(float a_x,float a_y/*,float a_z,bool a_doz*/){
938  unsigned int out = 0;
939  if(a_y> 1) out |= (1<<0);
940  if(a_y<-1) out |= (1<<1);
941  if(a_x> 1) out |= (1<<2);
942  if(a_x<-1) out |= (1<<3);
943  //if(!a_doz) return out;
944  //if(a_z<-1) out |= (1<<4);
945  //if(a_z> 0) out |= (1<<5);
946  return out;
947  }
948 
949 protected:
950  // picking region (in window coordinates, (0,0) = bottom-left ) :
951  float m_l;
952  float m_r;
953  float m_b;
954  float m_t;
955 
957 
958  bool m_done;
960 
961  std::vector<float> m_zs;
962  std::vector<float> m_ws;
963  std::vector<pick_t> m_picks;
964 
965  //OPTIMIZATION:
967 };
968 
969 }}
970 
971 #endif
tools::sg::pick_action::zs
const std::vector< float > & zs() const
Definition: pick_action:320
node
tools::sg::pick_element::node
sg::node & node()
Definition: pick_action:42
tools::sg::pick_action::set_win_size
void set_win_size(unsigned a_ww, unsigned int a_wh)
Definition: pick_action:220
tools::sg::primitive_visitor::add_lines_xy
bool add_lines_xy(size_t a_floatn, const float *a_xys, bool a_stop=false)
Definition: primitive_visitor:1907
tools::sg::pick_action::add_triangle
virtual bool add_triangle(float a_p1x, float a_p1y, float a_p1z, float a_p1w, float, float, float, float, float a_p2x, float a_p2y, float a_p2z, float a_p2w, float, float, float, float, float a_p3x, float a_p3y, float a_p3z, float a_p3w, float, float, float, float)
Definition: pick_action:117
tools::sg::pick_action::node
sg::node * node() const
Definition: pick_action:258
tools::sg::pick_action::add_triangle
virtual bool add_triangle(float a_p1x, float a_p1y, float a_p1z, float a_p1w, float a_p2x, float a_p2y, float a_p2z, float a_p2w, float a_p3x, float a_p3y, float a_p3z, float a_p3w)
Definition: pick_action:105
tools::sg::state
Definition: state:25
tools::sg::pick_action::ortho_out
static unsigned int ortho_out(float a_x, float a_y)
Definition: pick_action:937
tools::sg::pick_action::m_cx
float m_cx
Definition: pick_action:966
primitive_visitor
tools::sg::pick_action::reset
void reset()
Definition: pick_action:211
tools::sg::pick_action::get_area
void get_area(float &a_l, float &a_r, float &a_b, float &a_t) const
Definition: pick_action:241
tools::sg::pick_action::m_ws
std::vector< float > m_ws
Definition: pick_action:962
tools::sg::pick_action::project_normal
virtual bool project_normal(float &, float &, float &)
Definition: pick_action:128
tools::sg::pick_element::m_zs
std::vector< float > m_zs
Definition: pick_action:54
tools::sg::matrix_action::model_matrix
mat4f & model_matrix()
Definition: matrix_action:73
tools::sg::pick_element::m_node
sg::node & m_node
Definition: pick_action:53
tools::sg::pick_action::m_stop_at_first
bool m_stop_at_first
Definition: pick_action:956
tools::plane
Definition: plane:12
tools::sg::pick_action::is_inside
bool is_inside(float a_x, float a_y, float a_z, float a_w)
Definition: pick_action:542
tools::sg::pick_action::add_triangle_normal
virtual bool add_triangle_normal(float a_p1x, float a_p1y, float a_p1z, float a_p1w, float, float, float, float a_p2x, float a_p2y, float a_p2z, float a_p2w, float, float, float, float a_p3x, float a_p3y, float a_p3z, float a_p3w, float, float, float)
Definition: pick_action:149
tools::sg::pick_action::~pick_action
virtual ~pick_action()
Definition: pick_action:179
tools::sg::pick_action::set_stop_at_first
void set_stop_at_first(bool a_value)
Definition: pick_action:251
tools::sg::primitive_visitor::add_primitive
bool add_primitive(gl::mode_t a_mode, size_t a_floatn, const float *a_xyzs, bool a_stop=false)
Definition: primitive_visitor:1518
tools::sg::pick_action::set_node
void set_node(sg::node *a_node)
Definition: pick_action:257
tools::sg::pick_action::m_b
float m_b
Definition: pick_action:953
tools::plane::intersect
bool intersect(const line< VEC3 > &a_line, VEC3 &a_intersection) const
Definition: plane:63
tools::sg::node
Definition: node:28
tools::sg::win_action::m_wh
unsigned int m_wh
Definition: win_action:38
tools::sg::pick_element::state
const sg::state & state() const
Definition: pick_action:50
tools::sg::pick_action::add_pick
void add_pick(sg::node &a_node, const std::vector< float > &a_zs, const std::vector< float > &a_ws, const sg::state &a_state)
Definition: pick_action:265
tools::sg::pick_element::~pick_element
virtual ~pick_element()
Definition: pick_action:26
tools::sg::pick_element::node
const sg::node & node() const
Definition: pick_action:41
tools::sg::pick_action::pick_action
pick_action(std::ostream &a_out, unsigned int a_ww, unsigned int a_wh, float a_l, float a_r, float a_b, float a_t)
Definition: pick_action:167
tools::sg::matrix_action
Definition: matrix_action:15
tools::sg::pick_action::add__triangles
bool add__triangles(sg::node &a_node, size_t a_floatn, const float *a_xyzs, bool a_stop=false)
Definition: pick_action:494
tools::sg::win_action::m_ww
unsigned int m_ww
Definition: win_action:37
tools::sg::pick_action::add_line
virtual bool add_line(float a_bx, float a_by, float a_bz, float a_bw, float a_ex, float a_ey, float a_ez, float a_ew)
Definition: pick_action:80
tools::sg::pick_action::set_matrices_from_state
void set_matrices_from_state()
Definition: pick_action:330
tools::sg::pick_action::add_point
virtual bool add_point(float a_x, float a_y, float a_z, float a_w)
Definition: pick_action:67
tools::sg::pick_action::stop_at_first
bool stop_at_first() const
Definition: pick_action:252
tools::sg::pick_action::add__primitive_xy
bool add__primitive_xy(sg::node &a_node, gl::mode_t a_mode, const std::vector< float > &a_xys, bool a_stop=false, bool a_triangle_revert=false)
Definition: pick_action:361
tools::sg::pick_action::set_done
void set_done(bool a_value)
Definition: pick_action:254
tools::sg::primitive_visitor::add_lines
bool add_lines(size_t a_floatn, const float *a_xyzs, bool a_stop=false)
Definition: primitive_visitor:1236
tools::sg::pick_action::add_line_normal
virtual bool add_line_normal(float a_bx, float a_by, float a_bz, float a_bw, float, float, float, float a_ex, float a_ey, float a_ez, float a_ew, float, float, float)
Definition: pick_action:140
tools::sg::primitive_visitor::add_line_strip_xy
bool add_line_strip_xy(size_t a_floatn, const float *a_xys, bool a_stop=false)
Definition: primitive_visitor:1881
tools::sg::pick_action::project
virtual bool project(float &a_x, float &a_y, float &a_z, float &a_w)
Definition: pick_action:63
tools::sg::pick_element::pick_element
pick_element(sg::node &a_node, const std::vector< float > &a_zs, const std::vector< float > &a_ws, const sg::state &a_state)
Definition: pick_action:20
tools::sg::pick_action
Definition: pick_action:59
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::sg::pick_action::closest_pick
pick_t * closest_pick()
Definition: pick_action:290
tools::sg::pick_action::m_cy
float m_cy
Definition: pick_action:966
tools::sg::pick_action::pick_action
pick_action(const pick_action &a_from)
Definition: pick_action:181
tools::sg::pick_action::m_t
float m_t
Definition: pick_action:954
tools::sg::pick_action::dump_picks
void dump_picks()
Definition: pick_action:273
tools::sg::pick_action::m_sy
float m_sy
Definition: pick_action:966
tools::sg::action::m_out
std::ostream & m_out
Definition: action:55
tools::sg::pick_action::set_matrices_to_identity
void set_matrices_to_identity()
Definition: pick_action:326
tools::sg::pick_action::ortho_clip_line
static bool ortho_clip_line(float &a_bx, float &a_by, float &a_bz, float &a_bw, float &a_ex, float &a_ey, float &a_ez, float &a_ew, bool &a_toggle)
Definition: pick_action:823
tools::sg::state::m_wh
unsigned int m_wh
Definition: state:242
matrix_action
tools::sg::pick_element::operator=
pick_element & operator=(const pick_element &a_from)
Definition: pick_action:34
tools::sg::pick_action::add__primitive
bool add__primitive(sg::node &a_node, gl::mode_t a_mode, const std::vector< float > &a_xyzs, bool a_stop=false)
Definition: pick_action:452
tools::sg::primitive_visitor::operator=
primitive_visitor & operator=(const primitive_visitor &)
Definition: primitive_visitor:61
TOOLS_ACTION
#define TOOLS_ACTION(a__class, a__sclass, a__parent)
Definition: action:60
tools::sg::pick_action::ws
std::vector< float > & ws()
Definition: pick_action:324
tools::sg::states::m_states
std::vector< sg::state > m_states
Definition: states:90
tools::sg::pick_action::m_r
float m_r
Definition: pick_action:952
tools::sg::pick_action::add_triangle_normal
virtual bool add_triangle_normal(float a_p1x, float a_p1y, float a_p1z, float a_p1w, float, float, float, float, float, float, float, float a_p2x, float a_p2y, float a_p2z, float a_p2w, float, float, float, float, float, float, float, float a_p3x, float a_p3y, float a_p3z, float a_p3w, float, float, float, float, float, float, float)
Definition: pick_action:156
tools::sg::pick_action::add__line_strip_xy
bool add__line_strip_xy(sg::node &a_node, size_t a_floatn, const float *a_xys, bool a_stop=false)
Definition: pick_action:386
tools::sg::pick_action::intersect_triangle
bool intersect_triangle(float a_1x, float a_1y, float a_1z, float a_1w, float a_2x, float a_2y, float a_2z, float a_2w, float a_3x, float a_3y, float a_3z, float a_3w)
Definition: pick_action:594
tools::sg::pick_action::operator=
pick_action & operator=(const pick_action &a_from)
Definition: pick_action:194
tools::vec3f
Definition: vec3f:13
tools::sg::pick_element::state
sg::state & state()
Definition: pick_action:51
tools::sg::pick_action::m_node
sg::node * m_node
Definition: pick_action:959
tools::gl::mode_t
unsigned char mode_t
Definition: glprims:14
tools::sg::pick_action::add__lines_xy
bool add__lines_xy(sg::node &a_node, const std::vector< float > &a_xys, bool a_stop=false)
Definition: pick_action:407
tools::minimum
bool minimum(const std::vector< T > &a_vec, T &a_value)
Definition: vmanip:203
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::sg::pick_action::picks
const std::vector< pick_t > & picks() const
Definition: pick_action:271
tools::sg::pick_action::add__line_strip
bool add__line_strip(sg::node &a_node, size_t a_floatn, const float *a_xyzs, bool a_stop=false)
Definition: pick_action:473
tools::sg::state::m_proj
mat4f m_proj
Definition: state:244
tools::sg::pick_action::add_line
virtual bool add_line(float a_bx, float a_by, float a_bz, float a_bw, float, float, float, float, float a_ex, float a_ey, float a_ez, float a_ew, float, float, float, float)
Definition: pick_action:98
tools::sg::matrix_action::m_identity
mat4f m_identity
Definition: matrix_action:129
tools::sg::pick_action::add_point_normal
virtual bool add_point_normal(float a_x, float a_y, float a_z, float a_w, float, float, float, float, float, float, float)
Definition: pick_action:134
tools::sg::primitive_visitor::add_line_strip
bool add_line_strip(size_t a_floatn, const float *a_xyzs, bool a_stop=false)
Definition: primitive_visitor:787
tools::sg::pick_element::zs
const std::vector< float > & zs() const
Definition: pick_action:44
tools::sg::state::m_model
mat4f m_model
Definition: state:245
tools::sg::pick_action::set_to_pick_ndc
void set_to_pick_ndc()
Definition: pick_action:794
tools::sg::state::m_ww
unsigned int m_ww
Definition: state:241
tools::sg::pick_action::done
bool done() const
Definition: pick_action:255
tools::sg::pick_action::add__lines
bool add__lines(sg::node &a_node, const std::vector< float > &a_xyzs, bool a_stop=false)
Definition: pick_action:518
tools::sg::pick_element::m_state
sg::state m_state
Definition: pick_action:56
tools::sg::pick_action::add_point
virtual bool add_point(float a_x, float a_y, float a_z, float a_w, float, float, float, float)
Definition: pick_action:75
tools::sg::pick_element::pick_element
pick_element(const pick_element &a_from)
Definition: pick_action:28
tools::sg::pick_element::m_ws
std::vector< float > m_ws
Definition: pick_action:55
tools::sg::pick_action::intersect_line
bool intersect_line(float a_bx, float a_by, float a_bz, float a_bw, float a_ex, float a_ey, float a_ez, float a_ew)
Definition: pick_action:568
tools::sg::pick_action::ws
const std::vector< float > & ws() const
Definition: pick_action:323
tools::sg::pick_action::add_point_normal
virtual bool add_point_normal(float a_x, float a_y, float a_z, float a_w, float, float, float)
Definition: pick_action:129
tools::sg::action::out
std::ostream & out() const
Definition: action:51
tools::sg::pick_action::m_sx
float m_sx
Definition: pick_action:966
tools::line
Definition: line:13
tools::sg::pick_action::zs
std::vector< float > & zs()
Definition: pick_action:321
tools::sg::pick_action::to_pick_ndc
void to_pick_ndc(const float &a_fx, const float &a_fy, float &a_x, float &a_y) const
Definition: pick_action:818
tools::sg::pick_action::add_line_normal
virtual bool add_line_normal(float a_bx, float a_by, float a_bz, float a_bw, float, float, float, float, float, float, float, float a_ex, float a_ey, float a_ez, float a_ew, float, float, float, float, float, float, float)
Definition: pick_action:144
tools::sg::pick_action::m_zs
std::vector< float > m_zs
Definition: pick_action:961
tools::sg::pick_action::add__primitive_xy
bool add__primitive_xy(sg::node &a_node, gl::mode_t a_mode, size_t a_floatn, const float *a_xys, bool a_stop=false, bool a_triangle_revert=false)
Definition: pick_action:336
tools::sg::pick_action::pick_t
pick_element pick_t
Definition: pick_action:263
tools::sg::pick_action::set_area
void set_area(float a_l, float a_r, float a_b, float a_t)
Definition: pick_action:230
tools::sg::pick_element::ws
std::vector< float > & ws()
Definition: pick_action:48
tools::sg::pick_action::m_l
float m_l
Definition: pick_action:951
tools::sg::states::state
const sg::state & state() const
Definition: states:76
tools::sg::pick_action::m_done
bool m_done
Definition: pick_action:958
tools::sg::pick_element
Definition: pick_action:18
tools::sg::matrix_action::projection_matrix
mat4f & projection_matrix()
Definition: matrix_action:72
tools::sg::pick_element::ws
const std::vector< float > & ws() const
Definition: pick_action:47
tools::sg::primitive_visitor
Definition: primitive_visitor:20
tools::sg::pick_action::m_picks
std::vector< pick_t > m_picks
Definition: pick_action:963
tools::sg::primitive_visitor::add_triangles
bool add_triangles(size_t a_floatn, const float *a_xyzs, bool a_stop=false)
Definition: primitive_visitor:341
tools::sg::primitive_visitor::add_primitive_xy
bool add_primitive_xy(gl::mode_t a_mode, size_t a_floatn, const float *a_xys, bool a_stop=false, bool a_triangle_revert=false)
Definition: primitive_visitor:1937
tools::sg::pick_element::zs
std::vector< float > & zs()
Definition: pick_action:45