Unable to change google card board camera FOV
Asked Answered
D

2

0

Hello Every one,

I am developing a sniper game for android using Google card board unity SDK. Now there is need to tweak the camera’s FOV which leads me to interact a variable named ‘mockFieldOfView’ in CardBoard.cs. Tweaking that values in unity editor is so fine but as soon as I make build for android it doesn’t effect at all. Unable to figure out the issue. Any idea or suggestion would be highly appreciated.

Thanks in advance

Devotee answered 6/6, 2023 at 1:53 Comment(0)
D
0

Just pasting the google cardboard script. The most bottom part of the code is mockFieldOfView is the variable which manipulates the FOV of cardboard camera. Please go through it once

// Copyright 2014 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 && !UNITY_EDITOR
#define ANDROID_DEVICE
#endif
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

// A Cardboard object serves as the bridge between the C# and the Java/native
// components of the plugin.
//
// On each frame, it's responsible for
//  - Reading the current head orientation and eye transforms from the Java
//    vrtoolkit
//  - Triggering the native (C++) UnityRenderEvent callback at the end of the
//    frame.  This sends the texture containing the latest frame that Unity
//    rendered into the Java vrtoolkit to be corrected for lens distortion and
//    displayed on the device.
public class Cardboard : MonoBehaviour
{
	
		// Distinguish the two stereo eyes.
		public enum Eye
		{
				Left,
				Right
		}

		// Lacking any better knowledge, use this as the inter-pupillary distance.
		public const float NOMINAL_IPD = 0.06f;

		// The singleton instance of the Cardboard class.
		private static Cardboard sdk = null;

	public static Cardboard SDK 
	{
		get 
		{
			if (sdk == null) 
			{
				Debug.Log ("Creating SDK object");
				var go = new GameObject ("Cardboard SDK", typeof(Cardboard));
				go.transform.localPosition = Vector3.zero;
			}

			return sdk;
		}
	}

	// Whether VR-mode is enabled.
	[SerializeField]
	[HideInInspector]
	private bool
	vrModeEnabled = true;

	public bool VRModeEnabled 
	{
		get 
		{ 
			return vrModeEnabled; 
		}
		set 
		{
			vrModeEnabled = value;
		}
	}

	[SerializeField]
	[HideInInspector]
	private bool
	enableAlignmentMarker = true;
	// Whether to draw the alignment marker. The marker is a vertical line that
	// splits the viewport in half, designed to help users align the screen with the Cardboard.
	public bool EnableAlignmentMarker 
	{
		get 
		{
			return enableAlignmentMarker; 
		}
		set
		{
			enableAlignmentMarker = value;
#if ANDROID_DEVICE
          try {
              cardboardActivity.Call("setEnableAlignmentMarker", enableAlignmentMarker);
          } catch (AndroidJavaException e) {
              Debug.LogError("Failed to SetEnableAlignmentMarker: " + e);
          }
#endif
		}
	}

	[SerializeField]
	[HideInInspector]
	private bool
	enableSettingsButton = true;

	// Whether to draw the settings button. The settings button opens the Google
	// Cardboard app to allow the user to  configure their individual settings and Cardboard
	// headset parameters
	public bool EnableSettingsButton
	{
		get 
		{
			return enableSettingsButton; 
		}
		set 
		{
			enableSettingsButton = value;
#if ANDROID_DEVICE
          try {
              cardboardActivity.Call("setEnableSettingsButton", enableSettingsButton);
          } catch (AndroidJavaException e) {
              Debug.LogError("Failed to SetEnableSettingsButton: " + e);
          }
#endif
		}
	}

	// Whether the device is in the Cardboard.
	public bool InCardboard { get; private set; }
	// Defer updating InCardboard till end of frame.
	private bool newInCardboard;

#if UNITY_EDITOR
  // Helper for the custom editor script.
    public void SetInCardboard(bool value) 
	{
      newInCardboard = value; // Takes effect at end of frame.
    }
#endif

	// Whether the Cardboard trigger (i.e. magnet) was pulled.
	// True for exactly one frame (between 2 EndOfFrames) on each pull.
	public bool CardboardTriggered
	{ 
		get; 
		private set; 
	}

