mirror of https://github.com/bjornbytes/lovr.git
OpenVR organization;
This commit is contained in:
parent
ba68c0c127
commit
5e65ac019e
|
@ -22,49 +22,44 @@ extern void VR_ShutdownInternal();
|
|||
extern bool VR_IsHmdPresent();
|
||||
extern intptr_t VR_GetGenericInterface(const char* pchInterfaceVersion, EVRInitError* peError);
|
||||
extern bool VR_IsRuntimeInstalled();
|
||||
#define HEADSET_INDEX k_unTrackedDeviceIndex_Hmd
|
||||
|
||||
static ControllerHand openvrControllerGetHand(Controller* controller);
|
||||
|
||||
typedef struct {
|
||||
bool isMirrored;
|
||||
HeadsetEye mirrorEye;
|
||||
float offset;
|
||||
int msaa;
|
||||
|
||||
struct VR_IVRSystem_FnTable* system;
|
||||
struct VR_IVRCompositor_FnTable* compositor;
|
||||
struct VR_IVRChaperone_FnTable* chaperone;
|
||||
struct VR_IVRRenderModels_FnTable* renderModels;
|
||||
|
||||
unsigned int headsetIndex;
|
||||
HeadsetType type;
|
||||
|
||||
TrackedDevicePose_t poses[16];
|
||||
RenderModel_t* deviceModels[16];
|
||||
RenderModel_TextureMap_t* deviceTextures[16];
|
||||
|
||||
Canvas* canvas;
|
||||
vec_controller_t controllers;
|
||||
|
||||
HeadsetType type;
|
||||
bool isMirrored;
|
||||
HeadsetEye mirrorEye;
|
||||
float clipNear;
|
||||
float clipFar;
|
||||
|
||||
Canvas* canvas;
|
||||
float offset;
|
||||
int msaa;
|
||||
} HeadsetState;
|
||||
|
||||
static HeadsetState state;
|
||||
|
||||
static bool openvrIsController(TrackedDeviceIndex_t id) {
|
||||
if (!state.system->IsTrackedDeviceConnected(id)) {
|
||||
return false;
|
||||
static void getTransform(unsigned int device, mat4 transform) {
|
||||
TrackedDevicePose_t pose = state.poses[device];
|
||||
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
|
||||
mat4_identity(transform);
|
||||
} else {
|
||||
mat4_fromMat34(transform, pose.mDeviceToAbsoluteTracking.m);
|
||||
}
|
||||
}
|
||||
|
||||
switch (state.system->GetTrackedDeviceClass(id)) {
|
||||
case ETrackedDeviceClass_TrackedDeviceClass_Controller:
|
||||
case ETrackedDeviceClass_TrackedDeviceClass_GenericTracker:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
static bool isController(TrackedDeviceIndex_t id) {
|
||||
return state.system->IsTrackedDeviceConnected(id) &&
|
||||
state.system->GetTrackedDeviceClass(id) == ETrackedDeviceClass_TrackedDeviceClass_Controller ||
|
||||
state.system->GetTrackedDeviceClass(id) == ETrackedDeviceClass_TrackedDeviceClass_GenericTracker;
|
||||
}
|
||||
|
||||
static ControllerButton getButton(uint32_t button, ControllerHand hand) {
|
||||
|
@ -136,16 +131,13 @@ static void openvrPoll() {
|
|||
switch (vrEvent.eventType) {
|
||||
case EVREventType_VREvent_TrackedDeviceActivated: {
|
||||
uint32_t id = vrEvent.trackedDeviceIndex;
|
||||
if (openvrIsController(id)) {
|
||||
if (isController(id)) {
|
||||
Controller* controller = lovrAlloc(Controller, free);
|
||||
if (!controller) break;
|
||||
controller->id = id;
|
||||
vec_push(&state.controllers, controller);
|
||||
lovrRetain(controller);
|
||||
lovrEventPush((Event) {
|
||||
.type = EVENT_CONTROLLER_ADDED,
|
||||
.data.controller = { controller, 0 }
|
||||
});
|
||||
lovrEventPush((Event) { .type = EVENT_CONTROLLER_ADDED, .data.controller = { controller, 0 } });
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -155,10 +147,7 @@ static void openvrPoll() {
|
|||
Controller* controller = state.controllers.data[i];
|
||||
if (controller->id == vrEvent.trackedDeviceIndex) {
|
||||
lovrRetain(controller);
|
||||
lovrEventPush((Event) {
|
||||
.type = EVENT_CONTROLLER_REMOVED,
|
||||
.data.controller = { controller, 0 }
|
||||
});
|
||||
lovrEventPush((Event) { .type = EVENT_CONTROLLER_REMOVED, .data.controller = { controller, 0 } });
|
||||
vec_swapsplice(&state.controllers, i, 1);
|
||||
lovrRelease(controller);
|
||||
break;
|
||||
|
@ -170,7 +159,7 @@ static void openvrPoll() {
|
|||
case EVREventType_VREvent_ButtonUnpress: {
|
||||
bool isPress = vrEvent.eventType == EVREventType_VREvent_ButtonPress;
|
||||
|
||||
if (vrEvent.trackedDeviceIndex == state.headsetIndex && vrEvent.data.controller.button == EVRButtonId_k_EButton_ProximitySensor) {
|
||||
if (vrEvent.trackedDeviceIndex == HEADSET_INDEX && vrEvent.data.controller.button == EVRButtonId_k_EButton_ProximitySensor) {
|
||||
lovrEventPush((Event) { .type = EVENT_MOUNT, .data.boolean = { isPress } });
|
||||
break;
|
||||
}
|
||||
|
@ -179,10 +168,8 @@ static void openvrPoll() {
|
|||
Controller* controller = state.controllers.data[i];
|
||||
if (controller->id == vrEvent.trackedDeviceIndex) {
|
||||
ControllerButton button = getButton(vrEvent.data.controller.button, openvrControllerGetHand(controller));
|
||||
lovrEventPush((Event) {
|
||||
.type = isPress ? EVENT_CONTROLLER_PRESSED : EVENT_CONTROLLER_RELEASED,
|
||||
.data.controller = { controller, button }
|
||||
});
|
||||
EventType type = isPress ? EVENT_CONTROLLER_PRESSED : EVENT_CONTROLLER_RELEASED;
|
||||
lovrEventPush((Event) { .type = type, .data.controller = { controller, button } });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -196,27 +183,11 @@ static void openvrPoll() {
|
|||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ensureCanvas() {
|
||||
if (state.canvas) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t width, height;
|
||||
state.system->GetRecommendedRenderTargetSize(&width, &height);
|
||||
CanvasFlags flags = { .depth = { true, false, FORMAT_D24S8 }, .stereo = true, .msaa = state.msaa };
|
||||
state.canvas = lovrCanvasCreate(width * 2, height, flags);
|
||||
Texture* texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, true, false, state.msaa);
|
||||
lovrTextureAllocate(texture, width * 2, height, 1, FORMAT_RGBA);
|
||||
lovrCanvasSetAttachments(state.canvas, &(Attachment) { texture, 0, 0 }, 1);
|
||||
lovrRelease(texture);
|
||||
}
|
||||
|
||||
static bool openvrInit(float offset, int msaa) {
|
||||
if (!VR_IsHmdPresent() || !VR_IsRuntimeInstalled()) {
|
||||
return false;
|
||||
|
@ -224,42 +195,22 @@ static bool openvrInit(float offset, int msaa) {
|
|||
|
||||
EVRInitError vrError;
|
||||
VR_InitInternal(&vrError, EVRApplicationType_VRApplication_Scene);
|
||||
|
||||
if (vrError != EVRInitError_VRInitError_None) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[128];
|
||||
char buffer[64];
|
||||
sprintf(buffer, "FnTable:%s", IVRSystem_Version), state.system = (struct VR_IVRSystem_FnTable*) VR_GetGenericInterface(buffer, &vrError);
|
||||
sprintf(buffer, "FnTable:%s", IVRCompositor_Version), state.compositor = (struct VR_IVRCompositor_FnTable*) VR_GetGenericInterface(buffer, &vrError);
|
||||
sprintf(buffer, "FnTable:%s", IVRChaperone_Version), state.chaperone = (struct VR_IVRChaperone_FnTable*) VR_GetGenericInterface(buffer, &vrError);
|
||||
sprintf(buffer, "FnTable:%s", IVRRenderModels_Version), state.renderModels = (struct VR_IVRRenderModels_FnTable*) VR_GetGenericInterface(buffer, &vrError);
|
||||
|
||||
sprintf(buffer, "FnTable:%s", IVRSystem_Version);
|
||||
state.system = (struct VR_IVRSystem_FnTable*) VR_GetGenericInterface(buffer, &vrError);
|
||||
if (vrError != EVRInitError_VRInitError_None || !state.system) {
|
||||
if (!state.system || !state.compositor || !state.chaperone || !state.renderModels) {
|
||||
VR_ShutdownInternal();
|
||||
return false;
|
||||
}
|
||||
|
||||
sprintf(buffer, "FnTable:%s", IVRCompositor_Version);
|
||||
state.compositor = (struct VR_IVRCompositor_FnTable*) VR_GetGenericInterface(buffer, &vrError);
|
||||
if (vrError != EVRInitError_VRInitError_None || !state.compositor) {
|
||||
VR_ShutdownInternal();
|
||||
return false;
|
||||
}
|
||||
|
||||
sprintf(buffer, "FnTable:%s", IVRChaperone_Version);
|
||||
state.chaperone = (struct VR_IVRChaperone_FnTable*) VR_GetGenericInterface(buffer, &vrError);
|
||||
if (vrError != EVRInitError_VRInitError_None || !state.chaperone) {
|
||||
VR_ShutdownInternal();
|
||||
return false;
|
||||
}
|
||||
|
||||
sprintf(buffer, "FnTable:%s", IVRRenderModels_Version);
|
||||
state.renderModels = (struct VR_IVRRenderModels_FnTable*) VR_GetGenericInterface(buffer, &vrError);
|
||||
if (vrError != EVRInitError_VRInitError_None || !state.renderModels) {
|
||||
VR_ShutdownInternal();
|
||||
return false;
|
||||
}
|
||||
|
||||
state.system->GetStringTrackedDeviceProperty(k_unTrackedDeviceIndex_Hmd, ETrackedDeviceProperty_Prop_ManufacturerName_String, buffer, 128, NULL);
|
||||
state.system->GetStringTrackedDeviceProperty(HEADSET_INDEX, ETrackedDeviceProperty_Prop_ManufacturerName_String, buffer, 128, NULL);
|
||||
|
||||
if (!strncmp(buffer, "HTC", 128)) {
|
||||
state.type = HEADSET_VIVE;
|
||||
|
@ -271,23 +222,16 @@ static bool openvrInit(float offset, int msaa) {
|
|||
state.type = HEADSET_UNKNOWN;
|
||||
}
|
||||
|
||||
state.headsetIndex = k_unTrackedDeviceIndex_Hmd;
|
||||
state.isMirrored = true;
|
||||
state.mirrorEye = EYE_BOTH;
|
||||
state.offset = state.compositor->GetTrackingSpace() == ETrackingUniverseOrigin_TrackingUniverseStanding ? 0. : offset;
|
||||
state.msaa = msaa;
|
||||
state.canvas = NULL;
|
||||
state.clipNear = 0.1f;
|
||||
state.clipFar = 30.f;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
state.deviceModels[i] = NULL;
|
||||
state.deviceTextures[i] = NULL;
|
||||
}
|
||||
state.offset = state.compositor->GetTrackingSpace() == ETrackingUniverseOrigin_TrackingUniverseStanding ? 0. : offset;
|
||||
state.msaa = msaa;
|
||||
|
||||
vec_init(&state.controllers);
|
||||
for (uint32_t i = 0; i < k_unMaxTrackedDeviceCount; i++) {
|
||||
if (openvrIsController(i)) {
|
||||
if (isController(i)) {
|
||||
Controller* controller = lovrAlloc(Controller, free);
|
||||
if (!controller) continue;
|
||||
controller->id = i;
|
||||
|
@ -334,7 +278,7 @@ static HeadsetOrigin openvrGetOriginType() {
|
|||
|
||||
static bool openvrIsMounted() {
|
||||
VRControllerState_t input;
|
||||
state.system->GetControllerState(state.headsetIndex, &input, sizeof(input));
|
||||
state.system->GetControllerState(HEADSET_INDEX, &input, sizeof(input));
|
||||
return (input.ulButtonPressed >> EVRButtonId_k_EButton_ProximitySensor) & 1;
|
||||
}
|
||||
|
||||
|
@ -349,9 +293,7 @@ static void openvrSetMirrored(bool mirror, HeadsetEye eye) {
|
|||
}
|
||||
|
||||
static void openvrGetDisplayDimensions(int* width, int* height) {
|
||||
ensureCanvas();
|
||||
*width = lovrCanvasGetWidth(state.canvas);
|
||||
*height = lovrCanvasGetHeight(state.canvas);
|
||||
state.system->GetRecommendedRenderTargetSize(width, height);
|
||||
}
|
||||
|
||||
static void openvrGetClipDistance(float* clipNear, float* clipFar) {
|
||||
|
@ -369,73 +311,42 @@ static void openvrGetBoundsDimensions(float* width, float* depth) {
|
|||
}
|
||||
|
||||
static void openvrGetPose(float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
TrackedDevicePose_t pose = state.poses[state.headsetIndex];
|
||||
|
||||
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
|
||||
*x = *y = *z = *angle = *ax = *ay = *az = 0.f;
|
||||
return;
|
||||
}
|
||||
|
||||
float transform[16];
|
||||
mat4_fromMat44(transform, pose.mDeviceToAbsoluteTracking.m);
|
||||
|
||||
*x = transform[12];
|
||||
*y = transform[13];
|
||||
*z = transform[14];
|
||||
|
||||
float rotation[4];
|
||||
quat_fromMat4(rotation, transform);
|
||||
quat_getAngleAxis(rotation, angle, ax, ay, az);
|
||||
getTransform(HEADSET_INDEX, transform);
|
||||
mat4_getPose(transform, x, y, z, angle, ax, ay, az);
|
||||
}
|
||||
|
||||
static void openvrGetEyePose(HeadsetEye eye, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
TrackedDevicePose_t pose = state.poses[state.headsetIndex];
|
||||
|
||||
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
|
||||
*x = *y = *z = *angle = *ax = *ay = *az = 0.f;
|
||||
return;
|
||||
}
|
||||
|
||||
float transform[16];
|
||||
float eyeTransform[16];
|
||||
EVREye vrEye = (eye == EYE_LEFT) ? EVREye_Eye_Left : EVREye_Eye_Right;
|
||||
mat4_fromMat34(eyeTransform, state.system->GetEyeToHeadTransform(vrEye).m);
|
||||
mat4_fromMat44(transform, pose.mDeviceToAbsoluteTracking.m);
|
||||
|
||||
float transform[16];
|
||||
getTransform(HEADSET_INDEX, transform);
|
||||
mat4_multiply(transform, eyeTransform);
|
||||
|
||||
*x = transform[12];
|
||||
*y = transform[13];
|
||||
*z = transform[14];
|
||||
|
||||
float rotation[4];
|
||||
quat_fromMat4(rotation, transform);
|
||||
quat_getAngleAxis(rotation, angle, ax, ay, az);
|
||||
mat4_getPose(transform, x, y, z, angle, ax, ay, az);
|
||||
}
|
||||
|
||||
static void openvrGetVelocity(float* x, float* y, float* z) {
|
||||
TrackedDevicePose_t pose = state.poses[state.headsetIndex];
|
||||
|
||||
TrackedDevicePose_t pose = state.poses[HEADSET_INDEX];
|
||||
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
|
||||
*x = *y = *z = 0.f;
|
||||
return;
|
||||
} else {
|
||||
*x = pose.vVelocity.v[0];
|
||||
*y = pose.vVelocity.v[1];
|
||||
*z = pose.vVelocity.v[2];
|
||||
}
|
||||
|
||||
*x = pose.vVelocity.v[0];
|
||||
*y = pose.vVelocity.v[1];
|
||||
*z = pose.vVelocity.v[2];
|
||||
}
|
||||
|
||||
static void openvrGetAngularVelocity(float* x, float* y, float* z) {
|
||||
TrackedDevicePose_t pose = state.poses[state.headsetIndex];
|
||||
|
||||
TrackedDevicePose_t pose = state.poses[HEADSET_INDEX];
|
||||
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
|
||||
*x = *y = *z = 0.f;
|
||||
return;
|
||||
} else {
|
||||
*x = pose.vAngularVelocity.v[0];
|
||||
*y = pose.vAngularVelocity.v[1];
|
||||
*z = pose.vAngularVelocity.v[2];
|
||||
}
|
||||
|
||||
*x = pose.vAngularVelocity.v[0];
|
||||
*y = pose.vAngularVelocity.v[1];
|
||||
*z = pose.vAngularVelocity.v[2];
|
||||
}
|
||||
|
||||
static Controller** openvrGetControllers(uint8_t* count) {
|
||||
|
@ -456,23 +367,9 @@ static ControllerHand openvrControllerGetHand(Controller* controller) {
|
|||
}
|
||||
|
||||
static void openvrControllerGetPose(Controller* controller, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
TrackedDevicePose_t pose = state.poses[controller->id];
|
||||
|
||||
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
|
||||
*x = *y = *z = *angle = *ax = *ay = *az = 0.f;
|
||||
return;
|
||||
}
|
||||
|
||||
float transform[16];
|
||||
mat4_fromMat44(transform, pose.mDeviceToAbsoluteTracking.m);
|
||||
|
||||
*x = transform[12];
|
||||
*y = transform[13];
|
||||
*z = transform[14];
|
||||
|
||||
float rotation[4];
|
||||
quat_fromMat4(rotation, transform);
|
||||
quat_getAngleAxis(rotation, angle, ax, ay, az);
|
||||
getTransform(controller->id, transform);
|
||||
mat4_getPose(transform, x, y, z, angle, ax, ay, az);
|
||||
}
|
||||
|
||||
static float openvrControllerGetAxis(Controller* controller, ControllerAxis axis) {
|
||||
|
@ -519,7 +416,6 @@ static bool openvrControllerIsTouched(Controller* controller, ControllerButton b
|
|||
|
||||
static void openvrControllerVibrate(Controller* controller, float duration, float power) {
|
||||
if (duration <= 0) return;
|
||||
|
||||
uint32_t axis = 0;
|
||||
unsigned short uSeconds = (unsigned short) (duration * 1e6);
|
||||
state.system->TriggerHapticPulse(controller->id, axis, uSeconds);
|
||||
|
@ -634,12 +530,22 @@ static ModelData* openvrControllerNewModelData(Controller* controller) {
|
|||
}
|
||||
|
||||
static void openvrRenderTo(void (*callback)(void*), void* userdata) {
|
||||
float head[16], eye[16];
|
||||
if (!state.canvas) {
|
||||
uint32_t width, height;
|
||||
state.system->GetRecommendedRenderTargetSize(&width, &height);
|
||||
CanvasFlags flags = { .depth = { true, false, FORMAT_D24S8 }, .stereo = true, .msaa = state.msaa };
|
||||
state.canvas = lovrCanvasCreate(width * 2, height, flags);
|
||||
Texture* texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, true, false, state.msaa);
|
||||
lovrTextureAllocate(texture, width * 2, height, 1, FORMAT_RGBA);
|
||||
lovrCanvasSetAttachments(state.canvas, &(Attachment) { texture, 0, 0 }, 1);
|
||||
lovrRelease(texture);
|
||||
}
|
||||
|
||||
ensureCanvas();
|
||||
mat4_fromMat34(head, state.poses[state.headsetIndex].mDeviceToAbsoluteTracking.m);
|
||||
Camera camera = { .canvas = state.canvas };
|
||||
|
||||
float head[16], eye[16];
|
||||
getTransform(HEADSET_INDEX, head);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
EVREye vrEye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right;
|
||||
mat4_fromMat44(camera.projection[i], state.system->GetProjectionMatrix(vrEye, state.clipNear, state.clipFar).m);
|
||||
|
|
Loading…
Reference in New Issue