Back to home page

EIC code displayed by LXR

 
 

    


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  //{mat4f& _mtx = a_action.projection_matrix();
0078  // a_action.out() << "debug : tools::sg::base_camera::render : proj :" << std::endl;
0079  // a_action.out() << _mtx << std::endl;}
0080     a_action.load_proj_matrix(a_action.projection_matrix());
0081     a_action.load_model_matrix(a_action.model_matrix());
0082   }
0083   virtual void pick(pick_action& a_action) {
0084     _mult_matrix(a_action);
0085     set_state(a_action);
0086   }
0087   virtual void event(event_action& a_action){
0088     _mult_matrix(a_action);
0089     set_state(a_action);
0090   }
0091   virtual void get_matrix(get_matrix_action& a_action){
0092     _mult_matrix(a_action);
0093     set_state(a_action);
0094   }
0095   virtual void is_visible(visible_action& a_action){
0096     _mult_matrix(a_action);
0097     set_state(a_action);
0098   }
0099 protected:
0100   base_camera()
0101   :parent()
0102   ,znear(1)
0103   ,zfar(10)
0104   ,position(vec3f(0,0,1))
0105   ,orientation(rotf(vec3f(0,0,1),0)) //quat = vec4f(0,0,0,1)
0106   ,dx(0.01f)
0107   ,da(0.017f) //one degree.
0108   ,ds(0.99f)
0109   ,focal(1)
0110   {
0111 #ifdef TOOLS_MEM
0112     mem::increment(s_class().c_str());
0113 #endif
0114     add_fields();
0115   }
0116 public:
0117   virtual ~base_camera(){
0118 #ifdef TOOLS_MEM
0119     mem::decrement(s_class().c_str());
0120 #endif
0121   }
0122 protected:
0123   base_camera(const base_camera& a_from)
0124   :parent(a_from)
0125   ,znear(a_from.znear)
0126   ,zfar(a_from.zfar)
0127   ,position(a_from.position)
0128   ,orientation(a_from.orientation)
0129   ,dx(a_from.dx)
0130   ,da(a_from.da)
0131   ,ds(a_from.ds)
0132   ,focal(a_from.focal)
0133   {
0134 #ifdef TOOLS_MEM
0135     mem::increment(s_class().c_str());
0136 #endif
0137     add_fields();
0138   }
0139   base_camera& operator=(const base_camera& a_from){
0140     parent::operator=(a_from);
0141     znear = a_from.znear;
0142     zfar = a_from.zfar;
0143     position = a_from.position;
0144     orientation = a_from.orientation;
0145     dx = a_from.dx;
0146     da = a_from.da;
0147     ds = a_from.ds;
0148     focal = a_from.focal;
0149     m_lrbt.set_value(0,0,0,0);
0150     return *this;
0151   }
0152 protected: //operators:
0153   bool operator==(const base_camera& a_from) const{
0154     if(znear!=a_from.znear) return false;
0155     if(zfar!=a_from.zfar) return false;
0156     if(position!=a_from.position) return false;
0157     if(orientation!=a_from.orientation) return false;
0158     //we do not test dx,da,ds.
0159     return true;
0160   }
0161   //bool operator!=(const base_camera& a_from) const {
0162   //  return !operator==(a_from);
0163   //}
0164 public:
0165   void direction(vec3f& a_dir) const {
0166     orientation.value().mul_vec(vec3f(0,0,-1),a_dir);
0167   }
0168 
0169   void rotate_around_direction(float a_delta) {
0170   //vec3f dir;
0171   //orientation.value().mul_vec(vec3f(0,0,-1),dir);
0172   //orientation.value(rotf(dir,a_delta) * orientation.value());
0173     orientation.value(rotf(vec3f(0,0,-1),a_delta) * orientation.value());
0174   }
0175 
0176   void rotate_around_z(float a_delta) {
0177   //vec3f z;
0178   //orientation.value().mul_vec(vec3f(0,0,1),z);
0179   //orientation.value(rotf(z,a_delta) * orientation.value());
0180     orientation.value(rotf(vec3f(0,0,1),a_delta) * orientation.value());
0181   }
0182 
0183   void rotate_around_up(float a_delta){
0184     vec3f up;
0185     orientation.value().mul_vec(vec3f(0,1,0),up);
0186   //orientation.value(rotf(up,a_delta) * orientation.value());
0187     // must be the below so that rot-cam works for exlib/cbk/[astro,cfitsio] astro setup.
0188     // (astro setup change camera orientation).
0189     orientation.value(orientation.value() * rotf(up,a_delta));
0190   }
0191 
0192   void rotate_around_x(float a_delta){
0193     orientation.value(rotf(vec3f(1,0,0),a_delta) * orientation.value());
0194   }
0195 
0196   void rotate_around_x_at_focal(float a_delta){
0197     //from coin SoGuiExaminerViewerP::rotXWheelMotion.
0198     vec3f dir;
0199     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0200     vec3f focalpoint = position.value() + focal * dir;
0201     orientation.value(rotf(vec3f(1,0,0),a_delta) * orientation.value());
0202     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0203     position = focalpoint - focal * dir;
0204   }
0205 
0206   void rotate_around_y_at_focal(float a_delta){
0207     //from coin SoGuiExaminerViewerP::rotYWheelMotion.
0208     vec3f dir;
0209     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0210     vec3f focalpoint = position.value() + focal * dir;
0211     orientation.value(rotf(vec3f(0,1,0),a_delta) * orientation.value());
0212     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0213     position = focalpoint - focal * dir;
0214   }
0215 
0216   void rotate_around_z_at_focal(float a_delta){
0217     //from coin SoGuiExaminerViewerP::rotYWheelMotion.
0218     vec3f dir;
0219     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0220     vec3f focalpoint = position.value() + focal * dir;
0221     orientation.value(rotf(vec3f(0,0,1),a_delta) * orientation.value());
0222     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0223     position = focalpoint - focal * dir;
0224   }
0225 
0226   void rotate_to_dir(const vec3f& a_dir) {
0227     //rotate around up so that a_dir is in (dir,up) plane
0228 
0229     //NOTE : it is the invert of orientation which is used
0230     //       in projection matrix.
0231 
0232    {vec3f dir;
0233     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0234     vec3f up;
0235     orientation.value().mul_vec(vec3f(0,1,0),up);
0236     vec3f side;dir.cross(up,side);
0237     vec3f v = side * (side.dot(a_dir)) + dir * (dir.dot(a_dir));
0238     if(v.normalize()) orientation.value(orientation.value()*rotf(dir,v));}
0239 
0240     //rotate around dir^up so that a_dir matches dir.
0241    {vec3f dir;
0242     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0243     orientation.value(orientation.value()*rotf(dir,a_dir));}
0244 
0245 /*
0246     //check that dir is on a_dir :
0247    {vec3f dir;
0248     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0249     float cos_angle; //it should be 1
0250     if(!dir.cos_angle(a_dir,cos_angle)) {
0251       ::printf("debug : can't get angle\n");
0252       return;
0253     }
0254     ::printf("debug : cos_angle %g\n",cos_angle);}
0255 */
0256   }
0257 
0258   void pane_to(float a_x,float a_y,float a_z){
0259     //translate in view plane so that (a_x,a_y,a_z) is on direction.
0260 
0261     vec3f dir;
0262     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0263     vec3f up;
0264     orientation.value().mul_vec(vec3f(0,1,0),up);
0265     vec3f side;dir.cross(up,side);
0266 
0267     vec3f d(a_x,a_y,a_z);
0268     d.subtract(position.value());
0269 
0270     vec3f pos = position.value() + side * (side.dot(d)) + up * (up.dot(d));
0271     position.value(pos);
0272   }
0273 
0274   void translate_along_side(float a_delta){
0275     vec3f dir;
0276     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0277     vec3f up;
0278     orientation.value().mul_vec(vec3f(0,1,0),up);
0279     vec3f side;dir.cross(up,side);
0280     vec3f pos = position.value() + side * a_delta;
0281     position.value(pos);
0282   }
0283   void translate_along_up(float a_delta){
0284     vec3f dir;
0285     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0286     vec3f up;
0287     orientation.value().mul_vec(vec3f(0,1,0),up);
0288     vec3f pos = position.value() + up * a_delta;
0289     position.value(pos);
0290   }
0291   void translate_along_dir(float a_delta){
0292     vec3f dir;
0293     orientation.value().mul_vec(vec3f(0,0,-1),dir);
0294     vec3f pos = position.value() + dir * a_delta;
0295     position.value(pos);
0296   }
0297 
0298   bool look_at(const vec3f& a_dir,const vec3f& a_up) {
0299     vec3f z = -a_dir;
0300     vec3f y = a_up;
0301     vec3f x;y.cross(z,x);
0302 
0303     // recompute y to create a valid coordinate system
0304     z.cross(x,y);
0305 
0306     // normalize x and y to create an orthonormal coord system
0307     if(!x.normalize()) return false;
0308     if(!y.normalize()) return false;
0309     if(!z.normalize()) return false;
0310 
0311     // create a rotation matrix
0312     mat4f rot;
0313     rot.set_identity();
0314     rot.set_value(0,0,x[0]);
0315     rot.set_value(1,0,x[1]);
0316     rot.set_value(2,0,x[2]);
0317 
0318     rot.set_value(0,1,y[0]);
0319     rot.set_value(1,1,y[1]);
0320     rot.set_value(2,1,y[2]);
0321 
0322     rot.set_value(0,2,z[0]);
0323     rot.set_value(1,2,z[1]);
0324     rot.set_value(2,2,z[2]);
0325 
0326     orientation.value().set_value(rot);
0327     return true;
0328   }
0329 
0330   //NOTE : print is a Python keyword.
0331   void dump(std::ostream& a_out) {
0332     a_out << " znear " << znear.value() << std::endl;
0333     a_out << " zfar " << zfar.value() << std::endl;
0334     vec3f& pos = position.value();
0335     a_out << " pos " << pos[0] << " " << pos[1] << " " << pos[2] << std::endl;
0336     //FIXME : dump orientation.
0337   }
0338 
0339   bool is_type_ortho() const {return type()==camera_ortho?true:false;}
0340 
0341   bool height_at_focal(float& a_h) const {
0342     if(is_type_ortho()) {
0343       a_h = near_height();
0344     } else {
0345       if(!znear.value()) {a_h = near_height();return false;}
0346       a_h = focal.value()*near_height()/znear.value();
0347     }
0348     return true;
0349   }
0350 
0351   void astro_orientation(float a_ra,float a_dec/*,const vec3f&  a_center*/) {
0352     // a_ra, a_dec are in decimal degrees.
0353 
0354     // Camera default point toward -z with up along +y and +x at right.
0355 
0356     // Arrange so that camera points toward x with up along +z :
0357     rotf r(vec3f::s_y(),-fhalf_pi());
0358     r *= rotf(vec3f::s_x(),fhalf_pi());
0359     // Now -y is at right.
0360 
0361     // Then rotate it so that it points toward given (ra,dec) by keeping up upward +z direction.
0362     r *= rotf(vec3f::s_y(),-a_dec*fdeg2rad());
0363     r *= rotf(vec3f::s_z(),a_ra*fdeg2rad());
0364     orientation = r;
0365 
0366 /*
0367     position = a_center*0.99f;
0368     znear = 0.1f;
0369     zfar = 200.0f;
0370     focal = (a_center-position).length();
0371 */
0372 /*
0373     position = vec3f(0,0,0);
0374     znear = 1.0f;
0375     zfar = 2000.0f; //2*sky_radius.
0376     focal = a_center.length();
0377     da = 0.017f/100; //1/100 of a degree
0378 */
0379   }
0380 
0381   bool update_motion(int a_move) {
0382     float _dx = dx;
0383     float _da = da;
0384     float _ds = ds;
0385 
0386     if(a_move==move_rotate_right) { //should match camera_yaw().
0387       rotate_around_up(_da);
0388       return true;
0389     }
0390     if(a_move==move_rotate_left) {
0391       rotate_around_up(-_da);
0392       return true;
0393     }
0394 
0395     if(a_move==move_rotate_up) {  //should match camera_pitch().
0396       rotate_around_x(_da);
0397       return true;
0398     }
0399     if(a_move==move_rotate_down) {
0400       rotate_around_x(-_da);
0401       return true;
0402     }
0403 
0404     if(a_move==move_roll_plus) {  //should match camera_roll().
0405       rotate_around_direction(-_da);  //direction = -z, then the minus.
0406       return true;
0407     }
0408     if(a_move==move_roll_minus) {
0409       rotate_around_direction(_da);
0410       return true;
0411     }
0412 
0413     if(a_move==move_translate_right) {
0414       translate_along_side(_dx);
0415       return true;
0416     }
0417     if(a_move==move_translate_left) {
0418       translate_along_side(-_dx);
0419       return true;
0420     }
0421 
0422     if(a_move==move_up) {
0423       translate_along_up(_dx);
0424       return true;
0425     }
0426     if(a_move==move_down) {
0427       translate_along_up(-_dx);
0428       return true;
0429     }
0430     if(a_move==move_forward) {
0431       translate_along_dir(_dx);
0432       return true;
0433     }
0434     if(a_move==move_backward) {
0435       translate_along_dir(-_dx);
0436       return true;
0437     }
0438     if(a_move==move_zoom_in) {
0439       zoom(_ds);
0440       return true;
0441     }
0442     if(a_move==move_zoom_out) {
0443       zoom(1.0f/_ds);
0444       return true;
0445     }
0446 
0447     if(a_move==move_rotate_around_focal_right) {  //yaw around focal.
0448       rotate_around_y_at_focal(_da);
0449       return true;
0450     }
0451     if(a_move==move_rotate_around_focal_left) {
0452       rotate_around_y_at_focal(-_da);
0453       return true;
0454     }
0455     if(a_move==move_rotate_around_focal_up) {  //pitch around focal.
0456       rotate_around_x_at_focal(_da);
0457       return true;
0458     }
0459     if(a_move==move_rotate_around_focal_down) {
0460       rotate_around_x_at_focal(-_da);
0461       return true;
0462     }
0463     if(a_move==move_roll_around_focal_plus) {
0464       rotate_around_z_at_focal(_da);
0465       return true;
0466     }
0467     if(a_move==move_roll_around_focal_minus) {
0468       rotate_around_z_at_focal(-_da);
0469       return true;
0470     }
0471 
0472     return false;
0473   }
0474 protected:
0475   void update_sg(std::ostream& a_out) {
0476 
0477    {const vec4f& v = m_lrbt.value();
0478     float l = v[0];
0479     float r = v[1];
0480     float b = v[2];
0481     float t = v[3];
0482     float n = znear.value();
0483     float f = zfar.value();
0484     if(is_type_ortho()) {
0485       m_proj.set_ortho(l,r,b,t,n,f);
0486     } else {
0487       m_proj.set_frustum(l,r,b,t,n,f);
0488     }}
0489 
0490     if(orientation.value().quat()!=id_orientation()) //OPTIMIZATION
0491    {rotf rinv;
0492     if(orientation.value().inverse(rinv)) {
0493       mat4f mtx;
0494       rinv.value(mtx);
0495       m_proj.mul_mtx(mtx,m_tmp);
0496     } else {
0497       a_out << "update_sg :"
0498             << " get orientation inverse failed."
0499             << std::endl;
0500     }}
0501 
0502     m_proj.mul_translate(-position.value()[0],
0503                          -position.value()[1],
0504                          -position.value()[2]);
0505   }
0506 
0507   void _mult_matrix(matrix_action& a_action) {
0508     float l,r,b,t;
0509     get_lrbt(a_action.ww(),a_action.wh(),l,r,b,t);
0510     m_lrbt.set_value(l,r,b,t);
0511 
0512     if(touched()||m_lrbt.touched()) {
0513       update_sg(a_action.out());
0514       reset_touched();
0515       m_lrbt.reset_touched();
0516     }
0517 
0518     a_action.projection_matrix().mul_mtx(m_proj,m_tmp);
0519   }
0520 
0521   void set_state(matrix_action& a_action) {
0522     state& _state = a_action.state();
0523     _state.m_camera_ortho = is_type_ortho();
0524     _state.m_camera_znear = znear;
0525     _state.m_camera_zfar = zfar;
0526     _state.m_camera_position = position.value();
0527     _state.m_camera_orientation = orientation.value();
0528     //_state.m_camera_near_height = near_height();
0529     _state.m_camera_lrbt = m_lrbt.value();
0530     _state.m_proj = a_action.projection_matrix();
0531   }
0532 
0533 #if defined(TOOLS_MEM) && !defined(TOOLS_MEM_ATEXIT)
0534   static const vec4<float>& id_orientation() {static const vec4<float> s_v(0,0,0,1,false);return s_v;}
0535 #else
0536   static const vec4<float>& id_orientation() {static const vec4<float> s_v(0,0,0,1);return s_v;}
0537 #endif
0538 
0539 protected:
0540   //OPTIMIZATION :
0541   sf_vec4f m_lrbt;
0542   mat4f m_proj;
0543   float m_tmp[16];
0544 };
0545 
0546 }}
0547 
0548 #endif