	// Next frame's value of CardboardTriggered.
	private bool newCardboardTriggered = false;
	// Whether screen taps are converted to Cardboard trigger events.
	public bool TapIsTrigger 
	{

		get 
		{ 
			return tapIsTrigger; 
		}
		set 
		{
			tapIsTrigger = value;
#if ANDROID_DEVICE
          try {
              cardboardActivity.Call("setConvertTapIntoTrigger", tapIsTrigger);
          } catch (AndroidJavaException e) {
              Debug.LogError("Failed to setConvertTapIntoTrigger: " + e);
          }
#endif
		}
	}

	[SerializeField]
	[HideInInspector]
	private bool
	tapIsTrigger = false;

	// The texture that Unity renders the scene to. This is sent to the plugin,
	// which renders it to screen, correcting for lens distortion.
	public RenderTexture StereoScreen { get; private set; }

	// Transform from body to head.
	public Matrix4x4 HeadView { get { return headView; } }

	// The transformation from head to eye.
	public Matrix4x4 EyeView (Cardboard.Eye eye)
	{
		return eye == Cardboard.Eye.Left ? leftEyeView : rightEyeView;
	}

	// The projection matrix for a given eye.  This encodes the field of view,
	// IPD, and other parameters configured by the SDK.
	public Matrix4x4 Projection (Cardboard.Eye eye)
	{
		return eye == Cardboard.Eye.Left ? leftEyeProj : rightEyeProj;
	}

	// Local transformation of head.
	public Quaternion HeadRotation { get; private set; }

	// Local transformations of eyes relative to head.
	public Vector3 LeftEyeOffset  { get; private set; }

	public Vector3 RightEyeOffset { get; private set; }

	public Vector3 EyeOffset (Cardboard.Eye eye)
	{
		return eye == Cardboard.Eye.Left ? LeftEyeOffset : RightEyeOffset;
	}

	// Minimum distance from the user that an object may be viewed in stereo
	// without eye strain, in meters.  The stereo eye separation should
	// be scaled down if the "center of interest" is closer than this.  This
	// will set a lower limit on the disparity of the COI between the two eyes.
	// See CardboardEye.OnPreCull().
	public float MinimumComfortDistance 
	{
		get 
		{
			return 1.0f;
		}
	}

	// Maximum distance from the user that an object may be viewed in
	// stereo without eye strain, in meters.  The stereo eye separation
	// should be scaled up of if the COI is farther than this.  This will
	// set an upper limit on the disparity of the COI between the two eyes.
	// See CardboardEye.OnPreCull().
	// Note: For HMDs with optics that focus at infinity there really isn't a
	// maximum distance, so this number can be set to "really really big".
	public float MaximumComfortDistance 
	{
		get 
		{
			return 100000f;  // i.e. really really big.
		}
	}

	public float IPD 
	{
		get 
		{ 
			return NOMINAL_IPD; 
		}
	}

#if UNITY_IPHONE && !UNITY_EDITOR
  [DllImport("__Internal")]
#else
		[DllImport("RenderingPlugin")]
		#endif
      private static extern void InitFromUnity (int textureID);

#if ANDROID_DEVICE
  private const string cardboardClass =
      "com.google.vrtoolkit.cardboard.plugins.unity.UnityCardboardActivity";
  private AndroidJavaObject cardboardActivity;
#endif

	// Only call native layer once per frame.
	private bool updated = false;
	// Head and eye transforms retrieved from native SDK.
	private Matrix4x4 headView;
	private Matrix4x4 leftEyeView;
	private Matrix4x4 leftEyeProj;
	private Matrix4x4 rightEyeView;
	private Matrix4x4 rightEyeProj;

	// Configures which Cardboard features are enabled, depending on
	// the Unity features available.
	private class Config
	{
		// Features.
		public bool supportsRenderTextures;
		public bool isAndroid;
		public bool supportsAndroidRenderEvent;
		public bool isAtLeastUnity4_5;

		// Access to plugin.
		public bool canAccessActivity = false;

		// Should be called on main thread.
		public void initialize ()
		{
			supportsRenderTextures = SystemInfo.supportsRenderTextures;
			isAndroid = Application.platform == RuntimePlatform.Android;
			try 
			{
				Regex r = new Regex (@"(\d+\.\d+)\..*");
				string version = r.Replace (Application.unityVersion, "$1");
				if (new Version (version) >= new Version ("4.5")) 
				{
					isAtLeastUnity4_5 = true;
				}
			} 
			catch 
			{
				Debug.LogWarning ("Unable to determine Unity version from: " + Application.unityVersion);
			}
			supportsAndroidRenderEvent = isAtLeastUnity4_5 && isAndroid;
		}

