brainvr/Assets/Cardboard/Legacy/Scripts/CardboardAndroidDevice.cs
2015-07-24 05:07:03 +01:00

196 lines
6.7 KiB
C#

// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#if UNITY_ANDROID
using System.Runtime.InteropServices;
using UnityEngine;
// Android device using the Google Cardboard SDK for Android.
public class CardboardAndroidDevice : AndroidBaseVRDevice {
[DllImport("RenderingPlugin")]
private static extern void InitFromUnity(int textureID);
// Event IDs supported by our native render plugin.
private const int kPerformDistortionCorrection = 1;
private const int kDrawCardboardUILayer = 2;
private const string cardboardClass =
"com.google.vrtoolkit.cardboard.plugins.unity.UnityCardboardActivity";
private Matrix4x4 headView = new Matrix4x4();
private Matrix4x4 leftEyeView = new Matrix4x4();
private Matrix4x4 rightEyeView = new Matrix4x4();
private float[] frameInfo = null;
public override void Init() {
ConnectToActivity();
}
protected override void ConnectToActivity() {
try {
using (AndroidJavaClass player = new AndroidJavaClass(cardboardClass)) {
cardboardActivity = player.CallStatic<AndroidJavaObject>("getActivity");
}
} catch (AndroidJavaException e) {
cardboardActivity = null;
Debug.LogError("Cannot access UnityCardboardActivity. "
+ "Verify that the jar is in Assets/Plugins/Android. " + e);
}
}
public override void SetDistortionCorrectionEnabled(bool enabled) {
CallActivityMethod("setDistortionCorrectionEnabled", enabled);
}
public override void SetVRModeEnabled(bool enabled) {
CallActivityMethod("setVRModeEnabled", enabled);
}
public override void SetAlignmentMarkerEnabled(bool enabled) {
CallActivityMethod("setAlignmentMarkerEnabled", enabled);
}
public override void SetSettingsButtonEnabled(bool enabled) {
CallActivityMethod("setSettingsButtonEnabled", enabled);
}
public override void SetNeckModelScale(float scale) {
CallActivityMethod("setNeckModelFactor", scale);
}
public override void SetAutoDriftCorrectionEnabled(bool enabled) {
CallActivityMethod("setGyroBiasEstimationEnabled", enabled);
}
public override void SetStereoScreen(RenderTexture stereoScreen) {
if (cardboardActivity != null) {
InitFromUnity(stereoScreen != null ? stereoScreen.GetNativeTextureID() : 0);
}
}
public override void UpdateState() {
// Pass nominal clip distances - will correct later for each camera.
if (!CallActivityMethod(ref frameInfo, "getFrameParams", 1.0f /* near */, 1000.0f /* far */)) {
return;
}
// Extract the matrices (currently that's all we get back).
int j = 0;
for (int i = 0; i < 16; ++i, ++j) {
headView[i] = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
leftEyeView[i] = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
leftEyeDistortedProjection[i] = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
rightEyeView[i] = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
rightEyeDistortedProjection[i] = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
leftEyeUndistortedProjection[i] = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
rightEyeUndistortedProjection[i] = frameInfo[j];
}
leftEyeUndistortedViewport = new Rect(frameInfo[j], frameInfo[j+1],
frameInfo[j+2], frameInfo[j+3]);
leftEyeDistortedViewport = leftEyeUndistortedViewport;
j += 4;
rightEyeUndistortedViewport = new Rect(frameInfo[j], frameInfo[j+1],
frameInfo[j+2], frameInfo[j+3]);
rightEyeDistortedViewport = rightEyeUndistortedViewport;
// Convert views to left-handed coordinates because Unity uses them
// for Transforms, which is what we will update from the views.
// Also invert because the incoming matrices go from camera space to
// cardboard space, and we want the opposite.
// Lastly, cancel out the head rotation from the eye views,
// because we are applying that on a parent object.
leftEyePose.SetRightHanded(headView * leftEyeView.inverse);
rightEyePose.SetRightHanded(headView * rightEyeView.inverse);
headPose.SetRightHanded(headView.inverse);
}
override public void UpdateScreenData() {
CardboardProfile.Device device = new CardboardProfile.Device();
CardboardProfile.Screen screen = new CardboardProfile.Screen();
float[] lensData = null;
if (CallActivityMethod(ref lensData, "getLensParameters")) {
device.lenses.separation = lensData[0];
device.lenses.offset = lensData[1];
device.lenses.screenDistance = lensData[2];
device.lenses.alignment = (int)lensData[3];
}
float[] screenSize = null;
if (CallActivityMethod(ref screenSize, "getScreenSizeMeters")) {
screen.width = screenSize[0];
screen.height = screenSize[1];
screen.border = screenSize[2];
}
float[] distCoeff = null;
if (CallActivityMethod(ref distCoeff, "getDistortionCoefficients")) {
device.distortion.k1 = distCoeff[0];
device.distortion.k2 = distCoeff[1];
}
float[] invDistCoeff = null;
if (CallActivityMethod(ref invDistCoeff, "getInverseDistortionCoefficients")) {
device.inverse.k1 = invDistCoeff[0];
device.inverse.k2 = invDistCoeff[1];
}
float[] maxFov = null;
if (CallActivityMethod(ref maxFov, "getLeftEyeMaximumFOV")) {
device.maxFOV.outer = maxFov[0];
device.maxFOV.upper = maxFov[1];
device.maxFOV.inner = maxFov[2];
device.maxFOV.lower = maxFov[3];
}
Profile.screen = screen;
Profile.device = device;
}
public override void Recenter() {
CallActivityMethod("resetHeadTracker");
}
public override void SetTouchCoordinates(int x, int y) {
CallActivityMethod("setTouchCoordinates", x, y);
}
public override void PostRender(bool vrMode) {
if (vrMode) {
if (Cardboard.SDK.DistortionCorrection && Cardboard.SDK.NativeDistortionCorrectionSupported) {
GL.IssuePluginEvent(kPerformDistortionCorrection);
}
if (Cardboard.SDK.EnableAlignmentMarker || Cardboard.SDK.EnableSettingsButton) {
GL.IssuePluginEvent(kDrawCardboardUILayer);
}
GL.InvalidateState();
}
}
}
#endif