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     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