Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/sg/base_camera

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
  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_camera,node)
 26 public:
 27   sf<float> znear;
 28   sf<float> zfar;
 29   sf_vec3f position;
 30   //Camera orientation specified as a rotation value from the default
 31   //orientation where the camera is pointing along the negative z-axis,
 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() const {
 42     TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::base_camera)
 43     static const desc_fields s_v(parent::node_desc_fields(),8, //WARNING : take care of count.
 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 int,
 72                         float&,float&,float&,float&) = 0;
 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_camera::render : proj :" << std::endl;
 79  // a_action.out() << _mtx << std::endl;}
 80     a_action.load_proj_matrix(a_action.projection_matrix());
 81     a_action.load_model_matrix(a_action.model_matrix());
 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_action){
 92     _mult_matrix(a_action);
 93     set_state(a_action);
 94   }
 95   virtual void is_visible(visible_action& a_action){
 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 = vec4f(0,0,0,1)
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_from){
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) const{
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 false;
158     //we do not test dx,da,ds.
159     return true;
160   }
161   //bool operator!=(const base_camera& a_from) const {
162   //  return !operator==(a_from);
163   //}
164 public:
165   void direction(vec3f& a_dir) const {
166     orientation.value().mul_vec(vec3f(0,0,-1),a_dir);
167   }
168 
169   void rotate_around_direction(float a_delta) {
170   //vec3f dir;
171   //orientation.value().mul_vec(vec3f(0,0,-1),dir);
172   //orientation.value(rotf(dir,a_delta) * orientation.value());
173     orientation.value(rotf(vec3f(0,0,-1),a_delta) * orientation.value());
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) * orientation.value());
180     orientation.value(rotf(vec3f(0,0,1),a_delta) * orientation.value());
181   }
182 
183   void rotate_around_up(float a_delta){
184     vec3f up;
185     orientation.value().mul_vec(vec3f(0,1,0),up);
186   //orientation.value(rotf(up,a_delta) * orientation.value());
187     // must be the below so that rot-cam works for exlib/cbk/[astro,cfitsio] astro setup.
188     // (astro setup change camera orientation).
189     orientation.value(orientation.value() * rotf(up,a_delta));
190   }
191 
192   void rotate_around_x(float a_delta){
193     orientation.value(rotf(vec3f(1,0,0),a_delta) * orientation.value());
194   }
195 
196   void rotate_around_x_at_focal(float a_delta){
197     //from coin SoGuiExaminerViewerP::rotXWheelMotion.
198     vec3f dir;
199     orientation.value().mul_vec(vec3f(0,0,-1),dir);
200     vec3f focalpoint = position.value() + focal * dir;
201     orientation.value(rotf(vec3f(1,0,0),a_delta) * orientation.value());
202     orientation.value().mul_vec(vec3f(0,0,-1),dir);
203     position = focalpoint - focal * dir;
204   }
205 
206   void rotate_around_y_at_focal(float a_delta){
207     //from coin SoGuiExaminerViewerP::rotYWheelMotion.
208     vec3f dir;
209     orientation.value().mul_vec(vec3f(0,0,-1),dir);
210     vec3f focalpoint = position.value() + focal * dir;
211     orientation.value(rotf(vec3f(0,1,0),a_delta) * orientation.value());
212     orientation.value().mul_vec(vec3f(0,0,-1),dir);
213     position = focalpoint - focal * dir;
214   }
215 
216   void rotate_around_z_at_focal(float a_delta){
217     //from coin SoGuiExaminerViewerP::rotYWheelMotion.
218     vec3f dir;
219     orientation.value().mul_vec(vec3f(0,0,-1),dir);
220     vec3f focalpoint = position.value() + focal * dir;
221     orientation.value(rotf(vec3f(0,0,1),a_delta) * orientation.value());
222     orientation.value().mul_vec(vec3f(0,0,-1),dir);
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 (dir,up) plane
228 
229     //NOTE : it is the invert of orientation which is used
230     //       in projection matrix.
231 
232    {vec3f dir;
233     orientation.value().mul_vec(vec3f(0,0,-1),dir);
234     vec3f up;
235     orientation.value().mul_vec(vec3f(0,1,0),up);
236     vec3f side;dir.cross(up,side);
237     vec3f v = side * (side.dot(a_dir)) + dir * (dir.dot(a_dir));
238     if(v.normalize()) orientation.value(orientation.value()*rotf(dir,v));}
239 
240     //rotate around dir^up so that a_dir matches dir.
241    {vec3f dir;
242     orientation.value().mul_vec(vec3f(0,0,-1),dir);
243     orientation.value(orientation.value()*rotf(dir,a_dir));}
244 
245 /*
246     //check that dir is on a_dir :
247    {vec3f dir;
248     orientation.value().mul_vec(vec3f(0,0,-1),dir);
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_angle);}
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,a_z) is on direction.
260 
261     vec3f dir;
262     orientation.value().mul_vec(vec3f(0,0,-1),dir);
263     vec3f up;
264     orientation.value().mul_vec(vec3f(0,1,0),up);
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 * (side.dot(d)) + up * (up.dot(d));
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),dir);
277     vec3f up;
278     orientation.value().mul_vec(vec3f(0,1,0),up);
279     vec3f side;dir.cross(up,side);
280     vec3f pos = position.value() + side * a_delta;
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),dir);
286     vec3f up;
287     orientation.value().mul_vec(vec3f(0,1,0),up);
288     vec3f pos = position.value() + up * a_delta;
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),dir);
294     vec3f pos = position.value() + dir * a_delta;
295     position.value(pos);
296   }
297 
298   bool look_at(const vec3f& a_dir,const vec3f& a_up) {
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 coordinate system
304     z.cross(x,y);
305 
306     // normalize x and y to create an orthonormal coord system
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::endl;
333     a_out << " zfar " << zfar.value() << std::endl;
334     vec3f& pos = position.value();
335     a_out << " pos " << pos[0] << " " << pos[1] << " " << pos[2] << std::endl;
336     //FIXME : dump orientation.
337   }
338 
339   bool is_type_ortho() const {return type()==camera_ortho?true:false;}
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();return false;}
346       a_h = focal.value()*near_height()/znear.value();
347     }
348     return true;
349   }
350 
351   void astro_orientation(float a_ra,float a_dec/*,const vec3f&  a_center*/) {
352     // a_ra, a_dec are in decimal degrees.
353 
354     // Camera default point toward -z with up along +y and +x at right.
355 
356     // Arrange so that camera points toward x with up along +z :
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 given (ra,dec) by keeping up upward +z direction.
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 match camera_yaw().
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 match camera_pitch().
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 match camera_roll().
405       rotate_around_direction(-_da);  //direction = -z, then the minus.
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) {  //yaw around focal.
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) {  //pitch around focal.
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_orientation()) //OPTIMIZATION
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 failed."
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,t);
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_proj,m_tmp);
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.value();
528     //_state.m_camera_near_height = near_height();
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_ATEXIT)
534   static const vec4<float>& id_orientation() {static const vec4<float> s_v(0,0,0,1,false);return s_v;}
535 #else
536   static const vec4<float>& id_orientation() {static const vec4<float> s_v(0,0,0,1);return s_v;}
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