2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "game-camera.h"
20 #include <dali/public-api/render-tasks/render-task-list.h>
21 #include <dali/public-api/render-tasks/render-task.h>
22 #include <dali/public-api/events/touch-data.h>
23 #include <dali/public-api/events/touch-event.h>
29 // Input sensitivity, the larger value, the more sensitive input
30 // Default value has been chosen empirically
31 const float CAMERA_SENSITIVITY ( 90.0f );
33 // Vertical angle limit of the camera
34 const float CAMERA_VERTICAL_LIMIT ( 80.0f );
36 // Position where camera is instantiated by default
37 const Vector3 CAMERA_DEFAULT_POSITION ( 1.0f, -1.5f, -3.0f );
39 // Field-of-View in degrees
40 const float CAMERA_DEFAULT_FOV ( 60.0f );
43 const float CAMERA_DEFAULT_NEAR ( 0.1f );
46 const float CAMERA_DEFAULT_FAR ( 100.0f );
48 // Default forward vector
49 const Vector3 CAMERA_FORWARD ( 0.0f, 0.0f, 1.0f );
52 const Vector3 CAMERA_UP ( Vector3::YAXIS );
55 GameCamera::GameCamera()
56 : mFovY( CAMERA_DEFAULT_FOV ),
57 mNear( CAMERA_DEFAULT_NEAR ),
58 mFar( CAMERA_DEFAULT_FAR ),
59 mWalkingTouchId( -1 ),
60 mLookingTouchId( -1 ),
61 mPortraitMode( false )
65 GameCamera::~GameCamera()
68 mCameraActor.Remove( mInterceptorActor );
71 void GameCamera::Initialise( CameraActor defaultCamera, float fovY, float near, float far, const Vector2& sceneSize )
73 mCameraActor = defaultCamera;
79 mSceneSize = sceneSize;
80 mPortraitMode = mSceneSize.x < mSceneSize.y ? true : false;
82 // Initialise default camera
83 InitialiseDefaultCamera();
85 // Create input interceptor actor
86 CreateInterceptorActor();
89 mTimer = Timer::New( 16 );
90 mTimer.TickSignal().Connect( this, &GameCamera::OnTick );
94 bool GameCamera::OnTick()
96 // ---------------------------------------------------------------------
98 Vector2 tmp( mScreenLookDelta );
99 mScreenLookDelta = Vector2::ZERO;
103 float yaw = ( (tmp.y / mSceneSize.y ) * CAMERA_SENSITIVITY );
104 float pitch = ( (tmp.x / mSceneSize.x ) * CAMERA_SENSITIVITY );
105 mCameraYawPitch.y -= yaw;
106 mCameraYawPitch.x -= pitch;
107 if( abs( mCameraYawPitch.y ) > CAMERA_VERTICAL_LIMIT )
109 mCameraYawPitch.y = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.y < 0) ? -1.0f : 1.0f );
114 float yaw = ( (tmp.y / mSceneSize.x ) * CAMERA_SENSITIVITY );
115 float pitch = ( (tmp.x / mSceneSize.y ) * CAMERA_SENSITIVITY );
116 mCameraYawPitch.x -= yaw;
117 mCameraYawPitch.y -= pitch;
118 if( abs( mCameraYawPitch.x ) > CAMERA_VERTICAL_LIMIT )
120 mCameraYawPitch.x = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.x < 0) ? -1.0f : 1.0f );
125 Quaternion rotX( Degree( mCameraYawPitch.x), Vector3( 1.0f, 0.0f, 0.0f ) );
126 Quaternion rotY( Degree( mCameraYawPitch.y), Vector3( 0.0f, 1.0f, 0.0f ) );
129 Quaternion rotZ( Degree( mPortraitMode ? 90.0 : 0.0f), Vector3( 0.0f, 0.0f, 1.0f ) );
130 rotation = ( rotZ * rotX * rotY );
134 rotation = ( rotY * rotX );
136 mCameraActor.SetProperty( Actor::Property::ORIENTATION, rotation );
138 // ---------------------------------------------------------------------
140 Vector3 position( mCameraPosition );
142 // Rotate CAMERA_FORWARD vector
143 Vector3 forwardVector = rotation.Rotate( CAMERA_FORWARD );
145 // Cancel vertical movement
146 forwardVector.y = 0.0f;
149 forwardVector.Normalize();
151 // compute sideways vector
152 Vector3 sidewaysVector = forwardVector.Cross( CAMERA_UP );
154 sidewaysVector.Normalize();
156 const float forwardSpeed( mScreenWalkDelta.y / mSceneSize.y );
157 const float sidewaysSpeed( mScreenWalkDelta.x / mSceneSize.x );
159 // Adjust walking speed
162 position += forwardVector * (forwardSpeed * 0.5f);
166 position += forwardVector * (-forwardSpeed * 0.5f);
169 position += sidewaysVector * (sidewaysSpeed * 0.5f);
171 mCameraActor.SetProperty( Actor::Property::POSITION, position );
173 mCameraPosition = position;
178 void GameCamera::InitialiseDefaultCamera()
180 mCameraActor.SetProperty( Dali::Actor::Property::NAME, "GameCamera" );
181 mCameraActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
182 mCameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
183 mCameraActor.SetFieldOfView( Radian( Degree( mFovY ) ) );
185 // should be read from file
186 mCameraActor.SetNearClippingPlane( mNear );
187 mCameraActor.SetFarClippingPlane( mFar );
188 mCameraActor.SetProperty( Actor::Property::POSITION, CAMERA_DEFAULT_POSITION );
190 // Camera position is shadowed in order to avoid using.GetCurrentProperty< Vector3 >( Actor::Property::POSITION )
191 mCameraPosition = CAMERA_DEFAULT_POSITION;
194 void GameCamera::CreateInterceptorActor()
196 mInterceptorActor = Actor::New();
197 mInterceptorActor.SetProperty( Dali::Actor::Property::NAME, "GameInputInterceptor" );
198 mInterceptorActor.SetProperty( Actor::Property::SIZE, Vector3( mSceneSize.x, mSceneSize.y, 1 ) );
199 mInterceptorActor.SetProperty( Actor::Property::POSITION, Vector3( 0.0, 0.0, 1.0 ) );
200 mInterceptorActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
201 mInterceptorActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
202 mCameraActor.Add( mInterceptorActor );
204 // Connect TouchSignal to interceptor actor
205 mInterceptorActor.TouchSignal().Connect( this, &GameCamera::OnTouch );
208 bool GameCamera::OnTouch( Actor actor, const TouchData& touch )
210 for( int i = 0; i < (int)touch.GetPointCount() && i < 3; ++i )
212 int id = touch.GetDeviceId( i );
213 Vector2 tmp( touch.GetScreenPosition( i ) );
215 float halfWindowSize;
220 halfWindowSize = mSceneSize.y / 2;
226 halfWindowSize = mSceneSize.x / 2;
230 if( touch.GetState( i ) == PointState::STARTED )
233 if( position.x > halfWindowSize && mLookingTouchId < 0 )
235 mLookingTouchId = id;
236 mOldTouchLookPosition = position;
239 else if( position.x < halfWindowSize && mWalkingTouchId < 0 )
241 mWalkingTouchId = id;
242 mOldTouchWalkPosition = position;
243 mScreenWalkDelta = Vector2::ZERO;
246 else if( touch.GetState( i ) == PointState::FINISHED ||
247 touch.GetState( i ) == PointState::LEAVE ||
248 touch.GetState( i ) == PointState::INTERRUPTED
252 if( mLookingTouchId == id )
254 mScreenLookDelta = Vector2::ZERO;
255 mOldTouchLookPosition = Vector2::ZERO;
256 mLookingTouchId = -1;
259 else if( mWalkingTouchId == id )
261 mScreenWalkDelta = Vector2::ZERO;
262 mOldTouchWalkPosition = Vector2::ZERO;
263 mWalkingTouchId = -1;
269 if( mLookingTouchId == id )
271 mScreenLookDelta.x += ( position.x - mOldTouchLookPosition.x );
272 mScreenLookDelta.y += ( position.y - mOldTouchLookPosition.y );
273 mOldTouchLookPosition = position;
276 else if ( mWalkingTouchId == id )
278 mScreenWalkDelta.x += ( position.x - mOldTouchWalkPosition.x );
279 mScreenWalkDelta.y += ( position.y - mOldTouchWalkPosition.y );
280 mOldTouchWalkPosition = position;