////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2007-2020 , Inc. All Rights Reserved. // ////////////////////////////////////////////////////////////////////////// using System; using UnityEngine; namespace GCSeries.zView { public class VirtualCameraStandard : VirtualCamera { ////////////////////////////////////////////////////////////////// // Unity MonoBehaviour Callbacks ////////////////////////////////////////////////////////////////// void Awake() { // Dynamically create a new Unity camera and disable it to allow for manual // rendering via Camera.Render(). _camera = this.gameObject.AddComponent(); _camera.enabled = false; } ////////////////////////////////////////////////////////////////// // Virtual Camera Overrides ////////////////////////////////////////////////////////////////// public override void SetUp(ZView zView, IntPtr connection, ZView.ModeSetupPhase phase) { switch (phase) { case ZView.ModeSetupPhase.Initialization: this.UpdateImageResolution(zView, connection); break; case ZView.ModeSetupPhase.Completion: // Grab the image dimensions from the connection settings. UInt16 imageWidth = zView.GetSettingUInt16(connection, ZView.SettingKey.ImageWidth); UInt16 imageHeight = zView.GetSettingUInt16(connection, ZView.SettingKey.ImageHeight); // Create the render texture. _renderTexture = new RenderTexture((int)imageWidth, (int)imageHeight, 24, RenderTextureFormat.ARGB32); _renderTexture.filterMode = FilterMode.Point; _renderTexture.name = "RenderTextureStandard"; _renderTexture.Create(); // Cache the render texture's native texture pointer. Per Unity documentation, // calling GetNativeTexturePtr() when using multi-threaded rendering will // synchronize with the rendering thread (which is a slow operation). So, only // call and cache once upon initialization. _nativeTexturePtr = _renderTexture.GetNativeTexturePtr(); break; default: break; } } public override void TearDown() { // Reset the camera's target texture. _camera.targetTexture = null; // Reset the render texture's native texture pointer. _nativeTexturePtr = IntPtr.Zero; // Clean up the existing render texture. if (_renderTexture != null) { UnityEngine.Object.Destroy(_renderTexture); _renderTexture = null; } // Reset the image width and height. _imageWidth = 0; _imageHeight = 0; } public override void Render(ZView zView, IntPtr connection, IntPtr receivedFrame) { // Check to see if the image width or height changed and update them // accordingly. this.UpdateImageResolution(zView, connection); // Cache the camera's culling mask to be restored after it renders the frame. int cullingMask = _camera.cullingMask; if (zView.ActiveZCamera == null) { Debug.LogWarning("ZView's public property ActiveZCamera" + "is null, but must be assigned."); return; } if (zView.ActiveZCamera.transform != this._zCameraTransform) { this._zCameraTransform = zView.ActiveZCamera.transform; this._zCameraCamera = this._zCameraTransform.GetComponent(); } // Copy the center eye camera's attributes to the standard mode primary camera. _camera.CopyFrom(this._zCameraCamera); _camera.transform.position = this._zCameraTransform.position; _camera.transform.rotation = this._zCameraTransform.rotation; _camera.projectionMatrix = this._zCameraCamera.projectionMatrix; // Render the scene. _camera.cullingMask = cullingMask & ~(zView.StandardModeIgnoreLayers); _camera.targetTexture = _renderTexture; _camera.Render(); // Restore the camera's culling mask. _camera.cullingMask = cullingMask; } public override IntPtr GetNativeTexturePtr() { return _nativeTexturePtr; } ////////////////////////////////////////////////////////////////// // Private Methods ////////////////////////////////////////////////////////////////// private void UpdateImageResolution(ZView zView, IntPtr connection) { // Get the current viewport size. UInt16 imageWidth = (UInt16)Screen.currentResolution.width; UInt16 imageHeight = (UInt16)Screen.currentResolution.height; // Set image width and height. if (imageWidth != _imageWidth || imageHeight != _imageHeight) { // Begin settings batch. try { zView.BeginSettingsBatch(connection); } catch (PluginException e) { Debug.LogError(string.Format("Failed to begin settings batch for updating image resolution: {0}", e.PluginError)); return; } // Update image resolution. try { // Update the connection's image resolution settings. zView.SetSetting(connection, ZView.SettingKey.ImageWidth, imageWidth); zView.SetSetting(connection, ZView.SettingKey.ImageHeight, imageHeight); // Update the internally cached image resolution in order to check // if the image resolution has changed in subsequent frames. _imageWidth = imageWidth; _imageHeight = imageHeight; } catch (PluginException e) { Debug.LogError(string.Format("Failed to set image resolution settings: {0}", e.PluginError)); } // End settings batch. try { zView.EndSettingsBatch(connection); } catch (PluginException e) { Debug.LogError(string.Format("Failed to end settings batch for updating image resolution: {0}", e.PluginError)); } } } private Matrix4x4 FlipHandedness(Matrix4x4 matrix) { return s_flipHandednessMap * matrix * s_flipHandednessMap; } ////////////////////////////////////////////////////////////////// // Private Members ////////////////////////////////////////////////////////////////// private static readonly Matrix4x4 s_flipHandednessMap = Matrix4x4.Scale(new Vector4(1.0f, 1.0f, -1.0f)); private Camera _zCameraCamera = null; private Transform _zCameraTransform = null; private Camera _camera = null; private RenderTexture _renderTexture = null; private IntPtr _nativeTexturePtr = IntPtr.Zero; private UInt16 _imageWidth = 0; private UInt16 _imageHeight = 0; } }