|
|
- //======= Copyright (c) Valve Corporation, All rights reserved. ===============
- //
- // Purpose: Used to render an external camera of vr player (split front/back).
- //
- //=============================================================================
-
- using UnityEngine;
- using UnityEngine.Rendering;
- using Valve.VR;
-
- public class SteamVR_ExternalCamera : MonoBehaviour
- {
- [System.Serializable]
- public struct Config
- {
- public float x, y, z;
- public float rx, ry, rz;
- public float fov;
- public float near, far;
- public float sceneResolutionScale;
- public float frameSkip;
- public float nearOffset, farOffset;
- public float hmdOffset;
- public float r, g, b, a; // chroma key override
- public bool disableStandardAssets;
- }
-
- public Config config;
- public string configPath;
-
- public void ReadConfig()
- {
- try
- {
- var mCam = new HmdMatrix34_t();
- var readCamMatrix = false;
-
- object c = config; // box
- var lines = System.IO.File.ReadAllLines(configPath);
- foreach (var line in lines)
- {
- var split = line.Split('=');
- if (split.Length == 2)
- {
- var key = split[0];
- if (key == "m")
- {
- var values = split[1].Split(',');
- if (values.Length == 12)
- {
- mCam.m0 = float.Parse(values[0]);
- mCam.m1 = float.Parse(values[1]);
- mCam.m2 = float.Parse(values[2]);
- mCam.m3 = float.Parse(values[3]);
- mCam.m4 = float.Parse(values[4]);
- mCam.m5 = float.Parse(values[5]);
- mCam.m6 = float.Parse(values[6]);
- mCam.m7 = float.Parse(values[7]);
- mCam.m8 = float.Parse(values[8]);
- mCam.m9 = float.Parse(values[9]);
- mCam.m10 = float.Parse(values[10]);
- mCam.m11 = float.Parse(values[11]);
- readCamMatrix = true;
- }
- }
- #if !UNITY_METRO
- else if (key == "disableStandardAssets")
- {
- var field = c.GetType().GetField(key);
- if (field != null)
- field.SetValue(c, bool.Parse(split[1]));
- }
- else
- {
- var field = c.GetType().GetField(key);
- if (field != null)
- field.SetValue(c, float.Parse(split[1]));
- }
- #endif
- }
- }
- config = (Config)c; //unbox
-
- // Convert calibrated camera matrix settings.
- if (readCamMatrix)
- {
- var t = new SteamVR_Utils.RigidTransform(mCam);
- config.x = t.pos.x;
- config.y = t.pos.y;
- config.z = t.pos.z;
- var angles = t.rot.eulerAngles;
- config.rx = angles.x;
- config.ry = angles.y;
- config.rz = angles.z;
- }
- }
- catch { }
-
- // Clear target so AttachToCamera gets called to pick up any changes.
- target = null;
- #if !UNITY_METRO
- // Listen for changes.
- if (watcher == null)
- {
- var fi = new System.IO.FileInfo(configPath);
- watcher = new System.IO.FileSystemWatcher(fi.DirectoryName, fi.Name);
- watcher.NotifyFilter = System.IO.NotifyFilters.LastWrite;
- watcher.Changed += new System.IO.FileSystemEventHandler(OnChanged);
- watcher.EnableRaisingEvents = true;
- }
- }
-
- void OnChanged(object source, System.IO.FileSystemEventArgs e)
- {
- ReadConfig();
- }
-
- System.IO.FileSystemWatcher watcher;
- #else
- }
- #endif
- Camera cam;
- Transform target;
- GameObject clipQuad;
- Material clipMaterial;
-
- public void AttachToCamera(SteamVR_Camera vrcam)
- {
- if (target == vrcam.head)
- return;
-
- target = vrcam.head;
-
- var root = transform.parent;
- var origin = vrcam.head.parent;
- root.parent = origin;
- root.localPosition = Vector3.zero;
- root.localRotation = Quaternion.identity;
- root.localScale = Vector3.one;
-
- // Make a copy of the eye camera to pick up any camera fx.
- vrcam.enabled = false;
- var go = Instantiate(vrcam.gameObject);
- vrcam.enabled = true;
- go.name = "camera";
-
- DestroyImmediate(go.GetComponent<SteamVR_Camera>());
- DestroyImmediate(go.GetComponent<SteamVR_Fade>());
-
- cam = go.GetComponent<Camera>();
- cam.stereoTargetEye = StereoTargetEyeMask.None;
- cam.fieldOfView = config.fov;
- cam.useOcclusionCulling = false;
- cam.enabled = false; // manually rendered
-
- colorMat = new Material(Shader.Find("Custom/SteamVR_ColorOut"));
- alphaMat = new Material(Shader.Find("Custom/SteamVR_AlphaOut"));
- clipMaterial = new Material(Shader.Find("Custom/SteamVR_ClearAll"));
-
- var offset = go.transform;
- offset.parent = transform;
- offset.localPosition = new Vector3(config.x, config.y, config.z);
- offset.localRotation = Quaternion.Euler(config.rx, config.ry, config.rz);
- offset.localScale = Vector3.one;
-
- // Strip children of cloned object (AudioListener in particular).
- while (offset.childCount > 0)
- DestroyImmediate(offset.GetChild(0).gameObject);
-
- // Setup clipping quad (using camera clip causes problems with shadows).
- clipQuad = GameObject.CreatePrimitive(PrimitiveType.Quad);
- clipQuad.name = "ClipQuad";
- DestroyImmediate(clipQuad.GetComponent<MeshCollider>());
-
- var clipRenderer = clipQuad.GetComponent<MeshRenderer>();
- clipRenderer.material = clipMaterial;
- clipRenderer.shadowCastingMode = ShadowCastingMode.Off;
- clipRenderer.receiveShadows = false;
- clipRenderer.lightProbeUsage = LightProbeUsage.Off;
- clipRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off;
-
- var clipTransform = clipQuad.transform;
- clipTransform.parent = offset;
- clipTransform.localScale = new Vector3(1000.0f, 1000.0f, 1.0f);
- clipTransform.localRotation = Quaternion.identity;
-
- clipQuad.SetActive(false);
- }
-
- public float GetTargetDistance()
- {
- if (target == null)
- return config.near + 0.01f;
-
- var offset = cam.transform;
- var forward = new Vector3(offset.forward.x, 0.0f, offset.forward.z).normalized;
- var targetPos = target.position + new Vector3(target.forward.x, 0.0f, target.forward.z).normalized * config.hmdOffset;
-
- var distance = -(new Plane(forward, targetPos)).GetDistanceToPoint(offset.position);
- return Mathf.Clamp(distance, config.near + 0.01f, config.far - 0.01f);
- }
-
- Material colorMat, alphaMat;
-
- public void RenderNear()
- {
- var w = Screen.width / 2;
- var h = Screen.height / 2;
-
- if (cam.targetTexture == null || cam.targetTexture.width != w || cam.targetTexture.height != h)
- {
- var tex = new RenderTexture(w, h, 24, RenderTextureFormat.ARGB32);
- tex.antiAliasing = QualitySettings.antiAliasing == 0 ? 1 : QualitySettings.antiAliasing;
- cam.targetTexture = tex;
- }
-
- cam.nearClipPlane = config.near;
- cam.farClipPlane = config.far;
-
- var clearFlags = cam.clearFlags;
- var backgroundColor = cam.backgroundColor;
-
- cam.clearFlags = CameraClearFlags.Color;
- cam.backgroundColor = Color.clear;
-
- clipMaterial.color = new Color(config.r, config.g, config.b, config.a);
-
- float dist = Mathf.Clamp(GetTargetDistance() + config.nearOffset, config.near, config.far);
- var clipParent = clipQuad.transform.parent;
- clipQuad.transform.position = clipParent.position + clipParent.forward * dist;
-
- MonoBehaviour[] behaviours = null;
- bool[] wasEnabled = null;
- if (config.disableStandardAssets)
- {
- behaviours = cam.gameObject.GetComponents<MonoBehaviour>();
- wasEnabled = new bool[behaviours.Length];
- for (int i = 0; i < behaviours.Length; i++)
- {
- var behaviour = behaviours[i];
- if (behaviour.enabled && behaviour.GetType().ToString().StartsWith("UnityStandardAssets."))
- {
- behaviour.enabled = false;
- wasEnabled[i] = true;
- }
- }
- }
-
- clipQuad.SetActive(true);
-
- cam.Render();
-
- Graphics.DrawTexture(new Rect(0, 0, w, h), cam.targetTexture, colorMat);
-
- // Re-render scene with post-processing fx disabled (if necessary) since they override alpha.
- var pp = cam.gameObject.GetComponent("PostProcessingBehaviour") as MonoBehaviour;
- if ((pp != null) && pp.enabled)
- {
- pp.enabled = false;
- cam.Render();
- pp.enabled = true;
- }
-
- Graphics.DrawTexture(new Rect(w, 0, w, h), cam.targetTexture, alphaMat);
-
- // Restore settings.
- clipQuad.SetActive(false);
-
- if (behaviours != null)
- {
- for (int i = 0; i < behaviours.Length; i++)
- {
- if (wasEnabled[i])
- {
- behaviours[i].enabled = true;
- }
- }
- }
-
- cam.clearFlags = clearFlags;
- cam.backgroundColor = backgroundColor;
- }
-
- public void RenderFar()
- {
- cam.nearClipPlane = config.near;
- cam.farClipPlane = config.far;
- cam.Render();
-
- var w = Screen.width / 2;
- var h = Screen.height / 2;
- Graphics.DrawTexture(new Rect(0, h, w, h), cam.targetTexture, colorMat);
- }
-
- void OnGUI()
- {
- // Necessary for Graphics.DrawTexture to work even though we don't do anything here.
- }
-
- Camera[] cameras;
- Rect[] cameraRects;
- float sceneResolutionScale;
-
- void OnEnable()
- {
- // Move game view cameras to lower-right quadrant.
- cameras = FindObjectsOfType<Camera>() as Camera[];
- if (cameras != null)
- {
- var numCameras = cameras.Length;
- cameraRects = new Rect[numCameras];
- for (int i = 0; i < numCameras; i++)
- {
- var cam = cameras[i];
- cameraRects[i] = cam.rect;
-
- if (cam == this.cam)
- continue;
-
- if (cam.targetTexture != null)
- continue;
-
- if (cam.GetComponent<SteamVR_Camera>() != null)
- continue;
-
- cam.rect = new Rect(0.5f, 0.0f, 0.5f, 0.5f);
- }
- }
-
- if (config.sceneResolutionScale > 0.0f)
- {
- sceneResolutionScale = SteamVR_Camera.sceneResolutionScale;
- SteamVR_Camera.sceneResolutionScale = config.sceneResolutionScale;
- }
- }
-
- void OnDisable()
- {
- // Restore game view cameras.
- if (cameras != null)
- {
- var numCameras = cameras.Length;
- for (int i = 0; i < numCameras; i++)
- {
- var cam = cameras[i];
- if (cam != null)
- cam.rect = cameraRects[i];
- }
- cameras = null;
- cameraRects = null;
- }
-
- if (config.sceneResolutionScale > 0.0f)
- {
- SteamVR_Camera.sceneResolutionScale = sceneResolutionScale;
- }
- }
- }
-
|