Geant4 Cross Reference |
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 {} 34 pick_element& operator=(const pick_element& a_from){ 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: 53 sg::node& m_node; 54 std::vector<float> m_zs; 55 std::vector<float> m_ws; 56 sg::state m_state; 57 }; 58 59 class pick_action : public matrix_action, public primitive_visitor { 60 TOOLS_ACTION(pick_action,tools::sg::pick_action,matrix_action) 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) 188 ,m_stop_at_first(a_from.m_stop_at_first) 189 ,m_done(false) 190 ,m_node(0) 191 { 192 set_to_pick_ndc(); //OPTIMIZATION 193 } 194 pick_action& operator=(const pick_action& a_from){ 195 parent::operator=(a_from); 196 primitive_visitor::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; 201 m_stop_at_first = a_from.m_stop_at_first; 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 248 ///////////////////////////////////////////// 249 ///////////////////////////////////////////// 250 ///////////////////////////////////////////// 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 260 ///////////////////////////////////////////// 261 ///////////////////////////////////////////// 262 ///////////////////////////////////////////// 263 typedef pick_element pick_t; 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 290 pick_t* closest_pick() { 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 326 void set_matrices_to_identity() { 327 projection_matrix() = m_identity; 328 model_matrix() = m_identity; 329 } 330 void set_matrices_from_state() { 331 const sg::state& _state = state(); 332 projection_matrix() = _state.m_proj; 333 model_matrix() = _state.m_model; 334 } 335 public: 336 bool add__primitive_xy(sg::node& a_node, 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 361 bool add__primitive_xy(sg::node& a_node, 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 956 bool m_stop_at_first; 957 958 bool m_done; 959 sg::node* m_node; 960 961 std::vector<float> m_zs; 962 std::vector<float> m_ws; 963 std::vector<pick_t> m_picks; 964 965 //OPTIMIZATION: 966 float m_cx,m_cy,m_sx,m_sy; 967 }; 968 969 }} 970 971 #endif