• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //----------------------------------------------------------
TapCamera()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 
InitParameters()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 //----------------------------------------------------------
~TapCamera()89 TapCamera::~TapCamera()
90 {
91 
92 }
93 
Update()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 
GetRotationMatrix()137 Mat4& TapCamera::GetRotationMatrix()
138 {
139     return mat_rotation_;
140 }
141 
GetTransformMatrix()142 Mat4& TapCamera::GetTransformMatrix()
143 {
144     return mat_transform_;
145 }
146 
Reset(const bool bAnimate)147 void TapCamera::Reset( const bool bAnimate )
148 {
149     InitParameters();
150     Update();
151 
152 }
153 
154 //----------------------------------------------------------
155 //Drag control
156 //----------------------------------------------------------
BeginDrag(const Vec2 & v)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 
EndDrag()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 
Drag(const Vec2 & v)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 //----------------------------------------------------------
BeginPinch(const Vec2 & v1,const Vec2 & v2)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 
EndPinch()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 
Pinch(const Vec2 & v1,const Vec2 & v2)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 //----------------------------------------------------------
BallUpdate()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 
PointOnSphere(Vec2 & point)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