コード例 #1
0
    public OVRDirectComposition(GameObject parentObject, Camera mainCamera, OVRManager.CameraDevice cameraDevice, bool useDynamicLighting, OVRManager.DepthQuality depthQuality)
        : base(cameraDevice, useDynamicLighting, depthQuality)
    {
        Debug.Assert(directCompositionCameraGameObject == null);
        directCompositionCameraGameObject                  = new GameObject();
        directCompositionCameraGameObject.name             = "MRDirectCompositionCamera";
        directCompositionCameraGameObject.transform.parent = parentObject.transform;
        directCompositionCamera = directCompositionCameraGameObject.AddComponent <Camera>();
        directCompositionCamera.stereoTargetEye = StereoTargetEyeMask.None;
        directCompositionCamera.depth           = float.MaxValue;
        directCompositionCamera.rect            = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
        directCompositionCamera.clearFlags      = mainCamera.clearFlags;
        directCompositionCamera.backgroundColor = mainCamera.backgroundColor;
        directCompositionCamera.cullingMask     = mainCamera.cullingMask & (~OVRManager.instance.extraHiddenLayers);
        directCompositionCamera.nearClipPlane   = mainCamera.nearClipPlane;
        directCompositionCamera.farClipPlane    = mainCamera.farClipPlane;


        if (!hasCameraDeviceOpened)
        {
            Debug.LogError("Unable to open camera device " + cameraDevice);
        }
        else
        {
            Debug.Log("DirectComposition activated : useDynamicLighting " + (useDynamicLighting ? "ON" : "OFF"));
            CreateCameraFramePlaneObject(parentObject, directCompositionCamera, useDynamicLighting);
        }
    }
コード例 #2
0
 public void ReadFrom(OVRManager manager)
 {
     enableMixedReality = manager.enableMixedReality;
     compositionMethod  = manager.compositionMethod;
     extraHiddenLayers  = manager.extraHiddenLayers;
     externalCompositionBackdropColorRift  = manager.externalCompositionBackdropColorRift;
     externalCompositionBackdropColorQuest = manager.externalCompositionBackdropColorQuest;
     capturingCameraDevice             = manager.capturingCameraDevice;
     flipCameraFrameHorizontally       = manager.flipCameraFrameHorizontally;
     flipCameraFrameVertically         = manager.flipCameraFrameVertically;
     handPoseStateLatency              = manager.handPoseStateLatency;
     sandwichCompositionRenderLatency  = manager.sandwichCompositionRenderLatency;
     sandwichCompositionBufferedFrames = manager.sandwichCompositionBufferedFrames;
     chromaKeyColor              = manager.chromaKeyColor;
     chromaKeySimilarity         = manager.chromaKeySimilarity;
     chromaKeySmoothRange        = manager.chromaKeySmoothRange;
     chromaKeySpillRange         = manager.chromaKeySpillRange;
     useDynamicLighting          = manager.useDynamicLighting;
     depthQuality                = manager.depthQuality;
     dynamicLightingSmoothFactor = manager.dynamicLightingSmoothFactor;
     dynamicLightingDepthVariationClampingValue = manager.dynamicLightingDepthVariationClampingValue;
     virtualGreenScreenType              = manager.virtualGreenScreenType;
     virtualGreenScreenTopY              = manager.virtualGreenScreenTopY;
     virtualGreenScreenBottomY           = manager.virtualGreenScreenBottomY;
     virtualGreenScreenApplyDepthCulling = manager.virtualGreenScreenApplyDepthCulling;
     virtualGreenScreenDepthTolerance    = manager.virtualGreenScreenDepthTolerance;
 }
