diff options
Diffstat (limited to 'ndk/sources/android/helper/tapCamera.cpp')
| -rw-r--r-- | ndk/sources/android/helper/tapCamera.cpp | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/ndk/sources/android/helper/tapCamera.cpp b/ndk/sources/android/helper/tapCamera.cpp new file mode 100644 index 000000000..0b0f94b02 --- /dev/null +++ b/ndk/sources/android/helper/tapCamera.cpp @@ -0,0 +1,313 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//---------------------------------------------------------- +// tapCamera.cpp +// Camera control with tap +// +//---------------------------------------------------------- + +#include <fstream> +#include "tapCamera.h" + +const float TRANSFORM_FACTOR = 15.f; +const float TRANSFORM_FACTORZ = 10.f; + +const float MOMENTUM_FACTOR_DECREASE = 0.85f; +const float MOMENTUM_FACTOR_DECREASE_SHIFT = 0.9f; +const float MOMENTUM_FACTOR = 0.8f; +const float MOMENTUM_FACTOR_THRESHOLD = 0.001f; + +//---------------------------------------------------------- +// Ctor +//---------------------------------------------------------- +tapCamera::tapCamera(): + _bDragging(false), + _bPinching( false ), + _bMomentum(false), + _fBallRadius( 0.75f ), + _fPinchStartDistanceSQ( 0.f ), + _fRotation( 0.f ), + _fRotationStart( 0.f ), + _fRotationNow( 0.f ), + _fMomentumSteps( 0.f ), + _fFlipZ( 0.f ) +{ + //Init offset + initParameters(); + + _vFlip = vec2( 1.f, -1.f ); + _fFlipZ = -1.f; + _vPinchTransformFactor = vec3( 1.f, 1.f, 1.f ); + + _vBallCenter = vec2( 0, 0 ); + _vBallNow = vec2( 0, 0 ); + _vBallDown = vec2( 0, 0 ); + + _vecPinchStart = vec2( 0, 0 ); + _vecPinchStartCenter = vec2( 0, 0 ); + + _vFlip = vec2( 0, 0 ); + +} + +void tapCamera::initParameters() +{ + //Init parameters + _vecOffset = vec3(); + _vecOffsetNow = vec3(); + + _qBallRot = quaternion(); + _qBallNow = quaternion(); + _qBallNow.toMatrix(_mRotation); + _fRotation = 0.f; + + _vDragDelta = vec2(); + _vecOffsetDelta = vec3(); + + _bMomentum = false; +} + +//---------------------------------------------------------- +// Dtor +//---------------------------------------------------------- +tapCamera::~tapCamera() +{ + +} + +void tapCamera::update() +{ + if( _bMomentum ) + { + float fMomenttumSteps = _fMomentumSteps; + + //Momentum rotation + vec2 v = _vDragDelta; + beginDrag(vec2() ); //NOTE:This call reset _VDragDelta + drag(v * _vFlip); + + //Momentum shift + _vecOffset += _vecOffsetDelta; + + ballUpdate(); + endDrag(); + + //Decrease deltas + _vDragDelta = v * MOMENTUM_FACTOR_DECREASE; + _vecOffsetDelta = _vecOffsetDelta * MOMENTUM_FACTOR_DECREASE_SHIFT; + + //Count steps + _fMomentumSteps = fMomenttumSteps * MOMENTUM_FACTOR_DECREASE; + if( _fMomentumSteps < MOMENTUM_FACTOR_THRESHOLD ) + { + _bMomentum = false; + } + } + else + { + _vDragDelta *= MOMENTUM_FACTOR; + _vecOffsetDelta = _vecOffsetDelta * MOMENTUM_FACTOR; + ballUpdate(); + } + + vec3 vec = _vecOffset + _vecOffsetNow; + vec3 vecTmp(TRANSFORM_FACTOR, -TRANSFORM_FACTOR, TRANSFORM_FACTORZ); + + vec *= vecTmp * _vPinchTransformFactor; + + _mTransform = mat4::translation(vec); +} + +mat4& tapCamera::getRotationMatrix() +{ + return _mRotation; +} + +mat4& tapCamera::getTransformMatrix() +{ + return _mTransform; +} + +void tapCamera::reset(const bool bAnimate) +{ + initParameters(); + update(); + +} + +//---------------------------------------------------------- +//Drag control +//---------------------------------------------------------- +void tapCamera::beginDrag(const vec2& v) +{ + if( _bDragging ) + endDrag(); + + if( _bPinching ) + endPinch(); + + vec2 vec = v * _vFlip; + _vBallNow = vec; + _vBallDown = _vBallNow; + + _bDragging = true; + _bMomentum = false; + _vLastInput = vec; + _vDragDelta = vec2(); +} + +void tapCamera::endDrag() +{ + int i; + _qBallDown = _qBallNow; + _qBallRot = quaternion(); + + _bDragging = false; + _bMomentum = true; + _fMomentumSteps = 1.0f; +} + +void tapCamera::drag(const vec2& v ) +{ + if( !_bDragging ) + return; + + vec2 vec = v * _vFlip; + _vBallNow = vec; + + _vDragDelta = _vDragDelta * MOMENTUM_FACTOR + (vec - _vLastInput); + _vLastInput = vec; +} + +//---------------------------------------------------------- +//Pinch controll +//---------------------------------------------------------- +void tapCamera::beginPinch(const vec2& v1, const vec2& v2) +{ + if( _bDragging ) + endDrag(); + + if( _bPinching ) + endPinch(); + + beginDrag( vec2() ); + + _vecPinchStartCenter = (v1 + v2) / 2.f; + + vec2 vec = v1 - v2; + float fXDiff; + float fYDiff; + vec.value( fXDiff, fYDiff ); + + _fPinchStartDistanceSQ = fXDiff*fXDiff + fYDiff*fYDiff; + _fRotationStart = atan2f( fYDiff, fXDiff ); + _fRotationNow = 0; + + _bPinching = true; + _bMomentum = false; + + //Init momentum factors + _vecOffsetDelta = vec3(); +} + + +void tapCamera::endPinch() +{ + _bPinching = false; + _bMomentum = true; + _fMomentumSteps = 1.f; + _vecOffset += _vecOffsetNow; + _fRotation += _fRotationNow; + _vecOffsetNow = vec3(); + + _fRotationNow = 0; + + endDrag(); +} + +void tapCamera::pinch(const vec2& v1, const vec2& v2) +{ + if( !_bPinching ) + return; + + //Update momentum factor + _vecOffsetLast = _vecOffsetNow; + + float fXDiff, fYDiff; + vec2 vec = v1 - v2; + vec.value(fXDiff, fYDiff); + + float fDistanceSQ = fXDiff * fXDiff + fYDiff * fYDiff; + + float f = _fPinchStartDistanceSQ / fDistanceSQ; + if( f < 1.f) + f = -1.f / f + 1.0f; + else + f = f - 1.f; + if( isnan(f) ) f = 0.f; + + vec = (v1 + v2) / 2.f - _vecPinchStartCenter; + _vecOffsetNow = vec3( vec, + _fFlipZ * f ); + + //Update momentum factor + _vecOffsetDelta = _vecOffsetDelta * MOMENTUM_FACTOR + (_vecOffsetNow - _vecOffsetLast); + + // + //Update ration quaternion + float fRotation = atan2f( fYDiff, fXDiff ); + _fRotationNow = fRotation - _fRotationStart; + + //Trackball rotation + _qBallRot = quaternion( 0.f, 0.f, sinf(-_fRotationNow*0.5f), cosf(-_fRotationNow*0.5f) ); +} + +//---------------------------------------------------------- +//Trackball controll +//---------------------------------------------------------- +void tapCamera::ballUpdate() +{ + if (_bDragging) { + vec3 vFrom = pointOnSphere(_vBallDown); + vec3 vTo = pointOnSphere(_vBallNow); + + vec3 vec = vFrom.cross(vTo); + float w = vFrom.dot( vTo ); + + quaternion qDrag = quaternion(vec, w); + qDrag = qDrag * _qBallDown; + _qBallNow = _qBallRot * qDrag; + } + _qBallNow.toMatrix(_mRotation); +} + +vec3 tapCamera::pointOnSphere(vec2& point) +{ + vec3 ballMouse; + float mag; + vec2 vec = (point - _vBallCenter) / _fBallRadius; + mag = vec.dot( vec ); + if (mag > 1.f) + { + float scale = 1.f / sqrtf(mag); + vec *= scale; + ballMouse = vec3( vec, 0.f ); + } else { + ballMouse = vec3( vec, sqrtf(1.f - mag) ); + } + return (ballMouse); +} |
