You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			433 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			433 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
//======= 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;
 | 
						|
 | 
						|
namespace Valve.VR
 | 
						|
{
 | 
						|
    public class SteamVR_ExternalCamera : MonoBehaviour
 | 
						|
    {
 | 
						|
        private SteamVR_Action_Pose cameraPose = null;
 | 
						|
        private SteamVR_Input_Sources cameraInputSource = SteamVR_Input_Sources.Camera;
 | 
						|
 | 
						|
        [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;
 | 
						|
        }
 | 
						|
 | 
						|
        [Space()]
 | 
						|
        public Config config;
 | 
						|
        public string configPath;
 | 
						|
 | 
						|
        [Tooltip("This will automatically activate the action set the specified pose belongs to. And deactivate it when this component is disabled.")]
 | 
						|
        public bool autoEnableDisableActionSet = true;
 | 
						|
 | 
						|
        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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        System.IO.FileSystemWatcher watcher;
 | 
						|
#else
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
        public void SetupPose(SteamVR_Action_Pose newCameraPose, SteamVR_Input_Sources newCameraSource)
 | 
						|
        {
 | 
						|
            cameraPose = newCameraPose;
 | 
						|
            cameraInputSource = newCameraSource;
 | 
						|
 | 
						|
            AutoEnableActionSet();
 | 
						|
 | 
						|
            SteamVR_Behaviour_Pose poseBehaviour = this.gameObject.AddComponent<SteamVR_Behaviour_Pose>();
 | 
						|
            poseBehaviour.poseAction = newCameraPose;
 | 
						|
            poseBehaviour.inputSource = newCameraSource;
 | 
						|
        }
 | 
						|
 | 
						|
        public void SetupDeviceIndex(int deviceIndex)
 | 
						|
        {
 | 
						|
            SteamVR_TrackedObject trackedObject = this.gameObject.AddComponent<SteamVR_TrackedObject>();
 | 
						|
            trackedObject.SetDeviceIndex(deviceIndex);
 | 
						|
        }
 | 
						|
 | 
						|
        void OnChanged(object source, System.IO.FileSystemEventArgs e)
 | 
						|
        {
 | 
						|
            ReadConfig();
 | 
						|
        }
 | 
						|
 | 
						|
        Camera cam;
 | 
						|
        Transform target;
 | 
						|
        GameObject clipQuad;
 | 
						|
        Material clipMaterial;
 | 
						|
 | 
						|
        protected SteamVR_ActionSet activatedActionSet;
 | 
						|
        protected SteamVR_Input_Sources activatedInputSource;
 | 
						|
        public void AttachToCamera(SteamVR_Camera steamVR_Camera)
 | 
						|
        {
 | 
						|
            Camera vrcam;
 | 
						|
            if (steamVR_Camera == null)
 | 
						|
            {
 | 
						|
                vrcam = Camera.main;
 | 
						|
 | 
						|
                if (target == vrcam.transform)
 | 
						|
                    return;
 | 
						|
                target = vrcam.transform;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                vrcam = steamVR_Camera.camera;
 | 
						|
 | 
						|
                if (target == steamVR_Camera.head)
 | 
						|
                    return;
 | 
						|
                target = steamVR_Camera.head;
 | 
						|
            }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
            var root = transform.parent;
 | 
						|
            var origin = target.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
 | 
						|
            cam.rect = new Rect(0, 0, 1, 1); //fix order of operations issue
 | 
						|
 | 
						|
            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>();
 | 
						|
            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;
 | 
						|
            }
 | 
						|
 | 
						|
            AutoEnableActionSet();
 | 
						|
        }
 | 
						|
 | 
						|
        private void AutoEnableActionSet()
 | 
						|
        {
 | 
						|
            if (autoEnableDisableActionSet)
 | 
						|
            {
 | 
						|
                if (cameraPose != null)
 | 
						|
                {
 | 
						|
                    if (cameraPose.actionSet.IsActive(cameraInputSource) == false)
 | 
						|
                    {
 | 
						|
                        activatedActionSet = cameraPose.actionSet; //automatically activate the actionset if it isn't active already. (will deactivate on component disable)
 | 
						|
                        activatedInputSource = cameraInputSource;
 | 
						|
                        cameraPose.actionSet.Activate(cameraInputSource);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void OnDisable()
 | 
						|
        {
 | 
						|
            if (autoEnableDisableActionSet)
 | 
						|
            {
 | 
						|
                if (activatedActionSet != null) //deactivate the action set we activated for this camera
 | 
						|
                {
 | 
						|
                    activatedActionSet.Deactivate(activatedInputSource);
 | 
						|
                    activatedActionSet = null;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
 | 
						|
            // 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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
} |