mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Add Cardboard VR
Based on hrydgard/ppsspp/pull/12449
This commit is contained in:
		
							parent
							
								
									da3a9bfc96
								
							
						
					
					
						commit
						60235827c5
					
				
					 5 changed files with 174 additions and 6 deletions
				
			
		|  | @ -73,6 +73,14 @@ static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigne | |||
|                   framebuffer_x < layout.bottom_screen.right / 2) || | ||||
|                  (framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) && | ||||
|                   framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2)))); | ||||
|     } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||
|         return (framebuffer_y >= layout.bottom_screen.top && | ||||
|                 framebuffer_y < layout.bottom_screen.bottom && | ||||
|                 ((framebuffer_x >= layout.bottom_screen.left && | ||||
|                   framebuffer_x < layout.bottom_screen.right) || | ||||
|                  (framebuffer_x >= layout.cardboard.bottom_screen_right_eye + (layout.width / 2) && | ||||
|                   framebuffer_x < layout.cardboard.bottom_screen_right_eye + | ||||
|                                       layout.bottom_screen.GetWidth() + (layout.width / 2)))); | ||||
|     } else { | ||||
|         return (framebuffer_y >= layout.bottom_screen.top && | ||||
|                 framebuffer_y < layout.bottom_screen.bottom && | ||||
|  | @ -82,9 +90,14 @@ static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigne | |||
| } | ||||
| 
 | ||||
| std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { | ||||
|         if (new_x >= framebuffer_layout.width / 2) | ||||
|     if (new_x >= framebuffer_layout.width / 2) { | ||||
|         if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) | ||||
|             new_x -= framebuffer_layout.width / 2; | ||||
|         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) | ||||
|             new_x -= | ||||
|                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||
|     } | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { | ||||
|         new_x = std::max(new_x, framebuffer_layout.bottom_screen.left / 2); | ||||
|         new_x = std::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1); | ||||
|     } else { | ||||
|  | @ -102,9 +115,13 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | |||
|     if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | ||||
|         return; | ||||
| 
 | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide && | ||||
|         framebuffer_x >= framebuffer_layout.width / 2) | ||||
|         framebuffer_x -= framebuffer_layout.width / 2; | ||||
|     if (framebuffer_x >= framebuffer_layout.width / 2) { | ||||
|         if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) | ||||
|             framebuffer_x -= framebuffer_layout.width / 2; | ||||
|         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) | ||||
|             framebuffer_x -= | ||||
|                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||
|     } | ||||
|     std::lock_guard guard(touch_state->mutex); | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { | ||||
|         touch_state->touch_x = | ||||
|  | @ -191,6 +208,9 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height, | |||
|         } | ||||
|         UpdateMinimumWindowSize(min_size); | ||||
|     } | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||
|         layout = Layout::GetCardboardSettings(layout); | ||||
|     } | ||||
|     NotifyFramebufferLayoutChanged(layout); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -452,9 +452,92 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { | |||
|             break; | ||||
|         } | ||||
|     } | ||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||
|         layout = Layout::GetCardboardSettings(layout); | ||||
|     } | ||||
|     return layout; | ||||
| } | ||||
| 
 | ||||
