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.
		
		
		
		
		
			
		
			
				
	
	
		
			220 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			220 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
//======= Copyright (c) Valve Corporation, All rights reserved. ===============
 | 
						|
//
 | 
						|
// Purpose: Provides access to video feed and poses of tracked cameras.
 | 
						|
//
 | 
						|
// Usage:
 | 
						|
//			var source = SteamVR_TrackedCamera.Distorted();
 | 
						|
//			var source = SteamVR_TrackedCamera.Undistorted();
 | 
						|
// or
 | 
						|
//			var undistorted = true; // or false
 | 
						|
//			var source = SteamVR_TrackedCamera.Source(undistorted);
 | 
						|
//
 | 
						|
// - Distorted feeds are the decoded images from the camera.
 | 
						|
// - Undistorted feeds correct for the camera lens distortion (a.k.a. fisheye)
 | 
						|
//   to make straight lines straight.
 | 
						|
//
 | 
						|
// VideoStreamTexture objects must be symmetrically Acquired and Released to
 | 
						|
// ensure the video stream is activated, and shutdown properly once there are
 | 
						|
// no more consumers.  You only need to Acquire once when starting to use a
 | 
						|
// stream, and Release when you are done using it (as opposed to every frame).
 | 
						|
//
 | 
						|
//=============================================================================
 | 
						|
 | 
						|
using UnityEngine;
 | 
						|
using Valve.VR;
 | 
						|
 | 
						|