コード例 #3
0
	public void ReadFrom(OVRManager manager)
	{
		enableMixedReality = manager.enableMixedReality:
		compositionMethod = manager.compositionMethod:
		extraHiddenLayers = manager.extraHiddenLayers:
		capturingCameraDevice = manager.capturingCameraDevice:
		flipCameraFrameHorizontally = manager.flipCameraFrameHorizontally:
		flipCameraFrameVertically = manager.flipCameraFrameVertically:
		handPoseStateLatency = manager.handPoseStateLatency:
		sandwichCompositionRenderLatency = manager.sandwichCompositionRenderLatency:
		sandwichCompositionBufferedFrames = manager.sandwichCompositionBufferedFrames:
		chromaKeyColor = manager.chromaKeyColor:
		chromaKeySimilarity = manager.chromaKeySimilarity:
		chromaKeySmoothRange = manager.chromaKeySmoothRange:
		chromaKeySpillRange = manager.chromaKeySpillRange:
		useDynamicLighting = manager.useDynamicLighting:
		depthQuality = manager.depthQuality:
		dynamicLightingSmoothFactor = manager.dynamicLightingSmoothFactor:
		dynamicLightingDepthVariationClampingValue = manager.dynamicLightingDepthVariationClampingValue:
		virtualGreenScreenType = manager.virtualGreenScreenType:
		virtualGreenScreenTopY = manager.virtualGreenScreenTopY:
		virtualGreenScreenBottomY = manager.virtualGreenScreenBottomY:
		virtualGreenScreenApplyDepthCulling = manager.virtualGreenScreenApplyDepthCulling:
		virtualGreenScreenDepthTolerance = manager.virtualGreenScreenDepthTolerance:
	}
コード例 #4
0
    protected OVRCameraComposition(GameObject parentObject, Camera mainCamera, OVRManager.CameraDevice inCameraDevice, bool inUseDynamicLighting, OVRManager.DepthQuality depthQuality)
        : base(parentObject, mainCamera)
    {
        cameraDevice = OVRCompositionUtil.ConvertCameraDevice(inCameraDevice);

        Debug.Assert(!hasCameraDeviceOpened);
        Debug.Assert(!OVRPlugin.IsCameraDeviceAvailable(cameraDevice) || !OVRPlugin.HasCameraDeviceOpened(cameraDevice));
        hasCameraDeviceOpened = false;
        useDynamicLighting    = inUseDynamicLighting;

        bool cameraSupportsDepth = OVRPlugin.DoesCameraDeviceSupportDepth(cameraDevice);

        if (useDynamicLighting && !cameraSupportsDepth)
        {
            Debug.LogWarning("The camera device doesn't support depth. The result of dynamic lighting might not be correct");
        }

        if (OVRPlugin.IsCameraDeviceAvailable(cameraDevice))
        {
            OVRPlugin.CameraExtrinsics extrinsics;
            OVRPlugin.CameraIntrinsics intrinsics;
            OVRPlugin.Posef            calibrationRawPose;
            if (OVRPlugin.GetExternalCameraCount() > 0 && OVRPlugin.GetMixedRealityCameraInfo(0, out extrinsics, out intrinsics, out calibrationRawPose))
            {
                OVRPlugin.SetCameraDevicePreferredColorFrameSize(cameraDevice, intrinsics.ImageSensorPixelResolution.w, intrinsics.ImageSensorPixelResolution.h);
            }

            if (useDynamicLighting)
            {
                OVRPlugin.SetCameraDeviceDepthSensingMode(cameraDevice, OVRPlugin.CameraDeviceDepthSensingMode.Fill);
                OVRPlugin.CameraDeviceDepthQuality quality = OVRPlugin.CameraDeviceDepthQuality.Medium;
                if (depthQuality == OVRManager.DepthQuality.Low)
                {
                    quality = OVRPlugin.CameraDeviceDepthQuality.Low;
                }
                else if (depthQuality == OVRManager.DepthQuality.Medium)
                {
                    quality = OVRPlugin.CameraDeviceDepthQuality.Medium;
                }
                else if (depthQuality == OVRManager.DepthQuality.High)
                {
                    quality = OVRPlugin.CameraDeviceDepthQuality.High;
                }
                else
                {
                    Debug.LogWarning("Unknown depth quality");
                }
                OVRPlugin.SetCameraDevicePreferredDepthQuality(cameraDevice, quality);
            }

            Debug.LogFormat("Opening camera device {0}", cameraDevice);
            OVRPlugin.OpenCameraDevice(cameraDevice);
            if (OVRPlugin.HasCameraDeviceOpened(cameraDevice))
            {
                Debug.LogFormat("Opened camera device {0}", cameraDevice);
                hasCameraDeviceOpened = true;
            }
        }
    }
コード例 #5
0
 void SetupCameraDeviceField(string name, ref OVRManager.CameraDevice device)
 {
     EditorGUI.BeginChangeCheck();
     OVRManager.CameraDevice value = (OVRManager.CameraDevice)EditorGUILayout.EnumPopup(name, device);
     if (EditorGUI.EndChangeCheck())
     {
         Undo.RecordObject(target, "Changed " + name);
         device = value;
     }
 }