| FramebufferLayout GetCardboardSettings(FramebufferLayout layout) { | ||||
|     FramebufferLayout newLayout = layout; | ||||
|     float top_screen_left = 0; | ||||
|     float top_screen_top = 0; | ||||
|     float bottom_screen_left = 0; | ||||
|     float bottom_screen_top = 0; | ||||
| 
 | ||||
|     float cardboardScreenScale = Settings::values.cardboard_screen_size / 100.0f; | ||||
|     float top_screen_width = layout.top_screen.GetWidth() / 2.0f * cardboardScreenScale; | ||||
|     float top_screen_height = layout.top_screen.GetHeight() / 2.0f * cardboardScreenScale; | ||||
|     float bottom_screen_width = layout.bottom_screen.GetWidth() / 2.0f * cardboardScreenScale; | ||||
|     float bottom_screen_height = layout.bottom_screen.GetHeight() / 2.0f * cardboardScreenScale; | ||||
|     bool is_swapped = Settings::values.swap_screen; | ||||
|     bool is_portrait = layout.height > layout.width; | ||||
| 
 | ||||
|     float cardboardScreenWidth; | ||||
|     float cardboardScreenHeight; | ||||
|     switch (Settings::values.layout_option) { | ||||
|     case Settings::LayoutOption::MobileLandscape: | ||||
|     case Settings::LayoutOption::SideScreen: | ||||
|         // If orientation is portrait, only use MobilePortrait
 | ||||
|         if (!is_portrait) { | ||||
|             cardboardScreenWidth = top_screen_width + bottom_screen_width; | ||||
|             cardboardScreenHeight = is_swapped ? bottom_screen_height : top_screen_height; | ||||
|             if (is_swapped) | ||||
|                 top_screen_left += bottom_screen_width; | ||||
|             else | ||||
|                 bottom_screen_left += top_screen_width; | ||||
|             break; | ||||
|         } else { | ||||
|             [[fallthrough]]; | ||||
|         } | ||||
|     case Settings::LayoutOption::SingleScreen: | ||||
|     default: | ||||
|         if (!is_portrait) { | ||||
|             // Default values when using LayoutOption::SingleScreen
 | ||||
|             cardboardScreenWidth = is_swapped ? bottom_screen_width : top_screen_width; | ||||
|             cardboardScreenHeight = is_swapped ? bottom_screen_height : top_screen_height; | ||||
|             break; | ||||
|         } else { | ||||
|             [[fallthrough]]; | ||||
|         } | ||||
|     case Settings::LayoutOption::MobilePortrait: | ||||
|         cardboardScreenWidth = top_screen_width; | ||||
|         cardboardScreenHeight = top_screen_height + bottom_screen_height; | ||||
|         bottom_screen_left += (top_screen_width - bottom_screen_width) / 2.0f; | ||||
|         if (is_swapped) | ||||
|             top_screen_top += bottom_screen_height; | ||||
|         else | ||||
|             bottom_screen_top += top_screen_height; | ||||
|         break; | ||||
|     } | ||||
|     float cardboardMaxXShift = (layout.width / 2.0f - cardboardScreenWidth) / 2.0f; | ||||
|     float cardboardUserXShift = (Settings::values.cardboard_x_shift / 100.0f) * cardboardMaxXShift; | ||||
|     float cardboardMaxYShift = ((float)layout.height - cardboardScreenHeight) / 2.0f; | ||||
|     float cardboardUserYShift = (Settings::values.cardboard_y_shift / 100.0f) * cardboardMaxYShift; | ||||
| 
 | ||||
|     // Center the screens and apply user Y shift
 | ||||
|     newLayout.top_screen.left = top_screen_left + cardboardMaxXShift; | ||||
|     newLayout.top_screen.top = top_screen_top + cardboardMaxYShift + cardboardUserYShift; | ||||
|     newLayout.bottom_screen.left = bottom_screen_left + cardboardMaxXShift; | ||||
|     newLayout.bottom_screen.top = bottom_screen_top + cardboardMaxYShift + cardboardUserYShift; | ||||
| 
 | ||||
|     // Set the X coordinates for the right eye and apply user X shift
 | ||||
|     newLayout.cardboard.top_screen_right_eye = newLayout.top_screen.left - cardboardUserXShift; | ||||
|     newLayout.top_screen.left += cardboardUserXShift; | ||||
|     newLayout.cardboard.bottom_screen_right_eye = | ||||
|         newLayout.bottom_screen.left - cardboardUserXShift; | ||||
|     newLayout.bottom_screen.left += cardboardUserXShift; | ||||
|     newLayout.cardboard.user_x_shift = cardboardUserXShift; | ||||
| 
 | ||||
|     // Update right/bottom instead of passing new variables for width/height
 | ||||
|     newLayout.top_screen.right = newLayout.top_screen.left + top_screen_width; | ||||
|     newLayout.top_screen.bottom = newLayout.top_screen.top + top_screen_height; | ||||
|     newLayout.bottom_screen.right = newLayout.bottom_screen.left + bottom_screen_width; | ||||
|     newLayout.bottom_screen.bottom = newLayout.bottom_screen.top + bottom_screen_height; | ||||
| 
 | ||||
|     return newLayout; | ||||
| } | ||||
| 
 | ||||
| std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | ||||
|                                                        bool upright_screen) { | ||||
|     unsigned min_width, min_height; | ||||
|  |  | |||
|  | @ -9,6 +9,13 @@ | |||
| 
 | ||||
| namespace Layout { | ||||
| 
 | ||||
| /// Describes the horizontal coordinates for the right eye screen when using Cardboard VR
 | ||||
| struct CardboardSettings { | ||||
|     float top_screen_right_eye; | ||||
|     float bottom_screen_right_eye; | ||||
|     float user_x_shift; | ||||
| }; | ||||
| 
 | ||||
| /// Describes the layout of the window framebuffer (size and top/bottom screen positions)
 | ||||
| struct FramebufferLayout { | ||||
|     u32 width; | ||||
|  | @ -19,6 +26,8 @@ struct FramebufferLayout { | |||
|     Common::Rectangle<u32> bottom_screen; | ||||
|     bool is_rotated = true; | ||||
| 
 | ||||
|     CardboardSettings cardboard; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Returns the ration of pixel size of the top screen, compared to the native size of the 3DS | ||||
|      * screen. | ||||
|  | @ -104,6 +113,13 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height); | |||
|  */ | ||||
| FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale); | ||||
| 
 | ||||
| /**
 | ||||
|  * Convenience method for transforming a frame layout when using Cardboard VR | ||||
|  * @param layout frame layout to transform | ||||
|  * @return layout transformed with the user cardboard settings | ||||
|  */ | ||||
| FramebufferLayout GetCardboardSettings(FramebufferLayout layout); | ||||
| 
 | ||||
| std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | ||||
|                                                        bool upright_screen); | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,7 +40,14 @@ enum class MicInputType { | |||
|     Static, | ||||
| }; | ||||
| 
 | ||||
| enum class StereoRenderOption { Off, SideBySide, Anaglyph, Interlaced, ReverseInterlaced }; | ||||
| enum class StereoRenderOption { | ||||
|     Off, | ||||
|     SideBySide, | ||||
|     Anaglyph, | ||||
|     Interlaced, | ||||
|     ReverseInterlaced, | ||||
|     CardboardVR | ||||
| }; | ||||
| 
 | ||||
| namespace NativeButton { | ||||
| enum Values { | ||||
|  | @ -190,6 +197,10 @@ struct Values { | |||
|     StereoRenderOption render_3d; | ||||
|     std::atomic<u8> factor_3d; | ||||
| 
 | ||||
|     int cardboard_screen_size; | ||||
|     int cardboard_x_shift; | ||||
|     int cardboard_y_shift; | ||||
| 
 | ||||
|     bool filter_mode; | ||||
|     std::string pp_shader_name; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue