Warning, /include/Geant4/tools/sg/pick_action is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_sg_pick_action
0005 #define tools_sg_pick_action
0006
0007 #include "matrix_action"
0008 #include "primitive_visitor"
0009
0010 #include "../lina/plane"
0011 #include "../vmanip"
0012
0013 #include "node"
0014
0015 namespace tools {
0016 namespace sg {
0017
0018 class pick_element {
0019 public:
0020 pick_element(sg::node& a_node,const std::vector<float>& a_zs,const std::vector<float>& a_ws,const sg::state& a_state)
0021 :m_node(a_node)
0022 ,m_zs(a_zs)
0023 ,m_ws(a_ws)
0024 ,m_state(a_state)
0025 {}
0026 virtual ~pick_element(){}
0027 public:
0028 pick_element(const pick_element& a_from)
0029 :m_node(a_from.m_node)
0030 ,m_zs(a_from.m_zs)
0031 ,m_ws(a_from.m_ws)
0032 ,m_state(a_from.m_state)
0033 {}
0034 pick_element& operator=(const pick_element& a_from){
0035 m_zs = a_from.m_zs;
0036 m_ws = a_from.m_ws;
0037 m_state = a_from.m_state;
0038 return *this;
0039 }
0040 public:
0041 const sg::node& node() const {return m_node;}
0042 sg::node& node() {return m_node;}
0043
0044 const std::vector<float>& zs() const {return m_zs;}
0045 std::vector<float>& zs() {return m_zs;}
0046
0047 const std::vector<float>& ws() const {return m_ws;}
0048 std::vector<float>& ws() {return m_ws;}
0049
0050 const sg::state& state() const {return m_state;}
0051 sg::state& state() {return m_state;}
0052 protected:
0053 sg::node& m_node;
0054 std::vector<float> m_zs;
0055 std::vector<float> m_ws;
0056 sg::state m_state;
0057 };
0058
0059 class pick_action : public matrix_action, public primitive_visitor {
0060 TOOLS_ACTION(pick_action,tools::sg::pick_action,matrix_action)
0061 protected:
0062
0063 virtual bool project(float& a_x,float& a_y,float& a_z,float& a_w) {
0064 return parent::project_point(a_x,a_y,a_z,a_w);
0065 }
0066
0067 virtual bool add_point(float a_x,float a_y,float a_z,float a_w) {
0068 if(is_inside(a_x,a_y,a_z,a_w)) { //we have a pick.
0069 m_done = true;
0070 return false; //to stop
0071 }
0072 return true; //continue.
0073 }
0074
0075 virtual bool add_point(float a_x,float a_y,float a_z,float a_w,
0076 float,float,float,float) {
0077 return pick_action::add_point(a_x,a_y,a_z,a_w);
0078 }
0079
0080 virtual bool add_line(float a_bx,float a_by,float a_bz,float a_bw,
0081 float a_ex,float a_ey,float a_ez,float a_ew) {
0082 if(is_inside(a_bx,a_by,a_bz,a_bw)) {
0083 m_done = true;
0084 return false;
0085 }
0086 if(is_inside(a_ex,a_ey,a_ez,a_ew)) {
0087 m_done = true;
0088 return false;
0089 }
0090 if(intersect_line(a_bx,a_by,a_bz,a_bw,
0091 a_ex,a_ey,a_ez,a_ew)) {
0092 m_done = true;
0093 return false;
0094 }
0095 return true;
0096 }
0097
0098 virtual bool add_line(float a_bx,float a_by,float a_bz,float a_bw,
0099 float,float,float,float,
0100 float a_ex,float a_ey,float a_ez,float a_ew,
0101 float,float,float,float){
0102 return pick_action::add_line(a_bx,a_by,a_bz,a_bw,a_ex,a_ey,a_ez,a_ew);
0103 }
0104
0105 virtual bool add_triangle(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
0106 float a_p2x,float a_p2y,float a_p2z,float a_p2w,
0107 float a_p3x,float a_p3y,float a_p3z,float a_p3w){
0108 if(intersect_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
0109 a_p2x,a_p2y,a_p2z,a_p2w,
0110 a_p3x,a_p3y,a_p3z,a_p3w)) {
0111 m_done = true;
0112 return false;
0113 }
0114 return true;
0115 }
0116
0117 virtual bool add_triangle(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
0118 float,float,float,float,
0119 float a_p2x,float a_p2y,float a_p2z,float a_p2w,
0120 float,float,float,float,
0121 float a_p3x,float a_p3y,float a_p3z,float a_p3w,
0122 float,float,float,float){
0123 return pick_action::add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
0124 a_p2x,a_p2y,a_p2z,a_p2w,
0125 a_p3x,a_p3y,a_p3z,a_p3w);
0126 }
0127
0128 virtual bool project_normal(float&,float&,float&) {return true;}
0129 virtual bool add_point_normal(float a_x,float a_y,float a_z,float a_w,
0130 float,float,float) {
0131 return pick_action::add_point(a_x,a_y,a_z,a_w);
0132 }
0133
0134 virtual bool add_point_normal(float a_x,float a_y,float a_z,float a_w,
0135 float,float,float,
0136 float,float,float,float) {
0137 return pick_action::add_point(a_x,a_y,a_z,a_w);
0138 }
0139
0140 virtual bool add_line_normal(float a_bx,float a_by,float a_bz,float a_bw, float,float,float,
0141 float a_ex,float a_ey,float a_ez,float a_ew, float,float,float) {
0142 return pick_action::add_line(a_bx,a_by,a_bz,a_bw,a_ex,a_ey,a_ez,a_ew);
0143 }
0144 virtual bool add_line_normal(float a_bx,float a_by,float a_bz,float a_bw, float,float,float, float,float,float,float,
0145 float a_ex,float a_ey,float a_ez,float a_ew, float,float,float, float,float,float,float) {
0146 return pick_action::add_line(a_bx,a_by,a_bz,a_bw,a_ex,a_ey,a_ez,a_ew);
0147 }
0148
0149 virtual bool add_triangle_normal(float a_p1x,float a_p1y,float a_p1z,float a_p1w, float,float,float,
0150 float a_p2x,float a_p2y,float a_p2z,float a_p2w, float,float,float,
0151 float a_p3x,float a_p3y,float a_p3z,float a_p3w, float,float,float) {
0152 return pick_action::add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
0153 a_p2x,a_p2y,a_p2z,a_p2w,
0154 a_p3x,a_p3y,a_p3z,a_p3w);
0155 }
0156 virtual bool add_triangle_normal(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
0157 float,float,float, float,float,float,float,
0158 float a_p2x,float a_p2y,float a_p2z,float a_p2w,
0159 float,float,float, float,float,float,float,
0160 float a_p3x,float a_p3y,float a_p3z,float a_p3w,
0161 float,float,float, float,float,float,float) {
0162 return pick_action::add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
0163 a_p2x,a_p2y,a_p2z,a_p2w,
0164 a_p3x,a_p3y,a_p3z,a_p3w);
0165 }
0166 public:
0167 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)
0168 :parent(a_out,a_ww,a_wh)
0169 ,m_l(a_l)
0170 ,m_r(a_r)
0171 ,m_b(a_b)
0172 ,m_t(a_t)
0173 ,m_stop_at_first(false) //same as selection
0174 ,m_done(false)
0175 ,m_node(0)
0176 {
0177 set_to_pick_ndc(); //OPTIMIZATION
0178 }
0179 virtual ~pick_action(){}
0180 public:
0181 pick_action(const pick_action& a_from)
0182 :parent(a_from)
0183 ,primitive_visitor(a_from)
0184 ,m_l(a_from.m_l)
0185 ,m_r(a_from.m_r)
0186 ,m_b(a_from.m_b)
0187 ,m_t(a_from.m_t)
0188 ,m_stop_at_first(a_from.m_stop_at_first)
0189 ,m_done(false)
0190 ,m_node(0)
0191 {
0192 set_to_pick_ndc(); //OPTIMIZATION
0193 }
0194 pick_action& operator=(const pick_action& a_from){
0195 parent::operator=(a_from);
0196 primitive_visitor::operator=(a_from);
0197 m_l = a_from.m_l;
0198 m_r = a_from.m_r;
0199 m_b = a_from.m_b;
0200 m_t = a_from.m_t;
0201 m_stop_at_first = a_from.m_stop_at_first;
0202 m_done = false;
0203 m_node = 0;
0204 m_zs.clear();
0205 m_ws.clear();
0206 m_picks.clear();
0207 set_to_pick_ndc(); //OPTIMIZATION
0208 return *this;
0209 }
0210 public:
0211 void reset() {
0212 parent::reset();
0213 m_done = false;
0214 m_node = 0;
0215 m_zs.clear();
0216 m_ws.clear();
0217 m_picks.clear();
0218 }
0219
0220 void set_win_size(unsigned a_ww,unsigned int a_wh) {
0221 m_ww = a_ww;
0222 m_wh = a_wh;
0223 sg::state& _state = state();
0224 _state.m_ww = a_ww;
0225 _state.m_wh = a_wh;
0226 m_states.clear();
0227 reset();
0228 }
0229
0230 void set_area(float a_l,float a_r,float a_b,float a_t) {
0231 // a_l,a_r,a_b,a_t are in window coordinates (pixels)
0232 // but handled in floats for intersection computation precision.
0233 // WARNING : we must have a_t>a_b and a_r>a_l. No check is done for that.
0234 m_l = a_l;
0235 m_r = a_r;
0236 m_b = a_b;
0237 m_t = a_t;
0238 set_to_pick_ndc(); //OPTIMIZATION
0239 }
0240
0241 void get_area(float& a_l,float& a_r,float& a_b,float& a_t) const {
0242 a_l = m_l;
0243 a_r = m_r;
0244 a_b = m_b;
0245 a_t = m_t;
0246 }
0247
0248 /////////////////////////////////////////////
0249 /////////////////////////////////////////////
0250 /////////////////////////////////////////////
0251 void set_stop_at_first(bool a_value) {m_stop_at_first = a_value;}
0252 bool stop_at_first() const {return m_stop_at_first;}
0253
0254 void set_done(bool a_value) {m_done = a_value;}
0255 bool done() const {return m_done;}
0256
0257 void set_node(sg::node* a_node) {m_node = a_node;}
0258 sg::node* node() const {return m_node;}
0259
0260 /////////////////////////////////////////////
0261 /////////////////////////////////////////////
0262 /////////////////////////////////////////////
0263 typedef pick_element pick_t;
0264
0265 void add_pick(sg::node& a_node,
0266 const std::vector<float>& a_zs,
0267 const std::vector<float>& a_ws,
0268 const sg::state& a_state) {
0269 m_picks.push_back(pick_t(a_node,a_zs,a_ws,a_state));
0270 }
0271 const std::vector<pick_t>& picks() const {return m_picks;}
0272
0273 void dump_picks() {
0274 m_out << "tools::sg::pick_action :"
0275 << " number of picks " << m_picks.size()
0276 << std::endl;
0277 std::vector<pick_t>::const_iterator it;
0278 for(it=m_picks.begin();it!=m_picks.end();++it) {
0279 m_out << " " << (*it).node().s_cls();
0280
0281 std::vector<float>::const_iterator itz;
0282 for(itz=(*it).zs().begin();itz!=(*it).zs().end();++itz) {
0283 m_out << " " << *itz;
0284 }
0285
0286 m_out << std::endl;
0287 }
0288 }
0289
0290 pick_t* closest_pick() {
0291 if(m_picks.empty()) return 0;
0292 //closest point is minimum z !
0293 // near -> -1
0294 // far -> 1
0295
0296 // find first pick_t with not empty zs :
0297 pick_t* pck = 0;
0298 float z;
0299 std::vector<pick_t>::const_iterator it;
0300 for(it=m_picks.begin();it!=m_picks.end();++it) {
0301 if(minimum((*it).zs(),z)) {
0302 pck = (pick_t*)&(*it);
0303 break;
0304 }
0305 }
0306 if(!pck) return 0;
0307 it++;
0308 for(;it!=m_picks.end();++it) {
0309 float zi;
0310 if(minimum((*it).zs(),zi)) {
0311 if(zi<=z) {
0312 pck = (pick_t*)&(*it);
0313 z = zi;
0314 }
0315 }
0316 }
0317 return pck;
0318 }
0319
0320 const std::vector<float>& zs() const {return m_zs;}
0321 std::vector<float>& zs() {return m_zs;}
0322
0323 const std::vector<float>& ws() const {return m_ws;}
0324 std::vector<float>& ws() {return m_ws;}
0325
0326 void set_matrices_to_identity() {
0327 projection_matrix() = m_identity;
0328 model_matrix() = m_identity;
0329 }
0330 void set_matrices_from_state() {
0331 const sg::state& _state = state();
0332 projection_matrix() = _state.m_proj;
0333 model_matrix() = _state.m_model;
0334 }
0335 public:
0336 bool add__primitive_xy(sg::node& a_node,
0337 gl::mode_t a_mode,
0338 size_t a_floatn,const float* a_xys,
0339 bool a_stop = false,
0340 bool a_triangle_revert = false){
0341 if(!a_floatn) return false;
0342 if(m_stop_at_first){
0343 add_primitive_xy(a_mode,a_floatn,a_xys,a_stop,a_triangle_revert);
0344 if(m_done) {
0345 m_node = &a_node;
0346 return true;
0347 }
0348 } else {
0349 m_done = false;
0350 m_zs.clear();
0351 add_primitive_xy(a_mode,a_floatn,a_xys,a_stop,a_triangle_revert);
0352 if(m_done) {
0353 add_pick(a_node,m_zs,m_ws,state());
0354 m_done = false;
0355 return true;
0356 }
0357 }
0358 return false;
0359 }
0360
0361 bool add__primitive_xy(sg::node& a_node,
0362 gl::mode_t a_mode,
0363 const std::vector<float>& a_xys,
0364 bool a_stop = false,
0365 bool a_triangle_revert = false){
0366 if(a_xys.empty()) return false;
0367 if(m_stop_at_first){
0368 add_primitive_xy(a_mode,a_xys,a_stop,a_triangle_revert);
0369 if(m_done) {
0370 m_node = &a_node;
0371 return true;
0372 }
0373 } else {
0374 m_done = false;
0375 m_zs.clear();
0376 add_primitive_xy(a_mode,a_xys,a_stop,a_triangle_revert);
0377 if(m_done) {
0378 add_pick(a_node,m_zs,m_ws,state());
0379 m_done = false;
0380 return true;
0381 }
0382 }
0383 return false;
0384 }
0385
0386 bool add__line_strip_xy(sg::node& a_node,size_t a_floatn,const float* a_xys,bool a_stop = false){
0387 if(!a_floatn) return false;
0388 if(m_stop_at_first){
0389 add_line_strip_xy(a_floatn,a_xys,a_stop);
0390 if(m_done) {
0391 m_node = &a_node;
0392 return true;
0393 }
0394 } else {
0395 m_done = false;
0396 m_zs.clear();
0397 add_line_strip_xy(a_floatn,a_xys,a_stop);
0398 if(m_done) {
0399 add_pick(a_node,m_zs,m_ws,state());
0400 m_done = false;
0401 return true;
0402 }
0403 }
0404 return false;
0405 }
0406
0407 bool add__lines_xy(sg::node& a_node,
0408 const std::vector<float>& a_xys,
0409 bool a_stop = false) {
0410 if(a_xys.empty()) return false;
0411 if(m_stop_at_first){
0412 add_lines_xy(a_xys,a_stop);
0413 if(m_done) {
0414 m_node = &a_node;
0415 return true;
0416 }
0417 } else {
0418 m_done = false;
0419 m_zs.clear();
0420 add_lines_xy(a_xys,a_stop);
0421 if(m_done) {
0422 add_pick(a_node,m_zs,m_ws,state());
0423 m_done = false;
0424 return true;
0425 }
0426 }
0427 return false;
0428 }
0429
0430 public:
0431 bool add__primitive(sg::node& a_node,gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs,bool a_stop = false){
0432 if(!a_floatn) return false;
0433 if(m_stop_at_first){
0434 add_primitive(a_mode,a_floatn,a_xyzs,a_stop);
0435 if(m_done) {
0436 m_node = &a_node;
0437 return true;
0438 }
0439 } else {
0440 m_done = false;
0441 m_zs.clear();
0442 add_primitive(a_mode,a_floatn,a_xyzs,a_stop);
0443 if(m_done) {
0444 add_pick(a_node,m_zs,m_ws,state());
0445 m_done = false;
0446 return true;
0447 }
0448 }
0449 return false;
0450 }
0451
0452 bool add__primitive(sg::node& a_node,gl::mode_t a_mode,const std::vector<float>& a_xyzs,bool a_stop = false) {
0453 if(a_xyzs.empty()) return false;
0454 if(m_stop_at_first){
0455 add_primitive(a_mode,a_xyzs,a_stop);
0456 if(m_done) {
0457 m_node = &a_node;
0458 return true;
0459 }
0460 } else {
0461 m_done = false;
0462 m_zs.clear();
0463 add_primitive(a_mode,a_xyzs,a_stop);
0464 if(m_done) {
0465 add_pick(a_node,m_zs,m_ws,state());
0466 m_done = false;
0467 return true;
0468 }
0469 }
0470 return false;
0471 }
0472
0473 bool add__line_strip(sg::node& a_node,size_t a_floatn,const float* a_xyzs,bool a_stop = false){
0474 if(!a_floatn) return false;
0475 if(m_stop_at_first){
0476 add_line_strip(a_floatn,a_xyzs,a_stop);
0477 if(m_done) {
0478 m_node = &a_node;
0479 return true;
0480 }
0481 } else {
0482 m_done = false;
0483 m_zs.clear();
0484 add_line_strip(a_floatn,a_xyzs,a_stop);
0485 if(m_done) {
0486 add_pick(a_node,m_zs,m_ws,state());
0487 m_done = false;
0488 return true;
0489 }
0490 }
0491 return false;
0492 }
0493
0494 bool add__triangles(sg::node& a_node,
0495 size_t a_floatn,
0496 const float* a_xyzs,
0497 bool a_stop = false){
0498 if(!a_floatn) return false;
0499 if(m_stop_at_first){
0500 add_triangles(a_floatn,a_xyzs,a_stop);
0501 if(m_done) {
0502 m_node = &a_node;
0503 return true;
0504 }
0505 } else {
0506 m_done = false;
0507 m_zs.clear();
0508 add_triangles(a_floatn,a_xyzs,a_stop);
0509 if(m_done) {
0510 add_pick(a_node,m_zs,m_ws,state());
0511 m_done = false;
0512 return true;
0513 }
0514 }
0515 return false;
0516 }
0517
0518 bool add__lines(sg::node& a_node,
0519 const std::vector<float>& a_xyzs,
0520 bool a_stop = false){
0521 if(a_xyzs.empty()) return false;
0522 if(m_stop_at_first){
0523 add_lines(a_xyzs,a_stop);
0524 if(m_done) {
0525 m_node = &a_node;
0526 return true;
0527 }
0528 } else {
0529 m_done = false;
0530 m_zs.clear();
0531 add_lines(a_xyzs,a_stop);
0532 if(m_done) {
0533 add_pick(a_node,m_zs,m_ws,state());
0534 m_done = false;
0535 return true;
0536 }
0537 }
0538 return false;
0539 }
0540
0541 public: //for markers
0542 bool is_inside(float a_x,float a_y,float a_z,float a_w) {
0543 //std::cout << "debug : tools::sg::pick_action::is_inside :"
0544 // << " x " << a_x
0545 // << " y " << a_y
0546 // << std::endl;
0547
0548 // In principle we should receive (because of proj x model matrix
0549 // mult of world coord points) point in [-1,1]x[-1,1].
0550
0551 float x,y;
0552 to_pick_ndc(a_x,a_y,x,y);
0553
0554 if(x<-1) return false;
0555 if(1<x) return false;
0556 if(y<-1) return false;
0557 if(1<y) return false;
0558
0559 //std::cout << "debug : tools::sg::pick_action::is_inside :"
0560 // << " inside !"
0561 // << std::endl;
0562
0563 m_zs.push_back(a_z);
0564 m_ws.push_back(a_w);
0565
0566 return true;
0567 }
0568 bool intersect_line(float a_bx,float a_by,float a_bz,float a_bw,
0569 float a_ex,float a_ey,float a_ez,float a_ew) {
0570
0571 // a_bz, a_ez are used only to compute the intersection point.
0572
0573 float bx,by;
0574 to_pick_ndc(a_bx,a_by,bx,by);
0575 float ex,ey;
0576 to_pick_ndc(a_ex,a_ey,ex,ey);
0577
0578 //no check on z is done.
0579 float bz = a_bz;
0580 float bw = a_bw;
0581 float ez = a_ez;
0582 float ew = a_ew;
0583
0584 bool toggle;
0585 if(!ortho_clip_line(bx,by,bz,bw, ex,ey,ez,ew, toggle)) return false;
0586
0587 m_zs.push_back(bz);
0588 m_ws.push_back(bw);
0589
0590 return true;
0591 }
0592
0593 protected:
0594 bool intersect_triangle(float a_1x,float a_1y,float a_1z,float a_1w,
0595 float a_2x,float a_2y,float a_2z,float a_2w,
0596 float a_3x,float a_3y,float a_3z,float a_3w) {
0597 //test a triangle.
0598
0599 if(is_inside(a_1x,a_1y,a_1z,a_1w)) return true;
0600 if(is_inside(a_2x,a_2y,a_2z,a_2w)) return true;
0601 if(is_inside(a_3x,a_3y,a_3z,a_3w)) return true;
0602
0603 // alll points are outside.
0604
0605 float x1,y1;
0606 to_pick_ndc(a_1x,a_1y,x1,y1);
0607 float x2,y2;
0608 to_pick_ndc(a_2x,a_2y,x2,y2);
0609
0610 bool toggle;
0611 float bx,by,bz,bw,ex,ey,ez,ew;
0612
0613 bx = x1;
0614 by = y1;
0615 bz = a_1z;
0616 bw = a_1w;
0617
0618 ex = x2;
0619 ey = y2;
0620 ez = a_2z;
0621 ew = a_2w;
0622 if(ortho_clip_line(bx,by,bz,bw, ex,ey,ez,ew, toggle)) {
0623 m_zs.push_back(bz);
0624 m_ws.push_back(bw);
0625 return true;
0626 }
0627
0628 float x3,y3;
0629 to_pick_ndc(a_3x,a_3y,x3,y3);
0630
0631 bx = x2;
0632 by = y2;
0633 bz = a_2z;
0634 bw = a_2w;
0635
0636 ex = x3;
0637 ey = y3;
0638 ez = a_3z;
0639 ew = a_3w;
0640 if(ortho_clip_line(bx,by,bz,bw, ex,ey,ez,ew, toggle)) {
0641 m_zs.push_back(bz);
0642 m_ws.push_back(bw);
0643 return true;
0644 }
0645
0646 bx = x1;
0647 by = y1;
0648 bz = a_1z;
0649 bw = a_1w;
0650
0651 ex = x3;
0652 ey = y3;
0653 ez = a_3z;
0654 ew = a_3w;
0655 if(ortho_clip_line(bx,by,bz,bw, ex,ey,ez,ew, toggle)) {
0656 m_zs.push_back(bz);
0657 m_ws.push_back(bw);
0658 return true;
0659 }
0660
0661 // no intersection with edges.
0662 // but the triangle may surround [-1,1]x[-1,1] !
0663
0664 // test if O=(0,0) is inside the triangle :
0665
0666 float xo = 0;
0667 float yo = 0;
0668 //float zo = 0;
0669
0670 {float cp2 = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1); //(2-1).cross(3-1)
0671 if(cp2==0) return false; // (1,2,3) aligned points.
0672 float cp1 = (x2-x1)*(yo-y1)-(y2-y1)*(xo-x1);
0673 if(cp1==0) { // O on (1,2). We can't pass here.
0674 //m_out << "pick_action::intersect_triangle : case 0." << std::endl;
0675 //m_zs.push_back(???);
0676 //m_ws.push_back(???);
0677 return false;
0678 }
0679 if((cp1*cp2)<0) return false;} // O 3 not on same side than (1,2)
0680
0681 {float cp2 = (x3-x2)*(y1-y2)-(y3-y2)*(x1-x2); //(3-2).cross(1-2)
0682 if(cp2==0) return false; // (1,2,3) aligned points.
0683 float cp1 = (x3-x2)*(yo-y2)-(y3-y2)*(xo-x2);
0684 if(cp1==0) { // O on (2,3). We can't pass here.
0685 //m_out << "pick_action::intersect_triangle : case 1." << std::endl;
0686 //m_zs.push_back(???);
0687 //m_ws.push_back(???);
0688 return false;
0689 }
0690 if((cp1*cp2)<0) return false;} // O 1 not on same side than (2,3)
0691
0692 {float cp2 = (x1-x3)*(y2-y3)-(y1-y3)*(x2-x3); //(1-3).cross(2-3)
0693 if(cp2==0) return false; // (1,2,3) aligned points.
0694 float cp1 = (x1-x3)*(yo-y3)-(y1-y3)*(xo-x3);
0695 if(cp1==0) { // O on (3,1). We can't pass here.
0696 //m_out << "pick_action::intersect_triangle : case 2." << std::endl;
0697 //m_zs.push_back(???);
0698 //m_ws.push_back(???);
0699 return false;
0700 }
0701 if((cp1*cp2)<0) return false;} // O 2 not on same side than (3,1)
0702
0703 //std::cout << " (0,0) inside. " << std::endl;
0704
0705 //get z of O=(0,0) on the triangle :
0706
0707 //NOTE : optimize ?
0708
0709 vec3f O(0,0,0);
0710 line<vec3f> ln(O,O+vec3f(0,0,1));
0711
0712 vec3f pz;
0713 {vec3f p1(x1,y1,a_1z);
0714 vec3f p2(x2,y2,a_2z);
0715 vec3f p3(x3,y3,a_3z);
0716 plane<vec3f> pl(p1,p2,p3);
0717 if(!pl.intersect(ln,pz)) {
0718 m_out << "pick_action::intersect_triangle :"
0719 << " z plane/line intersection failed."
0720 << std::endl;
0721 return false;
0722 }}
0723
0724 // we can get w by the same plane intersection by changing the zs to ws :
0725 // (in the xy plane, 1,2,3 points have same projection, then the
0726 // z axis intersection with the triangle hits the same point done with zs
0727 // than with ws).
0728 vec3f pw;
0729 {vec3f p1(x1,y1,a_1w);
0730 vec3f p2(x2,y2,a_2w);
0731 vec3f p3(x3,y3,a_3w);
0732 plane<vec3f> pl(p1,p2,p3);
0733 if(!pl.intersect(ln,pw)) {
0734 m_out << "pick_action::intersect_triangle :"
0735 << " plane/line intersection failed."
0736 << std::endl;
0737 return false;
0738 }}
0739 //::printf("debug : w planey %g\n",p[2]);
0740
0741 //m_out << "pick_action::intersect_triangle :"
0742 // << " p " << p[0] << " " << p[1] << " " << p[2]
0743 // << std::endl;
0744
0745 m_zs.push_back(pz[2]);
0746 m_ws.push_back(pw[2]);
0747
0748 /*
0749 // check by using interpolation :
0750 {vec3f p1(x1,y1,a_1z);
0751 vec3f p2(x2,y2,a_2z);
0752 vec3f p3(x3,y3,a_3z);
0753 line<vec3f> l1p(p1,pz);
0754 line<vec3fy> l23(p2,p3);
0755 vec3f q; //on 23 side.
0756 float prec = 1e10-8;
0757 if(!l1p.intersect(l23,q,prec)) {
0758 m_out << "pick_action::intersect_triangle :"
0759 << " line/line intersection failed."
0760 << std::endl;
0761 return false;
0762 }
0763 float dq2 = (q-p2).length();
0764 float d32 = (p3-p2).length();
0765 if(d32==0) {
0766 m_out << "pick_action::intersect_triangle :"
0767 << " zero d32."
0768 << std::endl;
0769 return false;
0770 }
0771 float dp1 = (pz-p1).length();
0772 float dq1 = (q-p1).length();
0773 if(dq1==0) {
0774 m_out << "pick_action::intersect_triangle :"
0775 << " zero dq1."
0776 << std::endl;
0777 return false;
0778 }
0779
0780 float wq = a_2w + (a_3w-a_2w)*(dq2/d32);
0781 float wp = a_1w + (wq-a_1w)*(dp1/dq1);
0782
0783 float zq = a_2z + (a_3z-a_2z)*(dq2/d32);
0784 float zp = a_1z + (zq-a_1z)*(dp1/dq1);
0785
0786 ::printf("debug : pz[2] %g zp %g\n",pz[2],zp);
0787 ::printf("debug : pw[2] %g wp %g\n",pw[2],wp);
0788 }
0789 */
0790
0791 return true;
0792 }
0793 protected:
0794 void set_to_pick_ndc() { //OPTIMIZATION
0795 float cx = (m_l+m_r)/2;
0796 cx /= float(m_ww);
0797 cx *= 2;
0798 float cy = (m_b+m_t)/2;
0799 cy /= float(m_wh);
0800 cy *= 2;
0801
0802 float sx = m_r-m_l;
0803 sx /= float(m_ww);
0804 sx *= 2;
0805 float sy = m_t-m_b;
0806 sy /= float(m_wh);
0807 sy *= 2;
0808
0809 //then now cx,cy,sx,sw in [0,2]x[0,2] coords.
0810 cx -= 1;
0811 cy -= 1;
0812 //then now cx,cy,sx,sw in [-1,1]x[-1,1] coords.
0813 m_cx = cx;
0814 m_cy = cy;
0815 m_sx = sx;
0816 m_sy = sy;
0817 }
0818 void to_pick_ndc(const float& a_fx,const float& a_fy,float& a_x,float& a_y) const {
0819 a_x = 2*(a_fx-m_cx)/m_sx;
0820 a_y = 2*(a_fy-m_cy)/m_sy;
0821 }
0822 protected:
0823 static bool ortho_clip_line(float& a_bx,float& a_by,float& a_bz,float& a_bw,
0824 float& a_ex,float& a_ey,float& a_ez,float& a_ew,
0825 /*bool a_doz,*/bool& a_toggle) {
0826 // it tests against a [-1,1]x[-1,1] box.
0827
0828 // toggle means that at return begin contains end and end contains begin).
0829 //
0830 // begin out, end out
0831 // output : a_toggle = false, return false.
0832 // begin in, end in
0833 // output : a_toggle = false, return true.
0834 // begin in, end out
0835 // output : a_toggle = true, begin = clipping point, return true.
0836 // begin out, end in
0837 // output : a_toggle = false, begin = clipping point, return true.
0838
0839 a_toggle = false;
0840
0841 const unsigned int FILTER__NOZ = 0xf; //4 left right bits set to 1.
0842 //const unsigned int FILTER__Z = 0x3f; //6 left right bits set to 1.
0843
0844 bool accept = false;
0845 bool done = false;
0846 do {
0847 unsigned int bout = ortho_out(a_bx,a_by/*,a_bz,a_doz*/);
0848 unsigned int eout = ortho_out(a_ex,a_ey/*,a_ez,a_doz*/);
0849 bool reject = ( (bout & eout & FILTER__NOZ) !=0 ? true : false);
0850 if(reject) { //begin and end have a common "outside bit" raised.
0851 done = true;
0852 } else {
0853 accept = !bout && !eout;
0854 if(accept) { //begin and end have all outside-bits to zero.
0855 done = true;
0856 } else {
0857 if(!bout) { // begin inside. toggle begin and end.
0858 unsigned int tout = eout;
0859 float tx = a_ex;
0860 float ty = a_ey;
0861 float tz = a_ez;
0862 float tw = a_ew;
0863
0864 eout = bout;
0865 a_ex = a_bx;
0866 a_ey = a_by;
0867 a_ez = a_bz;
0868 a_ew = a_bw;
0869
0870 bout = tout;
0871 a_bx = tx;
0872 a_by = ty;
0873 a_bz = tz;
0874 a_bw = tw;
0875
0876 a_toggle = true;
0877 }
0878 if(bout & (1<<0)) { // by > 1
0879 float t = a_ey - a_by;
0880 //CHECK_DIV(t,"ClipLineParallel")
0881 t = (1 - a_by)/t;
0882 a_bx += (a_ex - a_bx) * t;
0883 a_by = 1;
0884 a_bz += (a_ez - a_bz) * t;
0885 a_bw += (a_ew - a_bw) * t;
0886 } else if(bout & (1<<1)) { // by < -1
0887 float t = a_ey-a_by;
0888 //CHECK_DIV(t,"ClipLineParallel")
0889 t = (-1 - a_by)/t;
0890 a_bx += (a_ex - a_bx) * t;
0891 a_by = -1;
0892 a_bz += (a_ez - a_bz) * t;
0893 a_bw += (a_ew - a_bw) * t;
0894 } else if(bout & (1<<2)) { // bx > 1
0895 float t = a_ex-a_bx;
0896 //CHECK_DIV (t,"ClipLineParallel")
0897 t = (1 - a_bx)/t;
0898 a_bx = 1;
0899 a_by += (a_ey - a_by) * t;
0900 a_bz += (a_ez - a_bz) * t;
0901 a_bw += (a_ew - a_bw) * t;
0902 } else if(bout & (1<<3)) { // bx < -1
0903 float t = a_ex-a_bx;
0904 //CHECK_DIV (t,"ClipLineParallel")
0905 t = (-1 - a_bx)/t;
0906 a_bx = -1;
0907 a_by += (a_ey - a_by) * t;
0908 a_bz += (a_ez - a_bz) * t;
0909 a_bw += (a_ew - a_bw) * t;
0910 }
0911 // z = -1.
0912 // z = 0.
0913 // G.Barrand : do not do z clipping
0914 /* else if(a_doz && (bout & (1<<4)) ) { //bz < -1
0915 float t = a_ez-a_bz;
0916 //CHECK_DIV (t,"ClipLineParallel")
0917 t = (-1 - a_z)/t;
0918 a_bx += (a_ex - a_bx) * t;
0919 a_by += (a_ey - a_by) * t;
0920 a_bz = -1;
0921 a_bw += (a_ew - a_bw) * t;
0922 } else if(a_doz && (bout & (1<<5)) ) { //bz > 0
0923 t = a_ez - a_bz;
0924 //CHECK_DIV (t,"ClipLineParallel")
0925 t = (- a_bz)/t;
0926 a_bx += (a_ex - a_bx) * t;
0927 a_by += (a_ey - a_by) * t;
0928 a_bz = 0;
0929 a_bw += (a_ew - a_bw) * t;
0930 } */
0931 }
0932 }
0933 } while (!done);
0934 return accept;
0935 }
0936
0937 static unsigned int ortho_out(float a_x,float a_y/*,float a_z,bool a_doz*/){
0938 unsigned int out = 0;
0939 if(a_y> 1) out |= (1<<0);
0940 if(a_y<-1) out |= (1<<1);
0941 if(a_x> 1) out |= (1<<2);
0942 if(a_x<-1) out |= (1<<3);
0943 //if(!a_doz) return out;
0944 //if(a_z<-1) out |= (1<<4);
0945 //if(a_z> 0) out |= (1<<5);
0946 return out;
0947 }
0948
0949 protected:
0950 // picking region (in window coordinates, (0,0) = bottom-left ) :
0951 float m_l;
0952 float m_r;
0953 float m_b;
0954 float m_t;
0955
0956 bool m_stop_at_first;
0957
0958 bool m_done;
0959 sg::node* m_node;
0960
0961 std::vector<float> m_zs;
0962 std::vector<float> m_ws;
0963 std::vector<pick_t> m_picks;
0964
0965 //OPTIMIZATION:
0966 float m_cx,m_cy,m_sx,m_sy;
0967 };
0968
0969 }}
0970
0971 #endif