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