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/events/touch-event.h>
21 #include <dali/public-api/render-tasks/render-task-list.h>
22 #include <dali/public-api/render-tasks/render-task.h>
28 // Input sensitivity, the larger value, the more sensitive input
29 // Default value has been chosen empirically
30 const float CAMERA_SENSITIVITY(90.0f);
32 // Vertical angle limit of the camera
33 const float CAMERA_VERTICAL_LIMIT(80.0f);
35 // Position where camera is instantiated by default
36 const Vector3 CAMERA_DEFAULT_POSITION(1.0f, -1.5f, -3.0f);
38 // Field-of-View in degrees
39 const float CAMERA_DEFAULT_FOV(60.0f);
42 const float CAMERA_DEFAULT_NEAR(0.1f);
45 const float CAMERA_DEFAULT_FAR(100.0f);
47 // Default forward vector
48 const Vector3 CAMERA_FORWARD(0.0f, 0.0f, 1.0f);
51 const Vector3 CAMERA_UP(Vector3::YAXIS);
54 GameCamera::GameCamera()
55 : mFovY(CAMERA_DEFAULT_FOV),
56 mNear(CAMERA_DEFAULT_NEAR),
57 mFar(CAMERA_DEFAULT_FAR),
64 GameCamera::~GameCamera()
67 mCameraActor.Remove(mInterceptorActor);
70 void GameCamera::Initialise(CameraActor defaultCamera, float fovY, float near, float far, const Vector2& sceneSize)
72 mCameraActor = defaultCamera;
78 mSceneSize = sceneSize;
79 mPortraitMode = mSceneSize.x < mSceneSize.y ? true : false;
81 // Initialise default camera
82 InitialiseDefaultCamera();
84 // Create input interceptor actor
85 CreateInterceptorActor();
88 mTimer = Timer::New(16);
89 mTimer.TickSignal().Connect(this, &GameCamera::OnTick);
93 bool GameCamera::OnTick()
95 // ---------------------------------------------------------------------
97 Vector2 tmp(mScreenLookDelta);
98 mScreenLookDelta = Vector2::ZERO;
102 float yaw = ((tmp.y / mSceneSize.y) * CAMERA_SENSITIVITY);
103 float pitch = ((tmp.x / mSceneSize.x) * CAMERA_SENSITIVITY);
104 mCameraYawPitch.y -= yaw;
105 mCameraYawPitch.x -= pitch;
106 if(abs(mCameraYawPitch.y) > CAMERA_VERTICAL_LIMIT)
108 mCameraYawPitch.y = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.y < 0) ? -1.0f : 1.0f);
113 float yaw = ((tmp.y / mSceneSize.x) * CAMERA_SENSITIVITY);
114 float pitch = ((tmp.x / mSceneSize.y) * CAMERA_SENSITIVITY);
115 mCameraYawPitch.x -= yaw;
116 mCameraYawPitch.y -= pitch;
117 if(abs(mCameraYawPitch.x) > CAMERA_VERTICAL_LIMIT)
119 mCameraYawPitch.x = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.x < 0) ? -1.0f : 1.0f);
124 Quaternion rotX(Degree(mCameraYawPitch.x), Vector3(1.0f, 0.0f, 0.0f));
125 Quaternion rotY(Degree(mCameraYawPitch.y), Vector3(0.0f, 1.0f, 0.0f));
128 Quaternion rotZ(Degree(mPortraitMode ? 90.0 : 0.0f), Vector3(0.0f, 0.0f, 1.0f));
129 rotation = (rotZ * rotX * rotY);
133 rotation = (rotY * rotX);
135 mCameraActor.SetProperty(Actor::Property::ORIENTATION, rotation);
137 // ---------------------------------------------------------------------
139 Vector3 position(mCameraPosition);
141 // Rotate CAMERA_FORWARD vector
142 Vector3 forwardVector = rotation.Rotate(CAMERA_FORWARD);
144 // Cancel vertical movement
145 forwardVector.y = 0.0f;
148 forwardVector.Normalize();
150 // compute sideways vector
151 Vector3 sidewaysVector = forwardVector.Cross(CAMERA_UP);
153 sidewaysVector.Normalize();
155 const float forwardSpeed(mScreenWalkDelta.y / mSceneSize.y);
156 const float sidewaysSpeed(mScreenWalkDelta.x / mSceneSize.x);
158 // Adjust walking speed
161 position += forwardVector * (forwardSpeed * 0.5f);
165 position += forwardVector * (-forwardSpeed * 0.5f);
168 position += sidewaysVector * (sidewaysSpeed * 0.5f);
170 mCameraActor.SetProperty(Actor::Property::POSITION, position);
172 mCameraPosition = position;
177 void GameCamera::InitialiseDefaultCamera()
179 mCameraActor.SetProperty(Dali::Actor::Property::NAME, "GameCamera");
180 mCameraActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
181 mCameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
182 mCameraActor.SetFieldOfView(Radian(Degree(mFovY)));
184 // should be read from file
185 mCameraActor.SetNearClippingPlane(mNear);
186 mCameraActor.SetFarClippingPlane(mFar);
187 mCameraActor.SetProperty(Actor::Property::POSITION, CAMERA_DEFAULT_POSITION);
189 // Camera position is shadowed in order to avoid using.GetCurrentProperty< Vector3 >( Actor::Property::POSITION )
190 mCameraPosition = CAMERA_DEFAULT_POSITION;
193 void GameCamera::CreateInterceptorActor()
195 mInterceptorActor = Actor::New();
196 mInterceptorActor.SetProperty(Dali::Actor::Property::NAME, "GameInputInterceptor");
197 mInterceptorActor.SetProperty(Actor::Property::SIZE, Vector3(mSceneSize.x, mSceneSize.y, 1));
198 mInterceptorActor.SetProperty(Actor::Property::POSITION, Vector3(0.0, 0.0, 1.0));
199 mInterceptorActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
200 mInterceptorActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
201 mCameraActor.Add(mInterceptorActor);
203 // Connect TouchedSignal to interceptor actor
204 mInterceptorActor.TouchedSignal().Connect(this, &GameCamera::OnTouch);
207 bool GameCamera::OnTouch(Actor actor, const TouchEvent& touch)
209 for(int i = 0; i < (int)touch.GetPointCount() && i < 3; ++i)
211 int id = touch.GetDeviceId(i);
212 Vector2 tmp(touch.GetScreenPosition(i));
214 float halfWindowSize;
219 halfWindowSize = mSceneSize.y / 2;
225 halfWindowSize = mSceneSize.x / 2;
229 if(touch.GetState(i) == PointState::STARTED)
232 if(position.x > halfWindowSize && mLookingTouchId < 0)
234 mLookingTouchId = id;
235 mOldTouchLookPosition = position;
238 else if(position.x < halfWindowSize && mWalkingTouchId < 0)
240 mWalkingTouchId = id;
241 mOldTouchWalkPosition = position;
242 mScreenWalkDelta = Vector2::ZERO;
245 else if(touch.GetState(i) == PointState::FINISHED ||
246 touch.GetState(i) == PointState::LEAVE ||
247 touch.GetState(i) == PointState::INTERRUPTED)
250 if(mLookingTouchId == id)
252 mScreenLookDelta = Vector2::ZERO;
253 mOldTouchLookPosition = Vector2::ZERO;
254 mLookingTouchId = -1;
257 else if(mWalkingTouchId == id)
259 mScreenWalkDelta = Vector2::ZERO;
260 mOldTouchWalkPosition = Vector2::ZERO;
261 mWalkingTouchId = -1;
267 if(mLookingTouchId == id)
269 mScreenLookDelta.x += (position.x - mOldTouchLookPosition.x);
270 mScreenLookDelta.y += (position.y - mOldTouchLookPosition.y);
271 mOldTouchLookPosition = position;
274 else if(mWalkingTouchId == id)
276 mScreenWalkDelta.x += (position.x - mOldTouchWalkPosition.x);
277 mScreenWalkDelta.y += (position.y - mOldTouchWalkPosition.y);
278 mOldTouchWalkPosition = position;