OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/android/vr_shell/vr_shell.h" | 5 #include "chrome/browser/android/vr_shell/vr_shell.h" |
6 | 6 |
7 #include <thread> | 7 #include <thread> |
8 | 8 |
9 #include "chrome/browser/android/vr_shell/ui_scene.h" | 9 #include "chrome/browser/android/vr_shell/ui_scene.h" |
10 #include "chrome/browser/android/vr_shell/vr_compositor.h" | 10 #include "chrome/browser/android/vr_shell/vr_compositor.h" |
(...skipping 22 matching lines...) Expand all Loading... | |
33 | 33 |
34 static constexpr gvr::Vec3f kDesktopPositionDefault = {0.0f, 0.0f, -2.0f}; | 34 static constexpr gvr::Vec3f kDesktopPositionDefault = {0.0f, 0.0f, -2.0f}; |
35 static constexpr float kDesktopHeightDefault = 1.6f; | 35 static constexpr float kDesktopHeightDefault = 1.6f; |
36 | 36 |
37 // Screen angle in degrees. 0 = vertical, positive = top closer. | 37 // Screen angle in degrees. 0 = vertical, positive = top closer. |
38 static constexpr float kDesktopScreenTiltDefault = 0; | 38 static constexpr float kDesktopScreenTiltDefault = 0; |
39 | 39 |
40 static constexpr float kScreenHeightRatio = 1.0f; | 40 static constexpr float kScreenHeightRatio = 1.0f; |
41 static constexpr float kScreenWidthRatio = 16.0f / 9.0f; | 41 static constexpr float kScreenWidthRatio = 16.0f / 9.0f; |
42 | 42 |
43 static constexpr float kReticleWidth = 0.05f; | 43 static constexpr float kReticleWidth = 0.025f; |
44 static constexpr float kReticleHeight = 0.05f; | 44 static constexpr float kReticleHeight = 0.025f; |
45 | 45 |
46 static constexpr float kLaserWidth = 0.01f; | 46 static constexpr float kLaserWidth = 0.01f; |
47 | 47 |
48 // The neutral direction is fixed in world space, this is the | 48 // The neutral direction is fixed in world space, this is the |
49 // reference angle pointing forward towards the horizon when the | 49 // reference angle pointing forward towards the horizon when the |
50 // controller orientation is reset. This should match the yaw angle | 50 // controller orientation is reset. This should match the yaw angle |
51 // where the main screen is placed. | 51 // where the main screen is placed. |
52 static constexpr gvr::Vec3f kNeutralPose = {0.0f, 0.0f, -1.0f}; | 52 static constexpr gvr::Vec3f kNeutralPose = {0.0f, 0.0f, -1.0f}; |
53 | 53 |
54 static constexpr gvr::Vec3f kOrigin = {0.0f, 0.0f, 0.0f}; | |
55 | |
54 // In lieu of an elbow model, we assume a position for the user's hand. | 56 // In lieu of an elbow model, we assume a position for the user's hand. |
55 // TODO(mthiesse): Handedness options. | 57 // TODO(mthiesse): Handedness options. |
56 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f}; | 58 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f}; |
57 | 59 |
58 static constexpr float kReticleZOffset = 0.01f; | 60 // Fraction of the z-distance to the object the cursor is drawn at to avoid |
61 // rounding errors drawing the cursor behind the object. | |
62 static constexpr float kReticleZOffset = 0.99f; | |
59 | 63 |
60 // UI element 0 is the browser content rectangle. | 64 // UI element 0 is the browser content rectangle. |
61 static constexpr int kBrowserUiElementId = 0; | 65 static constexpr int kBrowserUiElementId = 0; |
62 | 66 |
63 vr_shell::VrShell* g_instance; | 67 vr_shell::VrShell* g_instance; |
64 | 68 |
65 } // namespace | 69 } // namespace |
66 | 70 |
67 namespace vr_shell { | 71 namespace vr_shell { |
68 | 72 |
69 VrShell::VrShell(JNIEnv* env, jobject obj, | 73 VrShell::VrShell(JNIEnv* env, jobject obj, |
70 content::ContentViewCore* content_core, | 74 content::ContentViewCore* content_core, |
71 ui::WindowAndroid* content_window) | 75 ui::WindowAndroid* content_window) |
72 : desktop_screen_tilt_(kDesktopScreenTiltDefault), | 76 : desktop_screen_tilt_(kDesktopScreenTiltDefault), |
73 desktop_height_(kDesktopHeightDefault), | 77 desktop_height_(kDesktopHeightDefault), |
74 desktop_position_(kDesktopPositionDefault), | 78 desktop_position_(kDesktopPositionDefault), |
79 cursor_distance_(-kDesktopPositionDefault.z), | |
75 content_cvc_(content_core), | 80 content_cvc_(content_core), |
76 delegate_(nullptr), | 81 delegate_(nullptr), |
77 weak_ptr_factory_(this) { | 82 weak_ptr_factory_(this) { |
78 g_instance = this; | 83 g_instance = this; |
79 j_vr_shell_.Reset(env, obj); | 84 j_vr_shell_.Reset(env, obj); |
80 content_compositor_view_.reset(new VrCompositor(content_window)); | 85 content_compositor_view_.reset(new VrCompositor(content_window)); |
81 | 86 |
82 float screen_width = kScreenWidthRatio * desktop_height_; | 87 float screen_width = kScreenWidthRatio * desktop_height_; |
83 float screen_height = kScreenHeightRatio * desktop_height_; | 88 float screen_height = kScreenHeightRatio * desktop_height_; |
84 std::unique_ptr<ContentRectangle> rect(new ContentRectangle()); | 89 std::unique_ptr<ContentRectangle> rect(new ContentRectangle()); |
85 rect->id = kBrowserUiElementId; | 90 rect->id = kBrowserUiElementId; |
86 rect->size = {screen_width, screen_height, 1.0f}; | 91 rect->size = {screen_width, screen_height, 1.0f}; |
87 scene_.AddUiElement(rect); | 92 scene_.AddUiElement(rect); |
88 | 93 |
89 desktop_plane_ = scene_.GetUiElementById(kBrowserUiElementId); | 94 desktop_plane_ = scene_.GetUiElementById(kBrowserUiElementId); |
90 | 95 |
91 content_cvc_->GetWebContents()->GetRenderWidgetHostView() | 96 content_cvc_->GetWebContents()->GetRenderWidgetHostView() |
92 ->GetRenderWidgetHost()->WasResized(); | 97 ->GetRenderWidgetHost()->WasResized(); |
93 } | 98 } |
94 | 99 |
95 void VrShell::UpdateCompositorLayers(JNIEnv* env, | 100 void VrShell::UpdateCompositorLayers(JNIEnv* env, |
96 const JavaParamRef<jobject>& obj) { | 101 const JavaParamRef<jobject>& obj) { |
97 content_compositor_view_->SetLayer(content_cvc_); | 102 content_compositor_view_->SetLayer(content_cvc_); |
98 } | 103 } |
99 | 104 |
100 void VrShell::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 105 void VrShell::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
101 delete this; | 106 delete this; |
102 g_instance = nullptr; | |
103 gl::init::ClearGLBindings(); | |
104 } | 107 } |
105 | 108 |
106 bool RegisterVrShell(JNIEnv* env) { | 109 bool RegisterVrShell(JNIEnv* env) { |
107 return RegisterNativesImpl(env); | 110 return RegisterNativesImpl(env); |
108 } | 111 } |
109 | 112 |
110 VrShell::~VrShell() { | 113 VrShell::~VrShell() { |
114 g_instance = nullptr; | |
115 gl::init::ClearGLBindings(); | |
111 } | 116 } |
112 | 117 |
113 void VrShell::SetDelegate(JNIEnv* env, | 118 void VrShell::SetDelegate(JNIEnv* env, |
114 const base::android::JavaParamRef<jobject>& obj, | 119 const base::android::JavaParamRef<jobject>& obj, |
115 const base::android::JavaParamRef<jobject>& delegate) { | 120 const base::android::JavaParamRef<jobject>& delegate) { |
116 delegate_ = VrShellDelegate::getNativeDelegate(env, delegate); | 121 delegate_ = VrShellDelegate::getNativeDelegate(env, delegate); |
117 } | 122 } |
118 | 123 |
119 void VrShell::GvrInit(JNIEnv* env, | 124 void VrShell::GvrInit(JNIEnv* env, |
120 const JavaParamRef<jobject>& obj, | 125 const JavaParamRef<jobject>& obj, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 gvr::Vec3f translation = getTranslation(mat); | 180 gvr::Vec3f translation = getTranslation(mat); |
176 | 181 |
177 // Use the eye midpoint as the origin for Cardboard mode, but apply an offset | 182 // Use the eye midpoint as the origin for Cardboard mode, but apply an offset |
178 // for the controller. | 183 // for the controller. |
179 if (controller_active_) { | 184 if (controller_active_) { |
180 translation.x += kHandPosition.x; | 185 translation.x += kHandPosition.x; |
181 translation.y += kHandPosition.y; | 186 translation.y += kHandPosition.y; |
182 translation.z += kHandPosition.z; | 187 translation.z += kHandPosition.z; |
183 } | 188 } |
184 | 189 |
185 // We can only be intersecting the desktop plane at the moment. | 190 float desktop_dist = scene_.GetUiElementById(kBrowserUiElementId) |
186 float distance_to_plane = desktop_plane_->GetRayDistance(translation, | 191 ->GetRayDistance(translation, forward); |
187 forward); | 192 gvr::Vec3f cursor_position = GetRayPoint(translation, forward, desktop_dist); |
188 look_at_vector_ = GetRayPoint(translation, forward, distance_to_plane); | 193 look_at_vector_ = cursor_position; |
194 cursor_distance_ = desktop_dist; | |
195 | |
196 // Determine which UI element (if any) the cursor is pointing to. | |
197 float closest_element = std::numeric_limits<float>::infinity(); | |
198 int closest_element_index = -1; | |
199 int pixel_x, pixel_y; | |
bshe
2016/09/22 23:28:42
you might get uninitalized variable error from ASA
mthiesse
2016/09/23 14:54:34
Done.
| |
200 | |
201 for (std::size_t i = 0; i < scene_.GetUiElements().size(); ++i) { | |
202 const ContentRectangle& plane = *scene_.GetUiElements()[i].get(); | |
203 float distance_to_plane = plane.GetRayDistance(kOrigin, cursor_position); | |
204 gvr::Vec3f plane_intersection_point = | |
205 GetRayPoint(kOrigin, cursor_position, distance_to_plane); | |
206 gvr::Vec3f rect_2d_point = | |
207 MatrixVectorMul(plane.transform.from_world, plane_intersection_point); | |
208 float x = rect_2d_point.x + 0.5f; | |
209 float y = 0.5f - rect_2d_point.y; | |
210 if (distance_to_plane > 0 && distance_to_plane < closest_element) { | |
211 bool is_inside = x >= 0.0f && x < 1.0f && y >= 0.0f && y < 1.0f; | |
212 if (is_inside) { | |
213 closest_element = distance_to_plane; | |
214 cursor_distance_ = desktop_dist * distance_to_plane; | |
215 closest_element_index = i; | |
216 pixel_x = int((plane.copy_rect.width * x) + plane.copy_rect.x); | |
217 pixel_y = int((plane.copy_rect.height * y) + plane.copy_rect.y); | |
218 look_at_vector_ = plane_intersection_point; | |
219 } | |
220 } | |
221 } | |
222 // TODO(mthiesse): Create input events for CVC using pixel_x/y. | |
189 } | 223 } |
190 | 224 |
191 void ApplyNeckModel(gvr::Mat4f& mat_forward) { | 225 void ApplyNeckModel(gvr::Mat4f& mat_forward) { |
192 // This assumes that the input matrix is a pure rotation matrix. The | 226 // This assumes that the input matrix is a pure rotation matrix. The |
193 // input object_from_reference matrix has the inverse rotation of | 227 // input object_from_reference matrix has the inverse rotation of |
194 // the head rotation. Invert it (this is just a transpose). | 228 // the head rotation. Invert it (this is just a transpose). |
195 gvr::Mat4f mat = MatrixTranspose(mat_forward); | 229 gvr::Mat4f mat = MatrixTranspose(mat_forward); |
196 | 230 |
197 // Position of the point between the eyes, relative to the neck pivot: | 231 // Position of the point between the eyes, relative to the neck pivot: |
198 const float kNeckHorizontalOffset = -0.080f; // meters in Z | 232 const float kNeckHorizontalOffset = -0.080f; // meters in Z |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 DrawVrShell(target_time.monotonic_system_time_nanos); | 264 DrawVrShell(target_time.monotonic_system_time_nanos); |
231 } | 265 } |
232 | 266 |
233 frame.Unbind(); | 267 frame.Unbind(); |
234 frame.Submit(*buffer_viewport_list_, head_pose_); | 268 frame.Submit(*buffer_viewport_list_, head_pose_); |
235 } | 269 } |
236 | 270 |
237 void VrShell::DrawVrShell(int64_t time) { | 271 void VrShell::DrawVrShell(int64_t time) { |
238 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; | 272 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; |
239 | 273 |
240 forward_vector_ = getForwardVector(head_pose_); | |
241 | |
242 gvr::Vec3f headPos = getTranslation(head_pose_); | 274 gvr::Vec3f headPos = getTranslation(head_pose_); |
243 if (headPos.x == 0.0f && headPos.y == 0.0f && headPos.z == 0.0f) { | 275 if (headPos.x == 0.0f && headPos.y == 0.0f && headPos.z == 0.0f) { |
244 // This appears to be a 3DOF pose without a neck model. Add one. | 276 // This appears to be a 3DOF pose without a neck model. Add one. |
245 // The head pose has redundant data. Assume we're only using the | 277 // The head pose has redundant data. Assume we're only using the |
246 // object_from_reference_matrix, we're not updating position_external. | 278 // object_from_reference_matrix, we're not updating position_external. |
247 // TODO: Not sure what object_from_reference_matrix is. The new api removed | 279 // TODO: Not sure what object_from_reference_matrix is. The new api removed |
248 // it. For now, removing it seems working fine. | 280 // it. For now, removing it seems working fine. |
249 ApplyNeckModel(head_pose_); | 281 ApplyNeckModel(head_pose_); |
250 } | 282 } |
251 | 283 |
252 desktop_plane_->translation.x = desktop_position_.x; | 284 forward_vector_ = getForwardVector(head_pose_); |
253 desktop_plane_->translation.y = desktop_position_.y; | 285 |
254 desktop_plane_->translation.z = desktop_position_.z; | 286 desktop_plane_->translation = desktop_position_; |
255 | 287 |
256 // Update the render position of all UI elements (including desktop). | 288 // Update the render position of all UI elements (including desktop). |
257 scene_.UpdateTransforms(screen_tilt, time); | 289 scene_.UpdateTransforms(screen_tilt, time); |
258 | 290 |
259 UpdateController(); | 291 UpdateController(); |
260 | 292 |
261 // Everything should be positioned now, ready for drawing. | 293 // Everything should be positioned now, ready for drawing. |
262 gvr::Mat4f left_eye_view_matrix = | 294 gvr::Mat4f left_eye_view_matrix = |
263 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE), head_pose_); | 295 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE), head_pose_); |
264 gvr::Mat4f right_eye_view_matrix = | 296 gvr::Mat4f right_eye_view_matrix = |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 } | 357 } |
326 | 358 |
327 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( | 359 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( |
328 texture_handle, combined_matrix, copy_rect); | 360 texture_handle, combined_matrix, copy_rect); |
329 } | 361 } |
330 } | 362 } |
331 | 363 |
332 void VrShell::DrawCursor() { | 364 void VrShell::DrawCursor() { |
333 gvr::Mat4f mat; | 365 gvr::Mat4f mat; |
334 SetIdentityM(mat); | 366 SetIdentityM(mat); |
335 // Scale the pointer. | 367 |
336 ScaleM(mat, mat, kReticleWidth, kReticleHeight, 1.0f); | 368 // Scale the pointer to have a fixed FOV size at any distance. |
369 ScaleM(mat, mat, kReticleWidth * cursor_distance_, | |
370 kReticleHeight * cursor_distance_, 1.0f); | |
371 | |
337 // Place the pointer at the screen plane intersection point. | 372 // Place the pointer at the screen plane intersection point. |
338 TranslateM(mat, mat, look_at_vector_.x, look_at_vector_.y, | 373 TranslateM(mat, mat, look_at_vector_.x * kReticleZOffset, |
339 look_at_vector_.z + kReticleZOffset); | 374 look_at_vector_.y * kReticleZOffset, |
375 look_at_vector_.z * kReticleZOffset); | |
340 gvr::Mat4f mv = MatrixMul(view_matrix_, mat); | 376 gvr::Mat4f mv = MatrixMul(view_matrix_, mat); |
341 gvr::Mat4f mvp = MatrixMul(projection_matrix_, mv); | 377 gvr::Mat4f mvp = MatrixMul(projection_matrix_, mv); |
342 vr_shell_renderer_->GetReticleRenderer()->Draw(mvp); | 378 vr_shell_renderer_->GetReticleRenderer()->Draw(mvp); |
343 | 379 |
344 // Draw the laser only for controllers. | 380 // Draw the laser only for controllers. |
345 if (!controller_active_) { | 381 if (!controller_active_) { |
346 return; | 382 return; |
347 } | 383 } |
348 // Find the length of the beam (from hand to target). | 384 // Find the length of the beam (from hand to target). |
349 float xdiff = (kHandPosition.x - look_at_vector_.x); | 385 float xdiff = (kHandPosition.x - look_at_vector_.x); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
463 const JavaParamRef<jobject>& content_web_contents, | 499 const JavaParamRef<jobject>& content_web_contents, |
464 jlong content_window_android) { | 500 jlong content_window_android) { |
465 content::ContentViewCore* c_core = content::ContentViewCore::FromWebContents( | 501 content::ContentViewCore* c_core = content::ContentViewCore::FromWebContents( |
466 content::WebContents::FromJavaWebContents(content_web_contents)); | 502 content::WebContents::FromJavaWebContents(content_web_contents)); |
467 return reinterpret_cast<intptr_t>(new VrShell( | 503 return reinterpret_cast<intptr_t>(new VrShell( |
468 env, obj, c_core, | 504 env, obj, c_core, |
469 reinterpret_cast<ui::WindowAndroid*>(content_window_android))); | 505 reinterpret_cast<ui::WindowAndroid*>(content_window_android))); |
470 } | 506 } |
471 | 507 |
472 } // namespace vr_shell | 508 } // namespace vr_shell |
OLD | NEW |