namespace Valve.VR
 | 
						|
{
 | 
						|
    public class SteamVR_TrackedCamera
 | 
						|
    {
 | 
						|
        public class VideoStreamTexture
 | 
						|
        {
 | 
						|
            public VideoStreamTexture(uint deviceIndex, bool undistorted)
 | 
						|
            {
 | 
						|
                this.undistorted = undistorted;
 | 
						|
                videostream = Stream(deviceIndex);
 | 
						|
            }
 | 
						|
            public bool undistorted { get; private set; }
 | 
						|
            public uint deviceIndex { get { return videostream.deviceIndex; } }
 | 
						|
            public bool hasCamera { get { return videostream.hasCamera; } }
 | 
						|
            public bool hasTracking { get { Update(); return header.trackedDevicePose.bPoseIsValid; } }
 | 
						|
            public uint frameId { get { Update(); return header.nFrameSequence; } }
 | 
						|
            public VRTextureBounds_t frameBounds { get; private set; }
 | 
						|
            public EVRTrackedCameraFrameType frameType { get { return undistorted ? EVRTrackedCameraFrameType.Undistorted : EVRTrackedCameraFrameType.Distorted; } }
 | 
						|
 | 
						|
            Texture2D _texture;
 | 
						|
            public Texture2D texture { get { Update(); return _texture; } }
 | 
						|
 | 
						|
            public SteamVR_Utils.RigidTransform transform { get { Update(); return new SteamVR_Utils.RigidTransform(header.trackedDevicePose.mDeviceToAbsoluteTracking); } }
 | 
						|
            public Vector3 velocity { get { Update(); var pose = header.trackedDevicePose; return new Vector3(pose.vVelocity.v0, pose.vVelocity.v1, -pose.vVelocity.v2); } }
 | 
						|
            public Vector3 angularVelocity { get { Update(); var pose = header.trackedDevicePose; return new Vector3(-pose.vAngularVelocity.v0, -pose.vAngularVelocity.v1, pose.vAngularVelocity.v2); } }
 | 
						|
 | 
						|
            public TrackedDevicePose_t GetPose() { Update(); return header.trackedDevicePose; }
 | 
						|
 | 
						|
            public ulong Acquire()
 | 
						|
            {
 | 
						|
                return videostream.Acquire();
 | 
						|
            }
 | 
						|
            public ulong Release()
 | 
						|
            {
 | 
						|
                var result = videostream.Release();
 | 
						|
 | 
						|
                if (videostream.handle == 0)
 | 
						|
                {
 | 
						|
                    Object.Destroy(_texture);
 | 
						|
                    _texture = null;
 | 
						|
                }
 | 
						|
 | 
						|
                return result;
 | 
						|
            }
 | 
						|
 | 
						|
            int prevFrameCount = -1;
 | 
						|
            void Update()
 | 
						|
            {
 | 
						|
                if (Time.frameCount == prevFrameCount)
 | 
						|
                    return;
 | 
						|
 | 
						|
                prevFrameCount = Time.frameCount;
 | 
						|
 | 
						|
                if (videostream.handle == 0)
 | 
						|
                    return;
 | 
						|
 | 
						|
                var vr = SteamVR.instance;
 | 
						|
                if (vr == null)
 | 
						|
                    return;
 | 
						|
 | 
						|
                var trackedCamera = OpenVR.TrackedCamera;
 | 
						|
                if (trackedCamera == null)
 | 
						|
                    return;
 | 
						|
 | 
						|
                var nativeTex = System.IntPtr.Zero;
 | 
						|
                var deviceTexture = (_texture != null) ? _texture : new Texture2D(2, 2);
 | 
						|
                var headerSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(header.GetType());
 | 
						|
 | 
						|
                if (vr.textureType == ETextureType.OpenGL)
 | 
						|
                {
 | 
						|
                    if (glTextureId != 0)
 | 
						|
                        trackedCamera.ReleaseVideoStreamTextureGL(videostream.handle, glTextureId);
 | 
						|
 | 
						|
                    if (trackedCamera.GetVideoStreamTextureGL(videostream.handle, frameType, ref glTextureId, ref header, headerSize) != EVRTrackedCameraError.None)
 | 
						|
                        return;
 | 
						|
 | 
						|
                    nativeTex = (System.IntPtr)glTextureId;
 | 
						|
                }
 | 
						|
                else if (vr.textureType == ETextureType.DirectX)
 | 
						|
                {
 | 
						|
                    if (trackedCamera.GetVideoStreamTextureD3D11(videostream.handle, frameType, deviceTexture.GetNativeTexturePtr(), ref nativeTex, ref header, headerSize) != EVRTrackedCameraError.None)
 | 
						|
                        return;
 | 
						|
                }
 | 
						|
 | 
						|
                if (_texture == null)
 | 
						|
                {
 | 
						|
                    _texture = Texture2D.CreateExternalTexture((int)header.nWidth, (int)header.nHeight, TextureFormat.RGBA32, false, false, nativeTex);
 | 
						|
 | 
						|
                    uint width = 0, height = 0;
 | 
						|
                    var frameBounds = new VRTextureBounds_t();
 | 
						|
                    if (trackedCamera.GetVideoStreamTextureSize(deviceIndex, frameType, ref frameBounds, ref width, ref height) == EVRTrackedCameraError.None)
 | 
						|
                    {
 | 
						|
                        // Account for textures being upside-down in Unity.
 | 
						|
                        frameBounds.vMin = 1.0f - frameBounds.vMin;
 | 
						|
                        frameBounds.vMax = 1.0f - frameBounds.vMax;
 | 
						|
                        this.frameBounds = frameBounds;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    _texture.UpdateExternalTexture(nativeTex);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            uint glTextureId;
 | 
						|
            VideoStream videostream;
 | 
						|
            CameraVideoStreamFrameHeader_t header;
 | 
						|
        }
 | 
						|
 | 
						|
        #region Top level accessors.
 | 
						|
 | 
						|
        public static VideoStreamTexture Distorted(int deviceIndex = (int)OpenVR.k_unTrackedDeviceIndex_Hmd)
 | 
						|
        {
 | 
						|
            if (distorted == null)
 | 
						|
                distorted = new VideoStreamTexture[OpenVR.k_unMaxTrackedDeviceCount];
 | 
						|
            if (distorted[deviceIndex] == null)
 | 
						|
                distorted[deviceIndex] = new VideoStreamTexture((uint)deviceIndex, false);
 | 
						|
            return distorted[deviceIndex];
 | 
						|
        }
 | 
						|
 | 
						|
        public static VideoStreamTexture Undistorted(int deviceIndex = (int)OpenVR.k_unTrackedDeviceIndex_Hmd)
 | 
						|
        {
 | 
						|
            if (undistorted == null)
 | 
						|
                undistorted = new VideoStreamTexture[OpenVR.k_unMaxTrackedDeviceCount];
 | 
						|
            if (undistorted[deviceIndex] == null)
 | 
						|
                undistorted[deviceIndex] = new VideoStreamTexture((uint)deviceIndex, true);
 | 
						|
            return undistorted[deviceIndex];
 | 
						|
        }
 | 
						|
 | 
						|
        public static VideoStreamTexture Source(bool undistorted, int deviceIndex = (int)OpenVR.k_unTrackedDeviceIndex_Hmd)
 | 
						|
        {
 | 
						|
            return undistorted ? Undistorted(deviceIndex) : Distorted(deviceIndex);
 | 
						|
        }
 | 
						|
 | 
						|
        private static VideoStreamTexture[] distorted, undistorted;
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Internal class to manage lifetime of video streams (per device).
 | 
						|
 | 
						|
        class VideoStream
 | 
						|
        {
 | 
						|
            public VideoStream(uint deviceIndex)
 | 
						|
            {
 | 
						|
                this.deviceIndex = deviceIndex;
 | 
						|
                var trackedCamera = OpenVR.TrackedCamera;
 | 
						|
                if (trackedCamera != null)
 | 
						|
                    trackedCamera.HasCamera(deviceIndex, ref _hasCamera);
 | 
						|
            }
 | 
						|
            public uint deviceIndex { get; private set; }
 | 
						|
 | 
						|
            ulong _handle;
 | 
						|
            public ulong handle { get { return _handle; } }
 | 
						|
 | 
						|
            bool _hasCamera;
 | 
						|
            public bool hasCamera { get { return _hasCamera; } }
 | 
						|
 | 
						|
            ulong refCount;
 | 
						|
            public ulong Acquire()
 | 
						|
            {
 | 
						|
                if (_handle == 0 && hasCamera)
 | 
						|
                {
 | 
						|
                    var trackedCamera = OpenVR.TrackedCamera;
 | 
						|
                    if (trackedCamera != null)
 | 
						|
                        trackedCamera.AcquireVideoStreamingService(deviceIndex, ref _handle);
 | 
						|
                }
 | 
						|
                return ++refCount;
 | 
						|
            }
 | 
						|
            public ulong Release()
 | 
						|
            {
 | 
						|
                if (refCount > 0 && --refCount == 0 && _handle != 0)
 | 
						|
                {
 | 
						|
                    var trackedCamera = OpenVR.TrackedCamera;
 | 
						|
                    if (trackedCamera != null)
 | 
						|
                        trackedCamera.ReleaseVideoStreamingService(_handle);
 | 
						|
                    _handle = 0;
 | 
						|
                }
 | 
						|
                return refCount;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        static VideoStream Stream(uint deviceIndex)
 | 
						|
        {
 | 
						|
            if (videostreams == null)
 | 
						|
                videostreams = new VideoStream[OpenVR.k_unMaxTrackedDeviceCount];
 | 
						|
            if (videostreams[deviceIndex] == null)
 | 
						|
                videostreams[deviceIndex] = new VideoStream(deviceIndex);
 | 
						|
            return videostreams[deviceIndex];
 | 
						|
        }
 | 
						|
 | 
						|
        static VideoStream[] videostreams;
 | 
						|
 | 
						|
        #endregion
 | 
						|
    }
 | 
						|
} |