Go to the documentation of this file.00001 #ifndef OPENTISSUE_UTILITY_TRACKBALL_BELL_H
00002 #define OPENTISSUE_UTILITY_TRACKBALL_BELL_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/utility/trackball/trackball_generic.h>
00013
00014 namespace OpenTissue
00015 {
00016 namespace utility
00017 {
00018 namespace trackball
00019 {
00020
00021 template<typename real_type_ = double>
00022 class Bell : public GenericTrackball<real_type_>
00023 {
00024 public:
00025
00026 typedef GenericTrackball<real_type_> base_type;
00027 typedef typename base_type::real_type real_type;
00028 typedef typename base_type::vector3_type vector3_type;
00029 typedef typename base_type::matrix3x3_type matrix3x3_type;
00030 typedef typename base_type::quaternion_type quaternion_type;
00031 typedef typename base_type::gl_transform_type gl_transform_type;
00032
00033 public:
00034
00035 Bell()
00036 : base_type()
00037 {
00038 reset();
00039 }
00040
00041 Bell(real_type const & radius)
00042 : base_type(radius)
00043 {
00044 reset();
00045 }
00046
00047 void reset()
00048 {
00049 base_type::reset();
00050 project_onto_surface(this->m_anchor_position);
00051 project_onto_surface(this->m_current_position);
00052 }
00053
00054 void begin_drag(real_type const & x, real_type const & y)
00055 {
00056 this->m_angle = 0.0;
00057 this->m_axis.clear();
00058
00059 this->m_xform_anchor = this->m_xform_current;
00060 this->m_xform_incremental = diag(1.0);
00061 this->m_xform_current = diag(1.0);
00062
00063 this->m_anchor_position = vector3_type(x,y,0);
00064 project_onto_surface(this->m_anchor_position);
00065 this->m_current_position = vector3_type(x,y,0);
00066 project_onto_surface(this->m_current_position);
00067 }
00068
00069 void drag(real_type const & x, real_type const & y)
00070 {
00071 this->m_current_position = vector3_type(x,y,0);
00072 project_onto_surface(this->m_current_position);
00073 compute_incremental(this->m_anchor_position,this->m_current_position,this->m_xform_incremental);
00074 }
00075
00076 void end_drag(real_type const & x, real_type const & y)
00077 {
00078 this->m_current_position = vector3_type(x,y,0);
00079 project_onto_surface(this->m_current_position);
00080 compute_incremental(this->m_anchor_position,this->m_current_position,this->m_xform_incremental);
00081 }
00082
00083 private:
00084
00085 void project_onto_surface(vector3_type & P)
00086 {
00087 using std::sqrt;
00088 const static real_type radius2 = this->m_radius * this->m_radius;
00089 real_type length2 = P(0)*P(0) + P(1)*P(1);
00090
00091 if (length2 <= radius2 / 2.0)
00092 P(2) = sqrt(radius2 - length2);
00093 else
00094 {
00095 P(2) = radius2 / (2.0 * sqrt(length2));
00096 real_type length = sqrt(length2 + P[2] * P[2]);
00097 P /= length;
00098 }
00099 }
00100
00101 void compute_incremental(vector3_type const & anchor, vector3_type const & current, matrix3x3_type & transform)
00102 {
00103 quaternion_type Q_anchor ( 0, unit(anchor) );
00104 quaternion_type Q_current( 0, unit(current) );
00105 quaternion_type Q_rot = -prod(Q_current,Q_anchor);
00106 this->m_axis = Q_rot.v();
00107 this->m_angle = atan2(length(this->m_axis), Q_rot.s());
00108 transform = Q_rot;
00109 }
00110 };
00111 }
00112 }
00113 }
00114
00115
00116 #endif