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

Unified Diff: chrome/browser/android/vr_shell/vr_shell.cc

Issue 2301633002: Refactor Vr activity into ChromeTabbedActivity. (Closed)
Patch Set: Clean up vr_util Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/android/vr_shell/vr_shell.cc
diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc
index cbc58091fe6421241007f0f10fd073949453836f..61fef6a8944c251ee8a5767006da88e35c586f6b 100644
--- a/chrome/browser/android/vr_shell/vr_shell.cc
+++ b/chrome/browser/android/vr_shell/vr_shell.cc
@@ -4,65 +4,40 @@
#include "chrome/browser/android/vr_shell/vr_shell.h"
+#include <thread>
+
#include "chrome/browser/android/vr_shell/vr_shell_renderer.h"
#include "chrome/browser/android/vr_shell/vr_util.h"
#include "jni/VrShell_jni.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/init/gl_factory.h"
-namespace vr_shell {
-
-namespace {
-// Constant taken from treasure_hunt demo.
-const long kPredictionTimeWithoutVsyncNanos = 50000000;
-
-const float kZNear = 0.1f;
-const float kZFar = 1000.0f;
-
-// Content rect in world coordinates. Height and width are currently supplied
-// as DrawFrame arguments.
-const gvr::Vec3f kContentRectPositionDefault = {0.0f, 0.0f, -1.0f};
-
-} // namespace
-
-ContentRect::ContentRect() {
- SetIdentity();
-}
+using base::android::JavaParamRef;
-ContentRect::~ContentRect() {}
-
-void ContentRect::SetIdentity() {
- transfrom_to_world.m[0][0] = 1;
- transfrom_to_world.m[0][1] = 0;
- transfrom_to_world.m[0][2] = 0;
- transfrom_to_world.m[0][3] = 0;
- transfrom_to_world.m[1][0] = 0;
- transfrom_to_world.m[1][1] = 1;
- transfrom_to_world.m[1][2] = 0;
- transfrom_to_world.m[1][3] = 0;
- transfrom_to_world.m[2][0] = 0;
- transfrom_to_world.m[2][1] = 0;
- transfrom_to_world.m[2][2] = 1;
- transfrom_to_world.m[2][3] = 0;
- transfrom_to_world.m[3][0] = 0;
- transfrom_to_world.m[3][1] = 0;
- transfrom_to_world.m[3][2] = 0;
- transfrom_to_world.m[3][3] = 1;
-}
+namespace vr_shell {
-void ContentRect::Translate(float x, float y, float z) {
- transfrom_to_world.m[0][3] += x;
- transfrom_to_world.m[1][3] += y;
- transfrom_to_world.m[2][3] += z;
-}
+constexpr gvr::Vec3f VrShell::kDesktopPositionDefault;
VrShell::VrShell(JNIEnv* env, jobject obj) {
j_vr_shell_.Reset(env, obj);
+ ui_rects_.emplace_back(new ContentRectangle());
+ desktop_plane_ = ui_rects_.back().get();
+ desktop_plane_->id = 0;
+ desktop_plane_->copyRect = {0.0f, 0.0f, 1.0f, 1.0f};
+ // TODO(cjgrant): If we use the native path for content clicks, fix this.
+ desktop_plane_->windowRect = {0, 0, 0, 0};
+ desktop_plane_->translation = {0.0f, 0.0f, 0.0f};
+ desktop_plane_->xAnchoring = XNONE;
+ desktop_plane_->yAnchoring = YNONE;
+ desktop_plane_->anchorZ = false;
+ desktop_plane_->orientationAxisAngle = {{1.0f, 0.0f, 0.0f, 0.0f}};
+ desktop_plane_->rotationAxisAngle = {{0.0f, 0.0f, 0.0f, 0.0f}};
}
void VrShell::Destroy(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
delete this;
+ gl::init::ClearGLBindings();
}
bool RegisterVrShell(JNIEnv* env) {
@@ -72,24 +47,27 @@ bool RegisterVrShell(JNIEnv* env) {
VrShell::~VrShell() {}
void VrShell::GvrInit(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
+ const JavaParamRef<jobject>& obj,
jlong native_gvr_api) {
gvr_api_ =
gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(native_gvr_api));
}
void VrShell::InitializeGl(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jint texture_data_handle) {
- gl::init::InitializeGLOneOff();
+ const JavaParamRef<jobject>& obj,
+ jint textureDataHandle) {
+ CHECK(gl::GetGLImplementation() != gl::kGLImplementationNone ||
+ gl::init::InitializeGLOneOff());
+
+ content_texture_id_ = textureDataHandle;
gvr_api_->InitializeGl();
std::vector<gvr::BufferSpec> specs;
specs.push_back(gvr_api_->CreateBufferSpec());
render_size_ = specs[0].GetSize();
swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapchain(specs)));
- content_rect_.reset(new ContentRect());
- content_rect_->content_texture_handle =
- reinterpret_cast<int>(texture_data_handle);
+
+ desktop_plane_->contentTextureHandle = content_texture_id_;
+
vr_shell_renderer_.reset(new VrShellRenderer());
buffer_viewport_list_.reset(
new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList()));
@@ -97,20 +75,67 @@ void VrShell::InitializeGl(JNIEnv* env,
new gvr::BufferViewport(gvr_api_->CreateBufferViewport()));
}
+void ApplyNeckModel(gvr::Mat4f& mat_forward) {
+ // This assumes that the input matrix is a pure rotation matrix. The
+ // input object_from_reference matrix has the inverse rotation of
+ // the head rotation. Invert it (this is just a transpose).
+ gvr::Mat4f mat = MatrixTranspose(mat_forward);
+
+ // Position of the point between the eyes, relative to the neck pivot:
+ const float kNeckHorizontalOffset = -0.080f; // meters in Z
+ const float kNeckVerticalOffset = 0.075f; // meters in Y
+
+ std::array<float, 4> neckOffset = {
+ {0.0f, kNeckVerticalOffset, kNeckHorizontalOffset, 1.0f}};
+
+ // Rotate eyes around neck pivot point.
+ auto offset = MatrixVectorMul(mat, neckOffset);
+
+ // Measure new position relative to original center of head, because
+ // applying a neck model should not elevate the camera.
+ offset[1] -= kNeckVerticalOffset;
+
+ // Right-multiply the inverse translation onto the
+ // object_from_reference_matrix.
+ translateMRight(mat_forward, mat_forward, -offset[0], -offset[1], -offset[2]);
+}
+
void VrShell::DrawFrame(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj) {
+ const JavaParamRef<jobject>& obj) {
+ // Java passes in a screen height of 1.0 with a width based on the configured
+ // aspect ratio. The overall size is handled here, scale to match the user's
+ // preferred overall screen height while maintaining the aspect ratio.
amp 2016/09/01 20:50:41 Could be just me, but I don't understand this comm
mthiesse 2016/09/02 01:05:33 More stale comments, sorry.
+ float screen_width = kScreenWidthMeters * desktop_height_;
+ float screen_height = kScreenHeightMeters * desktop_height_;
+
+ float screenTilt = desktop_screen_tilt_ * M_PI / 180.0f;
+
buffer_viewport_list_->SetToRecommendedBufferViewports();
+
gvr::Frame frame = swap_chain_->AcquireFrame();
gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time);
- // Content area positioning.
- content_rect_->SetIdentity();
- content_rect_->Translate(kContentRectPositionDefault.x,
- kContentRectPositionDefault.y,
- kContentRectPositionDefault.z);
-
+ gvr::Vec3f headPos = getTranslation(head_pose_);
+ if (headPos.x == 0.0f && headPos.y == 0.0f && headPos.z == 0.0f) {
+ // This appears to be a 3DOF pose without a neck model. Add one.
+ // The head pose has redundant data. Assume we're only using the
+ // object_from_reference_matrix, we're not updating position_external.
+ // TODO: Not sure what object_from_reference_matrix is. The new api removed
+ // it. For now, removing it seems working fine.
+ ApplyNeckModel(head_pose_);
+ }
+
+ desktop_plane_->size = {screen_width, screen_height, 1.0f};
+ desktop_plane_->translation.x = desktop_position_.x;
+ desktop_plane_->translation.y = desktop_position_.y;
+ desktop_plane_->translation.z = desktop_position_.z;
+
+ // Update position of all UI elements (including desktop)
+ UpdateTransforms(screen_width, screen_width, screenTilt);
amp 2016/09/01 20:50:40 Are the first two params both supposed to be width
mthiesse 2016/09/02 01:05:33 Good catch, that was a typo.
+
+ // Everything should be positioned now, ready for drawing.
gvr::Mat4f left_eye_view_matrix =
MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE), head_pose_);
gvr::Mat4f right_eye_view_matrix =
@@ -128,10 +153,6 @@ void VrShell::DrawFrame(JNIEnv* env,
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
- // Enable transparency.
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE,
buffer_viewport_.get());
DrawEye(left_eye_view_matrix, *buffer_viewport_);
@@ -160,40 +181,89 @@ void VrShell::DrawEye(const gvr::Mat4f& view_matrix,
PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- DrawContentRect();
+ DrawUI();
}
-void VrShell::DrawContentRect() {
- gvr::Mat4f content_rect_combined_matrix =
- MatrixMul(view_matrix_, content_rect_->transfrom_to_world);
- content_rect_combined_matrix =
- MatrixMul(projection_matrix_, content_rect_combined_matrix);
- vr_shell_renderer_->GetTexturedQuadRenderer()->Draw(
- content_rect_->content_texture_handle, content_rect_combined_matrix);
+void VrShell::DrawUI() {
+ for (std::size_t i = 0; i < ui_rects_.size(); ++i) {
+ gvr::Mat4f combinedMatrix =
+ MatrixMul(view_matrix_, ui_rects_[i].get()->mTransform.mToWorld);
+ combinedMatrix = MatrixMul(projection_matrix_, combinedMatrix);
+ vr_shell_renderer_->GetTexturedQuadRenderer()->Draw(
+ ui_rects_[i].get()->contentTextureHandle, combinedMatrix,
+ ui_rects_[i].get()->copyRect);
+ }
}
-void VrShell::OnPause(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj) {
+void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) {
if (gvr_api_ == nullptr)
return;
gvr_api_->PauseTracking();
}
-void VrShell::OnResume(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj) {
+void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) {
if (gvr_api_ == nullptr)
return;
- gvr_api_->RefreshViewerProfile();
+ // Refreshing the viewer profile accesses disk, so we do it off main thread
+ // to avoid strict mode errors.
+ std::thread t([this] { gvr_api_->RefreshViewerProfile(); });
+ t.join();
gvr_api_->ResumeTracking();
}
+void VrShell::UpdateTransforms(float screenWidthMeters,
+ float screenHeightMeters,
+ float screenTilt) {
+ // TODO(mthiesse): Thread safety. This is not thread safe.
+ for (std::unique_ptr<ContentRectangle>& rect : ui_rects_) {
+ rect->mTransform.SetIdentity();
+ rect->mTransform.Scale(rect->size.x, rect->size.y, rect->size.z);
+ float xAnchorTranslate;
+ switch (rect->xAnchoring) {
+ case XLEFT:
+ xAnchorTranslate = desktop_position_.x - screenWidthMeters * 0.5;
+ break;
+ case XRIGHT:
+ xAnchorTranslate = desktop_position_.x + screenWidthMeters * 0.5;
+ break;
+ case XCENTER:
+ xAnchorTranslate = desktop_position_.x;
+ break;
+ case XNONE:
+ xAnchorTranslate = 0;
+ break;
+ }
+ float yAnchorTranslate;
+ switch (rect->yAnchoring) {
+ case YTOP:
+ yAnchorTranslate = desktop_position_.y + screenHeightMeters * 0.5;
+ break;
+ case YBOTTOM:
+ yAnchorTranslate = desktop_position_.y - screenHeightMeters * 0.5;
+ break;
+ case YCENTER:
+ yAnchorTranslate = desktop_position_.y;
+ break;
+ case YNONE:
+ yAnchorTranslate = 0;
+ break;
+ }
+ float zAnchorTranslate = rect->anchorZ ? desktop_position_.z : 0;
+ rect->mTransform.Translate(xAnchorTranslate + rect->translation.x,
+ yAnchorTranslate + rect->translation.y,
+ zAnchorTranslate + rect->translation.z);
+ // TODO(cjgrant): Establish which exact rotations we'll provide.
+ // Adjust for screen tilt.
+ rect->mTransform.Rotate(1.0f, 0.0f, 0.0f, screenTilt);
+ }
+}
+
// ----------------------------------------------------------------------------
// Native JNI methods
// ----------------------------------------------------------------------------
-jlong Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) {
- VrShell* vrShell = new VrShell(env, obj);
- return reinterpret_cast<intptr_t>(vrShell);
+jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
+ return reinterpret_cast<intptr_t>(new VrShell(env, obj));
}
} // namespace vr_shell

Powered by Google App Engine
This is Rietveld 408576698