Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 2 // See the file tools.license for terms. 3 4 #ifndef tools_sg_base_camera 5 #define tools_sg_base_camera 6 7 #include "node" 8 9 #include "sf_vec3f" 10 #include "sf_vec4f" 11 #include "sf_rotf" 12 13 #include "render_action" 14 #include "pick_action" 15 #include "event_action" 16 #include "visible_action" 17 #include "enums" 18 19 #include "../mathf" //astro 20 21 namespace tools { 22 namespace sg { 23 24 class base_camera : public node { 25 TOOLS_HEADER(base_camera,tools::sg::base_cam 26 public: 27 sf<float> znear; 28 sf<float> zfar; 29 sf_vec3f position; 30 //Camera orientation specified as a rotation 31 //orientation where the camera is pointing a 32 //with "up" along the positive y-axis. 33 sf_rotf orientation; 34 35 //for viewers : 36 sf<float> dx; 37 sf<float> da; 38 sf<float> ds; 39 sf<float> focal; 40 public: 41 virtual const desc_fields& node_desc_fields( 42 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::bas 43 static const desc_fields s_v(parent::node_ 44 TOOLS_ARG_FIELD_DESC(znear), 45 TOOLS_ARG_FIELD_DESC(zfar), 46 TOOLS_ARG_FIELD_DESC(position), 47 TOOLS_ARG_FIELD_DESC(orientation), 48 TOOLS_ARG_FIELD_DESC(dx), 49 TOOLS_ARG_FIELD_DESC(da), 50 TOOLS_ARG_FIELD_DESC(ds), 51 TOOLS_ARG_FIELD_DESC(focal) 52 ); 53 return s_v; 54 } 55 private: 56 void add_fields(){ 57 add_field(&znear); 58 add_field(&zfar); 59 add_field(&position); 60 add_field(&orientation); 61 62 add_field(&dx); 63 add_field(&da); 64 add_field(&ds); 65 add_field(&focal); 66 } 67 public: 68 virtual float near_height() const = 0; 69 virtual void zoom(float) = 0; 70 virtual camera_type type() const = 0; 71 virtual void get_lrbt(unsigned int,unsigned 72 float&,float&,float&,f 73 public: 74 virtual void render(render_action& a_action) 75 _mult_matrix(a_action); 76 set_state(a_action); 77 //{mat4f& _mtx = a_action.projection_matrix() 78 // a_action.out() << "debug : tools::sg::base 79 // a_action.out() << _mtx << std::endl;} 80 a_action.load_proj_matrix(a_action.project 81 a_action.load_model_matrix(a_action.model_ 82 } 83 virtual void pick(pick_action& a_action) { 84 _mult_matrix(a_action); 85 set_state(a_action); 86 } 87 virtual void event(event_action& a_action){ 88 _mult_matrix(a_action); 89 set_state(a_action); 90 } 91 virtual void get_matrix(get_matrix_action& a 92 _mult_matrix(a_action); 93 set_state(a_action); 94 } 95 virtual void is_visible(visible_action& a_ac 96 _mult_matrix(a_action); 97 set_state(a_action); 98 } 99 protected: 100 base_camera() 101 :parent() 102 ,znear(1) 103 ,zfar(10) 104 ,position(vec3f(0,0,1)) 105 ,orientation(rotf(vec3f(0,0,1),0)) //quat = 106 ,dx(0.01f) 107 ,da(0.017f) //one degree. 108 ,ds(0.99f) 109 ,focal(1) 110 { 111 #ifdef TOOLS_MEM 112 mem::increment(s_class().c_str()); 113 #endif 114 add_fields(); 115 } 116 public: 117 virtual ~base_camera(){ 118 #ifdef TOOLS_MEM 119 mem::decrement(s_class().c_str()); 120 #endif 121 } 122 protected: 123 base_camera(const base_camera& a_from) 124 :parent(a_from) 125 ,znear(a_from.znear) 126 ,zfar(a_from.zfar) 127 ,position(a_from.position) 128 ,orientation(a_from.orientation) 129 ,dx(a_from.dx) 130 ,da(a_from.da) 131 ,ds(a_from.ds) 132 ,focal(a_from.focal) 133 { 134 #ifdef TOOLS_MEM 135 mem::increment(s_class().c_str()); 136 #endif 137 add_fields(); 138 } 139 base_camera& operator=(const base_camera& a_ 140 parent::operator=(a_from); 141 znear = a_from.znear; 142 zfar = a_from.zfar; 143 position = a_from.position; 144 orientation = a_from.orientation; 145 dx = a_from.dx; 146 da = a_from.da; 147 ds = a_from.ds; 148 focal = a_from.focal; 149 m_lrbt.set_value(0,0,0,0); 150 return *this; 151 } 152 protected: //operators: 153 bool operator==(const base_camera& a_from) c 154 if(znear!=a_from.znear) return false; 155 if(zfar!=a_from.zfar) return false; 156 if(position!=a_from.position) return false 157 if(orientation!=a_from.orientation) return 158 //we do not test dx,da,ds. 159 return true; 160 } 161 //bool operator!=(const base_camera& a_from) 162 // return !operator==(a_from); 163 //} 164 public: 165 void direction(vec3f& a_dir) const { 166 orientation.value().mul_vec(vec3f(0,0,-1), 167 } 168 169 void rotate_around_direction(float a_delta) 170 //vec3f dir; 171 //orientation.value().mul_vec(vec3f(0,0,-1), 172 //orientation.value(rotf(dir,a_delta) * orie 173 orientation.value(rotf(vec3f(0,0,-1),a_del 174 } 175 176 void rotate_around_z(float a_delta) { 177 //vec3f z; 178 //orientation.value().mul_vec(vec3f(0,0,1),z 179 //orientation.value(rotf(z,a_delta) * orient 180 orientation.value(rotf(vec3f(0,0,1),a_delt 181 } 182 183 void rotate_around_up(float a_delta){ 184 vec3f up; 185 orientation.value().mul_vec(vec3f(0,1,0),u 186 //orientation.value(rotf(up,a_delta) * orien 187 // must be the below so that rot-cam works 188 // (astro setup change camera orientation) 189 orientation.value(orientation.value() * ro 190 } 191 192 void rotate_around_x(float a_delta){ 193 orientation.value(rotf(vec3f(1,0,0),a_delt 194 } 195 196 void rotate_around_x_at_focal(float a_delta) 197 //from coin SoGuiExaminerViewerP::rotXWhee 198 vec3f dir; 199 orientation.value().mul_vec(vec3f(0,0,-1), 200 vec3f focalpoint = position.value() + foca 201 orientation.value(rotf(vec3f(1,0,0),a_delt 202 orientation.value().mul_vec(vec3f(0,0,-1), 203 position = focalpoint - focal * dir; 204 } 205 206 void rotate_around_y_at_focal(float a_delta) 207 //from coin SoGuiExaminerViewerP::rotYWhee 208 vec3f dir; 209 orientation.value().mul_vec(vec3f(0,0,-1), 210 vec3f focalpoint = position.value() + foca 211 orientation.value(rotf(vec3f(0,1,0),a_delt 212 orientation.value().mul_vec(vec3f(0,0,-1), 213 position = focalpoint - focal * dir; 214 } 215 216 void rotate_around_z_at_focal(float a_delta) 217 //from coin SoGuiExaminerViewerP::rotYWhee 218 vec3f dir; 219 orientation.value().mul_vec(vec3f(0,0,-1), 220 vec3f focalpoint = position.value() + foca 221 orientation.value(rotf(vec3f(0,0,1),a_delt 222 orientation.value().mul_vec(vec3f(0,0,-1), 223 position = focalpoint - focal * dir; 224 } 225 226 void rotate_to_dir(const vec3f& a_dir) { 227 //rotate around up so that a_dir is in (di 228 229 //NOTE : it is the invert of orientation w 230 // in projection matrix. 231 232 {vec3f dir; 233 orientation.value().mul_vec(vec3f(0,0,-1), 234 vec3f up; 235 orientation.value().mul_vec(vec3f(0,1,0),u 236 vec3f side;dir.cross(up,side); 237 vec3f v = side * (side.dot(a_dir)) + dir * 238 if(v.normalize()) orientation.value(orient 239 240 //rotate around dir^up so that a_dir match 241 {vec3f dir; 242 orientation.value().mul_vec(vec3f(0,0,-1), 243 orientation.value(orientation.value()*rotf 244 245 /* 246 //check that dir is on a_dir : 247 {vec3f dir; 248 orientation.value().mul_vec(vec3f(0,0,-1), 249 float cos_angle; //it should be 1 250 if(!dir.cos_angle(a_dir,cos_angle)) { 251 ::printf("debug : can't get angle\n"); 252 return; 253 } 254 ::printf("debug : cos_angle %g\n",cos_angl 255 */ 256 } 257 258 void pane_to(float a_x,float a_y,float a_z){ 259 //translate in view plane so that (a_x,a_y 260 261 vec3f dir; 262 orientation.value().mul_vec(vec3f(0,0,-1), 263 vec3f up; 264 orientation.value().mul_vec(vec3f(0,1,0),u 265 vec3f side;dir.cross(up,side); 266 267 vec3f d(a_x,a_y,a_z); 268 d.subtract(position.value()); 269 270 vec3f pos = position.value() + side * (sid 271 position.value(pos); 272 } 273 274 void translate_along_side(float a_delta){ 275 vec3f dir; 276 orientation.value().mul_vec(vec3f(0,0,-1), 277 vec3f up; 278 orientation.value().mul_vec(vec3f(0,1,0),u 279 vec3f side;dir.cross(up,side); 280 vec3f pos = position.value() + side * a_de 281 position.value(pos); 282 } 283 void translate_along_up(float a_delta){ 284 vec3f dir; 285 orientation.value().mul_vec(vec3f(0,0,-1), 286 vec3f up; 287 orientation.value().mul_vec(vec3f(0,1,0),u 288 vec3f pos = position.value() + up * a_delt 289 position.value(pos); 290 } 291 void translate_along_dir(float a_delta){ 292 vec3f dir; 293 orientation.value().mul_vec(vec3f(0,0,-1), 294 vec3f pos = position.value() + dir * a_del 295 position.value(pos); 296 } 297 298 bool look_at(const vec3f& a_dir,const vec3f& 299 vec3f z = -a_dir; 300 vec3f y = a_up; 301 vec3f x;y.cross(z,x); 302 303 // recompute y to create a valid coordinat 304 z.cross(x,y); 305 306 // normalize x and y to create an orthonor 307 if(!x.normalize()) return false; 308 if(!y.normalize()) return false; 309 if(!z.normalize()) return false; 310 311 // create a rotation matrix 312 mat4f rot; 313 rot.set_identity(); 314 rot.set_value(0,0,x[0]); 315 rot.set_value(1,0,x[1]); 316 rot.set_value(2,0,x[2]); 317 318 rot.set_value(0,1,y[0]); 319 rot.set_value(1,1,y[1]); 320 rot.set_value(2,1,y[2]); 321 322 rot.set_value(0,2,z[0]); 323 rot.set_value(1,2,z[1]); 324 rot.set_value(2,2,z[2]); 325 326 orientation.value().set_value(rot); 327 return true; 328 } 329 330 //NOTE : print is a Python keyword. 331 void dump(std::ostream& a_out) { 332 a_out << " znear " << znear.value() << std 333 a_out << " zfar " << zfar.value() << std:: 334 vec3f& pos = position.value(); 335 a_out << " pos " << pos[0] << " " << pos[1 336 //FIXME : dump orientation. 337 } 338 339 bool is_type_ortho() const {return type()==c 340 341 bool height_at_focal(float& a_h) const { 342 if(is_type_ortho()) { 343 a_h = near_height(); 344 } else { 345 if(!znear.value()) {a_h = near_height(); 346 a_h = focal.value()*near_height()/znear. 347 } 348 return true; 349 } 350 351 void astro_orientation(float a_ra,float a_de 352 // a_ra, a_dec are in decimal degrees. 353 354 // Camera default point toward -z with up 355 356 // Arrange so that camera points toward x 357 rotf r(vec3f::s_y(),-fhalf_pi()); 358 r *= rotf(vec3f::s_x(),fhalf_pi()); 359 // Now -y is at right. 360 361 // Then rotate it so that it points toward 362 r *= rotf(vec3f::s_y(),-a_dec*fdeg2rad()); 363 r *= rotf(vec3f::s_z(),a_ra*fdeg2rad()); 364 orientation = r; 365 366 /* 367 position = a_center*0.99f; 368 znear = 0.1f; 369 zfar = 200.0f; 370 focal = (a_center-position).length(); 371 */ 372 /* 373 position = vec3f(0,0,0); 374 znear = 1.0f; 375 zfar = 2000.0f; //2*sky_radius. 376 focal = a_center.length(); 377 da = 0.017f/100; //1/100 of a degree 378 */ 379 } 380 381 bool update_motion(int a_move) { 382 float _dx = dx; 383 float _da = da; 384 float _ds = ds; 385 386 if(a_move==move_rotate_right) { //should m 387 rotate_around_up(_da); 388 return true; 389 } 390 if(a_move==move_rotate_left) { 391 rotate_around_up(-_da); 392 return true; 393 } 394 395 if(a_move==move_rotate_up) { //should mat 396 rotate_around_x(_da); 397 return true; 398 } 399 if(a_move==move_rotate_down) { 400 rotate_around_x(-_da); 401 return true; 402 } 403 404 if(a_move==move_roll_plus) { //should mat 405 rotate_around_direction(-_da); //direct 406 return true; 407 } 408 if(a_move==move_roll_minus) { 409 rotate_around_direction(_da); 410 return true; 411 } 412 413 if(a_move==move_translate_right) { 414 translate_along_side(_dx); 415 return true; 416 } 417 if(a_move==move_translate_left) { 418 translate_along_side(-_dx); 419 return true; 420 } 421 422 if(a_move==move_up) { 423 translate_along_up(_dx); 424 return true; 425 } 426 if(a_move==move_down) { 427 translate_along_up(-_dx); 428 return true; 429 } 430 if(a_move==move_forward) { 431 translate_along_dir(_dx); 432 return true; 433 } 434 if(a_move==move_backward) { 435 translate_along_dir(-_dx); 436 return true; 437 } 438 if(a_move==move_zoom_in) { 439 zoom(_ds); 440 return true; 441 } 442 if(a_move==move_zoom_out) { 443 zoom(1.0f/_ds); 444 return true; 445 } 446 447 if(a_move==move_rotate_around_focal_right) 448 rotate_around_y_at_focal(_da); 449 return true; 450 } 451 if(a_move==move_rotate_around_focal_left) 452 rotate_around_y_at_focal(-_da); 453 return true; 454 } 455 if(a_move==move_rotate_around_focal_up) { 456 rotate_around_x_at_focal(_da); 457 return true; 458 } 459 if(a_move==move_rotate_around_focal_down) 460 rotate_around_x_at_focal(-_da); 461 return true; 462 } 463 if(a_move==move_roll_around_focal_plus) { 464 rotate_around_z_at_focal(_da); 465 return true; 466 } 467 if(a_move==move_roll_around_focal_minus) { 468 rotate_around_z_at_focal(-_da); 469 return true; 470 } 471 472 return false; 473 } 474 protected: 475 void update_sg(std::ostream& a_out) { 476 477 {const vec4f& v = m_lrbt.value(); 478 float l = v[0]; 479 float r = v[1]; 480 float b = v[2]; 481 float t = v[3]; 482 float n = znear.value(); 483 float f = zfar.value(); 484 if(is_type_ortho()) { 485 m_proj.set_ortho(l,r,b,t,n,f); 486 } else { 487 m_proj.set_frustum(l,r,b,t,n,f); 488 }} 489 490 if(orientation.value().quat()!=id_orientat 491 {rotf rinv; 492 if(orientation.value().inverse(rinv)) { 493 mat4f mtx; 494 rinv.value(mtx); 495 m_proj.mul_mtx(mtx,m_tmp); 496 } else { 497 a_out << "update_sg :" 498 << " get orientation inverse faile 499 << std::endl; 500 }} 501 502 m_proj.mul_translate(-position.value()[0], 503 -position.value()[1], 504 -position.value()[2]) 505 } 506 507 void _mult_matrix(matrix_action& a_action) { 508 float l,r,b,t; 509 get_lrbt(a_action.ww(),a_action.wh(),l,r,b 510 m_lrbt.set_value(l,r,b,t); 511 512 if(touched()||m_lrbt.touched()) { 513 update_sg(a_action.out()); 514 reset_touched(); 515 m_lrbt.reset_touched(); 516 } 517 518 a_action.projection_matrix().mul_mtx(m_pro 519 } 520 521 void set_state(matrix_action& a_action) { 522 state& _state = a_action.state(); 523 _state.m_camera_ortho = is_type_ortho(); 524 _state.m_camera_znear = znear; 525 _state.m_camera_zfar = zfar; 526 _state.m_camera_position = position.value( 527 _state.m_camera_orientation = orientation. 528 //_state.m_camera_near_height = near_heigh 529 _state.m_camera_lrbt = m_lrbt.value(); 530 _state.m_proj = a_action.projection_matrix 531 } 532 533 #if defined(TOOLS_MEM) && !defined(TOOLS_MEM_A 534 static const vec4<float>& id_orientation() { 535 #else 536 static const vec4<float>& id_orientation() { 537 #endif 538 539 protected: 540 //OPTIMIZATION : 541 sf_vec4f m_lrbt; 542 mat4f m_proj; 543 float m_tmp[16]; 544 }; 545 546 }} 547 548 #endif