コード例 #6
0
	protected OVRCameraComposition(OVRManager.CameraDevice inCameraDevice, bool inUseDynamicLighting, OVRManager.DepthQuality depthQuality)
	{
		cameraDevice = OVRCompositionUtil.ConvertCameraDevice(inCameraDevice):

		Debug.Assert(!hasCameraDeviceOpened):
		Debug.Assert(!OVRPlugin.IsCameraDeviceAvailable(cameraDevice) || !OVRPlugin.HasCameraDeviceOpened(cameraDevice)):
		hasCameraDeviceOpened = false:
		useDynamicLighting = inUseDynamicLighting:

		bool cameraSupportsDepth = OVRPlugin.DoesCameraDeviceSupportDepth(cameraDevice):
		if (useDynamicLighting && !cameraSupportsDepth)
		{
			Debug.LogWarning("The camera device doesn't support depth. The result of dynamic lighting might not be correct"):
		}

		if (OVRPlugin.IsCameraDeviceAvailable(cameraDevice))
		{
			OVRPlugin.CameraExtrinsics extrinsics:
			OVRPlugin.CameraIntrinsics intrinsics:
			if (OVRPlugin.GetExternalCameraCount() > 0 && OVRPlugin.GetMixedRealityCameraInfo(0, out extrinsics, out intrinsics))
			{
				OVRPlugin.SetCameraDevicePreferredColorFrameSize(cameraDevice, intrinsics.ImageSensorPixelResolution.w, intrinsics.ImageSensorPixelResolution.h):
			}

			if (useDynamicLighting)
			{
				OVRPlugin.SetCameraDeviceDepthSensingMode(cameraDevice, OVRPlugin.CameraDeviceDepthSensingMode.Fill):
				OVRPlugin.CameraDeviceDepthQuality quality = OVRPlugin.CameraDeviceDepthQuality.Medium:
				if (depthQuality == OVRManager.DepthQuality.Low)
				{
					quality = OVRPlugin.CameraDeviceDepthQuality.Low:
				}
				else if (depthQuality == OVRManager.DepthQuality.Medium)
				{
					quality = OVRPlugin.CameraDeviceDepthQuality.Medium:
				}
				else if (depthQuality == OVRManager.DepthQuality.High)
				{
					quality = OVRPlugin.CameraDeviceDepthQuality.High:
				}
				else
				{
					Debug.LogWarning("Unknown depth quality"):
				}
				OVRPlugin.SetCameraDevicePreferredDepthQuality(cameraDevice, quality):
			}

			OVRPlugin.OpenCameraDevice(cameraDevice):
			if (OVRPlugin.HasCameraDeviceOpened(cameraDevice))
			{
				hasCameraDeviceOpened = true:
			}
		}
	}
コード例 #7
0
    protected OVRCameraComposition(OVRManager.CameraDevice inCameraDevice, bool inUseDynamicLighting, OVRManager.DepthQuality depthQuality)
    {
        this.cameraDevice          = OVRCompositionUtil.ConvertCameraDevice(inCameraDevice);
        this.hasCameraDeviceOpened = false;
        this.useDynamicLighting    = inUseDynamicLighting;
        bool flag = OVRPlugin.DoesCameraDeviceSupportDepth(this.cameraDevice);

        if (this.useDynamicLighting && !flag)
        {
            Debug.LogWarning("The camera device doesn't support depth. The result of dynamic lighting might not be correct");
        }
        if (OVRPlugin.IsCameraDeviceAvailable(this.cameraDevice))
        {
            OVRPlugin.CameraExtrinsics cameraExtrinsics;
            OVRPlugin.CameraIntrinsics cameraIntrinsics;
            if (OVRPlugin.GetExternalCameraCount() > 0 && OVRPlugin.GetMixedRealityCameraInfo(0, out cameraExtrinsics, out cameraIntrinsics))
            {
                OVRPlugin.SetCameraDevicePreferredColorFrameSize(this.cameraDevice, cameraIntrinsics.ImageSensorPixelResolution.w, cameraIntrinsics.ImageSensorPixelResolution.h);
            }
            if (this.useDynamicLighting)
            {
                OVRPlugin.SetCameraDeviceDepthSensingMode(this.cameraDevice, OVRPlugin.CameraDeviceDepthSensingMode.Fill);
                OVRPlugin.CameraDeviceDepthQuality depthQuality2 = OVRPlugin.CameraDeviceDepthQuality.Medium;
                if (depthQuality == OVRManager.DepthQuality.Low)
                {
                    depthQuality2 = OVRPlugin.CameraDeviceDepthQuality.Low;
                }
                else if (depthQuality == OVRManager.DepthQuality.Medium)
                {
                    depthQuality2 = OVRPlugin.CameraDeviceDepthQuality.Medium;
                }
                else if (depthQuality == OVRManager.DepthQuality.High)
                {
                    depthQuality2 = OVRPlugin.CameraDeviceDepthQuality.High;
                }
                else
                {
                    Debug.LogWarning("Unknown depth quality");
                }
                OVRPlugin.SetCameraDevicePreferredDepthQuality(this.cameraDevice, depthQuality2);
            }
            OVRPlugin.OpenCameraDevice(this.cameraDevice);
            if (OVRPlugin.HasCameraDeviceOpened(this.cameraDevice))
            {
                this.hasCameraDeviceOpened = true;
            }
        }
    }
