public void Update(ref bool dataChanged, ref bool sceneChanged) { // frame number and timestamp scene.frameNumber = Time.frameCount; scene.timestamp = Time.time; // poll hand controllers to force detection // InputTracking.GetLocalPosition(XRNode.LeftHand); // InputTracking.GetLocalPosition(XRNode.RightHand); // get new node data InputTracking.GetNodeStates(nodeStates); foreach (XRNodeState state in nodeStates) { Actor actor = null; if (actors.TryGetValue(state.uniqueID, out actor)) { // update position, orientation, and tracking state Bone bone = actor.bones[0]; bone.tracked = state.tracked; if (bone.tracked) { Vector3 pos; if (state.TryGetPosition(out pos)) { bone.CopyFrom(pos); } else { bone.tracked = false; } Quaternion rot; if (state.TryGetRotation(out rot)) { bone.CopyFrom(rot); } else { bone.tracked = false; } } dataChanged = true; } else { actor = CreateActor(state); Debug.Log("New actor added: " + actor.name); sceneChanged = true; } } dataChanged = true; }
public void Update(ref bool dataChanged, ref bool sceneChanged) { compositor.GetLastPoses(poses, gamePoses); // frame number and timestamp scene.frameNumber = Time.frameCount; scene.timestamp = Time.time; for (int idx = 0; idx < trackedDevices.Count; idx++) { // update position, orientation, and tracking state int controllerIdx = trackedDevices[idx].controllerIdx; Bone bone = scene.actors[idx].bones[0]; HmdMatrix34_t pose = poses[controllerIdx].mDeviceToAbsoluteTracking; Matrix4x4 m = Matrix4x4.identity; m[0, 0] = pose.m0; m[0, 1] = pose.m1; m[0, 2] = pose.m2; m[0, 3] = pose.m3; m[1, 0] = pose.m4; m[1, 1] = pose.m5; m[1, 2] = pose.m6; m[1, 3] = pose.m7; m[2, 0] = pose.m8; m[2, 1] = pose.m9; m[2, 2] = pose.m10; m[2, 3] = pose.m11; MathUtil.ToggleLeftRightHandedMatrix(ref m); bone.CopyFrom(MathUtil.GetTranslation(m), MathUtil.GetRotation(m)); bone.tracked = poses[controllerIdx].bDeviceIsConnected && poses[controllerIdx].bPoseIsValid; // if this is also an input device, update inputs Device dev = trackedDevices[idx].device; if (dev != null) { system.GetControllerStateWithPose( ETrackingUniverseOrigin.TrackingUniverseStanding, (uint)controllerIdx, ref state, (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t)), ref poses[controllerIdx]); if (trackedDevices[idx].deviceClass == ETrackedDeviceClass.Controller) { // hand controller // trigger button dev.channels[0].value = state.rAxis1.x; // menu button dev.channels[1].value = (state.ulButtonPressed & (1ul << (int)EVRButtonId.k_EButton_ApplicationMenu)) != 0 ? 1 : 0; // grip button dev.channels[2].value = (state.ulButtonPressed & (1ul << (int)EVRButtonId.k_EButton_Grip)) != 0 ? 1 : 0; // touchpad (button4, axis1/2 and axis1raw/2raw) float touchpadPressed = (state.ulButtonPressed & (1ul << (int)EVRButtonId.k_EButton_SteamVR_Touchpad)) != 0 ? 1 : 0; dev.channels[3].value = touchpadPressed; dev.channels[4].value = state.rAxis0.x * touchpadPressed; dev.channels[5].value = state.rAxis0.y * touchpadPressed; dev.channels[6].value = state.rAxis0.x; dev.channels[7].value = state.rAxis0.y; // touchpad as buttons Vector2 touchpad = new Vector2(state.rAxis0.x, state.rAxis0.y) * touchpadPressed; float distance = touchpad.magnitude; if (distance < 0.3f) { touchpad = Vector2.zero; } // using angle to determine which circular segment the finger is on // instead of purely <> comparisons on coordinates float angle = Mathf.Rad2Deg * Mathf.Atan2(touchpad.y, touchpad.x); // +135 +90 +45 // +180/-180 0 to allow for overlap, angles are 67.5 around a direction // -135 -90 -45 dev.channels[8].value = ((angle > 0 - 67.5f) && (angle < 0 + 67.5f)) ? touchpadPressed : 0; // right dev.channels[9].value = ((angle > 180 - 67.5f) || (angle < -180 + 67.5f)) ? touchpadPressed : 0; // left dev.channels[10].value = ((angle > 90 - 67.5f) && (angle < 90 + 67.5f)) ? touchpadPressed : 0; // up dev.channels[11].value = ((angle > -90 - 67.5f) && (angle < -90 + 67.5f)) ? touchpadPressed : 0; // down // rumble output > convert value [0...1] to time // rumble output > convert value [0...1] to time float duration = Mathf.Clamp01(dev.channels[12].value) * 1000.0f * 1000.0f / updateRate; duration = Mathf.Clamp(duration, 0, 30000); system.TriggerHapticPulse((uint)controllerIdx, 0, (ushort)duration); } else if (trackedDevices[idx].deviceClass == ETrackedDeviceClass.GenericTracker) { // generic tracker // grip button dev.channels[0].value = (state.ulButtonPressed & (1ul << (int)EVRButtonId.k_EButton_Grip)) != 0 ? 1 : 0; // trigger button dev.channels[1].value = (state.ulButtonPressed & (1ul << (int)EVRButtonId.k_EButton_SteamVR_Trigger)) != 0 ? 1 : 0; // touchpad dev.channels[2].value = (state.ulButtonPressed & (1ul << (int)EVRButtonId.k_EButton_SteamVR_Touchpad)) != 0 ? 1 : 0; // menu button dev.channels[3].value = (state.ulButtonPressed & (1ul << (int)EVRButtonId.k_EButton_ApplicationMenu)) != 0 ? 1 : 0; // rumble output > convert value [0...1] to time float duration = Mathf.Clamp01(dev.channels[4].value) * 1.0f; duration = Mathf.Clamp(duration, 0, 30000); system.TriggerHapticPulse((uint)controllerIdx, 0, (ushort)duration); } } } dataChanged = true; }