Home | History | Annotate | Download | only in ndk_helper
      1 /*
      2  * Copyright 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //----------------------------------------------------------
     18 //  tapCamera.cpp
     19 //  Camera control with tap
     20 //
     21 //----------------------------------------------------------
     22 #include <fstream>
     23 #include "tapCamera.h"
     24 
     25 namespace ndk_helper
     26 {
     27 
     28 const float TRANSFORM_FACTOR = 15.f;
     29 const float TRANSFORM_FACTORZ = 10.f;
     30 
     31 const float MOMENTUM_FACTOR_DECREASE = 0.85f;
     32 const float MOMENTUM_FACTOR_DECREASE_SHIFT = 0.9f;
     33 const float MOMENTUM_FACTOR = 0.8f;
     34 const float MOMENTUM_FACTOR_THRESHOLD = 0.001f;
     35 
     36 //----------------------------------------------------------
     37 //  Ctor
     38 //----------------------------------------------------------
     39 TapCamera::TapCamera() :
     40                 dragging_( false ),
     41                 pinching_( false ),
     42                 momentum_( false ),
     43                 ball_radius_( 0.75f ),
     44                 pinch_start_distance_SQ_( 0.f ),
     45                 camera_rotation_( 0.f ),
     46                 camera_rotation_start_( 0.f ),
     47                 camera_rotation_now_( 0.f ),
     48                 momemtum_steps_( 0.f ),
     49                 flip_z_( 0.f )
     50 {
     51     //Init offset
     52     InitParameters();
     53 
     54     vec_flip_ = Vec2( 1.f, -1.f );
     55     flip_z_ = -1.f;
     56     vec_pinch_transform_factor_ = Vec3( 1.f, 1.f, 1.f );
     57 
     58     vec_ball_center_ = Vec2( 0, 0 );
     59     vec_ball_now_ = Vec2( 0, 0 );
     60     vec_ball_down_ = Vec2( 0, 0 );
     61 
     62     vec_pinch_start_ = Vec2( 0, 0 );
     63     vec_pinch_start_center_ = Vec2( 0, 0 );
     64 
     65     vec_flip_ = Vec2( 0, 0 );
     66 
     67 }
     68 
     69 void TapCamera::InitParameters()
     70 {
     71     //Init parameters
     72     vec_offset_ = Vec3();
     73     vec_offset_now_ = Vec3();
     74 
     75     quat_ball_rot_ = Quaternion();
     76     quat_ball_now_ = Quaternion();
     77     quat_ball_now_.ToMatrix( mat_rotation_ );
     78     camera_rotation_ = 0.f;
     79 
     80     vec_drag_delta_ = Vec2();
     81     vec_offset_delta_ = Vec3();
     82 
     83     momentum_ = false;
     84 }
     85 
     86 //----------------------------------------------------------
     87 //  Dtor
     88 //----------------------------------------------------------
     89 TapCamera::~TapCamera()
     90 {
     91 
     92 }
     93 
     94 void TapCamera::Update()
     95 {
     96     if( momentum_ )
     97     {
     98         float momenttum_steps = momemtum_steps_;
     99 
    100         //Momentum rotation
    101         Vec2 v = vec_drag_delta_;
    102         BeginDrag( Vec2() ); //NOTE:This call reset _VDragDelta
    103         Drag( v * vec_flip_ );
    104 
    105         //Momentum shift
    106         vec_offset_ += vec_offset_delta_;
    107 
    108         BallUpdate();
    109         EndDrag();
    110 
    111         //Decrease deltas
    112         vec_drag_delta_ = v * MOMENTUM_FACTOR_DECREASE;
    113         vec_offset_delta_ = vec_offset_delta_ * MOMENTUM_FACTOR_DECREASE_SHIFT;
    114 
    115         //Count steps
    116         momemtum_steps_ = momenttum_steps * MOMENTUM_FACTOR_DECREASE;
    117         if( momemtum_steps_ < MOMENTUM_FACTOR_THRESHOLD )
    118         {
    119             momentum_ = false;
    120         }
    121     }
    122     else
    123     {
    124         vec_drag_delta_ *= MOMENTUM_FACTOR;
    125         vec_offset_delta_ = vec_offset_delta_ * MOMENTUM_FACTOR;
    126         BallUpdate();
    127     }
    128 
    129     Vec3 vec = vec_offset_ + vec_offset_now_;
    130     Vec3 vec_tmp( TRANSFORM_FACTOR, -TRANSFORM_FACTOR, TRANSFORM_FACTORZ );
    131 
    132     vec *= vec_tmp * vec_pinch_transform_factor_;
    133 
    134     mat_transform_ = Mat4::Translation( vec );
    135 }
    136 
    137 Mat4& TapCamera::GetRotationMatrix()
    138 {
    139     return mat_rotation_;
    140 }
    141 
    142 Mat4& TapCamera::GetTransformMatrix()
    143 {
    144     return mat_transform_;
    145 }
    146 
    147 void TapCamera::Reset( const bool bAnimate )
    148 {
    149     InitParameters();
    150     Update();
    151 
    152 }
    153 
    154 //----------------------------------------------------------
    155 //Drag control
    156 //----------------------------------------------------------
    157 void TapCamera::BeginDrag( const Vec2& v )
    158 {
    159     if( dragging_ )
    160         EndDrag();
    161 
    162     if( pinching_ )
    163         EndPinch();
    164 
    165     Vec2 vec = v * vec_flip_;
    166     vec_ball_now_ = vec;
    167     vec_ball_down_ = vec_ball_now_;
    168 
    169     dragging_ = true;
    170     momentum_ = false;
    171     vec_last_input_ = vec;
    172     vec_drag_delta_ = Vec2();
    173 }
    174 
    175 void TapCamera::EndDrag()
    176 {
    177     quat_ball_down_ = quat_ball_now_;
    178     quat_ball_rot_ = Quaternion();
    179 
    180     dragging_ = false;
    181     momentum_ = true;
    182     momemtum_steps_ = 1.0f;
    183 }
    184 
    185 void TapCamera::Drag( const Vec2& v )
    186 {
    187     if( !dragging_ )
    188         return;
    189 
    190     Vec2 vec = v * vec_flip_;
    191     vec_ball_now_ = vec;
    192 
    193     vec_drag_delta_ = vec_drag_delta_ * MOMENTUM_FACTOR + (vec - vec_last_input_);
    194     vec_last_input_ = vec;
    195 }
    196 
    197 //----------------------------------------------------------
    198 //Pinch controll
    199 //----------------------------------------------------------
    200 void TapCamera::BeginPinch( const Vec2& v1, const Vec2& v2 )
    201 {
    202     if( dragging_ )
    203         EndDrag();
    204 
    205     if( pinching_ )
    206         EndPinch();
    207 
    208     BeginDrag( Vec2() );
    209 
    210     vec_pinch_start_center_ = (v1 + v2) / 2.f;
    211 
    212     Vec2 vec = v1 - v2;
    213     float x_diff;
    214     float y_diff;
    215     vec.Value( x_diff, y_diff );
    216 
    217     pinch_start_distance_SQ_ = x_diff * x_diff + y_diff * y_diff;
    218     camera_rotation_start_ = atan2f( y_diff, x_diff );
    219     camera_rotation_now_ = 0;
    220 
    221     pinching_ = true;
    222     momentum_ = false;
    223 
    224     //Init momentum factors
    225     vec_offset_delta_ = Vec3();
    226 }
    227 
    228 void TapCamera::EndPinch()
    229 {
    230     pinching_ = false;
    231     momentum_ = true;
    232     momemtum_steps_ = 1.f;
    233     vec_offset_ += vec_offset_now_;
    234     camera_rotation_ += camera_rotation_now_;
    235     vec_offset_now_ = Vec3();
    236 
    237     camera_rotation_now_ = 0;
    238 
    239     EndDrag();
    240 }
    241 
    242 void TapCamera::Pinch( const Vec2& v1, const Vec2& v2 )
    243 {
    244     if( !pinching_ )
    245         return;
    246 
    247     //Update momentum factor
    248     vec_offset_last_ = vec_offset_now_;
    249 
    250     float x_diff, y_diff;
    251     Vec2 vec = v1 - v2;
    252     vec.Value( x_diff, y_diff );
    253 
    254     float fDistanceSQ = x_diff * x_diff + y_diff * y_diff;
    255 
    256     float f = pinch_start_distance_SQ_ / fDistanceSQ;
    257     if( f < 1.f )
    258         f = -1.f / f + 1.0f;
    259     else
    260         f = f - 1.f;
    261     if( isnan( f ) )
    262         f = 0.f;
    263 
    264     vec = (v1 + v2) / 2.f - vec_pinch_start_center_;
    265     vec_offset_now_ = Vec3( vec, flip_z_ * f );
    266 
    267     //Update momentum factor
    268     vec_offset_delta_ = vec_offset_delta_ * MOMENTUM_FACTOR
    269             + (vec_offset_now_ - vec_offset_last_);
    270 
    271     //
    272     //Update ration quaternion
    273     float fRotation = atan2f( y_diff, x_diff );
    274     camera_rotation_now_ = fRotation - camera_rotation_start_;
    275 
    276     //Trackball rotation
    277     quat_ball_rot_ = Quaternion( 0.f, 0.f, sinf( -camera_rotation_now_ * 0.5f ),
    278             cosf( -camera_rotation_now_ * 0.5f ) );
    279 }
    280 
    281 //----------------------------------------------------------
    282 //Trackball controll
    283 //----------------------------------------------------------
    284 void TapCamera::BallUpdate()
    285 {
    286     if( dragging_ )
    287     {
    288         Vec3 vec_from = PointOnSphere( vec_ball_down_ );
    289         Vec3 vec_to = PointOnSphere( vec_ball_now_ );
    290 
    291         Vec3 vec = vec_from.Cross( vec_to );
    292         float w = vec_from.Dot( vec_to );
    293 
    294         Quaternion qDrag = Quaternion( vec, w );
    295         qDrag = qDrag * quat_ball_down_;
    296         quat_ball_now_ = quat_ball_rot_ * qDrag;
    297     }
    298     quat_ball_now_.ToMatrix( mat_rotation_ );
    299 }
    300 
    301 Vec3 TapCamera::PointOnSphere( Vec2& point )
    302 {
    303     Vec3 ball_mouse;
    304     float mag;
    305     Vec2 vec = (point - vec_ball_center_) / ball_radius_;
    306     mag = vec.Dot( vec );
    307     if( mag > 1.f )
    308     {
    309         float scale = 1.f / sqrtf( mag );
    310         vec *= scale;
    311         ball_mouse = Vec3( vec, 0.f );
    312     }
    313     else
    314     {
    315         ball_mouse = Vec3( vec, sqrtf( 1.f - mag ) );
    316     }
    317     return ball_mouse;
    318 }
    319 
    320 } //namespace ndkHelper
    321