コード例 #8
0
 public static OVRPlugin.CameraDevice ConvertCameraDevice(OVRManager.CameraDevice cameraDevice)
 {
     if (cameraDevice == OVRManager.CameraDevice.WebCamera0)
     {
         return(OVRPlugin.CameraDevice.WebCamera0);
     }
     if (cameraDevice == OVRManager.CameraDevice.WebCamera1)
     {
         return(OVRPlugin.CameraDevice.WebCamera1);
     }
     if (cameraDevice == OVRManager.CameraDevice.ZEDCamera)
     {
         return(OVRPlugin.CameraDevice.ZEDCamera);
     }
     return(OVRPlugin.CameraDevice.None);
 }
コード例 #9
0
	public static OVRPlugin.CameraDevice ConvertCameraDevice(OVRManager.CameraDevice cameraDevice)
	{
		if (cameraDevice == OVRManager.CameraDevice.WebCamera0)
		{
			return OVRPlugin.CameraDevice.WebCamera0:
		}
		else if (cameraDevice == OVRManager.CameraDevice.WebCamera1)
		{
			return OVRPlugin.CameraDevice.WebCamera1:
		}
		else if (cameraDevice == OVRManager.CameraDevice.ZEDCamera)
		{
			return OVRPlugin.CameraDevice.ZEDCamera:
		}
		else
		{
			return OVRPlugin.CameraDevice.None:
		}
	}
コード例 #10
0
 public OVRDirectComposition(GameObject parentObject, Camera mainCamera, OVRManager.CameraDevice cameraDevice, bool useDynamicLighting, OVRManager.DepthQuality depthQuality)
     : base(parentObject, mainCamera, cameraDevice, useDynamicLighting, depthQuality)
 {
     RefreshCameraObjects(parentObject, mainCamera);
 }
コード例 #11
0
    /// <summary>
    /// Updates the internal state of the Mixed Reality Camera. Called by OVRManager.
    /// </summary>

    public static void Update(GameObject parentObject, Camera mainCamera, OVRManager.CompositionMethod compositionMethod, bool useDynamicLighting, OVRManager.CameraDevice cameraDevice, OVRManager.DepthQuality depthQuality)
    {
        if (!OVRPlugin.initialized)
        {
            Debug.LogError("OVRPlugin not initialized");
            return;
        }

        if (!OVRPlugin.IsMixedRealityInitialized())
        {
            OVRPlugin.InitializeMixedReality();
        }

        if (!OVRPlugin.IsMixedRealityInitialized())
        {
            Debug.LogError("Unable to initialize MixedReality");
            return;
        }

        OVRPlugin.UpdateExternalCamera();
        OVRPlugin.UpdateCameraDevices();

        if (currentComposition != null && currentComposition.CompositionMethod() != compositionMethod)
        {
            currentComposition.Cleanup();
            currentComposition = null;
        }

        if (compositionMethod == OVRManager.CompositionMethod.External)
        {
            if (currentComposition == null)
            {
                currentComposition = new OVRExternalComposition(parentObject, mainCamera);
            }
        }
        else if (compositionMethod == OVRManager.CompositionMethod.Direct)
        {
            if (currentComposition == null)
            {
                currentComposition = new OVRDirectComposition(parentObject, mainCamera, cameraDevice, useDynamicLighting, depthQuality);
            }
        }
        else if (compositionMethod == OVRManager.CompositionMethod.Sandwich)
        {
            if (currentComposition == null)
            {
                currentComposition = new OVRSandwichComposition(parentObject, mainCamera, cameraDevice, useDynamicLighting, depthQuality);
            }
        }
        else
        {
            Debug.LogError("Unknown CompositionMethod : " + compositionMethod);
            return;
        }
        currentComposition.Update(mainCamera);
    }
