mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-29 15:29:26 -05:00
Merge branch 'master' into thesis/2025/black-hole
This commit is contained in:
@@ -127,9 +127,10 @@ public:
|
||||
*
|
||||
* \param quality The value for number of vertical lines of resolution. This will be
|
||||
* compared against the QualityValues array in order to set the correct
|
||||
* combobox index
|
||||
* combobox index
|
||||
* \tilt The tilt of the fisheye in degrees
|
||||
*/
|
||||
void setProjectionFisheye(int quality);
|
||||
void setProjectionFisheye(int quality, float tilt);
|
||||
|
||||
/**
|
||||
* Sets the window's projection type to spherical mirror, with the accompanying
|
||||
@@ -162,6 +163,21 @@ public:
|
||||
*/
|
||||
void setProjectionEquirectangular(int quality);
|
||||
|
||||
/**
|
||||
* Sets the window's projection type to blitting the contents of another window.
|
||||
*
|
||||
* \param windowBlitId The id of the window from which to blit
|
||||
*/
|
||||
void setProjectionBlit(int windowBlitId);
|
||||
|
||||
/**
|
||||
* This function must be called by users of this class whenever the total number of
|
||||
* windows has changed.
|
||||
*
|
||||
* \param newWindowCount the number of windows after the change
|
||||
*/
|
||||
void updateWindowCount(int newWindowCount);
|
||||
|
||||
signals:
|
||||
void windowChanged(int monitorIndex, int windowIndex, const QRectF& newDimensions);
|
||||
|
||||
@@ -171,6 +187,7 @@ private:
|
||||
QWidget* createSphericalMirrorWidget();
|
||||
QWidget* createCylindricalWidget();
|
||||
QWidget* createEquirectangularWidget();
|
||||
QWidget* createBlitWidget();
|
||||
|
||||
void onSizeXChanged(int newValue);
|
||||
void onSizeYChanged(int newValue);
|
||||
@@ -209,44 +226,39 @@ private:
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QDoubleSpinBox* fovH = nullptr;
|
||||
QDoubleSpinBox* fovV = nullptr;
|
||||
QLabel* labelFovH = nullptr;
|
||||
QLabel* labelFovV = nullptr;
|
||||
QPushButton* buttonLockFov = nullptr;
|
||||
} _planar;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QComboBox* quality = nullptr;
|
||||
QLabel* labelQuality = nullptr;
|
||||
QDoubleSpinBox* tilt = nullptr;
|
||||
} _fisheye;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QComboBox* quality = nullptr;
|
||||
QLabel* labelQuality = nullptr;
|
||||
} _sphericalMirror;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QComboBox* quality = nullptr;
|
||||
QLabel* labelQuality = nullptr;
|
||||
QDoubleSpinBox* heightOffset = nullptr;
|
||||
QLabel* labelHeightOffset = nullptr;
|
||||
} _cylindrical;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QLabel* labelInfo = nullptr;
|
||||
QComboBox* quality = nullptr;
|
||||
QLabel* labelQuality = nullptr;
|
||||
} _equirectangular;
|
||||
|
||||
struct {
|
||||
QWidget* widget = nullptr;
|
||||
QComboBox* windowId = nullptr;
|
||||
QLabel* unavailable = nullptr;
|
||||
} _blit;
|
||||
|
||||
const QIcon _lockIcon;
|
||||
const QIcon _unlockIcon;
|
||||
};
|
||||
|
||||
@@ -194,7 +194,7 @@ void DisplayWindowUnion::initialize(const std::vector<QRect>& monitorSizeList,
|
||||
},
|
||||
[&](const sgct::config::FisheyeProjection& p) {
|
||||
if (p.quality.has_value()) {
|
||||
wCtrl->setProjectionFisheye(*p.quality);
|
||||
wCtrl->setProjectionFisheye(*p.quality, p.tilt.value_or(0.f));
|
||||
}
|
||||
},
|
||||
[&](const sgct::config::PlanarProjection& p) {
|
||||
@@ -208,7 +208,12 @@ void DisplayWindowUnion::initialize(const std::vector<QRect>& monitorSizeList,
|
||||
wCtrl->setProjectionSphericalMirror(*p.quality);
|
||||
}
|
||||
},
|
||||
[&](const sgct::config::NoProjection&) {},
|
||||
[&](const sgct::config::NoProjection&) {
|
||||
// We can only generate blitting when there is no projection selected.
|
||||
if (w.blitWindowId.has_value()) {
|
||||
wCtrl->setProjectionBlit(*w.blitWindowId);
|
||||
}
|
||||
},
|
||||
[&](const sgct::config::ProjectionPlane&) {},
|
||||
[&](const sgct::config::CubemapProjection&) {},
|
||||
},
|
||||
@@ -251,6 +256,7 @@ void DisplayWindowUnion::updateWindows() {
|
||||
_addWindowButton->setEnabled(_nWindowsDisplayed != _windowControls.size());
|
||||
for (WindowControl* w : _windowControls) {
|
||||
w->showWindowLabel(_nWindowsDisplayed > 1);
|
||||
w->updateWindowCount(_nWindowsDisplayed);
|
||||
}
|
||||
|
||||
emit nWindowsChanged(_nWindowsDisplayed);
|
||||
|
||||
@@ -64,7 +64,8 @@ namespace {
|
||||
Fisheye,
|
||||
SphericalMirror,
|
||||
Cylindrical,
|
||||
Equirectangular
|
||||
Equirectangular,
|
||||
Blit
|
||||
};
|
||||
|
||||
constexpr int LineEditWidthFixedWindowSize = 95;
|
||||
@@ -378,7 +379,7 @@ WindowControl::WindowControl(int monitorIndex, int windowIndex,
|
||||
_projectionType = new QComboBox;
|
||||
_projectionType->addItems({
|
||||
"Planar Projection", "Fisheye", "Spherical Mirror Projection",
|
||||
"Cylindrical Projection", "Equirectangular Projection"
|
||||
"Cylindrical Projection", "Equirectangular Projection", "Copy Window Contents"
|
||||
});
|
||||
_projectionType->setToolTip("Select from the supported window projection types");
|
||||
_projectionType->setCurrentIndex(0);
|
||||
@@ -403,6 +404,9 @@ WindowControl::WindowControl(int monitorIndex, int windowIndex,
|
||||
_equirectangular.widget = createEquirectangularWidget();
|
||||
projectionLayout->addWidget(_equirectangular.widget);
|
||||
|
||||
_blit.widget = createBlitWidget();
|
||||
projectionLayout->addWidget(_blit.widget);
|
||||
|
||||
// We need to trigger this once to ensure that all of the defaults are correct
|
||||
onProjectionChanged(0);
|
||||
|
||||
@@ -424,21 +428,21 @@ QWidget* WindowControl::createPlanarWidget() {
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_planar.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection type is the 'regular' projection with a horizontal and a "
|
||||
"vertical field of view, given in degrees. The wider the field of view, the "
|
||||
"more content is shown at the same time, but everything becomes smaller. Very "
|
||||
"large values will introduce distortions on the corners."
|
||||
);
|
||||
_planar.labelInfo->setObjectName("info");
|
||||
_planar.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_planar.labelInfo, 0, 0, 1, 3);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 3);
|
||||
|
||||
_planar.labelFovH = new QLabel("Horizontal FOV");
|
||||
QLabel* labelFovH = new QLabel("Horizontal FOV");
|
||||
const QString hfovTip =
|
||||
"The total horizontal field of view of the viewport (degrees)";
|
||||
_planar.labelFovH->setToolTip(hfovTip);
|
||||
layout->addWidget(_planar.labelFovH, 1, 0);
|
||||
labelFovH->setToolTip(hfovTip);
|
||||
layout->addWidget(labelFovH, 1, 0);
|
||||
|
||||
_planar.fovH = new QDoubleSpinBox;
|
||||
_planar.fovH->setMinimum(FovEpsilon);
|
||||
@@ -452,11 +456,11 @@ QWidget* WindowControl::createPlanarWidget() {
|
||||
);
|
||||
layout->addWidget(_planar.fovH, 1, 1);
|
||||
|
||||
_planar.labelFovV = new QLabel("Vertical FOV");
|
||||
QLabel* labelFovV = new QLabel("Vertical FOV");
|
||||
const QString vfovTip = "The total vertical field of view of the viewport (degrees). "
|
||||
"Internally,\nthe values for 'up' & 'down' will each be half this value";
|
||||
_planar.labelFovV->setToolTip(vfovTip);
|
||||
layout->addWidget(_planar.labelFovV, 2, 0);
|
||||
labelFovV->setToolTip(vfovTip);
|
||||
layout->addWidget(labelFovV, 2, 0);
|
||||
|
||||
_planar.fovV = new QDoubleSpinBox;
|
||||
_planar.fovV->setMinimum(FovEpsilon);
|
||||
@@ -493,29 +497,29 @@ QWidget* WindowControl::createFisheyeWidget() {
|
||||
// *------------*-----------*
|
||||
// | { Informational text } | Row 0
|
||||
// | Quality * [DDDDD>] | Row 1
|
||||
// | [] Spout Output | Row 2
|
||||
// | Tilt * [oooooo] | Row 2
|
||||
// *------------*-----------*
|
||||
|
||||
QWidget* widget = new QWidget;
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_fisheye.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection provides a rendering in a format that is suitable for "
|
||||
"planetariums and other immersive environments. A field-of-view of 180 degrees "
|
||||
"is presented as a circular image in the center of the screen. For this "
|
||||
"projection a square window is suggested, but not necessary."
|
||||
);
|
||||
_fisheye.labelInfo->setObjectName("info");
|
||||
_fisheye.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_fisheye.labelInfo, 0, 0, 1, 2);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
_fisheye.labelQuality = new QLabel("Quality");
|
||||
QLabel* labelQuality = new QLabel("Quality");
|
||||
const QString qualityTip = "Determines the pixel resolution of the projection "
|
||||
"rendering. The higher resolution,\nthe better the rendering quality, but at the "
|
||||
"expense of increased rendering times";
|
||||
_fisheye.labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(_fisheye.labelQuality, 1, 0);
|
||||
"expense of increased rendering times.";
|
||||
labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(labelQuality, 1, 0);
|
||||
|
||||
_fisheye.quality = new QComboBox;
|
||||
_fisheye.quality->addItems(qualityList());
|
||||
@@ -523,6 +527,19 @@ QWidget* WindowControl::createFisheyeWidget() {
|
||||
_fisheye.quality->setCurrentIndex(2);
|
||||
layout->addWidget(_fisheye.quality, 1, 1);
|
||||
|
||||
QLabel* labelTilt = new QLabel("Tilt");
|
||||
const QString tiltTip = "Determines the tilt (in degrees) of the fisheye rendering. "
|
||||
"Changing this value will cause the entire rendering to be tilted by the set "
|
||||
"number of degrees.";
|
||||
labelTilt->setToolTip(tiltTip);
|
||||
layout->addWidget(labelTilt, 2, 0);
|
||||
|
||||
_fisheye.tilt = new QDoubleSpinBox;
|
||||
_fisheye.tilt->setToolTip(tiltTip);
|
||||
_fisheye.tilt->setMinimum(-180.0);
|
||||
_fisheye.tilt->setMaximum(180.0);
|
||||
layout->addWidget(_fisheye.tilt, 2, 1);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
@@ -536,22 +553,22 @@ QWidget* WindowControl::createSphericalMirrorWidget() {
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_sphericalMirror.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection is rendering a image suite for use with a spherical mirror "
|
||||
"projection as described by Paul Bourke (http://paulbourke.net/dome/mirrordome/) "
|
||||
"and which is a low-cost yet effective way to provide content for a sphericalal "
|
||||
"display surface using a regular projector."
|
||||
);
|
||||
_sphericalMirror.labelInfo->setObjectName("info");
|
||||
_sphericalMirror.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_sphericalMirror.labelInfo, 0, 0, 1, 2);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
_sphericalMirror.labelQuality = new QLabel("Quality");
|
||||
QLabel* labelQuality = new QLabel("Quality");
|
||||
const QString qualityTip = "Determines the pixel resolution of the projection "
|
||||
"rendering. The higher resolution,\nthe better the rendering quality, but at the "
|
||||
"expense of increased rendering times";
|
||||
_sphericalMirror.labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(_sphericalMirror.labelQuality, 1, 0);
|
||||
labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(labelQuality, 1, 0);
|
||||
|
||||
_sphericalMirror.quality = new QComboBox;
|
||||
_sphericalMirror.quality->addItems(qualityList());
|
||||
@@ -573,22 +590,22 @@ QWidget* WindowControl::createCylindricalWidget() {
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_cylindrical.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection type provides a cylindrical rendering that covers 360 degrees "
|
||||
"around the camera, which can be useful in immersive environments that are not "
|
||||
"spherical, but where, for example, all walls of a room are covered with "
|
||||
"projectors."
|
||||
);
|
||||
_cylindrical.labelInfo->setObjectName("info");
|
||||
_cylindrical.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_cylindrical.labelInfo, 0, 0, 1, 2);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
_cylindrical.labelQuality = new QLabel("Quality");
|
||||
QLabel* labelQuality = new QLabel("Quality");
|
||||
const QString qualityTip = "Determines the pixel resolution of the projection "
|
||||
"rendering. The higher resolution,\nthe better the rendering quality, but at the "
|
||||
"expense of increased rendering times";
|
||||
_cylindrical.labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(_cylindrical.labelQuality, 1, 0);
|
||||
labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(labelQuality, 1, 0);
|
||||
|
||||
_cylindrical.quality = new QComboBox;
|
||||
_cylindrical.quality->addItems(qualityList());
|
||||
@@ -596,13 +613,13 @@ QWidget* WindowControl::createCylindricalWidget() {
|
||||
_cylindrical.quality->setCurrentIndex(2);
|
||||
layout->addWidget(_cylindrical.quality, 1, 1);
|
||||
|
||||
_cylindrical.labelHeightOffset = new QLabel("Height Offset");
|
||||
QLabel* labelHeightOffset = new QLabel("Height Offset");
|
||||
const QString heightTip = "Offsets the height from which the cylindrical projection "
|
||||
"is generated.\nThis is, in general, only necessary if the user position is "
|
||||
"offset and\ncountering that offset is desired in order to continue producing\n"
|
||||
"a 'standard' cylindrical projection";
|
||||
_cylindrical.labelHeightOffset->setToolTip(heightTip);
|
||||
layout->addWidget(_cylindrical.labelHeightOffset, 2, 0);
|
||||
labelHeightOffset->setToolTip(heightTip);
|
||||
layout->addWidget(labelHeightOffset, 2, 0);
|
||||
|
||||
_cylindrical.heightOffset = new QDoubleSpinBox;
|
||||
_cylindrical.heightOffset->setMinimum(-1000000.0);
|
||||
@@ -611,7 +628,6 @@ QWidget* WindowControl::createCylindricalWidget() {
|
||||
_cylindrical.heightOffset->setToolTip(heightTip);
|
||||
layout->addWidget(_cylindrical.heightOffset, 2, 1);
|
||||
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
@@ -620,28 +636,27 @@ QWidget* WindowControl::createEquirectangularWidget() {
|
||||
// *------------*-----------*
|
||||
// | { Informational text } | Row 0
|
||||
// | Quality * [DDDDD>] | Row 1
|
||||
// | [] Spout Output | Row 2
|
||||
// *------------*-----------*
|
||||
QWidget* widget = new QWidget;
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
_equirectangular.labelInfo = new QLabel(
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection provides the rendering as an image in equirectangular "
|
||||
"projection, which is a common display type for 360 surround video. When "
|
||||
"uploading a video in equirectangular projection to YouTube, for example, it "
|
||||
"will use it as a 360 video."
|
||||
);
|
||||
_equirectangular.labelInfo->setObjectName("info");
|
||||
_equirectangular.labelInfo->setWordWrap(true);
|
||||
layout->addWidget(_equirectangular.labelInfo, 0, 0, 1, 2);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
_equirectangular.labelQuality = new QLabel("Quality");
|
||||
QLabel* labelQuality = new QLabel("Quality");
|
||||
const QString qualityTip = "Determines the pixel resolution of the projection "
|
||||
"rendering. The higher resolution,\nthe better the rendering quality, but at the "
|
||||
"expense of increased rendering times";
|
||||
_equirectangular.labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(_equirectangular.labelQuality, 1, 0);
|
||||
labelQuality->setToolTip(qualityTip);
|
||||
layout->addWidget(labelQuality, 1, 0);
|
||||
|
||||
_equirectangular.quality = new QComboBox;
|
||||
_equirectangular.quality->addItems(qualityList());
|
||||
@@ -652,6 +667,49 @@ QWidget* WindowControl::createEquirectangularWidget() {
|
||||
return widget;
|
||||
}
|
||||
|
||||
QWidget* WindowControl::createBlitWidget() {
|
||||
// Column 0 Column 1
|
||||
// *------------*-----------*
|
||||
// | { Informational text } | Row 0
|
||||
// | Window ID * [DDDDD>] | Row 1
|
||||
// | { Unavailability } | Row 2
|
||||
// *------------*-----------*
|
||||
|
||||
QWidget* widget = new QWidget;
|
||||
QGridLayout* layout = new QGridLayout(widget);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
QLabel* labelInfo = new QLabel(
|
||||
"This projection type will reuse the contents of another window. This can be "
|
||||
"useful for GUI windows that should show the 3D scene, but not incur the cost of "
|
||||
"rendering the scene twice. Note that the contents of the rendering will be "
|
||||
"copied in their entirety, which means that if the rendering windows have "
|
||||
"different aspect ratios, the image in the receiving window will be stretched."
|
||||
);
|
||||
labelInfo->setObjectName("info");
|
||||
labelInfo->setWordWrap(true);
|
||||
layout->addWidget(labelInfo, 0, 0, 1, 2);
|
||||
|
||||
QLabel* labelBlitId = new QLabel("Window ID");
|
||||
const QString blitTip = "Determines the window from which to copy the contents.";
|
||||
labelBlitId->setToolTip(blitTip);
|
||||
layout->addWidget(labelBlitId, 1, 0);
|
||||
|
||||
_blit.windowId = new QComboBox;
|
||||
_blit.windowId->setToolTip(blitTip);
|
||||
layout->addWidget(_blit.windowId, 1, 1);
|
||||
|
||||
_blit.unavailable = new QLabel(
|
||||
"It is only possible to copy the contents of another window if at least two "
|
||||
"windows have been created. Add a second window before selecting this projection "
|
||||
"type."
|
||||
);
|
||||
_blit.unavailable->setWordWrap(true);
|
||||
layout->addWidget(_blit.unavailable, 2, 0, 1, 2);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
void WindowControl::resetToDefaults() {
|
||||
//
|
||||
// Determine ideal window sizes
|
||||
@@ -684,9 +742,11 @@ void WindowControl::resetToDefaults() {
|
||||
_planar.fovV->setValue(DefaultFovShortEdge);
|
||||
_cylindrical.heightOffset->setValue(DefaultHeightOffset);
|
||||
_fisheye.quality->setCurrentIndex(2);
|
||||
_fisheye.tilt->setValue(0.0);
|
||||
_sphericalMirror.quality->setCurrentIndex(2);
|
||||
_cylindrical.quality->setCurrentIndex(2);
|
||||
_equirectangular.quality->setCurrentIndex(2);
|
||||
_blit.windowId->setCurrentIndex(0);
|
||||
emit windowChanged(_monitorIndexDefault, _windowIndex, _windowDimensions);
|
||||
}
|
||||
|
||||
@@ -736,6 +796,7 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
);
|
||||
window.draw2D = _render2D->isChecked();
|
||||
window.draw3D = _render3D->isChecked();
|
||||
|
||||
window.isDecorated = _windowDecoration->isChecked();
|
||||
if (_spoutOutput->isChecked()) {
|
||||
window.spout = sgct::config::Window::Spout{
|
||||
@@ -746,6 +807,8 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
window.name = _windowName->text().toStdString();
|
||||
}
|
||||
|
||||
window.viewports.clear();
|
||||
|
||||
// The rest of this function is just specifying the rendering, which we can skip if we
|
||||
// don't want to render 3D anyway
|
||||
if (!window.draw3D) {
|
||||
@@ -762,7 +825,7 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
vp.projection = sgct::config::FisheyeProjection {
|
||||
.fov = 180.f,
|
||||
.quality = Quality[_fisheye.quality->currentIndex()].first,
|
||||
.tilt = 0.f
|
||||
.tilt = static_cast<float>(_fisheye.tilt->value())
|
||||
};
|
||||
break;
|
||||
case ProjectionIndices::SphericalMirror:
|
||||
@@ -781,6 +844,16 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
.quality = Quality[_equirectangular.quality->currentIndex()].first
|
||||
};
|
||||
break;
|
||||
case ProjectionIndices::Blit:
|
||||
// We have to subtract here as SGCT uses 0-indexing, but we present it to the
|
||||
// user as 1-indexing
|
||||
window.blitWindowId = _blit.windowId->currentText().toInt() - 1;
|
||||
window.draw3D = false;
|
||||
|
||||
// We are falling through the planar value on purpose as for a variety of
|
||||
// reasons requires a projection to be defined even when we are blitting the
|
||||
// contents of another window.
|
||||
[[fallthrough]];
|
||||
case ProjectionIndices::Planar:
|
||||
{
|
||||
double fovH = _planar.fovH->value();
|
||||
@@ -799,8 +872,6 @@ void WindowControl::generateWindowInformation(sgct::config::Window& window) cons
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window.viewports.clear();
|
||||
window.viewports.push_back(vp);
|
||||
}
|
||||
|
||||
@@ -810,8 +881,9 @@ void WindowControl::setProjectionPlanar(float hfov, float vfov) {
|
||||
_projectionType->setCurrentIndex(static_cast<int>(ProjectionIndices::Planar));
|
||||
}
|
||||
|
||||
void WindowControl::setProjectionFisheye(int quality) {
|
||||
void WindowControl::setProjectionFisheye(int quality, float tilt) {
|
||||
_fisheye.quality->setCurrentIndex(indexForQuality(quality));
|
||||
_fisheye.tilt->setValue(tilt);
|
||||
_projectionType->setCurrentIndex(static_cast<int>(ProjectionIndices::Fisheye));
|
||||
}
|
||||
|
||||
@@ -835,6 +907,32 @@ void WindowControl::setProjectionEquirectangular(int quality) {
|
||||
);
|
||||
}
|
||||
|
||||
void WindowControl::setProjectionBlit(int windowBlitId) {
|
||||
// We add 1 here as SGCT uses a 0-indexing for the window idx, but we present it to
|
||||
// the user as a 1-indexing
|
||||
int idx = _blit.windowId->findText(QString::number(windowBlitId + 1));
|
||||
ghoul_assert(idx != -1, "Could not find window blit id");
|
||||
_blit.windowId->setCurrentIndex(idx);
|
||||
_projectionType->setCurrentIndex(
|
||||
static_cast<int>(ProjectionIndices::Blit)
|
||||
);
|
||||
}
|
||||
|
||||
void WindowControl::updateWindowCount(int newWindowCount) {
|
||||
QString currentIdx = _blit.windowId->currentText();
|
||||
_blit.windowId->clear();
|
||||
for (int idx = 0; idx < newWindowCount; idx++) {
|
||||
if (idx == _windowIndex) {
|
||||
continue;
|
||||
}
|
||||
_blit.windowId->addItem(QString::number(idx + 1));
|
||||
}
|
||||
_blit.windowId->setCurrentText(currentIdx);
|
||||
|
||||
// Set the correct visibility
|
||||
_blit.unavailable->setVisible(newWindowCount == 1);
|
||||
}
|
||||
|
||||
void WindowControl::onSizeXChanged(int newValue) {
|
||||
_windowDimensions.setWidth(newValue);
|
||||
if (_aspectRatioLocked) {
|
||||
@@ -896,6 +994,7 @@ void WindowControl::onProjectionChanged(int newSelection) const {
|
||||
_sphericalMirror.widget->setVisible(selected == ProjectionIndices::SphericalMirror);
|
||||
_cylindrical.widget->setVisible(selected == ProjectionIndices::Cylindrical);
|
||||
_equirectangular.widget->setVisible(selected == ProjectionIndices::Equirectangular);
|
||||
_blit.widget->setVisible(selected == ProjectionIndices::Blit);
|
||||
}
|
||||
|
||||
void WindowControl::onAspectRatioLockClicked() {
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
local globe = asset.require("../../titan")
|
||||
|
||||
|
||||
|
||||
local Layer = {
|
||||
Identifier = "Cassini_SAR_HiSAR_Global_Mosaic_351m",
|
||||
Name = "Cassini SAR - HiSAR Global Mosaic (351m)",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 20,
|
||||
FilePath = asset.resource("cassini_sar_hisar_global_mosaic_351m_sweden.wms"),
|
||||
Description = [[This global map of Titan is a preliminary product showing coverage from
|
||||
Synthetic Aperture Radar (SAR) and High Altitude Synthetic Aperture Radar (HiSAR)
|
||||
images at a pixel resolution of 351 meters per pixel (m). This mosaic merges Cassini
|
||||
swaths through flyby T104 into a single mosaic. (Description from URL)]]
|
||||
}
|
||||
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.globebrowsing.addLayer(globe.Titan.Identifier, "ColorLayers", Layer)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.globebrowsing.deleteLayer(globe.Titan.Identifier, "ColorLayers", Layer)
|
||||
end)
|
||||
|
||||
asset.export("layer", Layer)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Titan Cassini SAR - HiSAR Global Mosaic 351m",
|
||||
Description = "Cassini global synthetic aperture radar image layer for Titan",
|
||||
Author = "USGS",
|
||||
URL = "https://astrogeology.usgs.gov/search/map/titan_cassini_sar_hisar_global_mosaic_351m",
|
||||
License = "NASA/PDS"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<GDAL_WMS>
|
||||
<Service name="TMS">
|
||||
<ServerUrl>http://wms.itn.liu.se/Titan/HiSAR_Global_Mosaic_351m/tile/${z}/${y}/${x}</ServerUrl>
|
||||
</Service>
|
||||
<DataWindow>
|
||||
<UpperLeftX>-180.0</UpperLeftX>
|
||||
<UpperLeftY>90.0</UpperLeftY>
|
||||
<LowerRightX>180.0</LowerRightX>
|
||||
<LowerRightY>-90.0</LowerRightY>
|
||||
<SizeX>46080</SizeX>
|
||||
<SizeY>23040</SizeY>
|
||||
<TileLevel>7</TileLevel>
|
||||
<YOrigin>top</YOrigin>
|
||||
</DataWindow>
|
||||
<Projection>EPSG:4326</Projection>
|
||||
<BlockSizeX>512</BlockSizeX>
|
||||
<BlockSizeY>512</BlockSizeY>
|
||||
<BandsCount>1</BandsCount>
|
||||
<MaxConnections>10</MaxConnections>
|
||||
</GDAL_WMS>
|
||||
Reference in New Issue
Block a user