写给VR手游开发小白的教程:(二)UnityVR插件CardboardSDKForUnity解析(一)
2016-07-16 13:33
786 查看
现在我们已经有了开发环境,还没安装环境的小伙伴可以看上一篇:
(一)Unity3D进行Android开发的环境搭建(虚拟机调试)
今天主要介绍的是谷歌为自己的Cardboard平台提供的开发工具Cardboard SDK插件解析。Cardboard是谷歌公司在14年发布的一款极具创意的产品,由手机内部的传感器支持,它仅需硬纸板和两片透镜就能打造移动平台上的VR体验。Cardboard这里不多做介绍,网上可以买到原装正版,价格在50以内很便宜,有条件的人可以去体验一下。
在正式开始之前,先说明一下本节需要对Unity3D引擎有一些基础才能较流畅的看完,若是中间有疑问可以评论也可私信,疑问较多也可以再补充一章专门介绍基础的东西。
上一章忘记说了,如果是VR应用的话,就不要在虚拟机里跑了(虚拟机根本没有传感器去定位你的头部,也就不存在VR一说了,不过简单的小游戏还是可以在虚拟机上跑的,所以如果是跑大型应用的话,还是选择真机吧),虚拟机的存在其实纯粹是为了学习示例用的。
没有真机的同学,这个demo在Unity里也可以跑,具体按住Alt移动鼠标就相当于转动头部,按住Ctrl移动鼠标相当于歪脖子看。
/***************************************************************分割线*******************************************************************/
首先要为Unity安装这个插件,对于本插件,目前网上有些资源是不带demo的,正好我这边有一个带demo的,附上下载地址:
http://download.csdn.net/detail/mao_xiao_feng/9577849
导入以后,工程目录下多了以下两个文件夹,双击打开DemoScene下的场景
场景大概就是以下这个样子了,这个demo是插件中提供的官方示例,一定要把里面所有东西都研究透,才能很好理解SDK当中的每一个脚本的功能。
直接切入主题,看到CardboardMain这个物体已经被设为了Prefab,那么它一定是获得VR效果的关键性物体,事实上所有VR的实现都在这个物体极其子物体下,我们把它一层层的剥离开来。
CardboardMain物体上只绑定了这一个脚本,开始看源码
上面的源代码理解起来比较麻烦,我解析的时候会把变量定义等一些顺序调换一下
注释部分
The Cardboard object communicates with the head-mounted display in order to:Query the device for viewing parameters Retrieve the latest head tracking data Provide the rendered scene to the device for distortion correction 翻译/*Cardboard物体与头盔显示器进行交互以获得设备上的一些参数,返回最近头部跟踪数据,为被渲染的场景提供失真校正*/
定义了一个Cardboard类型的静态公有变量SDK,主要用来获取游戏中的Cardboard.cs脚本,可以看到它是只读的,即SDK提供了一个共有的访问接口,在任何时候它都只有一个实例。 // The singleton instance of the Cardboard class. 翻译/*Cardboard类的单件实例*/---关于单件模式,编程用的还是挺多的。
BaseVRDevice类型的私有静态变量device,BaseVRDevice也是插件当中定义的一个类,注意!!它与Cardboard类不同,它不是脚本类!!这个变量用的比较多 // The VR device that will be providing input data. 翻译/*VR设备(在这里直接理解为手机吧!)提供输入的数据*/
公有bool类型的变量DistortionCorrection,默认为true。DistortionCorrection我把它翻译为失真校正(暂且这样翻译吧),读属性不说了,写属性加了个if语句,想说明假如设备接入了并且支持失真校正功能,才能修改它的值,不然一直为true。(这个变量是控制扭曲的,开或者关的效果如下,差距应该一目了然)
同上还有VRModeEnabled(VR模式的使能,开了就是分屏),EnableAlignmentMarker(就是下图黄圈中间那根线,关了,线就没了),EnableSettingsButton(就是下图绿圈内的设置按钮,同样也是关了就没了),AutoDriftCorrection(这个属性还没搞懂先放着),NeckModelScale(这个是专业术语,应该是颈部的微调吧...猜的,值在0-1之间,调整的话视角会有微小的变化,但可以忽略不计)
后面从#if UNITY_IOS到#endif中间的部分是预编译部分,根据ios,unity_editor,android选择性的编译,可以根据自己的平台选择性的看。我们现在使用unity编辑器在运行,所以他编译的是#if UNITY_EDITOR到#endif中间的这部分。
RenderTexture类型的公有变量StereoScreen,渲染纹理是一种即时更新的纹理。//The texture that Unity renders the scene to. This is sent to the VR device,which renders it to screen, correcting for lens distortion. 翻译/*Unity渲染场景产生的纹理,它被传输到VR设备上,在屏幕上被绘制产生正确的透镜弯曲效果*/这个变量的读属性当vr模式或者distortionCorrection关闭时,为null,写属性也只有在支持distortionCorrection的时候可以使用,总的来说,可以把它看作产生弯曲效果的一个工具或者一个中间量。
bool类型只读属性的UseDistortionEffect,这个量是用来判断透镜效果是否开启的量,后面会用到。
CardboardProfile类型的公有变量Profile,也是只读的。 // Describes the current device, including phone screen. 翻译/*描述当前设备,包括手机屏幕*/
公有枚举类型Eye。 // Distinguish the stereo eyes. 翻译/*看立体效果时用来区分左右眼*/
公有枚举类型Distortion。这个量主要控制在某些特殊情况下是否需要透镜预览,在下面会用到
Pose3D类型的公有量HeadPose。 // The transformation of head from origin in the tracking system. 翻译/*在跟踪在系统中,头部距离起始点的信息*/由于这里Pose3D也是插件自定义的类,后续需要分析Pose3D这个类才能知道信息是如何传递的。同理还有变量EyePose。
返回Matrix4x4类型的方法Projection(Eye eye, Distortion distortion = Distortion.Distorted)返回结果是device.GetProjection(eye, distortion);从两个参数推断这个方法是要根据眼睛计算返回一个投影矩阵,在Unity圣典中阐述过Matrix4x4类型的投影矩阵,关于投影矩阵,涉及到计算机图形学的东西,我目前也正在学习,给一个链接大家可以学习一下。
http://blog.csdn.net/yanwei2016/article/details/7326180
Viewport(Eye eye, Distortion distortion = Distortion.Distorted)方法返回视口矩形,应该是处理在屏幕上的位置的一个方法
Vector2类型的变量ComfortableViewingRange,只读,控制我们去看空间中物体的一个最舒服的距离范围,这个量不需要去配置,理解就行。
私有方法InitDevice()用于初始化设备,因为涉及到BaseVRDevice类,我们以后再去解析其细节。
私有方法AddDummyCamera()用来添加一个黑色背景,当然背景也可以自己更换。
一些琐碎的定义先到这里
/********************************************************分割线********************************************************************/
NOTE: Each scene load causes an OnDestroy of the current SDK, followed by and Awake of a new one. That should not cause the underlying native code to hiccup. Exception: developer may call Application.DontDestroyOnLoad on the SDK if they want it to survive
across scene loads.
翻译/*说明:每一个新场景被加载会导致现在sdk的destroy,然后产生新的sdk,这会发生一些问题(这句话实在不会翻译了),所以开发者们在切换场景的时候如果希望sdk依然存活,可以使用Application.DontDestroyOnLoad*/。这里其实可以间接的说明SDK是采用的单件模式,因为我们无法用new()去创建,而且自始而终最多只有一个实例。
比较关键的awake函数来了
void Awake() {
if (sdk == null) {
sdk = this;
}
if (sdk != this) {
Debug.LogWarning("Cardboard SDK object should be a singleton.");
enabled = false;
return;
}
#if UNITY_IOS
Application.targetFrameRate = 60;
#endif
InitDevice();
AddDummyCamera();
StereoScreen = null;
}相信上面的语句根据我之前的解释大家都能看懂了
这个类中没有Update()所以我认为更新可能放在BaseVRDevice类型的device里面了。
我先码到这里(太累了),后面接着此篇,另外会解析BaseVRDevice这个类(很重要!!),还有CardboardProfile这个类。
总结:这一章还只是把每个类的功能和大致框架整理了一下,并没有涉及到很多细节的东西,也没有涉及到原理,注意我们现在还在顶端的父物体Cardboard物体上分析,后面当涉及到原理的的时候,就要开始看下层的Head,和它的子物体几个camera了。
(一)Unity3D进行Android开发的环境搭建(虚拟机调试)
今天主要介绍的是谷歌为自己的Cardboard平台提供的开发工具Cardboard SDK插件解析。Cardboard是谷歌公司在14年发布的一款极具创意的产品,由手机内部的传感器支持,它仅需硬纸板和两片透镜就能打造移动平台上的VR体验。Cardboard这里不多做介绍,网上可以买到原装正版,价格在50以内很便宜,有条件的人可以去体验一下。
在正式开始之前,先说明一下本节需要对Unity3D引擎有一些基础才能较流畅的看完,若是中间有疑问可以评论也可私信,疑问较多也可以再补充一章专门介绍基础的东西。
上一章忘记说了,如果是VR应用的话,就不要在虚拟机里跑了(虚拟机根本没有传感器去定位你的头部,也就不存在VR一说了,不过简单的小游戏还是可以在虚拟机上跑的,所以如果是跑大型应用的话,还是选择真机吧),虚拟机的存在其实纯粹是为了学习示例用的。
没有真机的同学,这个demo在Unity里也可以跑,具体按住Alt移动鼠标就相当于转动头部,按住Ctrl移动鼠标相当于歪脖子看。
/***************************************************************分割线*******************************************************************/
首先要为Unity安装这个插件,对于本插件,目前网上有些资源是不带demo的,正好我这边有一个带demo的,附上下载地址:
http://download.csdn.net/detail/mao_xiao_feng/9577849
导入以后,工程目录下多了以下两个文件夹,双击打开DemoScene下的场景
场景大概就是以下这个样子了,这个demo是插件中提供的官方示例,一定要把里面所有东西都研究透,才能很好理解SDK当中的每一个脚本的功能。
直接切入主题,看到CardboardMain这个物体已经被设为了Prefab,那么它一定是获得VR效果的关键性物体,事实上所有VR的实现都在这个物体极其子物体下,我们把它一层层的剥离开来。
CardboardMain物体上只绑定了这一个脚本,开始看源码
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; // The Cardboard object communicates with the head-mounted display in order to: // - Query the device for viewing parameters // - Retrieve the latest head tracking data // - Provide the rendered scene to the device for distortion correction public class Cardboard : MonoBehaviour { // The singleton instance of the Cardboard class. public static Cardboard SDK { get { if (sdk == null) { sdk = UnityEngine.Object.FindObjectOfType(); } if (sdk == null) { Debug.Log("Creating Cardboard object"); var go = new GameObject("Cardboard"); sdk = go.AddComponent(); go.transform.localPosition = Vector3.zero; } return sdk; } } private static Cardboard sdk = null; public bool DistortionCorrection { get { return distortionCorrection; } set { if (value != distortionCorrection && device != null) { device.SetDistortionCorrectionEnabled(value && NativeDistortionCorrectionSupported); } distortionCorrection = value; } } [SerializeField] private bool distortionCorrection = true; public bool VRModeEnabled { get { return vrModeEnabled; } set { if (value != vrModeEnabled && device != null) { device.SetVRModeEnabled(value); } vrModeEnabled = value; } } [SerializeField] private bool vrModeEnabled = true; public bool EnableAlignmentMarker { get { return enableAlignmentMarker; } set { if (value != enableAlignmentMarker && device != null) { device.SetAlignmentMarkerEnabled(value && NativeUILayerSupported); } enableAlignmentMarker = value; } } [SerializeField] private bool enableAlignmentMarker = true; public bool EnableSettingsButton { get { return enableSettingsButton; } set { if (value != enableSettingsButton && device != null) { device.SetSettingsButtonEnabled(value && NativeUILayerSupported); } enableSettingsButton = value; } } [SerializeField] private bool enableSettingsButton = true; public bool TapIsTrigger = true; public float NeckModelScale { get { return neckModelScale; } set { value = Mathf.Clamp01(value); if (!Mathf.Approximately(value, neckModelScale) && device != null) { device.SetNeckModelScale(value); } neckModelScale = value; } } [SerializeField] private float neckModelScale = 0.0f; public bool AutoDriftCorrection { get { return autoDriftCorrection; } set { if (value != autoDriftCorrection && device != null) { device.SetAutoDriftCorrectionEnabled(value); } autoDriftCorrection = value; } } [SerializeField] private bool autoDriftCorrection = true; #if UNITY_IOS public bool SyncWithCardboardApp { get { return syncWithCardboardApp; } set { if (value && value != syncWithCardboardApp) { Debug.LogWarning("Remember to enable iCloud capability in Xcode, " + "and set the 'iCloud Documents' checkbox. " + "Not doing this may cause the app to crash if the user tries to sync."); } syncWithCardboardApp = value; } } [SerializeField] private bool syncWithCardboardApp = false; #endif #if UNITY_EDITOR // Mock settings for in-editor emulation of Cardboard while playing. public bool autoUntiltHead = true; // Whether to perform distortion correction in the editor. public bool simulateDistortionCorrection = true; // Use unity remote as the input source. [HideInInspector] public bool UseUnityRemoteInput = false; public CardboardProfile.ScreenSizes ScreenSize { get { return screenSize; } set { if (value != screenSize) { screenSize = value; device.UpdateScreenData(); } } } [SerializeField] private CardboardProfile.ScreenSizes screenSize = CardboardProfile.ScreenSizes.Nexus5; public CardboardProfile.DeviceTypes DeviceType { get { return deviceType; } set { if (value != deviceType) { deviceType = value; device.UpdateScreenData(); } } } [SerializeField] public CardboardProfile.DeviceTypes deviceType = CardboardProfile.DeviceTypes.CardboardJun2014; #endif // The VR device that will be providing input data. private static BaseVRDevice device; public bool NativeDistortionCorrectionSupported { get; private set; } public bool NativeUILayerSupported { get; private set; } // The texture that Unity renders the scene to. This is sent to the VR device, // which renders it to screen, correcting for lens distortion. public RenderTexture StereoScreen { get { // Don't need it except for distortion correction. if (!distortionCorrection || !vrModeEnabled) { return null; } if (stereoScreen == null && NativeDistortionCorrectionSupported) { StereoScreen = CreateStereoScreen(); // Note: use set{} } return stereoScreen; } set { if (value == stereoScreen) { return; } if (!NativeDistortionCorrectionSupported && value != null) { Debug.LogError("Can't set StereoScreen: native distortion correction is not supported."); return; } if (stereoScreen != null) { stereoScreen.Release(); } stereoScreen = value; if (stereoScreen != null && !stereoScreen.IsCreated()) { stereoScreen.Create(); } if (device != null) { device.SetStereoScreen(stereoScreen); } } } private static RenderTexture stereoScreen = null; public bool UseDistortionEffect { get { return !NativeDistortionCorrectionSupported && distortionCorrection && vrModeEnabled && SystemInfo.supportsRenderTextures; } } // Describes the current device, including phone screen. public CardboardProfile Profile { get { return device.Profile; } } // Distinguish the stereo eyes. public enum Eye { Left, Right, Center } // When asking for project, viewport, etc, whether to assume viewing through // the lenses. public enum Distortion { Distorted, // Viewing through the lenses Undistorted // No lenses } // The transformation of head from origin in the tracking system. public Pose3D HeadPose { get { return device.GetHeadPose(); } } // The transformation from head to eye. public Pose3D EyePose(Eye eye) { return device.GetEyePose(eye); } // The projection matrix for a given eye. public Matrix4x4 Projection(Eye eye, Distortion distortion = Distortion.Distorted) { return device.GetProjection(eye, distortion); } // The screen-space rectangle each eye should render into. public Rect Viewport(Eye eye, Distortion distortion = Distortion.Distorted) { return device.GetViewport(eye, distortion); } // The distance range from the viewer in user-space meters where objects // may be viewed comfortably in stereo. If the center of interest falls // outside this range, the stereo eye separation should be adjusted to // keep the onscreen disparity within the limits set by this range. public Vector2 ComfortableViewingRange { get { return defaultComfortableViewingRange; } } private readonly Vector2 defaultComfortableViewingRange = new Vector2(1.0f, 100000.0f); private void InitDevice() { if (device != null) { device.Destroy(); } device = BaseVRDevice.GetDevice(); device.Init(); List diagnostics = new List(); NativeDistortionCorrectionSupported = device.SupportsNativeDistortionCorrection(diagnostics); if (diagnostics.Count > 0) { Debug.LogWarning("Built-in distortion correction disabled. Causes: [" + String.Join("; ", diagnostics.ToArray()) + "]"); } diagnostics.Clear(); NativeUILayerSupported = device.SupportsNativeUILayer(diagnostics); if (diagnostics.Count > 0) { Debug.LogWarning("Built-in UI layer disabled. Causes: [" + String.Join("; ", diagnostics.ToArray()) + "]"); } device.SetVRModeEnabled(vrModeEnabled); device.SetDistortionCorrectionEnabled(distortionCorrection && NativeDistortionCorrectionSupported); device.SetAlignmentMarkerEnabled(enableAlignmentMarker && NativeUILayerSupported); device.SetSettingsButtonEnabled(enableSettingsButton && NativeUILayerSupported); device.SetNeckModelScale(neckModelScale); device.SetAutoDriftCorrectionEnabled(autoDriftCorrection); device.UpdateScreenData(); } // NOTE: Each scene load causes an OnDestroy of the current SDK, followed // by and Awake of a new one. That should not cause the underlying native // code to hiccup. Exception: developer may call Application.DontDestroyOnLoad // on the SDK if they want it to survive across scene loads. void Awake() { if (sdk == null) { sdk = this; } if (sdk != this) { Debug.LogWarning("Cardboard SDK object should be a singleton."); enabled = false; return; } #if UNITY_IOS Application.targetFrameRate = 60; #endif InitDevice(); AddDummyCamera(); StereoScreen = null; } public event Action OnTrigger; public event Action OnTilt; public bool Triggered { get; private set; } public bool Tilted { get; private set; } private bool updated = false; private CardboardUILayer uiLayer = null; public void UpdateState() { if (!updated) { device.UpdateState(); if (TapIsTrigger) { if (Input.GetMouseButtonUp(0)) { device.triggered = true; } if (Input.GetKeyUp(KeyCode.Escape)) { device.tilted = true; } } updated = true; } } private void DispatchEvents() { Triggered = device.triggered; Tilted = device.tilted; device.triggered = false; device.tilted = false; if (Tilted) { if (OnTilt != null) { OnTilt(); } } if (Triggered) { if (OnTrigger != null) { OnTrigger(); } } } private void AddDummyCamera() { var go = gameObject; if (go.GetComponent()) { go = new GameObject("CardboardDummy"); go.transform.parent = gameObject.transform; } var cam = go.AddComponent(); cam.clearFlags = CameraClearFlags.SolidColor; cam.backgroundColor = Color.black; cam.cullingMask = 0; cam.useOcclusionCulling = false; cam.depth = -100; } IEnumerator EndOfFrame() { while (true) { yield return new WaitForEndOfFrame(); UpdateState(); device.PostRender(vrModeEnabled); if (vrModeEnabled && !NativeUILayerSupported) { if (uiLayer == null) { uiLayer = new CardboardUILayer(); } uiLayer.Draw(); } DispatchEvents(); updated = false; } } // Return a StereoScreen with sensible default values. public RenderTexture CreateStereoScreen() { return device.CreateStereoScreen(); } // Reset the tracker so that the user's current direction becomes forward. public void Recenter() { device.Recenter(); } // Set the screen coordinates of the mouse/touch event. public void SetTouchCoordinates(int x, int y) { device.SetTouchCoordinates(x, y); } void OnEnable() { device.OnPause(false); StartCoroutine("EndOfFrame"); } void OnDisable() { StopCoroutine("EndOfFrame"); device.OnPause(true); } void OnApplicationPause(bool pause) { device.OnPause(pause); } void OnApplicationFocus(bool focus) { device.OnFocus(focus); } void OnLevelWasLoaded(int level) { device.Reset(); } void OnDestroy() { if (device != null) { device.Destroy(); } if (sdk == this) { sdk = null; } } void OnApplicationQuit() { device.OnApplicationQuit(); } //********* OBSOLETE ACCESSORS ********* [System.Obsolete("Use DistortionCorrection instead.")] public bool nativeDistortionCorrection { get { return DistortionCorrection; } set { DistortionCorrection = value; } } [System.Obsolete("InCardboard is deprecated.")] public bool InCardboard { get { return true; } } [System.Obsolete("Use Triggered instead.")] public bool CardboardTriggered { get { return Triggered; } } [System.Obsolete("Use HeadPose instead.")] public Matrix4x4 HeadView { get { return HeadPose.Matrix; } } [System.Obsolete("Use HeadPose instead.")] public Quaternion HeadRotation { get { return HeadPose.Orientation; } } [System.Obsolete("Use HeadPose instead.")] public Vector3 HeadPosition { get { return HeadPose.Position; } } [System.Obsolete("Use EyePose() instead.")] public Matrix4x4 EyeView(Eye eye) { return EyePose(eye).Matrix; } [System.Obsolete("Use EyePose() instead.")] public Vector3 EyeOffset(Eye eye) { return EyePose(eye).Position; } [System.Obsolete("Use Projection() instead.")] public Matrix4x4 UndistortedProjection(Eye eye) { return Projection(eye, Distortion.Undistorted); } [System.Obsolete("Use Viewport() instead.")] public Rect EyeRect(Eye eye) { return Viewport(eye, Distortion.Distorted); } [System.Obsolete("Use ComfortableViewingRange instead.")] public float MinimumComfortDistance { get { return ComfortableViewingRange.x; } } [System.Obsolete("Use ComfortableViewingRange instead.")] public float MaximumComfortDistance { get { return ComfortableViewingRange.y; } } }
上面的源代码理解起来比较麻烦,我解析的时候会把变量定义等一些顺序调换一下
注释部分
The Cardboard object communicates with the head-mounted display in order to:Query the device for viewing parameters Retrieve the latest head tracking data Provide the rendered scene to the device for distortion correction 翻译/*Cardboard物体与头盔显示器进行交互以获得设备上的一些参数,返回最近头部跟踪数据,为被渲染的场景提供失真校正*/
定义了一个Cardboard类型的静态公有变量SDK,主要用来获取游戏中的Cardboard.cs脚本,可以看到它是只读的,即SDK提供了一个共有的访问接口,在任何时候它都只有一个实例。 // The singleton instance of the Cardboard class. 翻译/*Cardboard类的单件实例*/---关于单件模式,编程用的还是挺多的。
BaseVRDevice类型的私有静态变量device,BaseVRDevice也是插件当中定义的一个类,注意!!它与Cardboard类不同,它不是脚本类!!这个变量用的比较多 // The VR device that will be providing input data. 翻译/*VR设备(在这里直接理解为手机吧!)提供输入的数据*/
公有bool类型的变量DistortionCorrection,默认为true。DistortionCorrection我把它翻译为失真校正(暂且这样翻译吧),读属性不说了,写属性加了个if语句,想说明假如设备接入了并且支持失真校正功能,才能修改它的值,不然一直为true。(这个变量是控制扭曲的,开或者关的效果如下,差距应该一目了然)
同上还有VRModeEnabled(VR模式的使能,开了就是分屏),EnableAlignmentMarker(就是下图黄圈中间那根线,关了,线就没了),EnableSettingsButton(就是下图绿圈内的设置按钮,同样也是关了就没了),AutoDriftCorrection(这个属性还没搞懂先放着),NeckModelScale(这个是专业术语,应该是颈部的微调吧...猜的,值在0-1之间,调整的话视角会有微小的变化,但可以忽略不计)
后面从#if UNITY_IOS到#endif中间的部分是预编译部分,根据ios,unity_editor,android选择性的编译,可以根据自己的平台选择性的看。我们现在使用unity编辑器在运行,所以他编译的是#if UNITY_EDITOR到#endif中间的这部分。
RenderTexture类型的公有变量StereoScreen,渲染纹理是一种即时更新的纹理。//The texture that Unity renders the scene to. This is sent to the VR device,which renders it to screen, correcting for lens distortion. 翻译/*Unity渲染场景产生的纹理,它被传输到VR设备上,在屏幕上被绘制产生正确的透镜弯曲效果*/这个变量的读属性当vr模式或者distortionCorrection关闭时,为null,写属性也只有在支持distortionCorrection的时候可以使用,总的来说,可以把它看作产生弯曲效果的一个工具或者一个中间量。
bool类型只读属性的UseDistortionEffect,这个量是用来判断透镜效果是否开启的量,后面会用到。
CardboardProfile类型的公有变量Profile,也是只读的。 // Describes the current device, including phone screen. 翻译/*描述当前设备,包括手机屏幕*/
公有枚举类型Eye。 // Distinguish the stereo eyes. 翻译/*看立体效果时用来区分左右眼*/
公有枚举类型Distortion。这个量主要控制在某些特殊情况下是否需要透镜预览,在下面会用到
Pose3D类型的公有量HeadPose。 // The transformation of head from origin in the tracking system. 翻译/*在跟踪在系统中,头部距离起始点的信息*/由于这里Pose3D也是插件自定义的类,后续需要分析Pose3D这个类才能知道信息是如何传递的。同理还有变量EyePose。
返回Matrix4x4类型的方法Projection(Eye eye, Distortion distortion = Distortion.Distorted)返回结果是device.GetProjection(eye, distortion);从两个参数推断这个方法是要根据眼睛计算返回一个投影矩阵,在Unity圣典中阐述过Matrix4x4类型的投影矩阵,关于投影矩阵,涉及到计算机图形学的东西,我目前也正在学习,给一个链接大家可以学习一下。
http://blog.csdn.net/yanwei2016/article/details/7326180
Viewport(Eye eye, Distortion distortion = Distortion.Distorted)方法返回视口矩形,应该是处理在屏幕上的位置的一个方法
Vector2类型的变量ComfortableViewingRange,只读,控制我们去看空间中物体的一个最舒服的距离范围,这个量不需要去配置,理解就行。
私有方法InitDevice()用于初始化设备,因为涉及到BaseVRDevice类,我们以后再去解析其细节。
私有方法AddDummyCamera()用来添加一个黑色背景,当然背景也可以自己更换。
一些琐碎的定义先到这里
/********************************************************分割线********************************************************************/
NOTE: Each scene load causes an OnDestroy of the current SDK, followed by and Awake of a new one. That should not cause the underlying native code to hiccup. Exception: developer may call Application.DontDestroyOnLoad on the SDK if they want it to survive
across scene loads.
翻译/*说明:每一个新场景被加载会导致现在sdk的destroy,然后产生新的sdk,这会发生一些问题(这句话实在不会翻译了),所以开发者们在切换场景的时候如果希望sdk依然存活,可以使用Application.DontDestroyOnLoad*/。这里其实可以间接的说明SDK是采用的单件模式,因为我们无法用new()去创建,而且自始而终最多只有一个实例。
比较关键的awake函数来了
void Awake() {
if (sdk == null) {
sdk = this;
}
if (sdk != this) {
Debug.LogWarning("Cardboard SDK object should be a singleton.");
enabled = false;
return;
}
#if UNITY_IOS
Application.targetFrameRate = 60;
#endif
InitDevice();
AddDummyCamera();
StereoScreen = null;
}相信上面的语句根据我之前的解释大家都能看懂了
这个类中没有Update()所以我认为更新可能放在BaseVRDevice类型的device里面了。
我先码到这里(太累了),后面接着此篇,另外会解析BaseVRDevice这个类(很重要!!),还有CardboardProfile这个类。
总结:这一章还只是把每个类的功能和大致框架整理了一下,并没有涉及到很多细节的东西,也没有涉及到原理,注意我们现在还在顶端的父物体Cardboard物体上分析,后面当涉及到原理的的时候,就要开始看下层的Head,和它的子物体几个camera了。
相关文章推荐
- Kinect结合Unity3D引擎开发体感游戏(一)
- java自动生成验证码插件-kaptcha
- Android实现表情 抓取新浪表情
- 详解Android解析Xml的三种方式——DOM、SAX以及XMLpull
- Android ADT 23.0.0无法更新到23.0.2问题解决方案
- SDKMAN:轻松管理多个软件开发套件 (SDK) 的命令行工具
- jQuery插件实现文字无缝向上滚动效果代码
- jQuery菜单插件用法实例
- 加载flash9.ocx出现错误的解决方法
- jquery实现的代替传统checkbox样式插件
- 10款新鲜出炉的 jQuery 插件(Ajax 插件,有幻灯片、图片画廊、菜单等)
- jquery插件autocomplete用法示例
- 推荐40个非常优秀的jQuery插件和教程【系列三】
- Node.js插件的正确编写方式
- Parse正式发布开源PHP SDK
- 推荐十款免费 WordPress 插件
- NopCommerce架构分析之(四)基于路由实现灵活的插件机制
- Bootstrap教程JS插件弹出框学习笔记分享
- 使用JavaScript开发IE浏览器本地插件实例