티스토리 뷰

반응형

안녕하세요. Base Of Coding입니다.

이번엔, SteamVR_Behaviour_Pose.cs에 대한 코드 주석을 한 번 달아봤습니다.

틀린 부분이 있거나 수정 할 부분이 있다면 바로 댓글로 글 달아주시면 감사하겠습니다! 

VR 초보에게 도움을 부탁드립니다.

 

 

//======= Copyright (c) Valve Corporation, All rights reserved. ===============

using System;
using System.Threading;
using UnityEngine;
using UnityEngine.Events;
using Valve.VR;

namespace Valve.VR
{
    /// 
    /// This component simplifies the use of Pose actions. Adding it to a gameobject will auto set that transform's position and rotation every update to match the pose.
    /// Advanced velocity estimation is handled through a buffer of the last 30 updates.
    /// 
    public class SteamVR_Behaviour_Pose : MonoBehaviour
    {
        public SteamVR_Action_Pose poseAction = SteamVR_Input.GetAction("Pose");           // Pose라는, Action을 poseAction에 대입한다.

        [Tooltip("The device this action should apply to. Any if the action is not device specific.")]
        public SteamVR_Input_Sources inputSource;                       // 해당 스크립트가 붙어있는 물체가 어떤 부위인지를 가지고 있는 enum 클래스 변수

        [Tooltip("If not set, relative to parent")]
        public Transform origin;                            // 출발지 변수, 만약 설정하지 않았다면, 부모의 기준으로 출발지를 설정하게 된다.

        /// 현재 포즈의 상태를 확인하는데, 유효한 상태인지의 여부를 반환한다.
        public bool isValid { get { return poseAction[inputSource].poseIsValid; } }

        /// 포즈의 동작이 묶여있고, 업데이트가 가능한 지의 여부를 반환.
        public bool isActive { get { return poseAction[inputSource].active; } }                 


        /// 위치가 변환이 되거나 회전이 될 때마다 발생하는 이벤트
        public SteamVR_Behaviour_PoseEvent onTransformUpdated;

        /// 위치가 변환이 되거나, 회전값이 변경이 될 때마다 발생하는 이벤트
        public SteamVR_Behaviour_PoseEvent onTransformChanged;

        /// 기기가 연결되거나 끊어질 때마다 발생하는 이벤트
        public SteamVR_Behaviour_Pose_ConnectedChangedEvent onConnectedChanged;

        /// 기기의 트래킹 상태가 변경될 때 마다 시작하는 이벤트
        public SteamVR_Behaviour_Pose_TrackingChangedEvent onTrackingChanged;

        /// 장치의 장치번호가 변경될 때 마다 발생하는 이벤트
        public SteamVR_Behaviour_Pose_DeviceIndexChangedEvent onDeviceIndexChanged;


        /// 위치의 변환 또는 회전이 업데이트 될 때마다 발생하는 이벤트 핸들러
        public UpdateHandler onTransformUpdatedEvent;

        /// 위치가 변환이 되거나, 회전값이 변경이 될 때마다 발생하는 이벤트
        public ChangeHandler onTransformChangedEvent;

        /// 기기가 연결되거나 끊어질 때마다 발생하는 이벤트
        public DeviceConnectedChangeHandler onConnectedChangedEvent;

        /// 기기의 트래킹 상태가 변경될 때 마다 시작하는 이벤트
        public TrackingChangeHandler onTrackingChangedEvent;

        /// 장치의 장치번호가 변경될 때 마다 발생하는 이벤트
        public DeviceIndexChangedHandler onDeviceIndexChangedEvent;


        [Tooltip("Can be disabled to stop broadcasting bound device status changes")]
        public bool broadcastDeviceChanges = true;                                      // 바인딩된 장치 상태 변경을 중지하도록 비활성화 할 수 있는 bool형식 변수

        protected int deviceIndex = -1;                                                 // 장치 번호 변수

        protected SteamVR_HistoryBuffer historyBuffer = new SteamVR_HistoryBuffer(30);  // 버퍼 메모리를 30 바이트만큼 할당하여 대입한다. 


