diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java index 6d6301d3d2..c740e5b424 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java @@ -932,7 +932,8 @@ private void enterVRVideo(@VideoProjectionMenuWidget.VideoProjectionFlags int aP mediaHeight = mAttachedWindow.getWindowHeight(); } final boolean resetBorder = aProjection == VideoProjectionMenuWidget.VIDEO_PROJECTION_360 || - aProjection == VideoProjectionMenuWidget.VIDEO_PROJECTION_360_STEREO; + aProjection == VideoProjectionMenuWidget.VIDEO_PROJECTION_360_STEREO || + aProjection == VideoProjectionMenuWidget.VIDEO_PROJECTION_360_STEREO_LEFT_RIGHT; mAttachedWindow.enableVRVideoMode(mediaWidth, mediaHeight, resetBorder); // Handle video resize while in VR video playback if (mFullScreenMedia != null) { diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/VideoProjectionMenuWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/VideoProjectionMenuWidget.java index 4e04165233..f8bf1957f3 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/VideoProjectionMenuWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/VideoProjectionMenuWidget.java @@ -22,7 +22,7 @@ public class VideoProjectionMenuWidget extends MenuWidget { @IntDef(value = { VIDEO_PROJECTION_NONE, VIDEO_PROJECTION_3D_SIDE_BY_SIDE, VIDEO_PROJECTION_360, VIDEO_PROJECTION_360_STEREO, VIDEO_PROJECTION_180, VIDEO_PROJECTION_180_STEREO_LEFT_RIGHT, VIDEO_PROJECTION_180_STEREO_TOP_BOTTOM, - VIDEO_PROJECTION_3D_TOP_BOTTOM }) + VIDEO_PROJECTION_3D_TOP_BOTTOM, VIDEO_PROJECTION_360_STEREO_LEFT_RIGHT }) public @interface VideoProjectionFlags {} public static final int VIDEO_PROJECTION_NONE = -1; @@ -33,6 +33,7 @@ public class VideoProjectionMenuWidget extends MenuWidget { public static final int VIDEO_PROJECTION_180_STEREO_LEFT_RIGHT = 4; public static final int VIDEO_PROJECTION_180_STEREO_TOP_BOTTOM = 5; public static final int VIDEO_PROJECTION_3D_TOP_BOTTOM = 6; + public static final int VIDEO_PROJECTION_360_STEREO_LEFT_RIGHT = 7; public interface Delegate { void onVideoProjectionClick(@VideoProjectionFlags int aProjection); @@ -108,6 +109,9 @@ private void createMenuItems() { mItems.add(new ProjectionMenuItem(VIDEO_PROJECTION_360_STEREO, getContext().getString(R.string.video_mode_360_stereo), R.drawable.ic_icon_videoplayback_360_stereo)); + mItems.add(new ProjectionMenuItem(VIDEO_PROJECTION_360_STEREO_LEFT_RIGHT, getContext().getString(R.string.video_mode_360_stereo_leftright), + R.drawable.ic_icon_videoplayback_360_stereo_leftright)); + mItems.add(new ProjectionMenuItem(VIDEO_PROJECTION_180, getContext().getString(R.string.video_mode_180), R.drawable.ic_icon_videoplayback_180)); @@ -165,7 +169,10 @@ public void setSelectedProjection(@VideoProjectionFlags int aProjection) { autoEnter.set(projection.endsWith("_auto")); - if (projection.startsWith("360s")) { + if (projection.startsWith("360lr")) { + return VIDEO_PROJECTION_360_STEREO_LEFT_RIGHT; + } else if (projection.startsWith("360tb") || projection.startsWith("360s")) { + // "360s" predates the tb/lr distinction and is kept as an alias. return VIDEO_PROJECTION_360_STEREO; } else if (projection.startsWith("360")) { return VIDEO_PROJECTION_360; diff --git a/app/src/main/cpp/VRLayer.cpp b/app/src/main/cpp/VRLayer.cpp index f3961df63e..c9ec577028 100644 --- a/app/src/main/cpp/VRLayer.cpp +++ b/app/src/main/cpp/VRLayer.cpp @@ -30,6 +30,7 @@ struct VRLayer::State { std::function pendingEvent; std::string name; bool composited; + // Clear for layers drawing per-eye content, or both eyes get the left one. bool useSameLayerForBothEyes; State(): initialized(false), diff --git a/app/src/main/cpp/VRVideo.cpp b/app/src/main/cpp/VRVideo.cpp index f7803bb11f..e60c05b949 100644 --- a/app/src/main/cpp/VRVideo.cpp +++ b/app/src/main/cpp/VRVideo.cpp @@ -124,6 +124,10 @@ struct VRVideo::State { leftEye = createSphereProjection(false, device::EyeRect(0.0f, 0.5f, 1.0f, 0.5f)); rightEye = createSphereProjection(false, device::EyeRect(0.0f, 0.0f, 1.0f, 0.5f)); break; + case VRVideoProjection::VIDEO_PROJECTION_360_STEREO_LEFT_RIGHT: + leftEye = createSphereProjection(false, device::EyeRect(0.0f, 0.0f, 0.5f, 1.0f)); + rightEye = createSphereProjection(false, device::EyeRect(0.5f, 0.0f, 0.5f, 1.0f)); + break; case VRVideoProjection::VIDEO_PROJECTION_180: leftEye = createSphereProjection(true, device::EyeRect(0.0f, 0.0f, 1.0f, 1.0f)); break; @@ -152,6 +156,9 @@ struct VRVideo::State { case VRVideoProjection::VIDEO_PROJECTION_360_STEREO: create360StereoProjectionLayer(); break; + case VRVideoProjection::VIDEO_PROJECTION_360_STEREO_LEFT_RIGHT: + create360LRProjectionLayer(); + break; case VRVideoProjection::VIDEO_PROJECTION_180: create180ProjectionLayer(); break; @@ -267,6 +274,32 @@ struct VRVideo::State { rightTransform.ScaleInPlace(vrb::Vector(1.0f, 0.5f, 1.0f)); equirect->SetUVTransform(device::Eye::Right, rightTransform); + // Per-eye UV transforms need one layer per eye, else mono. + equirect->SetUseSameLayerForBothEyes(false); + + leftEye = vrb::Toggle::Create(create); + leftEye->AddNode(VRLayerNode::Create(create, equirect)); + rightEye = vrb::Toggle::Create(create); + rightEye->AddNode(VRLayerNode::Create(create, equirect)); + } + + void create360LRProjectionLayer() { + vrb::CreationContextPtr create = context.lock(); + DeviceDelegatePtr device = deviceWeak.lock(); + VRLayerEquirectPtr equirect = device->CreateLayerEquirect(window->GetLayer()); + layer = equirect; + + vrb::Matrix leftTransform = vrb::Matrix::Identity(); + leftTransform.ScaleInPlace(vrb::Vector(0.5f, 1.0f, 1.0f)); + equirect->SetUVTransform(device::Eye::Left, leftTransform); + + vrb::Matrix rightTransform = vrb::Matrix::Position(vrb::Vector(0.5f, 0.0f, 0.0f)); + rightTransform.ScaleInPlace(vrb::Vector(0.5f, 1.0f, 1.0f)); + equirect->SetUVTransform(device::Eye::Right, rightTransform); + + // Per-eye UV transforms need one layer per eye, else mono. + equirect->SetUseSameLayerForBothEyes(false); + leftEye = vrb::Toggle::Create(create); leftEye->AddNode(VRLayerNode::Create(create, equirect)); rightEye = vrb::Toggle::Create(create); @@ -292,6 +325,8 @@ struct VRVideo::State { vrb::Matrix uvTransform = vrb::Matrix::Identity(); uvTransform.ScaleInPlace(vrb::Vector(2.0f, 1.0f, 1.0f)); + // centers the hemisphere in front of the viewer. + uvTransform.TranslateInPlace(vrb::Vector(-0.5f, 0.0f, 0.0f)); equirect->SetUVTransform(device::Eye::Left, uvTransform); equirect->SetUVTransform(device::Eye::Right, uvTransform); @@ -342,10 +377,15 @@ struct VRVideo::State { vrb::Matrix uvTransform = vrb::Matrix::Identity(); uvTransform.ScaleInPlace(vrb::Vector(2.0f, 0.5f, 1.0f)); + // centers the hemisphere in front of the viewer. + uvTransform.TranslateInPlace(vrb::Vector(-0.5f, 0.0f, 0.0f)); equirect->SetUVTransform(device::Eye::Left, uvTransform); uvTransform.TranslateInPlace(vrb::Vector(0.0f, 0.5f, 0.0f)); equirect->SetUVTransform(device::Eye::Right, uvTransform); + // Per-eye UV transforms need one layer per eye, else mono. + equirect->SetUseSameLayerForBothEyes(false); + leftEye = create180LayerToggle(equirect); rightEye = create180LayerToggle(equirect); } diff --git a/app/src/main/cpp/VRVideo.h b/app/src/main/cpp/VRVideo.h index 4e77fdc8fa..6451b5ad8f 100644 --- a/app/src/main/cpp/VRVideo.h +++ b/app/src/main/cpp/VRVideo.h @@ -37,6 +37,7 @@ class VRVideo { VIDEO_PROJECTION_180_STEREO_LEFT_RIGHT = 4, VIDEO_PROJECTION_180_STEREO_TOP_BOTTOM = 5, VIDEO_PROJECTION_3D_TOP_BOTTOM = 6, + VIDEO_PROJECTION_360_STEREO_LEFT_RIGHT = 7, }; static VRVideoPtr Create(vrb::CreationContextPtr aContext, const WidgetPtr& aWindow, diff --git a/app/src/main/res/drawable/ic_icon_videoplayback_360_stereo.xml b/app/src/main/res/drawable/ic_icon_videoplayback_360_stereo.xml index 54a5290999..947e67efe1 100644 --- a/app/src/main/res/drawable/ic_icon_videoplayback_360_stereo.xml +++ b/app/src/main/res/drawable/ic_icon_videoplayback_360_stereo.xml @@ -7,4 +7,7 @@ + diff --git a/app/src/main/res/drawable/ic_icon_videoplayback_360_stereo_leftright.xml b/app/src/main/res/drawable/ic_icon_videoplayback_360_stereo_leftright.xml new file mode 100644 index 0000000000..2ad790c49e --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_videoplayback_360_stereo_leftright.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 2bd63c244a..7946be72ab 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -917,7 +917,10 @@ 360 - 360 Stereo + Stereo 360, oben nach unten + + + Stereo 360, links nach rechts 180 diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index ddb30c6273..f2f0b7bb38 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -968,7 +968,10 @@ 360 - 360 Stereo + Stereo 360 Top to Bottom + + + Stereo 360 Left to Right 180 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d758e430c2..fc6af9857f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1156,7 +1156,10 @@ 360 - 360 Stereo + Stereo 360 Top to Bottom + + + Stereo 360 Left to Right 180