コード例 #12
0
    /// <summary>
    /// Updates the internal state of the Mixed Reality Camera. Called by OVRManager.
    /// </summary>

    public static void Update(GameObject parentObject, Camera mainCamera, OVRManager.CompositionMethod compositionMethod, bool useDynamicLighting, OVRManager.CameraDevice cameraDevice, OVRManager.DepthQuality depthQuality)
    {
        if (!OVRPlugin.initialized)
        {
            Debug.LogError("OVRPlugin not initialized");
            return;
        }

        if (!OVRPlugin.IsMixedRealityInitialized())
        {
            OVRPlugin.InitializeMixedReality();
            if (OVRPlugin.IsMixedRealityInitialized())
            {
                Debug.Log("OVRPlugin_MixedReality initialized");
            }
            else
            {
                Debug.LogError("Unable to initialize OVRPlugin_MixedReality");
                return;
            }
        }

        if (!OVRPlugin.IsMixedRealityInitialized())
        {
            return;
        }

        OVRPlugin.UpdateExternalCamera();
#if !OVR_ANDROID_MRC
        OVRPlugin.UpdateCameraDevices();
#endif

#if OVR_ANDROID_MRC
        useFakeExternalCamera = OVRPlugin.Media.UseMrcDebugCamera();
#endif

        if (currentComposition != null && currentComposition.CompositionMethod() != compositionMethod)
        {
            currentComposition.Cleanup();
            currentComposition = null;
        }

        if (compositionMethod == OVRManager.CompositionMethod.External)
        {
            if (currentComposition == null)
            {
                currentComposition = new OVRExternalComposition(parentObject, mainCamera);
            }
        }
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
        else if (compositionMethod == OVRManager.CompositionMethod.Direct)
        {
            if (currentComposition == null)
            {
                currentComposition = new OVRDirectComposition(parentObject, mainCamera, cameraDevice, useDynamicLighting, depthQuality);
            }
        }
#endif
        else
        {
            Debug.LogError("Unknown CompositionMethod : " + compositionMethod);
            return;
        }
        currentComposition.Update(parentObject, mainCamera);
    }