        protected virtual void Start()
        {
            if (poseAction == null)         // poseAction이 null이라면
            {
                Debug.LogError("[SteamVR] No pose action set for this component");       // pose관련 컴포넌트가 없다는 LogError문을 로그창에 띄운다.
                return;
            }

            CheckDeviceIndex();         // 장치의 번호를 체크한다.

            if (origin == null)         
                origin = this.transform.parent;         // origin이 null값이라면, 부모를 origin에 대입한다.
        }

        protected virtual void OnEnable()
        {
            SteamVR.Initialize();           // SteamVR을 초기화한다.

            if (poseAction != null)         // poseAction이 null값이 아니라면
            {
                poseAction[inputSource].onUpdate += SteamVR_Behaviour_Pose_OnUpdate;
                poseAction[inputSource].onDeviceConnectedChanged += OnDeviceConnectedChanged;
                poseAction[inputSource].onTrackingChanged += OnTrackingChanged;
                poseAction[inputSource].onChange += SteamVR_Behaviour_Pose_OnChange;                // 각각에 이벤트에, 함수들을 추가한다.
            }
        }

        protected virtual void OnDisable()
        {
            if (poseAction != null)         // poseAction이 null값이 아니라면
            {
                poseAction[inputSource].onUpdate -= SteamVR_Behaviour_Pose_OnUpdate;
                poseAction[inputSource].onDeviceConnectedChanged -= OnDeviceConnectedChanged;
                poseAction[inputSource].onTrackingChanged -= OnTrackingChanged;
                poseAction[inputSource].onChange -= SteamVR_Behaviour_Pose_OnChange;                // 각각 이벤트에 함수들을 추가했던 것을 빼준다.
            }

            historyBuffer.Clear();          // historyBuffer를 지운다.
        }

        /// 
        /// 포즈를 업데이트 하는 함수.
        /// 
        /// Pose 관련 Action 이벤트
        /// 해당 부위의 enum 클래스
        private void SteamVR_Behaviour_Pose_OnUpdate(SteamVR_Action_Pose fromAction, SteamVR_Input_Sources fromSource)
        {
            UpdateHistoryBuffer();      // HistoryBuffer를 업데이트 한다.

            UpdateTransform();          // Transform도 업데이트 한다.

            if (onTransformUpdated != null)
                onTransformUpdated.Invoke(this, inputSource);           // onTransformUpdated가 null이 아니라면, onTransformUpdated에 있는 이벤트들을 실행한다.
            if (onTransformUpdatedEvent != null)                        
                onTransformUpdatedEvent.Invoke(this, inputSource);      // onTransformUpdatedEvent도 null이 아니라면, onTransformUpdatedEvent에 있는 이벤트들을 실행한다.
        }

        /// 
        /// Transform값을 Update하는 함수
        /// 
        protected virtual void UpdateTransform()
        {
            CheckDeviceIndex();         // 디바이스 번호를 체크한다.

            if (origin != null)         // origin은 null값이 아니라면, 비어있지 않다면
            {
                transform.position = origin.transform.TransformPoint(poseAction[inputSource].localPosition);            // poseAction[inputSource].localPosition값을, 월드 공간으로부터 로컬 공간으로 변경하여, transform.position에 대입
                transform.rotation = origin.rotation * poseAction[inputSource].localRotation;                           // 시작점의 회전값과 poseAction의 localRotation값을 곱하여, transform.rotation에 대입한다.
            }
            else        // 비어 있다면?
            {
                transform.localPosition = poseAction[inputSource].localPosition;
                transform.localRotation = poseAction[inputSource].localRotation;            // 각 부위의 포즈의 로컬 회전값과 위치값을 transform.localPosition과 transform.localRotation에 각각 대입한다.
            }
        }

        /// 
        /// 포즈를 변경하는 함수
        /// 
        /// Pose 관련 Action 이벤트
        /// 해당 부위의 enum 클래스
        private void SteamVR_Behaviour_Pose_OnChange(SteamVR_Action_Pose fromAction, SteamVR_Input_Sources fromSource)
        {
            if (onTransformChanged != null)
                onTransformChanged.Invoke(this, fromSource);

            if (onTransformChangedEvent != null)
                onTransformChangedEvent.Invoke(this, fromSource);

            // Transform이 변경되는 이벤트들이 비어있지 않다면, 해당 이벤트들에 추가 된 함수들을 전부 실행시켜준다.
        }
   
