00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "tango-gl/gesture_camera.h"
00018 #include "tango-gl/util.h"
00019 #include "glm/gtx/quaternion.hpp"
00020
00021 namespace {
00022
00023 const float kThirdPersonCameraDist = 7.0f;
00024
00025
00026 const float kThirdPersonFollowCameraDist = 2.0f;
00027
00028
00029 const float kTopDownCameraDist = 5.0f;
00030
00031
00032 const float kZoomSpeed = 10.0f;
00033
00034
00035 const float kMoveSpeed = 10.0f;
00036
00037
00038 const float kRotationSpeed = 2.0f;
00039
00040
00041 const float kCamViewMinDist = .1f;
00042 const float kCamViewMaxDist = 100.f;
00043
00044
00045
00046
00047 const float kHighFov = 65.0f;
00048 const float kLowFov = 65.0f;
00049 }
00050
00051 namespace tango_gl {
00052
00053 GestureCamera::GestureCamera() :
00054 cam_cur_target_rot_(1,0,0,0),
00055 start_touch_dist_(0.0f),
00056 cur_touch_dist_(0.0f)
00057 {
00058 cam_parent_transform_ = new Transform();
00059 SetParent(cam_parent_transform_);
00060 }
00061
00062 GestureCamera::~GestureCamera() { delete cam_parent_transform_; }
00063
00064 void GestureCamera::OnTouchEvent(int touch_count, TouchEvent event, float x0,
00065 float y0, float x1, float y1) {
00066
00067 if (camera_type_!=kFirstPerson && touch_count == 1) {
00068 switch (event) {
00069 case kTouch0Down: {
00070 cam_start_angle_ = cam_cur_angle_;
00071
00072 touch0_start_position_.x = x0;
00073 touch0_start_position_.y = y0;
00074 break;
00075 }
00076 case kTouchMove: {
00077 glm::vec2 offset;
00078
00079 float rotation_x = (touch0_start_position_.y - y0) * kRotationSpeed;
00080 float rotation_y = (touch0_start_position_.x - x0) * kRotationSpeed;
00081
00082 if(camera_type_!=kTopOrtho)
00083 cam_cur_angle_.x = cam_start_angle_.x + rotation_x;
00084 cam_cur_angle_.y = cam_start_angle_.y + rotation_y;
00085
00086 StartCameraToCurrentTransform();
00087
00088 break;
00089 }
00090 default: { break; }
00091 }
00092 }
00093 if (touch_count == 2) {
00094 switch (event) {
00095 case kTouch1Down: {
00096 float abs_x = x0 - x1;
00097 float abs_y = y0 - y1;
00098 start_touch_dist_ = std::sqrt(abs_x * abs_x + abs_y * abs_y);
00099 cam_start_dist_ = GetPosition().z;
00100 cam_start_fov_ = this->getFOV();
00101
00102
00103 touch0_start_position_.x = (x0+x1)/2.0f;
00104 touch0_start_position_.y = (y0+y1)/2.0f;
00105 break;
00106 }
00107 case kTouchMove: {
00108 float abs_x = x0 - x1;
00109 float abs_y = y0 - y1;
00110 float dist = start_touch_dist_ - std::sqrt(abs_x * abs_x + abs_y * abs_y);
00111
00112 if(camera_type_ == kFirstPerson)
00113 {
00114 this->SetFieldOfView(tango_gl::util::Clamp(cam_start_fov_ + dist * kZoomSpeed*10.0f, 45, 90));
00115 }
00116 else
00117 {
00118 cam_cur_dist_ = tango_gl::util::Clamp(cam_start_dist_ + dist * kZoomSpeed,
00119 kCamViewMinDist, kCamViewMaxDist);
00120
00121 this->SetOrthoMode(camera_type_ == kTopOrtho);
00122 if(camera_type_ == kTopOrtho)
00123 {
00124 this->SetOrthoScale(cam_cur_dist_);
00125 }
00126
00127 glm::vec2 touch_center_position((x0+x1)/2.0f, (y0+y1)/2.0f);
00128 glm::vec2 offset;
00129 offset.x = (touch_center_position.x - touch0_start_position_.x) * kMoveSpeed;
00130 offset.y = (touch_center_position.y - touch0_start_position_.y) * kMoveSpeed;
00131 touch0_start_position_ = touch_center_position;
00132
00133 StartCameraToCurrentTransform();
00134
00135 anchor_offset_ += glm::rotate(cam_parent_transform_->GetRotation(), glm::vec3(-offset.x, offset.y, 0));
00136 }
00137 break;
00138 }
00139 default: { break; }
00140 }
00141 }
00142 }
00143
00144 Segment GestureCamera::GetSegmentFromTouch(float normalized_x,
00145 float normalized_y,
00146 float touch_range) {
00147 float screen_height = touch_range * (2.0f * glm::tan(field_of_view_ * 0.5f));
00148 float screen_width = screen_height * aspect_ratio_;
00149
00150
00151
00152 normalized_x = normalized_x - 0.5f;
00153 normalized_y = 0.5f - normalized_y;
00154 glm::vec3 start =
00155 util::ApplyTransform(GetTransformationMatrix(), glm::vec3(0, 0, 0));
00156 glm::vec3 end = util::ApplyTransform(GetTransformationMatrix(),
00157 glm::vec3(normalized_x * screen_width, normalized_y * screen_height,
00158 -touch_range));
00159 Segment segment(start, end);
00160 return segment;
00161 }
00162
00163 void GestureCamera::SetAnchorPosition(const glm::vec3& pos, const glm::quat & rotation) {
00164
00165 cam_parent_transform_->SetPosition(pos+anchor_offset_);
00166
00167
00168 if(camera_type_ == kThirdPersonFollow)
00169 {
00170 cam_cur_target_rot_ = rotation;
00171 cam_cur_target_rot_.x = 0;
00172 cam_cur_target_rot_.z = 0;
00173 cam_cur_target_rot_ = glm::normalize(cam_cur_target_rot_);
00174 StartCameraToCurrentTransform();
00175 }
00176 }
00177
00178 void GestureCamera::SetCameraType(CameraType camera_index) {
00179 camera_type_ = camera_index;
00180 switch (camera_index) {
00181 case kFirstPerson:
00182 SetOrthoMode(false);
00183 SetFieldOfView(kLowFov);
00184 SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
00185 SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
00186 cam_cur_dist_ = 0.0f;
00187 anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
00188 cam_cur_angle_.x = 0.0f;
00189 cam_cur_angle_.y = 0.0f;
00190 cam_cur_target_rot_ = glm::quat(1,0,0,0);
00191 cam_parent_transform_->SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
00192 StartCameraToCurrentTransform();
00193 break;
00194 case kThirdPerson:
00195 case kThirdPersonFollow:
00196 SetOrthoMode(false);
00197 SetFieldOfView(kHighFov);
00198 SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
00199 SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
00200 cam_cur_dist_ = kThirdPersonFollow?kThirdPersonFollowCameraDist:kThirdPersonCameraDist;
00201 anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
00202 cam_cur_angle_.x = -M_PI / 6.0f;
00203 cam_cur_angle_.y = kThirdPersonFollow?0:M_PI / 4.0f;
00204 cam_cur_target_rot_ = glm::quat(1,0,0,0);
00205 StartCameraToCurrentTransform();
00206 break;
00207 case kTopDown:
00208 SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
00209 SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
00210 SetOrthoMode(false);
00211 SetFieldOfView(kHighFov);
00212 cam_cur_dist_ = kTopDownCameraDist;
00213 anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
00214 cam_cur_angle_.x = -M_PI / 2.0f;
00215 cam_cur_angle_.y = 0.0f;
00216 cam_cur_target_rot_ = glm::quat(1,0,0,0);
00217 StartCameraToCurrentTransform();
00218 break;
00219 case kTopOrtho:
00220 SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
00221 SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
00222 SetOrthoMode(true);
00223 SetOrthoScale(kTopDownCameraDist);
00224 SetOrthoCropFactor(-1.0f);
00225 cam_cur_dist_ = kTopDownCameraDist;
00226 anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
00227 cam_cur_angle_.x = -M_PI / 2.0f;
00228 cam_cur_angle_.y = 0.0f;
00229 cam_cur_target_rot_ = glm::quat(1,0,0,0);
00230 StartCameraToCurrentTransform();
00231 break;
00232 default:
00233 break;
00234 }
00235 }
00236
00237 void GestureCamera::StartCameraToCurrentTransform()
00238 {
00239
00240 glm::quat parent_cam_rot = glm::rotate(cam_cur_target_rot_, cam_cur_angle_.y, glm::vec3(0, 1, 0));
00241 parent_cam_rot = glm::rotate(parent_cam_rot, cam_cur_angle_.x, glm::vec3(1, 0, 0));
00242 cam_parent_transform_->SetRotation(parent_cam_rot);
00243
00244
00245 SetPosition(glm::vec3(0, 0, cam_cur_dist_));
00246 }
00247 }