読者です 読者をやめる 読者になる 読者になる

Unity / VRゲーム開発日記@長崎

Unityを使ったVRのゲーム開発をやってます。

ジェスチャーの追加 | Kinect v2 with MS-SDK

前回記事に引き続き、MS-SDKについて。


MS-SDKは、ジェスチャーの認識機能があり、
デフォルトで、ジャンプやスクワット、
手でのスワイプ動作などがある。


ジェスチャーの表現方法としては、
手や足などが、指定時間内にどのように変化したかを
確認する形となる。



また、新しいジェスチャーを追加するには、
その表現をコードで直書きしないといけない。


ここがちょっと面倒。


既存のジェスチャの表現は、
KinectGestures.cs
というファイルに記述されている。


このファイルに

CheckForGesture

という関数があり、各ジェスチャごとにcase文が存在する。
なので、自分でジェスチャを追加するには、表現したいジェスチャに近い
case文をコピってカスタマイズという流れ。



また、case文はenumとなってるので、
ファイル冒頭の

public enum Gestures

にジェスチャ名を追加しておく必要がある。




ちなみに、既存のジェスチャとして登録されているのは以下のとおり

public enum Gestures
{
	None = 0,
	RaiseRightHand,
	RaiseLeftHand,
	Psi,
	Tpose,
	Stop,
	Wave,
	SwipeLeft,
	SwipeRight,
	SwipeUp,
	SwipeDown,
	ZoomOut,
	ZoomIn,
	Wheel,
	Jump,
	Squat,
	Push,
	Pull,
	LeanLeft,
	LeanRight,
	KickLeft,
	KickRight,
}

例としてJumpの表現を確認してみる。

case Gestures.Jump:
	switch(gestureData.state)
	{
		case 0:  // gesture detection - phase 1
			if(jointsTracked[hipCenterIndex] && 
				(jointsPos[hipCenterIndex].y > 0.6f) && (jointsPos[hipCenterIndex].y < 1.2f))
			{
				SetGestureJoint(ref gestureData, timestamp, hipCenterIndex, jointsPos[hipCenterIndex]);
				gestureData.progress = 0.5f;
			}
			break;
	
		case 1:  // gesture phase 2 = complete
			if((timestamp - gestureData.timestamp) < 1.5f)
			{
				bool isInPose = jointsTracked[hipCenterIndex] &&
					(jointsPos[hipCenterIndex].y - gestureData.jointPos.y) > 0.15f && 
					Mathf.Abs(jointsPos[hipCenterIndex].x - gestureData.jointPos.x) < 0.2f;

				if(isInPose)
				{
					Vector3 jointPos = jointsPos[gestureData.joint];
					CheckPoseComplete(ref gestureData, timestamp, jointPos, isInPose, 0f);
				}
			}
			else
			{
				// cancel the gesture
				SetGestureCancelled(ref gestureData);
			}
			break;
	}
	break;

まず、変化の状態としてgestureData.stateを見ており、
2段階の変化を見ている様子。


フェーズ1では、
jointsTracked[hipCenterIndex]
が有効か、また有効なら
jointsPos[hipCenterIndex]のy座標が
0.6f~1.2fに収まるかを見ている。

この条件に当てはまれば、フェーズ1をクリアし、
ジャンプの準備が整ったと見る様子。

そのあとは、
フェーズ2へ。


フェーズ2ではtimestampが1.5f以下かというのを見ているので、
1.5秒以内に次の動作へ移ったかという事だろう。
この時間以上であれば、elseとなるので、
ジェスチャーをキャンセルして、またフェーズ1の条件を
満たすのを待つこととなる。


そして、1.5秒以内の動作で
jointsPos[hipCenterIndex]とgestureData.jointPosの
y座標の差が0.15以上かというのを見ている。


gestureData.jointPosが前回位置だと思われるので、
おしりの位置が前回より15cm以上上がってるかというのを見ているっぽい。


また、x値が0.2fかというのも見ているので、
横移動が大きい場合は、ジャンプとみなさない様子。




以上がジャンプの表現の解析。



2段階での表現となると、線形の動きしか取れなそう。
3段階のフェーズが他にないので、拡張できるかは要調査。


歩くとか、手を叩くとか、そのくらいの動作なら
簡単に追加できそうかな?



■前回記事icoc-dev.hatenablog.com