		public bool canApplyDistortionCorrection ()
		{
			return supportsRenderTextures && supportsAndroidRenderEvent	&& canAccessActivity;
		}

		public string getDistortionCorrectionDiagnostic ()
		{
			List<string> causes = new List<string> ();
			if (!isAndroid) 
			{
				causes.Add ("Must be running on Android device");
			}
			else if (!canAccessActivity) 
			{
				causes.Add ("Cannot access UnityCardboardActivity. " + "Verify that the jar is in Assets/Plugins/Android");
			}
			if (!supportsRenderTextures) 
			{
				causes.Add ("RenderTexture (Unity Pro feature) is unavailable");
			}
			if (!isAtLeastUnity4_5) 
			{
				causes.Add ("Unity 4.5+ is needed for Android UnityPluginEvent");
			}
			return String.Join ("; ", causes.ToArray ());
		}
	}

	private Config config = new Config ();

	void Awake ()
	{
		if (sdk == null) 
		{
			sdk = this;
		}
		else
		{
			Debug.LogWarning ("Cardboard SDK object should be a singleton.");
			enabled = false;
		}

		config.initialize ();

#if ANDROID_DEVICE
      try {
          AndroidJavaClass player = new AndroidJavaClass(cardboardClass);
          cardboardActivity = player.CallStatic<AndroidJavaObject>("getActivity");
          player.Dispose();
          cardboardActivity.Call("initFromUnity", gameObject.name);
          config.canAccessActivity = true;
      } catch (AndroidJavaException e) {
          Debug.LogError("Cannot access UnityCardboardActivity. "
                  + "Verify that the jar is in Assets/Plugins/Android. " + e);
      }
      // Force side-effectful initialization using serialized values.
      EnableAlignmentMarker = enableAlignmentMarker;
      EnableSettingsButton = enableSettingsButton;
      TapIsTrigger = tapIsTrigger;
#endif

		if (config.canApplyDistortionCorrection ()) 
		{
						Debug.Log ("Creating new cardboard screen texture");
						StereoScreen = new RenderTexture (Screen.width, Screen.height, 16,
                                           RenderTextureFormat.RGB565);
						StereoScreen.Create ();
						InitFromUnity (StereoScreen.GetNativeTextureID ());
				} else {
						if (!Application.isEditor) {
								Debug.LogWarning ("Lens distortion-correction disabled. Causes: ["
										+ config.getDistortionCorrectionDiagnostic () + "]");
						}
				}

				InCardboard = newInCardboard = false;
#if UNITY_EDITOR
      if (VRModeEnabled && Application.isPlaying) {
          SetInCardboard(true);
      }
#endif
				StartCoroutine ("EndOfFrame");
		}

#if UNITY_EDITOR
  private const float TAP_TIME_LIMIT = 0.2f;
  private float touchStartTime = 0;

  void Update() {
      if (!InCardboard) {
          return;  // Only simulate trigger pull if there is a trigger to pull.
      }
      if (Input.GetMouseButtonDown(0)) {
          touchStartTime = Time.time;
      } else if (Input.GetMouseButtonUp(0)) {
          if (Time.time - touchStartTime <= TAP_TIME_LIMIT) {
              newCardboardTriggered = true;
          }
          touchStartTime = 0;
      }
  }
#endif

#if ANDROID_DEVICE
  // Right-handed to left-handed matrix converter.
  private static readonly Matrix4x4 flipZ = Matrix4x4.Scale(new Vector3(1, 1, -1));

