VR模拟枪支打靶,消灭鬼怪,换弹以及上弦等等硬核枪支操作。 使用HTCVive设备,开启SteamVR进行游玩。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

167 lines
5.9 KiB

//========= Copyright 2016-2018, HTC Corporation. All rights reserved. ===========
using HTC.UnityPlugin.VRModuleManagement;
using System.Collections.Generic;
using UnityEngine;
namespace HTC.UnityPlugin.Vive
{
[ViveRoleEnum((int)TrackerRole.Invalid)]
public enum BodyRole
{
Invalid,
Head,
RightHand,
LeftHand,
RightFoot,
LeftFoot,
Hip,
}
public class BodyRoleHandler : ViveRole.MapHandler<BodyRole>
{
private float[] m_directionPoint = new float[VRModule.MAX_DEVICE_COUNT];
private float[] m_distanceSqr = new float[VRModule.MAX_DEVICE_COUNT];
private List<uint> m_sortedDevices = new List<uint>();
private bool IsTrackingDevice(uint deviceIndex)
{
return IsTrackingDevice(VRModule.GetCurrentDeviceState(deviceIndex).deviceClass);
}
private bool IsTrackingDevice(VRModuleDeviceClass deviceClass)
{
return deviceClass == VRModuleDeviceClass.HMD || deviceClass == VRModuleDeviceClass.Controller || deviceClass == VRModuleDeviceClass.GenericTracker;
}
public override void OnAssignedAsCurrentMapHandler() { Refresh(); }
public override void OnConnectedDeviceChanged(uint deviceIndex, VRModuleDeviceClass deviceClass, string deviceSN, bool connected)
{
if (!RoleMap.IsDeviceBound(deviceSN) && !IsTrackingDevice(deviceClass)) { return; }
Refresh();
}
public override void OnBindingChanged(string deviceSN, bool previousIsBound, BodyRole previousRole, bool currentIsBound, BodyRole currentRole)
{
uint deviceIndex;
if (!VRModule.TryGetConnectedDeviceIndex(deviceSN, out deviceIndex)) { return; }
Refresh();
}
public void Refresh()
{
m_sortedDevices.Clear();
UnmappingAll();
MappingRoleIfUnbound(BodyRole.Head, 0u);
// get related poses and record controller/tracker devices
var hmdPose = VivePose.GetPose(0u);
// preserve only y-axis rotation
hmdPose.rot = Quaternion.Euler(0f, hmdPose.rot.eulerAngles.y, 0f);
// move center to half height
hmdPose.pos = Vector3.Scale(hmdPose.pos, new Vector3(1f, 0.5f, 1f));
var halfHeight = hmdPose.pos.y;
var centerPoseInverse = hmdPose.GetInverse();
for (uint i = 1; i < VRModule.MAX_DEVICE_COUNT; ++i)
{
if (!IsTrackingDevice(i)) { continue; }
var relatedCenterPos = centerPoseInverse.InverseTransformPoint(VRModule.GetCurrentDeviceState(i).pose.pos);
m_directionPoint[i] = HandRoleHandler.GetDirectionPoint(new Vector2(relatedCenterPos.x, -relatedCenterPos.y));
m_distanceSqr[i] = relatedCenterPos.sqrMagnitude / (halfHeight * halfHeight);
m_sortedDevices.Add(i);
}
if (m_sortedDevices.Count == 0)
{
return;
}
var index = m_sortedDevices.Count - 1; // pointing last index
// find 2 feet, should be most farest 2 devices
m_sortedDevices.Sort(CompareDistance);
if (IsFoot(m_sortedDevices[index]))
{
if (m_sortedDevices.Count <= 1)
{
MappingRoleIfUnbound(BodyRole.RightFoot, m_sortedDevices[index]);
return;
}
if (!IsFoot(m_sortedDevices[index - 1]))
{
// only 1 foot found
MappingRoleIfUnbound(BodyRole.RightFoot, m_sortedDevices[index]);
m_sortedDevices.RemoveAt(index--);
if (index < 0) { return; }
}
else
{
// 2 feet found, determine lef/right foot
if (m_directionPoint[m_sortedDevices[index]] < m_directionPoint[m_sortedDevices[index - 1]])
{
MappingRoleIfUnbound(BodyRole.RightFoot, m_sortedDevices[index]);
MappingRoleIfUnbound(BodyRole.LeftFoot, m_sortedDevices[index - 1]);
}
else
{
MappingRoleIfUnbound(BodyRole.RightFoot, m_sortedDevices[index - 1]);
MappingRoleIfUnbound(BodyRole.LeftFoot, m_sortedDevices[index]);
}
m_sortedDevices.RemoveAt(index--);
m_sortedDevices.RemoveAt(index--);
if (index < 0) { return; }
}
}
// find 2 hands, should be most left and most right device
m_sortedDevices.Sort(CompareDirection);
// right most device as right hand
MappingRoleIfUnbound(BodyRole.RightHand, m_sortedDevices[0]);
if (m_sortedDevices.Count == 1) { return; }
// left most device as left hand
MappingRoleIfUnbound(BodyRole.LeftHand, m_sortedDevices[index]);
if (m_sortedDevices.Count == 2) { return; }
// middle one as hip
MappingRoleIfUnbound(BodyRole.Hip, m_sortedDevices[index / 2]);
}
private bool IsFoot(uint di)
{
var dist = m_distanceSqr[di];
var dir = m_directionPoint[di];
return dist > (0.25f * 0.25f) && dir > 3.5f && dir < 4.5f;
}
private int CompareDistance(uint d1, uint d2)
{
var dd1 = m_distanceSqr[d1];
var dd2 = m_distanceSqr[d2];
if (dd1 == dd2) { return 0; }
if (dd1 < dd2) { return -1; }
return 1;
}
private int CompareDirection(uint d1, uint d2)
{
var sd1 = m_directionPoint[d1];
var sd2 = m_directionPoint[d2];
if (sd1 == sd2) { return 0; }
if (sd1 < sd2) { return -1; }
return 1;
}
}
}