C++でOculus Touch ControllerとHMDの値を取得する

# 概要
Oculus SDKを使ってOculus Controllerの値を取得しました。Oculusの開発環境は、UnityでC#を使うことが一般的らしいのですが、今回はSDKの静的ライブラリを用いてC++で値を取得しました。

# 実行環境
次に実行環境を示します。

| Soft and Hard       |       バージョン | 
|:-----------------:|:------------------:|
| Windows 10 pro        |              16.04 |  
| Visual studio 2015        |              Community update 3 |   
| Oculus SDK         |              1.37.0 |

# 使用ライブラリ

使用するライブラリは、Oculus sdkのLibOVRというライブラリです。このライブラリをVisual studioでインクルードしたプロジェクトでC++で作成します。自分がプロジェクトを作成する場合には、一応、LibOVRKernelというライブラリも追加しました。の方は、ライブラリが無かったので、slnファイルを開き、ビルドしました。ライブラリの追加方法等は、以下の記事が参考になると思います。

https://qiita.com/yjiro0403/items/fb119d2206cf9178a57e

# Code

以下に作成したコードを示します。

```c++:getTouchControllerValue.rb

#include <iomanip>
#include <OVR_CAPI.h>
#include <thread>
#include <iostream>

#define COLW setw(15)

using namespace std;

int main()
{   
	
	ovrInitParams initParams = { ovrInit_RequestVersion + ovrInit_Invisible, OVR_MINOR_VERSION, NULL, 0, 0 };

	// Initialize our session with the Oculus HMD.
	if (ovr_Initialize(&initParams) == ovrSuccess)
	{
		ovrSession session = nullptr;
		ovrGraphicsLuid luid;
		ovrResult result = ovr_Create(&session, &luid);

		// Relative Touch Controller :
		if (result == ovrSuccess)
		{   
			ovrTrackingState ts;
			ovrInputState touchState;

			while (true)
			{
				ts = ovr_GetTrackingState(session, 0, true);

				// Realtive HMD value:
				ovrPoseStatef tempHeadPose = ts.HeadPose;
				ovrPosef tempPose          = tempHeadPose.ThePose;
				ovrQuatf tempOrient        = tempPose.Orientation;
				 
				std::cout << "Orientation (x,y,z):  " << COLW << tempOrient.x << ","
					<< COLW << tempOrient.y << "," << COLW << tempOrient.z
					<< std::endl;

				printf("\n");

				// Relative Touch Controller Right side value:
				ovrPoseStatef CurrRightHandPoses = ts.HandPoses[ovrHand_Right];
				ovrVector3f CurrPoseRight        = CurrRightHandPoses.ThePose.Position;
				ovrQuatf CurrOrientRight         = CurrRightHandPoses.ThePose.Orientation;

				std::cout << "Right hand orient (x,y,z):  " << COLW << CurrOrientRight.x << ","
					<< COLW << CurrOrientRight.y << "," << COLW << CurrOrientRight.z
					<< std::endl;

				//printf("\n");

				std::cout << "Right hand position (x,y,z):  " << COLW << CurrPoseRight.x << ","
					<< COLW << CurrPoseRight.y << "," << COLW << CurrPoseRight.z
					<< std::endl;

				// Relative Touch Controller Left side value:
				ovrPoseStatef CurrLeftHandPoses = ts.HandPoses[ovrHand_Left];
				ovrVector3f CurrPoseLeft        = CurrLeftHandPoses.ThePose.Position;
				ovrQuatf CurrOrientLeft         = CurrLeftHandPoses.ThePose.Orientation;

				printf("\n");

				std::cout << "Left hand orient (x,y,z):  " << COLW << CurrOrientLeft.x << ","
					<< COLW << CurrOrientLeft.y << "," << COLW << CurrOrientLeft.z
					<< std::endl;

				printf("\n");

				std::cout << "Left hand position (x,y,z):  " << COLW << CurrPoseLeft.x << ","
					<< COLW << CurrPoseLeft.y << "," << COLW << CurrPoseLeft.z
					<< std::endl;

				printf("\n");

				Relative Touch Controller Button State:

				if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Touch, &touchState))) {


					if (touchState.Buttons && ovrButton_A)
					{
						std::cout << "Pushed Botton_A !\n" << std::endl;
					}

					if (touchState.Buttons & ovrTouch_B)
					{
						std::cout << "Pushed Botton_B !\n" << std::endl;
					}

					if (touchState.Buttons & ovrTouch_X)
					{
						std::cout << "Pushed Botton_X !\n" << std::endl;
					}

					if (touchState.Buttons & ovrTouch_Y)
					{
						std::cout << "Pushed Botton_Y !\n" << std::endl;
					}

					std::cout << touchState.Buttons << std::endl;
					printf("%lf", touchState.HandTrigger[ovrHand_Left]);

					if (touchState.HandTrigger[ovrHand_Left] > 0.5f)
					{
						std::cout << "Pushed Left HandTrigger !\n" << std::endl;
					}

					if (touchState.IndexTrigger[ovrHand_Right] > 0.5f)
					{
						std::cout << "Pushed Right IndexTrigger !\n" << std::endl;
					}

					if (touchState.IndexTrigger[ovrHand_Left] > 0.5f)
					{
						std::cout << "Pushed Left IndexTrigger !\n" << std::endl;
					}
				}

				// Wait a bit to let us actually read stuff.
				std::this_thread::sleep_for(std::chrono::milliseconds(100));
			}

			ovr_Destroy(session);
		}

		ovr_Shutdown();
		// If we've fallen through to this point, the HMD is no longer
		// connected.
	}

	return 0;
}
```

# 注意点
基本的に、Oculus SDKのリファレンスを見ながら進めれば、いけると思います！詰まったところは、ovr_Initializeの際に、次のinit paramを渡さないと、touch controllerの各値が0のままになってしまう所で詰まりました。

```c++
ovrInitParams initParams = { ovrInit_RequestVersion + ovrInit_Invisible, OVR_MINOR_VERSION, NULL, 0, 0 };
```
参考にする方は、気を付けてください。また、おかしいところがあったら、言って頂けるととてもうれしいです！