Index: content/browser/vr/cardboard/cardboard_vr_device.cc |
diff --git a/content/browser/vr/cardboard/cardboard_vr_device.cc b/content/browser/vr/cardboard/cardboard_vr_device.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bfe0f68385c19776087871022998c7c9640a65fa |
--- /dev/null |
+++ b/content/browser/vr/cardboard/cardboard_vr_device.cc |
@@ -0,0 +1,211 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/vr/cardboard/cardboard_vr_device.h" |
+ |
+#include <math.h> |
+#include <algorithm> |
+ |
+#include "base/android/jni_android.h" |
+#include "base/android/jni_array.h" |
+#include "base/android/jni_string.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "jni/CardboardVRDevice_jni.h" |
+#include "ui/base/base_window.h" |
+ |
+using base::android::AttachCurrentThread; |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+void MatrixToOrientationQuat(const float m[16], blink::WebVRVector4& out) { |
+ float fTrace = m[0] + m[5] + m[10]; |
+ float fRoot; |
+ if ( fTrace > 0.0f ) { |
+ fRoot = sqrtf(1.0f + fTrace) * 2.0f; |
+ out.x = (m[9] - m[6]) / fRoot; |
+ out.y = (m[2] - m[8]) / fRoot; |
+ out.z = (m[4] - m[1]) / fRoot; |
+ out.w = 0.25f * fRoot; |
+ } else if ((m[0] > m[5]) && (m[0] > m[10])) { |
+ fRoot = sqrtf(1.0f + m[0] - m[5] - m[10]) * 2.0f; |
+ out.x = 0.25f * fRoot; |
+ out.y = (m[1] + m[4]) / fRoot; |
+ out.z = (m[2] + m[8]) / fRoot; |
+ out.w = (m[9] - m[6]) / fRoot; |
+ } else if (m[5] > m[10]) { |
+ fRoot = sqrtf(1.0f + m[5] - m[0] - m[10]) * 2.0f; |
+ out.x = (m[1] + m[4]) / fRoot; |
+ out.y = 0.25f * fRoot; |
+ out.z = (m[6] + m[9]) / fRoot; |
+ out.w = (m[2] - m[8]) / fRoot; |
+ } else { |
+ fRoot = sqrtf(1.0f + m[10] - m[0] - m[5]) * 2.0f; |
+ out.x = (m[2] + m[8]) / fRoot; |
+ out.y = (m[6] + m[9]) / fRoot; |
+ out.z = 0.25f * fRoot; |
+ out.w = (m[4] - m[1]) / fRoot; |
+ } |
+} |
+ |
+} |
+ |
+bool CardboardVRDevice::RegisterCardboardVRDevice(JNIEnv* env) { |
+ return RegisterNativesImpl(env); |
+} |
+ |
+CardboardVRDevice::CardboardVRDevice(VRDeviceProvider* provider) |
+ : VRDevice(provider) |
+ , frame_index_(0) |
+{ |
+ j_cardboard_device_.Reset( |
+ Java_CardboardVRDevice_create( |
+ AttachCurrentThread(), |
+ base::android::GetApplicationContext(), |
+ reinterpret_cast<intptr_t>(this))); |
+} |
+ |
+CardboardVRDevice::~CardboardVRDevice() { |
+ Java_CardboardVRDevice_stopTracking(AttachCurrentThread(), |
+ j_cardboard_device_.obj()); |
+} |
+ |
+void CardboardVRDevice::GetVRDevice(blink::WebVRDevice* device) { |
+ memset(device, 0, sizeof(blink::WebVRDevice)); |
+ |
+ { |
+ std::string tmp = base::StringPrintf("cardboard-%d", device->index); |
+ base::TruncateUTF8ToByteSize(tmp, blink::WebVRDevice::deviceIdLengthCap-1, |
no sievers
2015/03/26 19:55:14
nit: spaces around operator here and in line 85 an
|
+ &tmp); |
+ base::string16 tmp16 = base::UTF8ToUTF16(tmp); |
+ tmp16.copy(device->deviceId, blink::WebVRDevice::deviceIdLengthCap-1); |
+ } |
+ |
+ device->flags = blink::WebVRDeviceTypePosition | blink::WebVRDeviceTypeHMD; |
+ |
+ JNIEnv* env = AttachCurrentThread(); |
+ |
+ { |
+ ScopedJavaLocalRef<jstring> j_device_name; |
+ j_device_name = Java_CardboardVRDevice_getDeviceName( |
+ env, |
+ j_cardboard_device_.obj()); |
+ |
+ base::string16 tmp16; |
+ base::android::ConvertJavaStringToUTF16(env, j_device_name.obj(), &tmp16); |
+ tmp16.copy(device->deviceName, blink::WebVRDevice::deviceNameLengthCap-1); |
+ } |
+ |
+ ScopedJavaLocalRef<jfloatArray> j_fov(env, env->NewFloatArray(4)); |
+ Java_CardboardVRDevice_getFieldOfView(env, |
+ j_cardboard_device_.obj(), |
+ j_fov.obj()); |
+ |
+ std::vector<float> fov; |
+ base::android::JavaFloatArrayToFloatVector(env, |
+ j_fov.obj(), |
+ &fov); |
+ |
+ blink::WebVRHMDInfo& hmdInfo = device->hmdInfo; |
+ |
+ hmdInfo.leftEye.recommendedFieldOfView.upDegrees = fov[0]; |
+ hmdInfo.leftEye.recommendedFieldOfView.downDegrees = fov[1]; |
+ hmdInfo.leftEye.recommendedFieldOfView.leftDegrees = fov[2]; |
+ hmdInfo.leftEye.recommendedFieldOfView.rightDegrees = fov[3]; |
+ |
+ // Cardboard devices always assume a mirrored FOV, so this is just the left |
+ // eye FOV with the left and right degrees swapped. |
+ hmdInfo.rightEye.recommendedFieldOfView.upDegrees = fov[0]; |
+ hmdInfo.rightEye.recommendedFieldOfView.downDegrees = fov[1]; |
+ hmdInfo.rightEye.recommendedFieldOfView.leftDegrees = fov[3]; |
+ hmdInfo.rightEye.recommendedFieldOfView.rightDegrees = fov[2]; |
+ |
+ // Cardboard does not support configurable FOV. |
+ hmdInfo.leftEye.maximumFieldOfView = hmdInfo.leftEye.recommendedFieldOfView; |
+ hmdInfo.rightEye.maximumFieldOfView = hmdInfo.rightEye.recommendedFieldOfView; |
+ hmdInfo.leftEye.minimumFieldOfView = hmdInfo.leftEye.recommendedFieldOfView; |
+ hmdInfo.rightEye.minimumFieldOfView = hmdInfo.rightEye.recommendedFieldOfView; |
+ |
+ float ipd = Java_CardboardVRDevice_getIPD(env, |
+ j_cardboard_device_.obj()); |
+ |
+ hmdInfo.leftEye.eyeTranslation.x = ipd * -0.5f; |
+ hmdInfo.leftEye.eyeTranslation.y = 0.0f; |
+ hmdInfo.leftEye.eyeTranslation.z = 0.0f; |
+ |
+ hmdInfo.rightEye.eyeTranslation.x = ipd * 0.5f; |
+ hmdInfo.rightEye.eyeTranslation.y = 0.0f; |
+ hmdInfo.rightEye.eyeTranslation.z = 0.0f; |
+} |
+ |
+void CardboardVRDevice::GetOrientationPosition( |
+ blink::WebVRVector4& orientation, |
+ blink::WebVRVector3& position) { |
+ JNIEnv* env = AttachCurrentThread(); |
+ ScopedJavaLocalRef<jfloatArray> j_head_matrix(env, env->NewFloatArray(16)); |
+ Java_CardboardVRDevice_getSensorState(env, |
+ j_cardboard_device_.obj(), |
+ j_head_matrix.obj()); |
+ |
+ std::vector<float> head_matrix; |
+ base::android::JavaFloatArrayToFloatVector(env, |
+ j_head_matrix.obj(), |
+ &head_matrix); |
+ |
+ MatrixToOrientationQuat(&head_matrix[0], orientation); |
+ |
+ position.x = -head_matrix[12]; |
+ position.y = head_matrix[13]; |
+ position.z = head_matrix[14]; |
+} |
+ |
+void CardboardVRDevice::GetSensorState(blink::WebHMDSensorState* state) { |
+ memset(state, 0, sizeof(blink::WebHMDSensorState)); |
+ |
+ state->timestamp = frame_index_; |
+ state->frameIndex = frame_index_; |
+ state->flags = blink::WebVRSensorStateOrientation | |
+ blink::WebVRSensorStatePosition; |
+ |
+ GetOrientationPosition(state->orientation, state->position); |
+ |
+ frame_index_++; |
+} |
+ |
+void CardboardVRDevice::ResetSensor() { |
+ Java_CardboardVRDevice_resetSensor(AttachCurrentThread(), |
+ j_cardboard_device_.obj()); |
+} |
+ |
+void CardboardVRDevice::GetRenderTargetRects( |
+ blink::WebVRFieldOfView leftFov, |
+ blink::WebVRFieldOfView rightFov, |
+ blink::WebVRVector4* leftRect, |
+ blink::WebVRVector4* rightRect) { |
+ JNIEnv* env = AttachCurrentThread(); |
+ ScopedJavaLocalRef<jintArray> j_screen_size(env, env->NewIntArray(2)); |
+ Java_CardboardVRDevice_getScreenSize(env, |
+ j_cardboard_device_.obj(), |
+ j_screen_size.obj()); |
+ |
+ std::vector<int> screen_size; |
+ base::android::JavaIntArrayToIntVector(env, |
+ j_screen_size.obj(), |
+ &screen_size); |
+ |
+ leftRect->x = 0; |
+ leftRect->y = 0; |
+ leftRect->z = screen_size[0] / 2.0; |
+ leftRect->w = screen_size[1]; |
+ |
+ rightRect->x = screen_size[0] / 2.0; |
+ rightRect->y = 0; |
+ rightRect->z = screen_size[0] / 2.0; |
+ rightRect->w = screen_size[1]; |
+} |
+ |
+} // namespace content |