  // Call the SDK (if needed) to get the current transforms for the frame.
  // This is public so any game script can do this if they need the values.
  public bool UpdateState() {
      if (updated) {
          return true;
      }

      float[] frameInfo = null;
      try {
          // Pass nominal clip distances - will correct later for each camera.
          frameInfo = cardboardActivity.Call<float[]>("getFrameParams",
                  1.0f /* near */,
                  1000.0f /* far */);
      } catch (AndroidJavaException e) {
          Debug.LogError("Exception: " + e);
      }

      // FIXME: Should not call getFrameParams() more than once.
      if (frameInfo == null) {
          return false;
      }

      // Extract the matrices (currently that's all we get back).
      int j = 0;
      for (int i = 0; i < 16; ++i, ++j) {
          headView *= frameInfo[j];*

}
for (int i = 0; i < 16; ++i, ++j) {
leftEyeView = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
leftEyeProj = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
rightEyeView = frameInfo[j];
}
for (int i = 0; i < 16; ++i, ++j) {
rightEyeProj = frameInfo[j];
}

// 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.
leftEyeView = flipZ * headView * leftEyeView.inverse * flipZ;
rightEyeView = flipZ * headView * rightEyeView.inverse * flipZ;
headView = flipZ * headView.inverse * flipZ;

HeadRotation = Quaternion.LookRotation(headView.GetColumn(2),
headView.GetColumn(1));
LeftEyeOffset = leftEyeView.GetColumn(3);
RightEyeOffset = rightEyeView.GetColumn(3);

updated = true;
return true;
}
#else
// public float mockFieldOfView = 77.0f; // Vertical degrees.
* private float zeroParallaxDistance = 0.308f; // Meters in real world.*

#if UNITY_EDITOR
[Tooltip(“When playing in the editor, just release Ctrl to untilt the head.”)]
public bool autoUntiltHead = true;

// Use mouse to emulate head in the editor.
private float mouseX = 0;
* private float mouseY = 0;*
private float mouseZ = 0;
#endif

* // Mock implementation for use in the Unity editor.*
* public bool UpdateState ()*
* {*
* if (updated) {*
* return true;*
* }*

* // NOTE: View matrices have to be camera->world and use left-handed*
* // coordinates (+Z is forward). See the flip/invert/flip code*
* // in the Android version of this function.*

* headView = Matrix4x4.identity;*

#if UNITY_EDITOR
bool rolled = false;
if (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)) {
mouseX += Input.GetAxis(“Mouse X”) * 5;
if (mouseX <= -180) {
mouseX += 360;
} else if (mouseX > 180)
mouseX -= 360;
mouseY -= Input.GetAxis(“Mouse Y”) * 2.4f;
mouseY = Mathf.Clamp(mouseY, -80, 80);
} else if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) {
rolled = true;
mouseZ += Input.GetAxis(“Mouse X”) * 5;
mouseZ = Mathf.Clamp(mouseZ, -80, 80);
}
if (!rolled && autoUntiltHead) {
// People don’t usually leave their heads tilted to one side for long.
mouseZ = Mathf.Lerp(mouseZ, 0, Time.deltaTime / (Time.deltaTime + 0.1f));
}
var rot = Quaternion.Euler(mouseY, mouseX, mouseZ);
headView = Matrix4x4.TRS(Vector3.zero, rot, Vector3.one);
#endif

* float eyeoffset = -IPD / 2;*

* leftEyeView = Matrix4x4.identity;*
* leftEyeView [0, 3] = eyeoffset;*

* leftEyeProj = Matrix4x4.Perspective (mockFieldOfView,*
0.5f * Screen.width / Screen.height,
1.0f, 1000.0f);
_ leftEyeProj [0, 2] = eyeoffset / zeroParallaxDistance * leftEyeProj [0, 0];_

* // Right matrices same as left ones but for some sign flippage.*
* rightEyeView = leftEyeView;*
_ rightEyeView [0, 3] = -1;
rightEyeProj = leftEyeProj;*

rightEyeProj [0, 2] *= -1;_

* HeadRotation = Quaternion.LookRotation (headView.GetColumn (2),*
headView.GetColumn (1));
* LeftEyeOffset = leftEyeView.GetColumn (3);*
* RightEyeOffset = rightEyeView.GetColumn (3);*

* updated = true;*
* return true;*
* }*
#endif

#if ANDROID_DEVICE
// How long to hold a simulated screen tap.
private const float TAP_INJECTION_TIME = 0.1f;

private const long NO_DOWNTIME = -1; // Sentinel for when down time is not set.

private long downTime = NO_DOWNTIME; // Time the current tap injection started, if any.