コード例 #13
0
    public OVRSandwichComposition(GameObject parentObject, Camera mainCamera, OVRManager.CameraDevice cameraDevice, bool useDynamicLighting, OVRManager.DepthQuality depthQuality) : base(cameraDevice, useDynamicLighting, depthQuality)
    {
        this.frameRealtime      = Time.realtimeSinceStartup;
        this.historyRecordCount = OVRManager.instance.sandwichCompositionBufferedFrames;
        if (this.historyRecordCount < 1)
        {
            Debug.LogWarning("Invalid sandwichCompositionBufferedFrames in OVRManager. It should be at least 1");
            this.historyRecordCount = 1;
        }
        if (this.historyRecordCount > 16)
        {
            Debug.LogWarning("The value of sandwichCompositionBufferedFrames in OVRManager is too big. It would consume a lot of memory. It has been override to 16");
            this.historyRecordCount = 16;
        }
        this.historyRecordArray = new OVRSandwichComposition.HistoryRecord[this.historyRecordCount];
        for (int i = 0; i < this.historyRecordCount; i++)
        {
            this.historyRecordArray[i] = new OVRSandwichComposition.HistoryRecord();
        }
        this.historyRecordCursorIndex = 0;
        this.fgCamera = new GameObject("MRSandwichForegroundCamera")
        {
            transform =
            {
                parent = parentObject.transform
            }
        }.AddComponent <Camera>();
        this.fgCamera.depth           = 200f;
        this.fgCamera.clearFlags      = CameraClearFlags.Color;
        this.fgCamera.backgroundColor = Color.clear;
        this.fgCamera.cullingMask     = (mainCamera.cullingMask & ~OVRManager.instance.extraHiddenLayers);
        this.fgCamera.nearClipPlane   = mainCamera.nearClipPlane;
        this.fgCamera.farClipPlane    = mainCamera.farClipPlane;
        this.bgCamera = new GameObject("MRSandwichBackgroundCamera")
        {
            transform =
            {
                parent = parentObject.transform
            }
        }.AddComponent <Camera>();
        this.bgCamera.depth                    = 100f;
        this.bgCamera.clearFlags               = mainCamera.clearFlags;
        this.bgCamera.backgroundColor          = mainCamera.backgroundColor;
        this.bgCamera.cullingMask              = (mainCamera.cullingMask & ~OVRManager.instance.extraHiddenLayers);
        this.bgCamera.nearClipPlane            = mainCamera.nearClipPlane;
        this.bgCamera.farClipPlane             = mainCamera.farClipPlane;
        this.cameraProxyPlane                  = GameObject.CreatePrimitive(PrimitiveType.Quad);
        this.cameraProxyPlane.name             = "MRProxyClipPlane";
        this.cameraProxyPlane.transform.parent = parentObject.transform;
        this.cameraProxyPlane.GetComponent <Collider>().enabled = false;
        this.cameraProxyPlane.GetComponent <MeshRenderer>().shadowCastingMode = ShadowCastingMode.Off;
        Material material = new Material(Shader.Find("Oculus/OVRMRClipPlane"));

        this.cameraProxyPlane.GetComponent <MeshRenderer>().material = material;
        material.SetColor("_Color", Color.clear);
        material.SetFloat("_Visible", 0f);
        this.cameraProxyPlane.transform.localScale = new Vector3(1000f, 1000f, 1000f);
        this.cameraProxyPlane.SetActive(true);
        OVRMRForegroundCameraManager ovrmrforegroundCameraManager = this.fgCamera.gameObject.AddComponent <OVRMRForegroundCameraManager>();

        ovrmrforegroundCameraManager.clipPlaneGameObj = this.cameraProxyPlane;
        this.compositionCamera = new GameObject("MRSandwichCaptureCamera")
        {
            transform =
            {
                parent = parentObject.transform
            }
        }.AddComponent <Camera>();
        this.compositionCamera.stereoTargetEye = StereoTargetEyeMask.None;
        this.compositionCamera.depth           = float.MaxValue;
        this.compositionCamera.rect            = new Rect(0f, 0f, 1f, 1f);
        this.compositionCamera.clearFlags      = CameraClearFlags.Depth;
        this.compositionCamera.backgroundColor = mainCamera.backgroundColor;
        this.compositionCamera.cullingMask     = 1 << this.cameraFramePlaneLayer;
        this.compositionCamera.nearClipPlane   = mainCamera.nearClipPlane;
        this.compositionCamera.farClipPlane    = mainCamera.farClipPlane;
        if (!this.hasCameraDeviceOpened)
        {
            Debug.LogError("Unable to open camera device " + cameraDevice);
        }
        else
        {
            Debug.Log("SandwichComposition activated : useDynamicLighting " + ((!useDynamicLighting) ? "OFF" : "ON"));
            base.CreateCameraFramePlaneObject(parentObject, this.compositionCamera, useDynamicLighting);
            this.cameraFramePlaneObject.layer = this.cameraFramePlaneLayer;
            this.RefreshRenderTextures(mainCamera);
            this.compositionManager           = this.compositionCamera.gameObject.AddComponent <OVRSandwichComposition.OVRSandwichCompositionManager>();
            this.compositionManager.fgTexture = this.historyRecordArray[this.historyRecordCursorIndex].fgRenderTexture;
            this.compositionManager.bgTexture = this.historyRecordArray[this.historyRecordCursorIndex].bgRenderTexture;
        }
    }
