Skip to content

Commit baa9df9

Browse files
author
lawwong
committed
Update to v1.8.1
* New features - VIVE Focus Support - Required Unity 5.6 or later version - Download and install WaveVR SDK Unity plugin from https://hub.vive.com/profile/material-download - Enable VIVE Focus support under Edit > Preference > VIU Settings * Bug fix - Fix no tracking devices dectected when SteamVR plugin v1.2.3 is installed - Fix compile error in Unity 2018.1 - Fix VIUSettings changes not saved into asset data file
2 parents 43e3a72 + 3254927 commit baa9df9

28 files changed

+1318
-176
lines changed

Assets/HTC.UnityPlugin/PoseTracker/Pose.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ public static void SetRigidbodyAngularVelocity(Rigidbody rigidbody, Quaternion f
173173
{
174174
float angle;
175175
Vector3 axis;
176-
(to * Quaternion.Inverse(from)).ToAngleAxis(out angle, out axis);
176+
var fromToRot = to * Quaternion.Inverse(from);
177+
fromToRot.ToAngleAxis(out angle, out axis);
177178
while (angle > 180f) { angle -= 360f; }
178179

179180
if (Mathf.Approximately(angle, 0f) || float.IsNaN(axis.x) || float.IsNaN(axis.y) || float.IsNaN(axis.z))

Assets/HTC.UnityPlugin/Utility/RigidPose.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ public static void SetRigidbodyAngularVelocity(Rigidbody rigidbody, Quaternion f
175175
{
176176
float angle;
177177
Vector3 axis;
178-
(to * Quaternion.Inverse(from)).ToAngleAxis(out angle, out axis);
178+
var fromToRot = to * Quaternion.Inverse(from);
179+
fromToRot.ToAngleAxis(out angle, out axis);
179180
while (angle > 180f) { angle -= 360f; }
180181

181182
if (Mathf.Approximately(angle, 0f) || float.IsNaN(axis.x) || float.IsNaN(axis.y) || float.IsNaN(axis.z))

Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public override void OnActivated()
4343
if (system != null)
4444
{
4545
#if VIU_STEAMVR_1_2_3_OR_NEWER
46-
m_hasInputFocus = !system.IsInputAvailable();
46+
m_hasInputFocus = system.IsInputAvailable();
4747
#elif VIU_STEAMVR_1_1_1 || VIU_STEAMVR_1_2_0_OR_NEWER
4848
m_hasInputFocus = !system.IsInputFocusCapturedByAnotherProcess();
4949
#endif
@@ -261,4 +261,4 @@ private static string QueryDeviceStringProperty(CVRSystem system, uint deviceInd
261261
}
262262
#endif
263263
}
264-
}
264+
}
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
using HTC.UnityPlugin.Utility;
2+
using UnityEngine;
3+
#if VIU_WAVEVR && UNITY_ANDROID
4+
using wvr;
5+
#endif
6+
7+
namespace HTC.UnityPlugin.VRModuleManagement
8+
{
9+
public class WaveVRModule : VRModule.ModuleBase
10+
{
11+
#if VIU_WAVEVR && UNITY_ANDROID
12+
private const uint HMD_INDEX = 0;
13+
private const uint RIGHT_INDEX = 1;
14+
private const uint LEFT_INDEX = 2;
15+
private const uint DEVICE_COUNT = 3;
16+
private const uint INPUT_TYPE = (uint)(WVR_InputType.WVR_InputType_Button | WVR_InputType.WVR_InputType_Touch | WVR_InputType.WVR_InputType_Analog);
17+
18+
public static readonly Vector3 DEFAULT_NECK_POSITION = new Vector3(0.0f, -0.15f, 0.0f);
19+
public static readonly Vector3 DEFAULT_ELBOW_REST_POSITION = new Vector3(0.195f, -0.5f, 0.005f);
20+
public static readonly Vector3 DEFAULT_WRIST_REST_POSITION = new Vector3(0.0f, 0.0f, 0.25f);
21+
public static readonly Vector3 DEFAULT_CONTROLLER_REST_POSITION = new Vector3(0.0f, 0.0f, 0.05f);
22+
public static readonly Vector3 DEFAULT_ARM_EXTENSION_OFFSET = new Vector3(-0.13f, 0.14f, 0.08f);
23+
public static readonly Vector3 RIGHT_ARM_MULTIPLIER = new Vector3(1f, 1f, 1f);
24+
public static readonly Vector3 LEFT_ARM_MULTIPLIER = new Vector3(1f, 1f, 1f);
25+
public const float DEFAULT_ELBOW_BEND_RATIO = 0.6f;
26+
public const float MIN_EXTENSION_ANGLE = 7.0f;
27+
public const float MAX_EXTENSION_ANGLE = 60.0f;
28+
public const float EXTENSION_WEIGHT = 0.4f;
29+
30+
private Vector3 handedMultiplier;
31+
32+
private WVR_DeviceType[] m_deviceTypes = new WVR_DeviceType[]
33+
{
34+
WVR_DeviceType.WVR_DeviceType_HMD,
35+
WVR_DeviceType.WVR_DeviceType_Controller_Right,
36+
WVR_DeviceType.WVR_DeviceType_Controller_Left,
37+
};
38+
private WVR_DevicePosePair_t[] m_poses = new WVR_DevicePosePair_t[DEVICE_COUNT]; // HMD, R, L controllers.
39+
private WVR_AnalogState_t[] m_analogStates = new WVR_AnalogState_t[2];
40+
41+
public override bool ShouldActiveModule()
42+
{
43+
return true;
44+
}
45+
46+
public override void OnActivated()
47+
{
48+
var instance = Object.FindObjectOfType<WaveVR_Init>();
49+
if (instance == null)
50+
{
51+
VRModule.Instance.gameObject.AddComponent<WaveVR_Init>();
52+
}
53+
}
54+
55+
public override void OnDeactivated() { }
56+
57+
public override uint GetRightControllerDeviceIndex() { return RIGHT_INDEX; }
58+
59+
public override uint GetLeftControllerDeviceIndex() { return LEFT_INDEX; }
60+
61+
public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState)
62+
{
63+
if (WaveVR.Instance == null) { return; }
64+
65+
WVR_PoseOriginModel poseOrigin;
66+
switch (VRModule.trackingSpaceType)
67+
{
68+
case VRModuleTrackingSpaceType.RoomScale:
69+
{ poseOrigin = WVR_PoseOriginModel.WVR_PoseOriginModel_OriginOnGround; break; }
70+
case VRModuleTrackingSpaceType.Stationary:
71+
default:
72+
{ poseOrigin = WVR_PoseOriginModel.WVR_PoseOriginModel_OriginOnHead; break; }
73+
}
74+
75+
IVRModuleDeviceStateRW headState = null;
76+
IVRModuleDeviceStateRW rightState = null;
77+
IVRModuleDeviceStateRW leftState = null;
78+
79+
Interop.WVR_GetSyncPose(poseOrigin, m_poses, DEVICE_COUNT);
80+
81+
for (int i = 0; i < DEVICE_COUNT; ++i)
82+
{
83+
var deviceType = m_poses[i].type;
84+
var devicePose = m_poses[i].pose;
85+
86+
if (deviceType == m_deviceTypes[i] && devicePose.IsValidPose)
87+
{
88+
currState[i].isConnected = true;
89+
if (deviceType == WVR_DeviceType.WVR_DeviceType_HMD)
90+
{
91+
currState[i].deviceClass = VRModuleDeviceClass.HMD;
92+
currState[i].deviceModel = VRModuleDeviceModel.ViveFocusHMD;
93+
}
94+
else
95+
{
96+
currState[i].deviceClass = VRModuleDeviceClass.Controller;
97+
currState[i].deviceModel = VRModuleDeviceModel.ViveFocusFinch;
98+
}
99+
100+
var rigidTransform = new WaveVR_Utils.RigidTransform(devicePose.PoseMatrix);
101+
102+
currState[i].isPoseValid = true;
103+
currState[i].isOutOfRange = false;
104+
currState[i].isCalibrating = false;
105+
currState[i].isUninitialized = false;
106+
107+
currState[i].velocity = new Vector3(devicePose.Velocity.v0, devicePose.Velocity.v1, -devicePose.Velocity.v2);
108+
currState[i].angularVelocity = new Vector3(-devicePose.AngularVelocity.v0, -devicePose.AngularVelocity.v1, devicePose.AngularVelocity.v2);
109+
110+
currState[i].position = rigidTransform.pos;
111+
currState[i].rotation = rigidTransform.rot;
112+
113+
switch (deviceType)
114+
{
115+
case WVR_DeviceType.WVR_DeviceType_HMD:
116+
headState = currState[i];
117+
break;
118+
case WVR_DeviceType.WVR_DeviceType_Controller_Right:
119+
rightState = currState[i];
120+
break;
121+
case WVR_DeviceType.WVR_DeviceType_Controller_Left:
122+
leftState = currState[i];
123+
break;
124+
}
125+
126+
uint buttons = 0;
127+
uint touches = 0;
128+
129+
// FIXME: What does WVR_GetInputTypeCount means?
130+
//var analogCount = Interop.WVR_GetInputTypeCount(deviceType, WVR_InputType.WVR_InputType_Analog);
131+
//if (m_analogStates == null || m_analogStates.Length < analogCount) { m_analogStates = new WVR_AnalogState_t[analogCount]; }
132+
133+
if (Interop.WVR_GetInputDeviceState(deviceType, INPUT_TYPE, ref buttons, ref touches, m_analogStates, m_analogStates.Length))
134+
{
135+
const uint dpadMask =
136+
(1 << (int)(WVR_InputId.WVR_InputId_Alias1_Touchpad)) |
137+
(1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Left)) |
138+
(1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Up)) |
139+
(1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Right)) |
140+
(1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Down));
141+
142+
const uint triggerBumperMask =
143+
(1 << (int)(WVR_InputId.WVR_InputId_Alias1_Trigger)) |
144+
(1 << (int)(WVR_InputId.WVR_InputId_Alias1_Bumper));
145+
146+
currState[i].SetButtonPress(VRModuleRawButton.System, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_System)) != 0u);
147+
currState[i].SetButtonPress(VRModuleRawButton.ApplicationMenu, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Menu)) != 0u);
148+
currState[i].SetButtonPress(VRModuleRawButton.Touchpad, (buttons & dpadMask) != 0u);
149+
currState[i].SetButtonPress(VRModuleRawButton.Trigger, (buttons & triggerBumperMask) != 0u);
150+
currState[i].SetButtonPress(VRModuleRawButton.Grip, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Grip)) != 0u);
151+
currState[i].SetButtonPress(VRModuleRawButton.DPadLeft, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Left)) != 0u);
152+
currState[i].SetButtonPress(VRModuleRawButton.DPadUp, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Up)) != 0u);
153+
currState[i].SetButtonPress(VRModuleRawButton.DPadRight, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Right)) != 0u);
154+
currState[i].SetButtonPress(VRModuleRawButton.DPadDown, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Down)) != 0u);
155+
156+
currState[i].SetButtonTouch(VRModuleRawButton.System, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_System)) != 0u);
157+
currState[i].SetButtonTouch(VRModuleRawButton.ApplicationMenu, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Menu)) != 0u);
158+
currState[i].SetButtonTouch(VRModuleRawButton.Touchpad, (touches & dpadMask) != 0u);
159+
currState[i].SetButtonTouch(VRModuleRawButton.Trigger, (touches & triggerBumperMask) != 0u);
160+
currState[i].SetButtonTouch(VRModuleRawButton.Grip, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Grip)) != 0u);
161+
currState[i].SetButtonTouch(VRModuleRawButton.DPadLeft, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Left)) != 0u);
162+
currState[i].SetButtonTouch(VRModuleRawButton.DPadUp, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Up)) != 0u);
163+
currState[i].SetButtonTouch(VRModuleRawButton.DPadRight, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Right)) != 0u);
164+
currState[i].SetButtonTouch(VRModuleRawButton.DPadDown, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Down)) != 0u);
165+
166+
for (int j = 0, jmax = m_analogStates.Length; j < jmax; ++j)
167+
{
168+
switch (m_analogStates[j].id)
169+
{
170+
case WVR_InputId.WVR_InputId_Alias1_Trigger:
171+
if (m_analogStates[j].type == WVR_AnalogType.WVR_AnalogType_Trigger)
172+
{
173+
currState[i].SetAxisValue(VRModuleRawAxis.Trigger, m_analogStates[j].axis.x);
174+
}
175+
break;
176+
case WVR_InputId.WVR_InputId_Alias1_Touchpad:
177+
if (m_analogStates[j].type == WVR_AnalogType.WVR_AnalogType_TouchPad && currState[i].GetButtonTouch(VRModuleRawButton.Touchpad))
178+
{
179+
currState[i].SetAxisValue(VRModuleRawAxis.TouchpadX, m_analogStates[j].axis.x);
180+
currState[i].SetAxisValue(VRModuleRawAxis.TouchpadY, m_analogStates[j].axis.y);
181+
}
182+
else
183+
{
184+
currState[i].SetAxisValue(VRModuleRawAxis.TouchpadX, 0f);
185+
currState[i].SetAxisValue(VRModuleRawAxis.TouchpadY, 0f);
186+
}
187+
break;
188+
}
189+
}
190+
}
191+
else
192+
{
193+
currState[i].buttonPressed = 0u;
194+
currState[i].buttonTouched = 0u;
195+
for (int j = 0, jmax = currState[i].axisValue.Length; j < jmax; ++j) { currState[i].axisValue[j] = 0f; }
196+
}
197+
}
198+
else
199+
{
200+
if (prevState[i].isConnected)
201+
{
202+
currState[i].Reset();
203+
}
204+
}
205+
}
206+
207+
// add right arm
208+
if (rightState != null && rightState.isConnected && rightState.position == Vector3.zero)
209+
{
210+
rightState.position = GetControllerPositionWithVirtualArm(GetNeckPose(headState.pose), rightState.rotation, RIGHT_ARM_MULTIPLIER);
211+
}
212+
213+
// add left arm
214+
if (leftState != null && leftState.isConnected && leftState.position == Vector3.zero)
215+
{
216+
leftState.position = GetControllerPositionWithVirtualArm(GetNeckPose(headState.pose), leftState.rotation, LEFT_ARM_MULTIPLIER);
217+
}
218+
}
219+
220+
private static RigidPose GetNeckPose(RigidPose headPose)
221+
{
222+
var headForward = headPose.forward;
223+
return new RigidPose(headPose.pos + DEFAULT_NECK_POSITION, Quaternion.FromToRotation(Vector3.forward, new Vector3(headForward.x, 0f, headForward.z)));
224+
}
225+
226+
private static float GetExtensionRatio(Vector3 v)
227+
{
228+
var xAngle = 90f - Vector3.Angle(v, Vector3.up);
229+
return Mathf.Clamp01(Mathf.InverseLerp(MIN_EXTENSION_ANGLE, MAX_EXTENSION_ANGLE, xAngle));
230+
}
231+
232+
private static Quaternion GetLerpRotation(Quaternion xyRotation, float extensionRatio)
233+
{
234+
float totalAngle = Quaternion.Angle(xyRotation, Quaternion.identity);
235+
float lerpSuppresion = 1.0f - Mathf.Pow(totalAngle / 180.0f, 6.0f);
236+
float inverseElbowBendRatio = 1.0f - DEFAULT_ELBOW_BEND_RATIO;
237+
float lerpValue = inverseElbowBendRatio + DEFAULT_ELBOW_BEND_RATIO * extensionRatio * EXTENSION_WEIGHT;
238+
lerpValue *= lerpSuppresion;
239+
return Quaternion.Lerp(Quaternion.identity, xyRotation, lerpValue);
240+
}
241+
242+
private static Vector3 GetControllerPositionWithVirtualArm(RigidPose neckPose, Quaternion ctrlRot, Vector3 sideMultiplier)
243+
{
244+
var localCtrlForward = (Quaternion.Inverse(neckPose.rot) * ctrlRot) * Vector3.forward;
245+
var localCtrlXYRot = Quaternion.FromToRotation(Vector3.forward, localCtrlForward);
246+
var extensionRatio = GetExtensionRatio(localCtrlForward);
247+
var lerpRotation = GetLerpRotation(localCtrlXYRot, extensionRatio);
248+
249+
var elbowPose = new RigidPose(
250+
Vector3.Scale(DEFAULT_ELBOW_REST_POSITION, sideMultiplier) + Vector3.Scale(DEFAULT_ARM_EXTENSION_OFFSET, sideMultiplier) * extensionRatio,
251+
Quaternion.Inverse(lerpRotation) * localCtrlXYRot);
252+
var wristPose = new RigidPose(
253+
Vector3.Scale(DEFAULT_WRIST_REST_POSITION, sideMultiplier),
254+
lerpRotation);
255+
var palmPose = new RigidPose(
256+
Vector3.Scale(DEFAULT_CONTROLLER_REST_POSITION, sideMultiplier),
257+
Quaternion.identity);
258+
259+
var finalCtrlPose = neckPose * elbowPose * wristPose * palmPose;
260+
return finalCtrlPose.pos;
261+
}
262+
263+
public override void TriggerViveControllerHaptic(uint deviceIndex, ushort durationMicroSec = 500)
264+
{
265+
Interop.WVR_TriggerVibrator(m_deviceTypes[deviceIndex], WVR_InputId.WVR_InputId_Alias1_Touchpad, durationMicroSec);
266+
}
267+
#endif
268+
}
269+
}

Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs.meta

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/HTC.UnityPlugin/VRModule/VRModule.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,5 +188,12 @@ public static void TriggerViveControllerHaptic(uint deviceIndex, ushort duration
188188
#else
189189
false;
190190
#endif
191+
192+
public static readonly bool isWaveVRPluginDetected =
193+
#if VIU_WAVEVR
194+
true;
195+
#else
196+
false;
197+
#endif
191198
}
192199
}

Assets/HTC.UnityPlugin/VRModule/VRModuleDeviceState.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public enum VRModuleDeviceModel
3030
KnucklesRight,
3131
DaydreamHMD,
3232
DaydreamController,
33+
ViveFocusHMD,
34+
ViveFocusFinch,
3335
}
3436

3537
public enum VRModuleRawButton

0 commit comments

Comments
 (0)