FirstVR 제스처 식별 통합 방법

우선 여기에서는 FirstVR의 SDK를 수중에 다운로드하고 있어, 조금은 만진 적이 있는 것으로 먼저 이야기를 시작합니다.

아래에서 SDK에 포함된 OutputViewer 장면에 제스처 식별을 들여다 보면서 설명을 해 나갑니다. 이 장면입니다.



통합 절차는 다음 5단계가 필요합니다.

1, 제스처 식별자를 유지하기위한 게임 객체를 만듭니다.
2, CalibTestCtrl.cs를 1로 만든 게임 객체에 연결
3, CalibTestCtrl.cs가 필요없는 부분을 주석 처리
4, 제스처 등록과 관련된 버튼 3개 만들기
5, 버튼과 제스처 등록과 관련된 함수 연결

우선 1과 2에 관해서는 적당히 빈 오브젝트를 작성해 CalibTestCtrl.cs를 첨부하면 괜찮습니다.
문제는 여기에서입니다. CalibTestCtrl.cs는 CalibrationSample 장면 특정 스크립트이므로 다음의 필요가 없는 부분은 주석 처리해야 합니다. (뭐 사실은 전부 제일부터 쓰면 좋은 이야기입니다만 일단 이 기사에서는 움직이는 것을 우선 최우선으로 합니다.다른 기사에서 CalibTestCtrl을 사용하지 않는 방법도 쓸까라고 생각하고 있습니다.)

이미지와 텍스트 부분을 주석 처리하면 다음과 같은 느낌이 듭니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using FVRlib;
/// <summary>
/// This example shows how to create, calibrate and test a custom gesture.
/// </summary>
public class CalibTestCtrl : MonoBehaviour {

    // FVR 
    FVRConnection fvr;
    FVRGesture gesture;

    //Control variables
    int samplesPerSecond = 0;
    int roundLength = 0;
    int tCalibRounds = 0;
    int ntCalibRounds = 0;

    // Texts
    /*public Text samplesPerSecondTxt;
    public Text roundLengthTxt;
    public Text tCalibRoundsTxt;
    public Text ntCalibRoundsTxt;*/

    // Images
    /*public Image targetImg;
    public Image nonTargetImg;
    public Image testImg;*/

    //Buttons
    public Button targetBtn;
    public Button nonTargetBtn;
    public Button resetBtn;
    public Button[] varBtns;

    void Start () {
        /// When using the FVRContainer prefab, the FVRConnection won't be destroyed on load allowing you to keep your calibrated gestures and centering data.
        /// Since the FVRConnection comes from a previous scene, you can't drag and drop it into a public variable when you are making the scene. 
        /// So when the new scene gets loaded you will need to find the FVRConnection instance in order to use it. 
        fvr = FindObjectOfType (typeof(FVRConnection)) as FVRConnection;

        // Create a new custom gesture
        gesture = fvr.gestureManager.RegisterCustomGesture ("gestureName");

        // Display the default settings
        samplesPerSecond = fvr.gestureManager.calibrationSamplesPerSecond;
        roundLength = (int)fvr.gestureManager.calibrationRoundLength;
        //UpdateTexts ();

        // Button control
        targetBtn.interactable = false;
    }   

    void Update () {
        /// Custom gestures like all other FVR gestures, have a triggered and a held flag. which can be used for events.
        /// In this example, to test the gesture, we simply check if the gesture is being held and change the color of an image accordingly
        if (gesture.held) {
            //testImg.color = Color.green;
        } else {
            //testImg.color = Color.white;
        }
    }

    /// <summary>
    /// You can change the amount of samples that are to be taken every second of the calibration round, and fed into the svm.
    /// This value should always be higher than 1 and is limited by processing speeds.
    /// Recomended values are 10~20
    /// </summary>
    public void ChangeSPS(int dir){
        samplesPerSecond += 1 * dir;
        samplesPerSecond = samplesPerSecond < 1 ? 1 : samplesPerSecond;
        fvr.gestureManager.calibrationSamplesPerSecond = samplesPerSecond;
        //UpdateTexts ();
    }
    /// <summary>
    /// You can change the length of the calibration round.
    /// This length should always be higher than 0 and making it too long might affect the results in a negative way.
    /// Recomended values are 1~3
    /// </summary>
    public void ChangeRL(int dir){      
        roundLength += 1 * dir;
        roundLength = roundLength < 1 ? 1 : roundLength;
        fvr.gestureManager.calibrationRoundLength = (float)roundLength;
        //UpdateTexts ();
    }

    public void SetTargetPress(){
        StartCoroutine (Calibrate (true));
    }

