Exemplo n.º 1
0
OVR_PUBLIC_FUNCTION(ovrResult) ovr_SubmitFrame(ovrSession session, long long frameIndex, const ovrViewScaleDesc* viewScaleDesc,
	ovrLayerHeader const * const * layerPtrList, unsigned int layerCount)
{
	// TODO: Implement scaling through ApplyTransform().

	// Call WaitGetPoses() to do some cleanup from the previous frame.
	session->compositor->WaitGetPoses(session->poses, vr::k_unMaxTrackedDeviceCount, session->gamePoses, vr::k_unMaxTrackedDeviceCount);

	if (layerCount == 0)
		return ovrError_InvalidParameter;

	// The first layer is assumed to be the application scene.
	if (layerPtrList[0]->Type != ovrLayerType_EyeFov)
		return ovrSuccess_NotVisible;
	ovrLayerEyeFov* sceneLayer = (ovrLayerEyeFov*)layerPtrList[0];

	// Other layers are interpreted as overlays.
	for (size_t i = 1; i < vr::k_unMaxOverlayCount + 1; i++)
	{
		char keyName[vr::k_unVROverlayMaxKeyLength];
		snprintf(keyName, vr::k_unVROverlayMaxKeyLength, "Revive_%d", i);

		// Look if the overlay already exists.
		vr::VROverlayHandle_t overlay;
		vr::EVROverlayError err = session->overlay->FindOverlay(keyName, &overlay);

		// If this layer is defined in the list, show it. If not, hide the layer if it exists.
		if (i < layerCount)
		{
			// Create a new overlay if it doesn't exist.
			if (err == vr::VROverlayError_UnknownOverlay)
			{
				char title[vr::k_unVROverlayMaxNameLength];
				snprintf(title, vr::k_unVROverlayMaxNameLength, "Revive Layer %d", i);
				session->overlay->CreateOverlay(keyName, title, &overlay);
			}

			// A layer was added, but not defined, hide it.
			if (layerPtrList[i] == nullptr)
			{
				session->overlay->HideOverlay(overlay);
				continue;
			}

			// Overlays are assumed to be monoscopic quads.
			_ASSERT(layerPtrList[i]->Type == ovrLayerType_Quad);

			ovrLayerQuad* layer = (ovrLayerQuad*)layerPtrList[i];

			// Set the high quality overlay.
			if (layer->Header.Flags & ovrLayerFlag_HighQuality)
				session->overlay->SetHighQualityOverlay(overlay);

			// Transform the overlay.
			vr::HmdMatrix34_t transform = REV_OvrPoseToHmdMatrix(layer->QuadPoseCenter);
			session->overlay->SetOverlayWidthInMeters(overlay, layer->QuadSize.x);
			if (layer->Header.Flags & ovrLayerFlag_HeadLocked)
				session->overlay->SetOverlayTransformTrackedDeviceRelative(overlay, vr::k_unTrackedDeviceIndex_Hmd, &transform);
			else
				session->overlay->SetOverlayTransformAbsolute(overlay, session->compositor->GetTrackingSpace(), &transform);

			// Set the texture and show the overlay.
			ovrTextureSwapChain chain = layer->ColorTexture;
			vr::VRTextureBounds_t bounds = REV_ViewportToTextureBounds(layer->Viewport, layer->ColorTexture, layer->Header.Flags);
			session->overlay->SetOverlayTextureBounds(overlay, &bounds);
			session->overlay->SetOverlayTexture(overlay, &chain->current);

			// TODO: Handle overlay errors.
			session->overlay->ShowOverlay(overlay);
		}
		else
		{
			if (err == vr::VROverlayError_UnknownOverlay)
				break;

			// Hide all overlays no longer visible.
			session->overlay->HideOverlay(overlay);
		}
	}

	// Submit the scene layer.
	for (int i = 0; i < ovrEye_Count; i++)
	{
		ovrTextureSwapChain chain = sceneLayer->ColorTexture[i];
		session->ColorTexture[i] = chain;
		vr::VRTextureBounds_t bounds = REV_ViewportToTextureBounds(sceneLayer->Viewport[i], sceneLayer->ColorTexture[i], sceneLayer->Header.Flags);
		vr::EVRCompositorError err = session->compositor->Submit((vr::EVREye)i, &chain->current, &bounds);
		if (err != vr::VRCompositorError_None)
			return REV_CompositorErrorToOvrError(err);
	}

	return ovrSuccess;
}
Exemplo n.º 2
0
OVR_PUBLIC_FUNCTION(ovrResult) ovr_SubmitFrame(ovrSession session, long long frameIndex, const ovrViewScaleDesc* viewScaleDesc,
	ovrLayerHeader const * const * layerPtrList, unsigned int layerCount)
{
	// TODO: Implement scaling through ApplyTransform().

	if (!session)
		return ovrError_InvalidSession;

	if (layerCount == 0 || !layerPtrList)
		return ovrError_InvalidParameter;

	// Other layers are interpreted as overlays.
	for (size_t i = 0; i < ovrMaxLayerCount; i++)
	{
		// If this layer is defined in the list, show it. If not, hide the layer if it exists.
		if (i < layerCount)
		{
			// Create a new overlay if it doesn't exist.
			if (session->overlays[i] == vr::k_ulOverlayHandleInvalid)
			{
				char keyName[vr::k_unVROverlayMaxKeyLength];
				snprintf(keyName, vr::k_unVROverlayMaxKeyLength, "revive.runtime.layer%d", i);
				char title[vr::k_unVROverlayMaxNameLength];
				snprintf(title, vr::k_unVROverlayMaxNameLength, "Revive Layer %d", i);
				session->overlay->CreateOverlay(keyName, title, &session->overlays[i]);
			}

			// A layer was added, but not defined, hide it.
			if (layerPtrList[i] == nullptr)
			{
				session->overlay->HideOverlay(session->overlays[i]);
				continue;
			}

			// Overlays are assumed to be monoscopic quads.
			if (layerPtrList[i]->Type != ovrLayerType_Quad)
				continue;

			ovrLayerQuad* layer = (ovrLayerQuad*)layerPtrList[i];

			// Set the high quality overlay.
			// FIXME: Why are High quality overlays headlocked in OpenVR?
			//if (layer->Header.Flags & ovrLayerFlag_HighQuality)
			//	session->overlay->SetHighQualityOverlay(overlay);

			// Transform the overlay.
			vr::HmdMatrix34_t transform = REV_OvrPoseToHmdMatrix(layer->QuadPoseCenter);
			session->overlay->SetOverlayWidthInMeters(session->overlays[i], layer->QuadSize.x);
			if (layer->Header.Flags & ovrLayerFlag_HeadLocked)
				session->overlay->SetOverlayTransformTrackedDeviceRelative(session->overlays[i], vr::k_unTrackedDeviceIndex_Hmd, &transform);
			else
				session->overlay->SetOverlayTransformAbsolute(session->overlays[i], session->compositor->GetTrackingSpace(), &transform);

			// Set the texture and show the overlay.
			ovrTextureSwapChain chain = layer->ColorTexture;
			vr::VRTextureBounds_t bounds = REV_ViewportToTextureBounds(layer->Viewport, layer->ColorTexture, layer->Header.Flags);
			session->overlay->SetOverlayTextureBounds(session->overlays[i], &bounds);
			session->overlay->SetOverlayTexture(session->overlays[i], &chain->current);

			// TODO: Handle overlay errors.
			session->overlay->ShowOverlay(session->overlays[i]);
		}
		else
		{
			if (session->overlays[i] != vr::k_ulOverlayHandleInvalid)
			{
				// Destory all overlays no longer listed.
				session->overlay->DestroyOverlay(session->overlays[i]);
				session->overlays[i] = vr::k_ulOverlayHandleInvalid;
			}
		}
	}

	// The first layer is assumed to be the application scene.
	vr::EVRCompositorError err = vr::VRCompositorError_None;
	if (layerPtrList[0]->Type == ovrLayerType_EyeFov)
	{
		ovrLayerEyeFov* sceneLayer = (ovrLayerEyeFov*)layerPtrList[0];

		// Submit the scene layer.
		for (int i = 0; i < ovrEye_Count; i++)
		{
			ovrTextureSwapChain chain = sceneLayer->ColorTexture[i];
			vr::VRTextureBounds_t bounds = REV_ViewportToTextureBounds(sceneLayer->Viewport[i], sceneLayer->ColorTexture[i], sceneLayer->Header.Flags);

			float left, right, top, bottom;
			g_VRSystem->GetProjectionRaw((vr::EVREye)i, &left, &right, &top, &bottom);

			// Shrink the bounds to account for the overlapping fov
			ovrFovPort fov = sceneLayer->Fov[i];
			float uMin = 0.5f + 0.5f * left / fov.LeftTan;
			float uMax = 0.5f + 0.5f * right / fov.RightTan;
			float vMin = 0.5f - 0.5f * bottom / fov.UpTan;
			float vMax = 0.5f - 0.5f * top / fov.DownTan;

			// Combine the fov bounds with the viewport bounds
			bounds.uMin += uMin * bounds.uMax;
			bounds.uMax *= uMax;
			bounds.vMin += vMin * bounds.vMax;
			bounds.vMax *= vMax;

			if (chain->texture[i].eType == vr::API_OpenGL)
			{
				bounds.vMin = 1.0f - bounds.vMin;
				bounds.vMax = 1.0f - bounds.vMax;
			}

			err = session->compositor->Submit((vr::EVREye)i, &chain->current, &bounds);
			if (err != vr::VRCompositorError_None)
				break;
		}
	}

	// The first layer is assumed to be the application scene.
	if (layerPtrList[0]->Type == ovrLayerType_EyeMatrix)
	{
		ovrLayerEyeMatrix* sceneLayer = (ovrLayerEyeMatrix*)layerPtrList[0];

		// Submit the scene layer.
		for (int i = 0; i < ovrEye_Count; i++)
		{
			ovrTextureSwapChain chain = sceneLayer->ColorTexture[i];
			vr::VRTextureBounds_t bounds = REV_ViewportToTextureBounds(sceneLayer->Viewport[i], sceneLayer->ColorTexture[i], sceneLayer->Header.Flags);

			float left, right, top, bottom;
			g_VRSystem->GetProjectionRaw((vr::EVREye)i, &left, &right, &top, &bottom);

			// Shrink the bounds to account for the overlapping fov
			ovrVector2f fov = { .5f / sceneLayer->Matrix[i].M[0][0], .5f / sceneLayer->Matrix[i].M[1][1] };
			float uMin = 0.5f + 0.5f * left / fov.x;
			float uMax = 0.5f + 0.5f * right / fov.x;
			float vMin = 0.5f - 0.5f * bottom / fov.y;
			float vMax = 0.5f - 0.5f * top / fov.y;

			// Combine the fov bounds with the viewport bounds
			bounds.uMin += uMin * bounds.uMax;
			bounds.uMax *= uMax;
			bounds.vMin += vMin * bounds.vMax;
			bounds.vMax *= vMax;

			if (chain->texture[i].eType == vr::API_OpenGL)
			{
				bounds.vMin = 1.0f - bounds.vMin;
				bounds.vMax = 1.0f - bounds.vMax;
			}

			err = session->compositor->Submit((vr::EVREye)i, &chain->current, &bounds);
			if (err != vr::VRCompositorError_None)
				break;
		}
	}

	// Call WaitGetPoses() to do some cleanup from the previous frame.
	session->compositor->WaitGetPoses(session->poses, vr::k_unMaxTrackedDeviceCount, session->gamePoses, vr::k_unMaxTrackedDeviceCount);
	g_FrameIndex = frameIndex;

	return REV_CompositorErrorToOvrError(err);
}