        /// 
        /// 디바이스가 연결 또는 연결해제 되었을 때 실행되는 함수
        /// 
        /// 변경되는 액션
        /// 변경되는 부위
        /// 기기 연결 ? 기기 미 연결
        protected virtual void OnDeviceConnectedChanged(SteamVR_Action_Pose changedAction, SteamVR_Input_Sources changedSource, bool connected)
        {
            CheckDeviceIndex();     // 장치 번호 체크

            if (onConnectedChanged != null)
                onConnectedChanged.Invoke(this, inputSource, connected);
            if (onConnectedChangedEvent != null)
                onConnectedChangedEvent.Invoke(this, inputSource, connected);

            // 장치 연결 또는 해제될 때 실행되는 이벤트들이 비어있지 않다면, 해당 이벤트들에 추가된 함수들을 전부 실행시킨다.
        }

        /// 
        /// 기기의 트래킹 상태가 변경될 때 마다 시작하는 함수
        /// 
        /// 변경되는 액션
        /// 변경되는 부위
        /// 트래킹 상태 변경?
        protected virtual void OnTrackingChanged(SteamVR_Action_Pose changedAction, SteamVR_Input_Sources changedSource, ETrackingResult trackingChanged)
        {
            if (onTrackingChanged != null)
                onTrackingChanged.Invoke(this, inputSource, trackingChanged);
            if (onTrackingChangedEvent != null)
                onTrackingChangedEvent.Invoke(this, inputSource, trackingChanged);

            // 기기의 트래킹 상태가 변경되는 이벤트들이 비어있지 않다면, 해당 이벤트들에 추가되어 있는 함수들을 실행시킨다.
        }

        /// 
        /// 기기 번호 체크
        /// 
        protected virtual void CheckDeviceIndex()
        {
            if (poseAction[inputSource].active && poseAction[inputSource].deviceIsConnected)        // poseAction이 켜져있고, 해당 부위의 컨트롤러 또는 기기가 연결되어 있다면
            {
                int currentDeviceIndex = (int)poseAction[inputSource].trackedDeviceIndex;           // 현재 기기의 번호를 대입한다.

                if (deviceIndex != currentDeviceIndex)                  // 현재 기기의 번호가, 장치 번호와 다르다면
                {
                    deviceIndex = currentDeviceIndex;                   // 현재 기기 번호를 장치 번호에 대입해준다.

                    if (broadcastDeviceChanges)                         // 바인딩된 장치 상태 변경을 비활성화 하지 않았다면
                    {
                        this.gameObject.BroadcastMessage("SetInputSource", inputSource, SendMessageOptions.DontRequireReceiver);        // SetInputSource라는 메서드를, 자식 객체가 가지고 있는 스크립트중에 있다면, inputSource라는 값과 같이 넘긴다. SendMessageOptions.DontRequireReceiver는, 수신자가 필요없다는 뜻이다. 
                        this.gameObject.BroadcastMessage("SetDeviceIndex", deviceIndex, SendMessageOptions.DontRequireReceiver);        // SetDeviceIndex라는 메서드를, 자식 객체가 가지고 있는 스크립트중에 있다면, deviceIndex라는 값과 같이 넘긴다. SendMessageOptions.DontRequireReceiver는, 수신자가 필요없다는 뜻이다. 
                    }

                    if (onDeviceIndexChanged != null)
                        onDeviceIndexChanged.Invoke(this, inputSource, deviceIndex);
                    if (onDeviceIndexChangedEvent != null)
                        onDeviceIndexChangedEvent.Invoke(this, inputSource, deviceIndex);

                    // 디바이스 번호를 변경하는 이벤트들이 비어있지 않다면, 해당 이벤트들에 들어가있는 대리자들을 전부 실행시킨다.
                }
            }
        }

        /// 
        /// 포즈에 바인딩 된 장치의 장치번호를 반환하는 함수
        /// 
        public int GetDeviceIndex()
        {
            if (deviceIndex == -1)      // 만약에, deviceIndex가 -1이라면,
                CheckDeviceIndex();     // 장치번호를 다시 체크해서, deviceIndex를 변경한다.

            return deviceIndex;         // 그리고 변경 된 deviceIndex를 반환한다.
        }

        /// 포즈의 현재 속도를 반환하는 함수, ( 마지막 업데이트를 기준으로 한다. )
        public Vector3 GetVelocity()
        {
            return poseAction[inputSource].velocity;        // 해당 포즈의 속도를 반환한다.
        }

