Skip to content

Commit

Permalink
Add Cardboard VR
Browse files Browse the repository at this point in the history
  • Loading branch information
mosamadeeb authored and xperia64 committed Jan 10, 2021
1 parent da303ae commit 521a2f0
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,11 @@ private void addGraphicsSettings(ArrayList<SettingsItem> sl) {
Setting render3dMode = rendererSection.getSetting(SettingsFile.KEY_RENDER_3D);
Setting factor3d = rendererSection.getSetting(SettingsFile.KEY_FACTOR_3D);

SettingSection layoutSection = mSettings.getSection(Settings.SECTION_LAYOUT);
Setting cardboardScreenSize = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_SCREEN_SIZE);
Setting cardboardXShift = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_X_SHIFT);
Setting cardboardYShift = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_Y_SHIFT);

sl.add(new HeaderSetting(null, null, R.string.renderer, 0));
sl.add(new SliderSetting(SettingsFile.KEY_RESOLUTION_FACTOR, Settings.SECTION_RENDERER, R.string.internal_resolution, R.string.internal_resolution_description, 1, 4, "x", 1, resolutionFactor));
sl.add(new CheckBoxSetting(SettingsFile.KEY_FILTER_MODE, Settings.SECTION_RENDERER, R.string.linear_filtering, R.string.linear_filtering_description, true, filterMode));
Expand All @@ -367,6 +372,11 @@ private void addGraphicsSettings(ArrayList<SettingsItem> sl) {
sl.add(new HeaderSetting(null, null, R.string.stereoscopy, 0));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_RENDER_3D, Settings.SECTION_RENDERER, R.string.render3d, 0, R.array.render3dModes, R.array.render3dValues, 0, render3dMode));
sl.add(new SliderSetting(SettingsFile.KEY_FACTOR_3D, Settings.SECTION_RENDERER, R.string.factor3d, R.string.factor3d_description, 0, 100, "%", 0, factor3d));

sl.add(new HeaderSetting(null, null, R.string.cardboard_vr, 0));
sl.add(new SliderSetting(SettingsFile.KEY_CARDBOARD_SCREEN_SIZE, Settings.SECTION_LAYOUT, R.string.cardboard_screen_size, R.string.cardboard_screen_size_description, 30, 100, "%", 85, cardboardScreenSize));
sl.add(new SliderSetting(SettingsFile.KEY_CARDBOARD_X_SHIFT, Settings.SECTION_LAYOUT, R.string.cardboard_x_shift, R.string.cardboard_x_shift_description, -100, 100, "%", 0, cardboardXShift));
sl.add(new SliderSetting(SettingsFile.KEY_CARDBOARD_Y_SHIFT, Settings.SECTION_LAYOUT, R.string.cardboard_y_shift, R.string.cardboard_y_shift_description, -100, 100, "%", 0, cardboardYShift));
}

private void addAudioSettings(ArrayList<SettingsItem> sl) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public final class SettingsFile {

public static final String KEY_LAYOUT_OPTION = "layout_option";
public static final String KEY_SWAP_SCREEN = "swap_screen";
public static final String KEY_CARDBOARD_SCREEN_SIZE = "cardboard_screen_size";
public static final String KEY_CARDBOARD_X_SHIFT = "cardboard_x_shift";
public static final String KEY_CARDBOARD_Y_SHIFT = "cardboard_y_shift";

public static final String KEY_AUDIO_OUTPUT_ENGINE = "output_engine";
public static final String KEY_ENABLE_AUDIO_STRETCHING = "enable_audio_stretching";
Expand Down
6 changes: 6 additions & 0 deletions src/android/app/src/main/jni/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ void Config::ReadValues() {
static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_right", 360));
Settings::values.custom_bottom_bottom =
static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_bottom", 480));
Settings::values.cardboard_screen_size =
static_cast<int>(sdl2_config->GetInteger("Layout", "cardboard_screen_size", 85));
Settings::values.cardboard_x_shift =
static_cast<int>(sdl2_config->GetInteger("Layout", "cardboard_x_shift", 0));
Settings::values.cardboard_y_shift =
static_cast<int>(sdl2_config->GetInteger("Layout", "cardboard_y_shift", 0));

// Audio
Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false);
Expand Down
10 changes: 9 additions & 1 deletion src/android/app/src/main/jni/default_ini.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ bg_blue =
bg_green =
# Whether and how Stereoscopic 3D should be rendered
# 0 (default): Off, 1: Side by Side, 2: Anaglyph, 3: Interlaced
# 0 (default): Off, 1: Side by Side, 2: Anaglyph, 3: Interlaced, 4: Reverse Interlaced, 5: Cardboard VR
render_3d =
# Change 3D Intensity
Expand Down Expand Up @@ -182,6 +182,14 @@ custom_bottom_bottom =
# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
swap_screen =
# Screen placement settings when using Cardboard VR (render3d = 4)
# 30 - 100: Screen size as a percentage of the viewport. 85 (default)
cardboard_screen_size =
# -100 - 100: Screen X-Coordinate shift as a percentage of empty space. 0 (default)
cardboard_x_shift =
# -100 - 100: Screen Y-Coordinate shift as a percentage of empty space. 0 (default)
cardboard_y_shift =
[Audio]
# Whether or not to enable DSP LLE
# 0 (default): No, 1: Yes
Expand Down
4 changes: 4 additions & 0 deletions src/android/app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,16 @@
<item>Side by Side</item>
<item>Anaglyph</item>
<item>Interlaced</item>
<item>Reverse Interlaced</item>
<item>Cardboard VR</item>
</string-array>

<integer-array name="render3dValues">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
</integer-array>
</resources>
7 changes: 7 additions & 0 deletions src/android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@
<string name="render3d">Stereoscopic 3D Mode</string>
<string name="factor3d">Depth</string>
<string name="factor3d_description">Specifies the value of the 3D slider. This should be set to higher than 0% when Stereoscopic 3D is enabled.</string>
<string name="cardboard_vr">Cardboard VR</string>
<string name="cardboard_screen_size">Cardboard Screen size</string>
<string name="cardboard_screen_size_description">Scales the screen to a percentage of its original size.</string>
<string name="cardboard_x_shift">Horizontal shift</string>
<string name="cardboard_x_shift_description">Specifies the percentage of empty space to shift the screens horizontally. Positive values move the two eyes closer to the middle, while negative values move them away.</string>
<string name="cardboard_y_shift">Vertical shift</string>
<string name="cardboard_y_shift_description">Specifies the percentage of empty space to shift the screens vertically. Positive values move the two eyes towards the bottom, while negative values move them towards the top.</string>

<!-- Premium strings -->
<string name="premium_text">Premium</string>
Expand Down
30 changes: 25 additions & 5 deletions src/core/frontend/emu_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand All @@ -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 {
Expand All @@ -102,9 +115,13 @@ bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y))
return false;

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 =
Expand Down Expand Up @@ -192,6 +209,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);
}

Expand Down
83 changes: 83 additions & 0 deletions src/core/frontend/framebuffer_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions src/core/frontend/framebuffer_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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);

Expand Down
6 changes: 5 additions & 1 deletion src/core/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ enum class MicInputType {
Static,
};

enum class StereoRenderOption { Off, SideBySide, Anaglyph, Interlaced, ReverseInterlaced };
enum class StereoRenderOption { Off, SideBySide, Anaglyph, Interlaced, ReverseInterlaced, CardboardVR };

enum class GpuTimingMode {
Skip,
Expand Down Expand Up @@ -209,6 +209,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;

Expand Down
Loading

0 comments on commit 521a2f0

Please sign in to comment.