Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: chrome/browser/android/vr_shell/vr_shell.cc

Issue 2367543002: Implement UI hit testing + Reticle scaling (Closed)
Patch Set: Rebase + address comments Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/android/vr_shell/vr_shell.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/android/vr_shell/vr_shell.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698