Warning, /include/Geant4/tools/sg/base_camera 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_base_camera
0005 #define tools_sg_base_camera
0006
0007 #include "node"
0008
0009 #include "sf_vec3f"
0010 #include "sf_vec4f"
0011 #include "sf_rotf"
0012
0013 #include "render_action"
0014 #include "pick_action"
0015 #include "event_action"
0016 #include "visible_action"
0017 #include "enums"
0018
0019 #include "../mathf" //astro
0020
0021 namespace tools {
0022 namespace sg {
0023
0024 class base_camera : public node {
0025 TOOLS_HEADER(base_camera,tools::sg::base_camera,node)
0026 public:
0027 sf<float> znear;
0028 sf<float> zfar;
0029 sf_vec3f position;
0030 //Camera orientation specified as a rotation value from the default
0031 //orientation where the camera is pointing along the negative z-axis,
0032 //with "up" along the positive y-axis.
0033 sf_rotf orientation;
0034
0035 //for viewers :
0036 sf<float> dx;
0037 sf<float> da;
0038 sf<float> ds;
0039 sf<float> focal;
0040 public:
0041 virtual const desc_fields& node_desc_fields() const {
0042 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::base_camera)
0043 static const desc_fields s_v(parent::node_desc_fields(),8, //WARNING : take care of count.
0044 TOOLS_ARG_FIELD_DESC(znear),
0045 TOOLS_ARG_FIELD_DESC(zfar),
0046 TOOLS_ARG_FIELD_DESC(position),
0047 TOOLS_ARG_FIELD_DESC(orientation),
0048 TOOLS_ARG_FIELD_DESC(dx),
0049 TOOLS_ARG_FIELD_DESC(da),
0050 TOOLS_ARG_FIELD_DESC(ds),
0051 TOOLS_ARG_FIELD_DESC(focal)
0052 );
0053 return s_v;
0054 }
0055 private:
0056 void add_fields(){
0057 add_field(&znear);
0058 add_field(&zfar);
0059 add_field(&position);
0060 add_field(&orientation);
0061
0062 add_field(&dx);
0063 add_field(&da);
0064 add_field(&ds);
0065 add_field(&focal);
0066 }
0067 public:
0068 virtual float near_height() const = 0;
0069 virtual void zoom(float) = 0;
0070 virtual camera_type type() const = 0;
0071 virtual void get_lrbt(unsigned int,unsigned int,
0072 float&,float&,float&,float&) = 0;
0073 public:
0074 virtual void render(render_action& a_action) {
0075 _mult_matrix(a_action);
0076 set_state(a_action);
0077 a_action.load_proj_matrix(a_action.projection_matrix());
0078 a_action.load_model_matrix(a_action.model_matrix());
0079 }
0080 virtual void pick(pick_action& a_action) {
0081 _mult_matrix(a_action);
0082 set_state(a_action);
0083 }
0084 virtual void event(event_action& a_action){
0085 _mult_matrix(a_action);
0086 set_state(a_action);
0087 }
0088 virtual void get_matrix(get_matrix_action& a_action){
0089 _mult_matrix(a_action);
0090 set_state(a_action);
0091 }
0092 virtual void is_visible(visible_action& a_action){
0093 _mult_matrix(a_action);
0094 set_state(a_action);
0095 }
0096 protected:
0097 base_camera()
0098 :parent()
0099 ,znear(1)
0100 ,zfar(10)
0101 ,position(vec3f(0,0,1))
0102 ,orientation(rotf(vec3f(0,0,1),0)) //quat = vec4f(0,0,0,1)
0103 ,dx(0.01f)
0104 ,da(0.017f) //one degree.
0105 ,ds(0.99f)
0106 ,focal(1)
0107 {
0108 add_fields();
0109 }
0110 public:
0111 virtual ~base_camera(){
0112 }
0113 protected:
0114 base_camera(const base_camera& a_from)
0115 :parent(a_from)
0116 ,znear(a_from.znear)
0117 ,zfar(a_from.zfar)
0118 ,position(a_from.position)
0119 ,orientation(a_from.orientation)
0120 ,dx(a_from.dx)
0121 ,da(a_from.da)
0122 ,ds(a_from.ds)
0123 ,focal(a_from.focal)
0124 {
0125 add_fields();
0126 }
0127 base_camera& operator=(const base_camera& a_from){
0128 parent::operator=(a_from);
0129 znear = a_from.znear;
0130 zfar = a_from.zfar;
0131 position = a_from.position;
0132 orientation = a_from.orientation;
0133 dx = a_from.dx;
0134 da = a_from.da;
0135 ds = a_from.ds;
0136 focal = a_from.focal;
0137 m_lrbt.set_value(0,0,0,0);
0138 return *this;
0139 }
0140 protected: //operators:
0141 bool operator==(const base_camera& a_from) const{
0142 if(znear!=a_from.znear) return false;
0143 if(zfar!=a_from.zfar) return false;
0144 if(position!=a_from.position) return false;
0145 if(orientation!=a_from.orientation) return false;
0146 //we do not test dx,da,ds.
0147 return true;
0148 }
0149 public:
0150 void direction(vec3f& a_dir) const {
0151 orientation.value().mul_vec(vec3f(0,0,-1),a_dir);
0152 }
0153
0154 void rotate_around_direction(float a_delta) {
0155 orientation.value(rotf(vec3f(0,0,-1),a_delta) * orientation.value());
0156 }
0157
0158 void rotate_around_z(float a_delta) {
0159 orientation.value(rotf(vec3f(0,0,1),a_delta) * orientation.value());
0160 }
0161
0162 void rotate_around_up(float a_delta){
0163 vec3f up;
0164 orientation.value().mul_vec(vec3f(0,1,0),up);
0165 // must be the below so that rot-cam works for exlib/cbk/[astro,cfitsio] astro setup.
0166 // (astro setup change camera orientation).
0167 orientation.value(orientation.value() * rotf(up,a_delta));
0168 }
0169
0170 void rotate_around_x(float a_delta){
0171 orientation.value(rotf(vec3f(1,0,0),a_delta) * orientation.value());
0172 }
0173
0174 void rotate_around_x_at_focal(float a_delta){
0175 //from coin SoGuiExaminerViewerP::rotXWheelMotion.
0176 vec3f dir;
0177 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0178 vec3f focalpoint = position.value() + focal * dir;
0179 orientation.value(rotf(vec3f(1,0,0),a_delta) * orientation.value());
0180 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0181 position = focalpoint - focal * dir;
0182 }
0183
0184 void rotate_around_y_at_focal(float a_delta){
0185 //from coin SoGuiExaminerViewerP::rotYWheelMotion.
0186 vec3f dir;
0187 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0188 vec3f focalpoint = position.value() + focal * dir;
0189 orientation.value(rotf(vec3f(0,1,0),a_delta) * orientation.value());
0190 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0191 position = focalpoint - focal * dir;
0192 }
0193
0194 void rotate_around_z_at_focal(float a_delta){
0195 //from coin SoGuiExaminerViewerP::rotYWheelMotion.
0196 vec3f dir;
0197 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0198 vec3f focalpoint = position.value() + focal * dir;
0199 orientation.value(rotf(vec3f(0,0,1),a_delta) * orientation.value());
0200 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0201 position = focalpoint - focal * dir;
0202 }
0203
0204 void rotate_to_dir(const vec3f& a_dir) {
0205 //rotate around up so that a_dir is in (dir,up) plane
0206
0207 //NOTE : it is the invert of orientation which is used
0208 // in projection matrix.
0209
0210 {vec3f dir;
0211 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0212 vec3f up;
0213 orientation.value().mul_vec(vec3f(0,1,0),up);
0214 vec3f side;dir.cross(up,side);
0215 vec3f v = side * (side.dot(a_dir)) + dir * (dir.dot(a_dir));
0216 if(v.normalize()) orientation.value(orientation.value()*rotf(dir,v));}
0217
0218 //rotate around dir^up so that a_dir matches dir.
0219 {vec3f dir;
0220 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0221 orientation.value(orientation.value()*rotf(dir,a_dir));}
0222
0223 }
0224
0225 void pane_to(float a_x,float a_y,float a_z){
0226 //translate in view plane so that (a_x,a_y,a_z) is on direction.
0227
0228 vec3f dir;
0229 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0230 vec3f up;
0231 orientation.value().mul_vec(vec3f(0,1,0),up);
0232 vec3f side;dir.cross(up,side);
0233
0234 vec3f d(a_x,a_y,a_z);
0235 d.subtract(position.value());
0236
0237 vec3f pos = position.value() + side * (side.dot(d)) + up * (up.dot(d));
0238 position.value(pos);
0239 }
0240
0241 void translate_along_side(float a_delta){
0242 vec3f dir;
0243 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0244 vec3f up;
0245 orientation.value().mul_vec(vec3f(0,1,0),up);
0246 vec3f side;dir.cross(up,side);
0247 vec3f pos = position.value() + side * a_delta;
0248 position.value(pos);
0249 }
0250 void translate_along_up(float a_delta){
0251 vec3f dir;
0252 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0253 vec3f up;
0254 orientation.value().mul_vec(vec3f(0,1,0),up);
0255 vec3f pos = position.value() + up * a_delta;
0256 position.value(pos);
0257 }
0258 void translate_along_dir(float a_delta){
0259 vec3f dir;
0260 orientation.value().mul_vec(vec3f(0,0,-1),dir);
0261 vec3f pos = position.value() + dir * a_delta;
0262 position.value(pos);
0263 }
0264
0265 bool look_at(const vec3f& a_dir,const vec3f& a_up) {
0266 vec3f z = -a_dir;
0267 vec3f y = a_up;
0268 vec3f x;y.cross(z,x);
0269
0270 // recompute y to create a valid coordinate system
0271 z.cross(x,y);
0272
0273 // normalize x and y to create an orthonormal coord system
0274 if(!x.normalize()) return false;
0275 if(!y.normalize()) return false;
0276 if(!z.normalize()) return false;
0277
0278 // create a rotation matrix
0279 mat4f rot;
0280 rot.set_identity();
0281 rot.set_value(0,0,x[0]);
0282 rot.set_value(1,0,x[1]);
0283 rot.set_value(2,0,x[2]);
0284
0285 rot.set_value(0,1,y[0]);
0286 rot.set_value(1,1,y[1]);
0287 rot.set_value(2,1,y[2]);
0288
0289 rot.set_value(0,2,z[0]);
0290 rot.set_value(1,2,z[1]);
0291 rot.set_value(2,2,z[2]);
0292
0293 orientation.value().set_value(rot);
0294 return true;
0295 }
0296
0297 //NOTE : print is a Python keyword.
0298 void dump(std::ostream& a_out) {
0299 a_out << " znear " << znear.value() << std::endl;
0300 a_out << " zfar " << zfar.value() << std::endl;
0301 vec3f& pos = position.value();
0302 a_out << " pos " << pos[0] << " " << pos[1] << " " << pos[2] << std::endl;
0303 //FIXME : dump orientation.
0304 }
0305
0306 bool is_type_ortho() const {return type()==camera_ortho?true:false;}
0307
0308 bool height_at_focal(float& a_h) const {
0309 if(is_type_ortho()) {
0310 a_h = near_height();
0311 } else {
0312 if(!znear.value()) {a_h = near_height();return false;}
0313 a_h = focal.value()*near_height()/znear.value();
0314 }
0315 return true;
0316 }
0317
0318 void astro_orientation(float a_ra,float a_dec/*,const vec3f& a_center*/) {
0319 // a_ra, a_dec are in decimal degrees.
0320
0321 // Camera default point toward -z with up along +y and +x at right.
0322
0323 // Arrange so that camera points toward x with up along +z :
0324 rotf r(vec3f::s_y(),-fhalf_pi());
0325 r *= rotf(vec3f::s_x(),fhalf_pi());
0326 // Now -y is at right.
0327
0328 // Then rotate it so that it points toward given (ra,dec) by keeping up upward +z direction.
0329 r *= rotf(vec3f::s_y(),-a_dec*fdeg2rad());
0330 r *= rotf(vec3f::s_z(),a_ra*fdeg2rad());
0331 orientation = r;
0332 }
0333
0334 bool update_motion(int a_move) {
0335 float _dx = dx;
0336 float _da = da;
0337 float _ds = ds;
0338
0339 if(a_move==move_rotate_right) { //should match camera_yaw().
0340 rotate_around_up(_da);
0341 return true;
0342 }
0343 if(a_move==move_rotate_left) {
0344 rotate_around_up(-_da);
0345 return true;
0346 }
0347
0348 if(a_move==move_rotate_up) { //should match camera_pitch().
0349 rotate_around_x(_da);
0350 return true;
0351 }
0352 if(a_move==move_rotate_down) {
0353 rotate_around_x(-_da);
0354 return true;
0355 }
0356
0357 if(a_move==move_roll_plus) { //should match camera_roll().
0358 rotate_around_direction(-_da); //direction = -z, then the minus.
0359 return true;
0360 }
0361 if(a_move==move_roll_minus) {
0362 rotate_around_direction(_da);
0363 return true;
0364 }
0365
0366 if(a_move==move_translate_right) {
0367 translate_along_side(_dx);
0368 return true;
0369 }
0370 if(a_move==move_translate_left) {
0371 translate_along_side(-_dx);
0372 return true;
0373 }
0374
0375 if(a_move==move_up) {
0376 translate_along_up(_dx);
0377 return true;
0378 }
0379 if(a_move==move_down) {
0380 translate_along_up(-_dx);
0381 return true;
0382 }
0383 if(a_move==move_forward) {
0384 translate_along_dir(_dx);
0385 return true;
0386 }
0387 if(a_move==move_backward) {
0388 translate_along_dir(-_dx);
0389 return true;
0390 }
0391 if(a_move==move_zoom_in) {
0392 zoom(_ds);
0393 return true;
0394 }
0395 if(a_move==move_zoom_out) {
0396 zoom(1.0f/_ds);
0397 return true;
0398 }
0399
0400 if(a_move==move_rotate_around_focal_right) { //yaw around focal.
0401 rotate_around_y_at_focal(_da);
0402 return true;
0403 }
0404 if(a_move==move_rotate_around_focal_left) {
0405 rotate_around_y_at_focal(-_da);
0406 return true;
0407 }
0408 if(a_move==move_rotate_around_focal_up) { //pitch around focal.
0409 rotate_around_x_at_focal(_da);
0410 return true;
0411 }
0412 if(a_move==move_rotate_around_focal_down) {
0413 rotate_around_x_at_focal(-_da);
0414 return true;
0415 }
0416 if(a_move==move_roll_around_focal_plus) {
0417 rotate_around_z_at_focal(_da);
0418 return true;
0419 }
0420 if(a_move==move_roll_around_focal_minus) {
0421 rotate_around_z_at_focal(-_da);
0422 return true;
0423 }
0424
0425 return false;
0426 }
0427 protected:
0428 void update_sg(std::ostream& a_out) {
0429
0430 {const vec4f& v = m_lrbt.value();
0431 float l = v[0];
0432 float r = v[1];
0433 float b = v[2];
0434 float t = v[3];
0435 float n = znear.value();
0436 float f = zfar.value();
0437 if(is_type_ortho()) {
0438 m_proj.set_ortho(l,r,b,t,n,f);
0439 } else {
0440 m_proj.set_frustum(l,r,b,t,n,f);
0441 }}
0442
0443 if(orientation.value().quat()!=id_orientation()) //OPTIMIZATION
0444 {rotf rinv;
0445 if(orientation.value().inverse(rinv)) {
0446 mat4f mtx;
0447 rinv.value(mtx);
0448 m_proj.mul_mtx(mtx,m_tmp);
0449 } else {
0450 a_out << "update_sg :"
0451 << " get orientation inverse failed."
0452 << std::endl;
0453 }}
0454
0455 m_proj.mul_translate(-position.value()[0],
0456 -position.value()[1],
0457 -position.value()[2]);
0458 }
0459
0460 void _mult_matrix(matrix_action& a_action) {
0461 float l,r,b,t;
0462 get_lrbt(a_action.ww(),a_action.wh(),l,r,b,t);
0463 m_lrbt.set_value(l,r,b,t);
0464
0465 if(touched()||m_lrbt.touched()) {
0466 update_sg(a_action.out());
0467 reset_touched();
0468 m_lrbt.reset_touched();
0469 }
0470
0471 a_action.projection_matrix().mul_mtx(m_proj,m_tmp);
0472 }
0473
0474 void set_state(matrix_action& a_action) {
0475 state& _state = a_action.state();
0476 _state.m_camera_ortho = is_type_ortho();
0477 _state.m_camera_znear = znear;
0478 _state.m_camera_zfar = zfar;
0479 _state.m_camera_position = position.value();
0480 _state.m_camera_orientation = orientation.value();
0481 //_state.m_camera_near_height = near_height();
0482 _state.m_camera_lrbt = m_lrbt.value();
0483 _state.m_proj = a_action.projection_matrix();
0484 }
0485
0486 static const vec4<float>& id_orientation() {static const vec4<float> s_v(0,0,0,1);return s_v;}
0487
0488 protected:
0489 //OPTIMIZATION :
0490 sf_vec4f m_lrbt;
0491 mat4f m_proj;
0492 float m_tmp[16];
0493 };
0494
0495 }}
0496
0497 #endif