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

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

Issue 2367543002: Implement UI hit testing + Reticle scaling (Closed)
Patch Set: Created 4 years, 3 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/vr_compositor.h" 9 #include "chrome/browser/android/vr_shell/vr_compositor.h"
10 #include "chrome/browser/android/vr_shell/vr_gl_util.h" 10 #include "chrome/browser/android/vr_shell/vr_gl_util.h"
(...skipping 20 matching lines...) Expand all
31 31
32 static constexpr gvr::Vec3f kDesktopPositionDefault = {0.0f, 0.0f, -2.0f}; 32 static constexpr gvr::Vec3f kDesktopPositionDefault = {0.0f, 0.0f, -2.0f};
33 static constexpr float kDesktopHeightDefault = 1.6f; 33 static constexpr float kDesktopHeightDefault = 1.6f;
34 34
35 // Screen angle in degrees. 0 = vertical, positive = top closer. 35 // Screen angle in degrees. 0 = vertical, positive = top closer.
36 static constexpr float kDesktopScreenTiltDefault = 0; 36 static constexpr float kDesktopScreenTiltDefault = 0;
37 37
38 static constexpr float kScreenHeightRatio = 1.0f; 38 static constexpr float kScreenHeightRatio = 1.0f;
39 static constexpr float kScreenWidthRatio = 16.0f / 9.0f; 39 static constexpr float kScreenWidthRatio = 16.0f / 9.0f;
40 40
41 static constexpr float kReticleWidth = 0.05f; 41 static constexpr float kReticleWidth = 0.025f;
42 static constexpr float kReticleHeight = 0.05f; 42 static constexpr float kReticleHeight = 0.025f;
43 43
44 static constexpr float kLaserWidth = 0.01f; 44 static constexpr float kLaserWidth = 0.01f;
45 45
46 // The neutral direction is fixed in world space, this is the 46 // The neutral direction is fixed in world space, this is the
47 // reference angle pointing forward towards the horizon when the 47 // reference angle pointing forward towards the horizon when the
48 // controller orientation is reset. This should match the yaw angle 48 // controller orientation is reset. This should match the yaw angle
49 // where the main screen is placed. 49 // where the main screen is placed.
50 static constexpr gvr::Vec3f kNeutralPose = {0.0f, 0.0f, -1.0f}; 50 static constexpr gvr::Vec3f kNeutralPose = {0.0f, 0.0f, -1.0f};
51 51
52 static constexpr gvr::Vec3f kOrigin = {0.0f, 0.0f, 0.0f};
53
52 // In lieu of an elbow model, we assume a position for the user's hand. 54 // In lieu of an elbow model, we assume a position for the user's hand.
53 // TODO(mthiesse): Handedness options. 55 // TODO(mthiesse): Handedness options.
54 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f}; 56 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f};
55 57
56 static constexpr float kReticleZOffset = 0.01f; 58 // Fraction of the z-distance to the object the cursor is drawn at to avoid
59 // rounding errors drawing the cursor behind the object.
60 static constexpr float kReticleZOffset = 0.99f;
57 61
58 } // namespace 62 } // namespace
59 63
60 namespace vr_shell { 64 namespace vr_shell {
61 65
62 VrShell::VrShell(JNIEnv* env, jobject obj, 66 VrShell::VrShell(JNIEnv* env, jobject obj,
63 content::ContentViewCore* content_core, 67 content::ContentViewCore* content_core,
64 ui::WindowAndroid* content_window) 68 ui::WindowAndroid* content_window)
65 : desktop_screen_tilt_(kDesktopScreenTiltDefault), 69 : desktop_screen_tilt_(kDesktopScreenTiltDefault),
66 desktop_height_(kDesktopHeightDefault), 70 desktop_height_(kDesktopHeightDefault),
67 desktop_position_(kDesktopPositionDefault), 71 desktop_position_(kDesktopPositionDefault),
72 cursor_distance_(-kDesktopPositionDefault.z),
68 content_cvc_(content_core) { 73 content_cvc_(content_core) {
69 j_vr_shell_.Reset(env, obj); 74 j_vr_shell_.Reset(env, obj);
70 content_compositor_view_.reset(new VrCompositor(content_window)); 75 content_compositor_view_.reset(new VrCompositor(content_window));
71 ui_rects_.emplace_back(new ContentRectangle()); 76 ui_rects_.emplace_back(new ContentRectangle());
72 desktop_plane_ = ui_rects_.back().get(); 77 desktop_plane_ = ui_rects_.back().get();
73 desktop_plane_->id = 0; 78 desktop_plane_->id = 0;
74 desktop_plane_->copy_rect = {0.0f, 0.0f, 1.0f, 1.0f}; 79 desktop_plane_->copy_rect = {0.0f, 0.0f, 1.0f, 1.0f};
75 // TODO(cjgrant): If we use the native path for content clicks, fix this. 80 // TODO(cjgrant): If we use the native path for content clicks, fix this.
76 desktop_plane_->window_rect = {0, 0, 0, 0}; 81 desktop_plane_->window_rect = {0, 0, 0, 0};
77 desktop_plane_->translation = {0.0f, 0.0f, 0.0f}; 82 desktop_plane_->translation = {0.0f, 0.0f, 0.0f};
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 gvr::Vec3f translation = getTranslation(mat); 167 gvr::Vec3f translation = getTranslation(mat);
163 168
164 // Use the eye midpoint as the origin for Cardboard mode, but apply an offset 169 // Use the eye midpoint as the origin for Cardboard mode, but apply an offset
165 // for the controller. 170 // for the controller.
166 if (controller_active_) { 171 if (controller_active_) {
167 translation.x += kHandPosition.x; 172 translation.x += kHandPosition.x;
168 translation.y += kHandPosition.y; 173 translation.y += kHandPosition.y;
169 translation.z += kHandPosition.z; 174 translation.z += kHandPosition.z;
170 } 175 }
171 176
172 // We can only be intersecting the desktop plane at the moment. 177 float desktop_dist = ui_rects_[0]->GetRayDistance(translation, forward);
cjgrant 2016/09/22 18:59:04 Should use desktop_plane_ or scene_.GetUiElementBy
mthiesse 2016/09/22 22:01:33 Done.
173 float distance_to_plane = desktop_plane_->GetRayDistance(translation, 178 gvr::Vec3f cursor_position = GetRayPoint(translation, forward, desktop_dist);
cjgrant 2016/09/22 18:59:03 If you want, there's a better way to do this. Sin
mthiesse 2016/09/22 22:01:33 I'll get back to this when we have working control
174 forward); 179 look_at_vector_ = cursor_position;
175 look_at_vector_ = GetRayPoint(translation, forward, distance_to_plane); 180 cursor_distance_ = desktop_dist;
181
182 // Determine which UI element (if any) the cursor is pointing to.
183 float closest_element = std::numeric_limits<float>::infinity();
184 int closest_element_index = -1;
185 int pixel_x, pixel_y;
186
187 for (std::size_t i = 0; i < ui_rects_.size(); ++i) {
188 const ContentRectangle& plane = *ui_rects_[i].get();
189 float distance_to_plane = plane.GetRayDistance(kOrigin, cursor_position);
190 gvr::Vec3f plane_intersection_point =
191 GetRayPoint(kOrigin, cursor_position, distance_to_plane);
192 gvr::Vec3f rect_2d_point =
193 MatrixVectorMul(plane.transform.from_world, plane_intersection_point);
194 float x = rect_2d_point.x + 0.5f;
195 float y = 0.5f - rect_2d_point.y;
196 if (distance_to_plane > 0 && distance_to_plane < closest_element) {
197 bool is_inside = x >= 0.0f && x < 1.0f && y >= 0.0f && y < 1.0f;
198 if (is_inside) {
199 closest_element = distance_to_plane;
200 cursor_distance_ = desktop_dist * distance_to_plane;
201 closest_element_index = i;
202 pixel_x = int((plane.copy_rect.width * x) + plane.copy_rect.x);
203 pixel_y = int((plane.copy_rect.height * y) + plane.copy_rect.y);
204 look_at_vector_ = plane_intersection_point;
205 }
206 }
207 }
208 // TODO(mthiesse): Create input events for CVC using pixel_x/y.
176 } 209 }
177 210
178 void ApplyNeckModel(gvr::Mat4f& mat_forward) { 211 void ApplyNeckModel(gvr::Mat4f& mat_forward) {
179 // This assumes that the input matrix is a pure rotation matrix. The 212 // This assumes that the input matrix is a pure rotation matrix. The
180 // input object_from_reference matrix has the inverse rotation of 213 // input object_from_reference matrix has the inverse rotation of
181 // the head rotation. Invert it (this is just a transpose). 214 // the head rotation. Invert it (this is just a transpose).
182 gvr::Mat4f mat = MatrixTranspose(mat_forward); 215 gvr::Mat4f mat = MatrixTranspose(mat_forward);
183 216
184 // Position of the point between the eyes, relative to the neck pivot: 217 // Position of the point between the eyes, relative to the neck pivot:
185 const float kNeckHorizontalOffset = -0.080f; // meters in Z 218 const float kNeckHorizontalOffset = -0.080f; // meters in Z
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 frame.Unbind(); 253 frame.Unbind();
221 frame.Submit(*buffer_viewport_list_, head_pose_); 254 frame.Submit(*buffer_viewport_list_, head_pose_);
222 } 255 }
223 256
224 void VrShell::DrawVrShell() { 257 void VrShell::DrawVrShell() {
225 float screen_width = kScreenWidthRatio * desktop_height_; 258 float screen_width = kScreenWidthRatio * desktop_height_;
226 float screen_height = kScreenHeightRatio * desktop_height_; 259 float screen_height = kScreenHeightRatio * desktop_height_;
227 260
228 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; 261 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f;
229 262
230 forward_vector_ = getForwardVector(head_pose_);
231
232 gvr::Vec3f headPos = getTranslation(head_pose_); 263 gvr::Vec3f headPos = getTranslation(head_pose_);
233 if (headPos.x == 0.0f && headPos.y == 0.0f && headPos.z == 0.0f) { 264 if (headPos.x == 0.0f && headPos.y == 0.0f && headPos.z == 0.0f) {
234 // This appears to be a 3DOF pose without a neck model. Add one. 265 // This appears to be a 3DOF pose without a neck model. Add one.
235 // The head pose has redundant data. Assume we're only using the 266 // The head pose has redundant data. Assume we're only using the
236 // object_from_reference_matrix, we're not updating position_external. 267 // object_from_reference_matrix, we're not updating position_external.
237 // TODO: Not sure what object_from_reference_matrix is. The new api removed 268 // TODO: Not sure what object_from_reference_matrix is. The new api removed
238 // it. For now, removing it seems working fine. 269 // it. For now, removing it seems working fine.
239 ApplyNeckModel(head_pose_); 270 ApplyNeckModel(head_pose_);
240 } 271 }
241 272
273 forward_vector_ = getForwardVector(head_pose_);
274
242 desktop_plane_->size = {screen_width, screen_height, 1.0f}; 275 desktop_plane_->size = {screen_width, screen_height, 1.0f};
243 desktop_plane_->translation.x = desktop_position_.x; 276 desktop_plane_->translation.x = desktop_position_.x;
244 desktop_plane_->translation.y = desktop_position_.y; 277 desktop_plane_->translation.y = desktop_position_.y;
245 desktop_plane_->translation.z = desktop_position_.z; 278 desktop_plane_->translation.z = desktop_position_.z;
246 279
247 // Update position of all UI elements (including desktop) 280 // Update position of all UI elements (including desktop)
248 UpdateTransforms(screen_width, screen_height, screen_tilt); 281 UpdateTransforms(screen_width, screen_height, screen_tilt);
249 282
250 UpdateController(); 283 UpdateController();
251 284
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 combined_matrix = MatrixMul(projection_matrix_, combined_matrix); 335 combined_matrix = MatrixMul(projection_matrix_, combined_matrix);
303 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( 336 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw(
304 ui_rects_[i].get()->content_texture_handle, combined_matrix, 337 ui_rects_[i].get()->content_texture_handle, combined_matrix,
305 ui_rects_[i].get()->copy_rect); 338 ui_rects_[i].get()->copy_rect);
306 } 339 }
307 } 340 }
308 341
309 void VrShell::DrawCursor() { 342 void VrShell::DrawCursor() {
310 gvr::Mat4f mat; 343 gvr::Mat4f mat;
311 SetIdentityM(mat); 344 SetIdentityM(mat);
345
312 // Scale the pointer. 346 // Scale the pointer.
cjgrant 2016/09/22 18:59:04 ... to have a fixed FOV size at any distance. (?)
mthiesse 2016/09/22 22:01:33 Done.
313 ScaleM(mat, mat, kReticleWidth, kReticleHeight, 1.0f); 347 ScaleM(mat, mat, kReticleWidth * cursor_distance_,
348 kReticleHeight * cursor_distance_, 1.0f);
349
314 // Place the pointer at the screen plane intersection point. 350 // Place the pointer at the screen plane intersection point.
315 TranslateM(mat, mat, look_at_vector_.x, look_at_vector_.y, 351 TranslateM(mat, mat, look_at_vector_.x * kReticleZOffset,
cjgrant 2016/09/22 18:59:03 Why are x and y also being offset?
mthiesse 2016/09/22 22:01:33 We're moving it slightly towards the viewer while
316 look_at_vector_.z + kReticleZOffset); 352 look_at_vector_.y * kReticleZOffset,
353 look_at_vector_.z * kReticleZOffset);
317 gvr::Mat4f mv = MatrixMul(view_matrix_, mat); 354 gvr::Mat4f mv = MatrixMul(view_matrix_, mat);
318 gvr::Mat4f mvp = MatrixMul(projection_matrix_, mv); 355 gvr::Mat4f mvp = MatrixMul(projection_matrix_, mv);
319 vr_shell_renderer_->GetReticleRenderer()->Draw(mvp); 356 vr_shell_renderer_->GetReticleRenderer()->Draw(mvp);
320 357
321 // Draw the laser only for controllers. 358 // Draw the laser only for controllers.
322 if (!controller_active_) { 359 if (!controller_active_) {
323 return; 360 return;
324 } 361 }
325 // Find the length of the beam (from hand to target). 362 // Find the length of the beam (from hand to target).
326 float xdiff = (kHandPosition.x - look_at_vector_.x); 363 float xdiff = (kHandPosition.x - look_at_vector_.x);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 const JavaParamRef<jobject>& content_web_contents, 508 const JavaParamRef<jobject>& content_web_contents,
472 jlong content_window_android) { 509 jlong content_window_android) {
473 content::ContentViewCore* c_core = content::ContentViewCore::FromWebContents( 510 content::ContentViewCore* c_core = content::ContentViewCore::FromWebContents(
474 content::WebContents::FromJavaWebContents(content_web_contents)); 511 content::WebContents::FromJavaWebContents(content_web_contents));
475 return reinterpret_cast<intptr_t>(new VrShell( 512 return reinterpret_cast<intptr_t>(new VrShell(
476 env, obj, c_core, 513 env, obj, c_core,
477 reinterpret_cast<ui::WindowAndroid*>(content_window_android))); 514 reinterpret_cast<ui::WindowAndroid*>(content_window_android)));
478 } 515 }
479 516
480 } // namespace vr_shell 517 } // 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