// Fakes a screen tap by injecting a pointer-down and pointer-up events
// with a suitable delay between them.
IEnumerator DoAndroidScreenTap(int x, int y) {
if (downTime != NO_DOWNTIME) { // Sanity check.
yield break;
}
try {
downTime = cardboardActivity.Call(“injectTouchDown”, x, y);
} catch (AndroidJavaException e) {
Debug.LogError("Failed to inject touch down: " + e);
yield break;
}
yield return new WaitForSeconds(TAP_INJECTION_TIME);
try {
cardboardActivity.Call(“injectTouchUp”, x, y, downTime);
} catch (AndroidJavaException e) {
Debug.LogError("Failed to inject touch up: " + e);
}
downTime = NO_DOWNTIME;
}
#endif

* // Makes Unity see a mouse click (down + up) at the given pixel.*
* public void InjectMouseClick (int x, int y)*
* {*
#if ANDROID_DEVICE
if (downTime == NO_DOWNTIME) { // If not in the middle of a tap injection.
StartCoroutine(DoAndroidScreenTap(x, y));
}
#endif
* }*

* // Makes Unity see a mouse move to the given pixel.*
* public void InjectMouseMove (int x, int y)*
* {*
* if (x == (int)Input.mousePosition.x && y == (int)Input.mousePosition.y) {*
* return; // Don’t send a 0-pixel move.*
* }*
#if ANDROID_DEVICE
if (downTime == NO_DOWNTIME) { // If not in the middle of a tap injection.
try {
cardboardActivity.Call(“injectMouseMove”, x, y);
} catch (AndroidJavaException e) {
Debug.LogError("Failed to inject mouse move: " + e);
}
}
#endif
* }*

* void OnInsertedIntoCardboardInternal ()*
* {*
* newInCardboard = true;*
* }*

* void OnRemovedFromCardboardInternal ()*
* {*
* newInCardboard = false;*
* }*

* void OnCardboardTriggerInternal ()*
* {*
* newCardboardTriggered = true;*
* }*

* void OnDestroy ()*
* {*
* StopCoroutine (“EndOfFrame”);*
* if (sdk == this) {*
* sdk = null;*
* }*
* }*

* IEnumerator EndOfFrame ()*
* {*
* while (true) {*
* yield return new WaitForEndOfFrame ();*
* if (vrModeEnabled && StereoScreen != null && UpdateState ()) {*
* GL.InvalidateState (); // necessary for Windows, but not Mac.*
* GL.IssuePluginEvent (1);*
* }*
* InCardboard = newInCardboard;*
* CardboardTriggered = newCardboardTriggered;*
* newCardboardTriggered = false;*
* updated = false;*
* }*
* }*

#if !UNITY_EDITOR
* private GUIStyle style;*

* // The amount of time (in seconds) to show error message on GUI.*
* private const float GUI_ERROR_MSG_DURATION = 10;
_ private const string warning =
@"Distortion correction is disabled.*

Requires Unity Android Pro v4.5+.
See log for details.";_

* void OnGUI ()*
* {*
* if (Debug.isDebugBuild && !config.canApplyDistortionCorrection () &&*
* Time.realtimeSinceStartup <= GUI_ERROR_MSG_DURATION) {
_ DisplayDistortionCorrectionDisabledWarning ();
}
}*_

* private void DisplayDistortionCorrectionDisabledWarning ()*
* {*
* if (style == null) {*
* style = new GUIStyle ();*
* style.normal.textColor = Color.red;*
* style.alignment = TextAnchor.LowerCenter;*
* }*
* if (VRModeEnabled) {*
_ style.fontSize = (int)(50 * Screen.width / 1920f / 2);
* GUI.Label (new Rect (0, 0, Screen.width / 2, Screen.height), warning, style);
GUI.Label (new Rect (Screen.width / 2, 0, Screen.width / 2, Screen.height), warning, style);
} else {
style.fontSize = (int)(50 * Screen.width / 1920f);
GUI.Label (new Rect (0, 0, Screen.width, Screen.height), warning, style);
}
}
#endif*

#if UNITY_ANDROID
public float mockFieldOfView = 77.0f;
#endif
}_

Devotee answered 6/6, 2023 at 1:40 Comment(0)
M
0

Answered you here:

Margaretemargaretha answered 6/6, 2023 at 1:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.