コード例 #14
0
    public OVRSandwichComposition(GameObject parentObject, Camera mainCamera, OVRManager.CameraDevice cameraDevice, bool useDynamicLighting, OVRManager.DepthQuality depthQuality)
        : base(cameraDevice, useDynamicLighting, depthQuality)
    {
        frameRealtime = Time.realtimeSinceStartup;

        historyRecordCount = OVRManager.instance.sandwichCompositionBufferedFrames;
        if (historyRecordCount < 1)
        {
            Debug.LogWarning("Invalid sandwichCompositionBufferedFrames in OVRManager. It should be at least 1");
            historyRecordCount = 1;
        }
        if (historyRecordCount > 16)
        {
            Debug.LogWarning("The value of sandwichCompositionBufferedFrames in OVRManager is too big. It would consume a lot of memory. It has been override to 16");
            historyRecordCount = 16;
        }
        historyRecordArray = new HistoryRecord[historyRecordCount];
        for (int i = 0; i < historyRecordCount; ++i)
        {
            historyRecordArray[i] = new HistoryRecord();
        }
        historyRecordCursorIndex = 0;

        GameObject fgObject = new GameObject("MRSandwichForegroundCamera");

        fgObject.transform.parent = parentObject.transform;
        fgCamera                 = fgObject.AddComponent <Camera>();
        fgCamera.depth           = 200;
        fgCamera.clearFlags      = CameraClearFlags.SolidColor;
        fgCamera.backgroundColor = Color.clear;
        fgCamera.cullingMask     = mainCamera.cullingMask & (~OVRManager.instance.extraHiddenLayers);
        fgCamera.nearClipPlane   = mainCamera.nearClipPlane;
        fgCamera.farClipPlane    = mainCamera.farClipPlane;

        GameObject bgObject = new GameObject("MRSandwichBackgroundCamera");

        bgObject.transform.parent = parentObject.transform;
        bgCamera                 = bgObject.AddComponent <Camera>();
        bgCamera.depth           = 100;
        bgCamera.clearFlags      = mainCamera.clearFlags;
        bgCamera.backgroundColor = mainCamera.backgroundColor;
        bgCamera.cullingMask     = mainCamera.cullingMask & (~OVRManager.instance.extraHiddenLayers);
        bgCamera.nearClipPlane   = mainCamera.nearClipPlane;
        bgCamera.farClipPlane    = mainCamera.farClipPlane;

        // Create cameraProxyPlane for clipping
        Debug.Assert(cameraProxyPlane == null);
        cameraProxyPlane                  = GameObject.CreatePrimitive(PrimitiveType.Quad);
        cameraProxyPlane.name             = "MRProxyClipPlane";
        cameraProxyPlane.transform.parent = parentObject.transform;
        cameraProxyPlane.GetComponent <Collider>().enabled = false;
        cameraProxyPlane.GetComponent <MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
        Material clipMaterial = new Material(Shader.Find("Oculus/OVRMRClipPlane"));

        cameraProxyPlane.GetComponent <MeshRenderer>().material = clipMaterial;
        clipMaterial.SetColor("_Color", Color.clear);
        clipMaterial.SetFloat("_Visible", 0.0f);
        cameraProxyPlane.transform.localScale = new Vector3(1000, 1000, 1000);
        cameraProxyPlane.SetActive(true);
        OVRMRForegroundCameraManager foregroundCameraManager = fgCamera.gameObject.AddComponent <OVRMRForegroundCameraManager>();

        foregroundCameraManager.clipPlaneGameObj = cameraProxyPlane;

        GameObject compositionCameraObject = new GameObject("MRSandwichCaptureCamera");

        compositionCameraObject.transform.parent = parentObject.transform;
        compositionCamera = compositionCameraObject.AddComponent <Camera>();
        compositionCamera.stereoTargetEye = StereoTargetEyeMask.None;
        compositionCamera.depth           = float.MaxValue;
        compositionCamera.rect            = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
        compositionCamera.clearFlags      = CameraClearFlags.Depth;
        compositionCamera.backgroundColor = mainCamera.backgroundColor;
        compositionCamera.cullingMask     = 1 << cameraFramePlaneLayer;
        compositionCamera.nearClipPlane   = mainCamera.nearClipPlane;
        compositionCamera.farClipPlane    = mainCamera.farClipPlane;

        if (!hasCameraDeviceOpened)
        {
            Debug.LogError("Unable to open camera device " + cameraDevice);
        }
        else
        {
            Debug.Log("SandwichComposition activated : useDynamicLighting " + (useDynamicLighting ? "ON" : "OFF"));
            CreateCameraFramePlaneObject(parentObject, compositionCamera, useDynamicLighting);
            cameraFramePlaneObject.layer = cameraFramePlaneLayer;
            RefreshRenderTextures(mainCamera);
            compositionManager           = compositionCamera.gameObject.AddComponent <OVRSandwichCompositionManager>();
            compositionManager.fgTexture = historyRecordArray[historyRecordCursorIndex].fgRenderTexture;
            compositionManager.bgTexture = historyRecordArray[historyRecordCursorIndex].bgRenderTexture;
        }
    }