    public void SetNonTargetPress(){
        StartCoroutine (Calibrate (false));
    }

    // Reset the calibration data and start all over again
    public void ResetCalibrationPress(){
        fvr.gestureManager.ResetPatternData (gesture);
        tCalibRounds = 0;
        ntCalibRounds = 0;
        //UpdateTexts ();
        targetBtn.interactable = false;
        nonTargetBtn.GetComponentInChildren<Text> ().text = "Set\nDummy";
        foreach (Button b in varBtns) {
            b.interactable = true;
        }
    }

    // Updates the display texts
    /*void UpdateTexts(){
        tCalibRoundsTxt.text = tCalibRounds.ToString ();
        ntCalibRoundsTxt.text = ntCalibRounds.ToString ();
        samplesPerSecondTxt.text = samplesPerSecond.ToString ();
        roundLengthTxt.text = roundLength.ToString ();
    }*/

    /// <summary>
    /// Calibrate the gesture with target or non-target values.
    /// Calibration requires time, and it's best to let the user know what's going on, so this process is best done in a coroutine.
    /// </summary>
    IEnumerator Calibrate(bool target){
        if (target) {
            // Setting target values
            fvr.gestureManager.SetTargetData (gesture);
            tCalibRounds++;
        } else {
            // Setting non-target values
            fvr.gestureManager.SetNonTargetData (gesture);
            /// The first time we set a target or non-target value, the round length and samples per second are ignored and the SVM takes only one value with dummy data then
            /// the dummy data is replaced with real data. 
            /// After the first round the FVRGesture.calibrated flag is set to true and you are ready to start calibrating with real data
            if (gesture.calibrated) {
                ntCalibRounds++;
            }else{
                nonTargetBtn.GetComponentInChildren<Text> ().text = "Set\nNonTarget";
                foreach (Button b in varBtns) {
                    b.interactable = false;
                }
            }
        }
        // We dont wan't multiple coroutines taking the same data so it's good to block the user from starting a new one before this round is done
        targetBtn.interactable = false;
        nonTargetBtn.interactable = false;
        resetBtn.interactable = false;
        float t = 0;
        while (gesture.registering) {
            /// While the target or non-target data is being set, the FVRGesture.registering flag will be set to true.
            /// A count down or a image fill loading bar is a good way to let the user know your app is doing something.
            /// Once the porcess is done, the FVRGesture.registering flag will be set to false, and we will exit this while loop.
            t += Time.deltaTime;
            /*if(target)
                targetImg.fillAmount = t / (float)roundLength;
            else
                nonTargetImg.fillAmount = t / (float)roundLength;*/
            yield return null;
        }
        /*UpdateTexts ();
        targetImg.fillAmount = 0;
        nonTargetImg.fillAmount =0;*/
        // After the process is done you can enable whatever buttons you need to proceed with the calibration or move on with your app.
        targetBtn.interactable = true;
        nonTargetBtn.interactable = true;
        resetBtn.interactable = true;
    }
}


그런 다음 장면 뷰로 돌아가서 1에서 만든 게임 객체를 선택하여 CalibTestCtrl 부분을 봅니다. (여기서 빨간색 테두리 부분이 아래 이미지와 다른 경우는 코멘트 아웃을 잊어 버리거나 코멘트 아웃 한 후 파일을 저장하는 것을 잊어 버리므로주의하십시오.)

이 3개의 버튼에 이번은 버튼을 만들어 연결합니다.

· 타겟 제스처를 등록하는 버튼
· 타겟이 아닌 제스처를 등록하는 버튼
· 식별기를 재설정하는 버튼

그런 다음 각 버튼을 클릭하여 클릭하면 호출되는 함수도 마찬가지로 연결됩니다.

Target 제스처 등록 버튼 - SetTargetPress 함수
NonTarget 제스처 등록 - SetNonTargetPress 함수
Reset 버튼 - ResetCalibrationPress 함수

버튼과 함수의 연결은 다음과 같이 합니다.

우선 플러스 버튼을 누르고



1단계에서 만든 게임 객체를 이미지 부분으로 드래그 앤 드롭하고,



함수를 선택합니다.



이것을 Target 제스처의 등록 버튼, NonTargetGesture의 등록 버튼, Reset 버튼에 대해서 실시하는 것으로 제스처의 식별이 가능하게 됩니다.
그리고 CalibTestCtrl.cs의 gesture 변수의 속성인 held가 true인지 false인지에 따라 제스처를 결정할 수 있습니다.

이상으로 이해하기 어려운 부분도 있을까 생각합니다만 이것으로 한번에 제스처의 식별이 가능하게 됩니다.

좋은 웹페이지 즐겨찾기