        /// 포즈의 현재 각에 관련된 속도를 반환하는 함수 ( 마지막 업데이트를 기준으로 한다. )
        public Vector3 GetAngularVelocity()
        {
            return poseAction[inputSource].angularVelocity;         // 해당 포즈의 각 관련 속도를 반환한다.
        }

        /// 지정된 시간에 포즈의 속도를 반환하는 함수 다음값을 예측하거나, 과거값을 반환 할 수도 있음.
        public bool GetVelocitiesAtTimeOffset(float secondsFromNow, out Vector3 velocity, out Vector3 angularVelocity)
        {
            return poseAction[inputSource].GetVelocitiesAtTimeOffset(secondsFromNow, out velocity, out angularVelocity);
        }

        /// 이전에 기록 된 값을 사용하여, 포즈의 최고 속도를 찾고 해당 속도와 각 속도를 반환하는 함수.
        public void GetEstimatedPeakVelocities(out Vector3 velocity, out Vector3 angularVelocity)
        {
            int top = historyBuffer.GetTopVelocity(10, 1);      // 제일 높은 속도를 찾아 반환한 다음, top이란 변수에 대입.

            historyBuffer.GetAverageVelocities(out velocity, out angularVelocity, 2, top);  // 이전 속도와 각의 속도, 그리고 2 frame과, top에 대입된 값, 만약 top에 값이 없다면, -1이 된다.
                                                                                            // 그 값들을 GetAverageVelocities 함수에 매개변수로 넣어, 평균 속도값을 구한다.
        }

        protected int lastFrameUpdated;                 // 마지막 프레임 값을 가지는 변수
        protected void UpdateHistoryBuffer()            // 버퍼를 새로 갱신한다.
        {
            int currentFrame = Time.frameCount;         // 현재 프레임을 대입한다.
            if (lastFrameUpdated != currentFrame)       // lastFrameUpdated가 currentFrame과 다르다면
            {
                // historyBuffer를 업데이트한다. 위치값, 회전값, 속도값, 각의 속도값을.
                historyBuffer.Update(poseAction[inputSource].localPosition, poseAction[inputSource].localRotation, poseAction[inputSource].velocity, poseAction[inputSource].angularVelocity);

                // lastFrameUpdated에 현재 프레임을 대입.
                lastFrameUpdated = currentFrame;
            }
        }

        /// 
        /// 해당하는 기기의 이름을 반환한다.
        /// 
        /// 
        /// 
        /// VRInputString_Hand - Which hand the origin is in. E.g. "Left Hand"
        /// VRInputString_ControllerType - What kind of controller the user has in that hand.E.g. "Vive Controller"
        /// VRInputString_InputSource - What part of that controller is the origin. E.g. "Trackpad"
        /// VRInputString_All - All of the above. E.g. "Left Hand Vive Controller Trackpad"
        /// 
        /// 
        public string GetLocalizedName(params EVRInputStringBits[] localizedParts)
        {
            if (poseAction != null)
                return poseAction.GetLocalizedOriginPart(inputSource, localizedParts);
            return null;
        }

        public delegate void ActiveChangeHandler(SteamVR_Behaviour_Pose fromAction, SteamVR_Input_Sources fromSource, bool active);
        public delegate void ChangeHandler(SteamVR_Behaviour_Pose fromAction, SteamVR_Input_Sources fromSource);
        public delegate void UpdateHandler(SteamVR_Behaviour_Pose fromAction, SteamVR_Input_Sources fromSource);
        public delegate void TrackingChangeHandler(SteamVR_Behaviour_Pose fromAction, SteamVR_Input_Sources fromSource, ETrackingResult trackingState);
        public delegate void ValidPoseChangeHandler(SteamVR_Behaviour_Pose fromAction, SteamVR_Input_Sources fromSource, bool validPose);
        public delegate void DeviceConnectedChangeHandler(SteamVR_Behaviour_Pose fromAction, SteamVR_Input_Sources fromSource, bool deviceConnected);
        public delegate void DeviceIndexChangedHandler(SteamVR_Behaviour_Pose fromAction, SteamVR_Input_Sources fromSource, int newDeviceIndex);
    }
}

 

지금까지 Base Of Coding이였습니다.

감사합니다!

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함