From c3d3cdca3d180717db93139f71387664792357c2 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 3 May 2018 12:57:00 -0700 Subject: [PATCH] Add cubemap output format --- interface/src/Application.cpp | 6 +-- interface/src/Application.h | 2 +- .../scripting/WindowScriptingInterface.cpp | 4 +- .../src/scripting/WindowScriptingInterface.h | 6 +-- interface/src/ui/Snapshot.cpp | 51 +++++++++++++++++-- interface/src/ui/Snapshot.h | 4 +- scripts/system/notifications.js | 2 +- .../spectator-camera/spectatorCamera.js | 6 +-- 8 files changed, 64 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 462ae38131..d4a778d794 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7350,9 +7350,9 @@ void Application::takeSecondaryCameraSnapshot(const QString& filename) { }); } -void Application::takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const QString& filename) { - postLambdaEvent([filename, cameraPosition, this] { - Snapshot::save360Snapshot(cameraPosition, filename); +void Application::takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const QString& filename) { + postLambdaEvent([filename, cubemapOutputFormat, cameraPosition, this] { + Snapshot::save360Snapshot(cameraPosition, cubemapOutputFormat, filename); }); } diff --git a/interface/src/Application.h b/interface/src/Application.h index feef4493b1..f1053a9221 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -273,7 +273,7 @@ public: void takeSnapshot(bool notify, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString()); void takeSecondaryCameraSnapshot(const QString& filename = QString()); - void takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const QString& filename = QString()); + void takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const QString& filename = QString()); void shareSnapshot(const QString& filename, const QUrl& href = QUrl("")); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index f5416bf4c6..e6904aa667 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -431,8 +431,8 @@ void WindowScriptingInterface::takeSecondaryCameraSnapshot(const QString& filena qApp->takeSecondaryCameraSnapshot(filename); } -void WindowScriptingInterface::takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const QString& filename) { - qApp->takeSecondaryCamera360Snapshot(cameraPosition, filename); +void WindowScriptingInterface::takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const QString& filename) { + qApp->takeSecondaryCamera360Snapshot(cameraPosition, cubemapOutputFormat, filename); } void WindowScriptingInterface::shareSnapshot(const QString& path, const QUrl& href) { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index a39a152ad8..ba31159827 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -376,7 +376,7 @@ public slots: * * var filename = QString(); */ - void takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const QString& filename = QString()); + void takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat = false, const QString& filename = QString()); /**jsdoc * Emit a {@link Window.connectionAdded|connectionAdded} or a {@link Window.connectionError|connectionError} signal that @@ -588,13 +588,13 @@ signals: /**jsdoc * Triggered when a still equirectangular snapshot has been taken by calling {@link Window.takeSecondaryCamera360Snapshot|takeSecondaryCamera360Snapshot} - * @function Window.equirectangularSnapshotTaken + * @function Window.snapshot360Taken * @param {string} pathStillSnapshot - The path and name of the snapshot image file. * @param {boolean} notify - The value of the notify parameter that {@link Window.takeSecondaryCamera360Snapshot|takeSecondaryCamera360Snapshot} * was called with. * @returns {Signal} */ - void equirectangularSnapshotTaken(const QString& pathEquirectangularSnapshot, bool notify); + void snapshot360Taken(const QString& path360Snapshot, bool notify); /**jsdoc * Triggered when a snapshot submitted via {@link Window.shareSnapshot|shareSnapshot} is ready for sharing. The snapshot diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index c03c672e8b..3e020e2cb9 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -102,6 +103,7 @@ QString Snapshot::saveSnapshot(QImage image, const QString& filename) { } QString Snapshot::snapshotFilename; +bool Snapshot::cubemapOutputFormat; qint16 Snapshot::snapshotIndex = 0; bool Snapshot::oldEnabled = false; QVariant Snapshot::oldAttachedEntityId = 0; @@ -110,8 +112,9 @@ QVariant Snapshot::oldvFoV = 0; QVariant Snapshot::oldNearClipPlaneDistance = 0; QVariant Snapshot::oldFarClipPlaneDistance = 0; static const float CUBEMAP_SIDE_PIXEL_DIMENSION = 2048.0f; -void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const QString& filename) { +void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const QString& filename) { Snapshot::snapshotFilename = filename; + Snapshot::cubemapOutputFormat = cubemapOutputFormat; SecondaryCameraJobConfig* secondaryCameraRenderConfig = static_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera")); // Save initial values of secondary camera render config @@ -191,12 +194,54 @@ void Snapshot::takeNextSnapshot() { } // Process six QImages - QtConcurrent::run(Snapshot::convertToEquirectangular); + if (Snapshot::cubemapOutputFormat) { + QtConcurrent::run(Snapshot::convertToCubemap); + } else { + QtConcurrent::run(Snapshot::convertToEquirectangular); + } } Snapshot::snapshotIndex++; } +void Snapshot::convertToCubemap() { + float outputImageHeight = CUBEMAP_SIDE_PIXEL_DIMENSION * 3.0f; + float outputImageWidth = CUBEMAP_SIDE_PIXEL_DIMENSION * 4.0f; + + QImage outputImage(outputImageWidth, outputImageHeight, QImage::Format_RGB32); + + QPainter painter(&outputImage); + QPoint destPos; + + // Paint DownImage + destPos = QPoint(CUBEMAP_SIDE_PIXEL_DIMENSION, CUBEMAP_SIDE_PIXEL_DIMENSION * 2.0f); + painter.drawImage(destPos, Snapshot::imageArray[0]); + + // Paint FrontImage + destPos = QPoint(CUBEMAP_SIDE_PIXEL_DIMENSION, CUBEMAP_SIDE_PIXEL_DIMENSION); + painter.drawImage(destPos, Snapshot::imageArray[1]); + + // Paint LeftImage + destPos = QPoint(0, CUBEMAP_SIDE_PIXEL_DIMENSION); + painter.drawImage(destPos, Snapshot::imageArray[2]); + + // Paint BackImage + destPos = QPoint(CUBEMAP_SIDE_PIXEL_DIMENSION * 3.0f, CUBEMAP_SIDE_PIXEL_DIMENSION); + painter.drawImage(destPos, Snapshot::imageArray[3]); + + // Paint RightImage + destPos = QPoint(CUBEMAP_SIDE_PIXEL_DIMENSION * 2.0f, CUBEMAP_SIDE_PIXEL_DIMENSION); + painter.drawImage(destPos, Snapshot::imageArray[4]); + + // Paint UpImage + destPos = QPoint(CUBEMAP_SIDE_PIXEL_DIMENSION, 0); + painter.drawImage(destPos, Snapshot::imageArray[5]); + + painter.end(); + + emit DependencyManager::get()->snapshot360Taken(saveSnapshot(outputImage, Snapshot::snapshotFilename), true); +} + void Snapshot::convertToEquirectangular() { // I got help from StackOverflow while writing this code: // https://stackoverflow.com/questions/34250742/converting-a-cubemap-into-equirectangular-panorama @@ -278,7 +323,7 @@ void Snapshot::convertToEquirectangular() { } } - emit DependencyManager::get()->equirectangularSnapshotTaken(saveSnapshot(outputImage, Snapshot::snapshotFilename), true); + emit DependencyManager::get()->snapshot360Taken(saveSnapshot(outputImage, Snapshot::snapshotFilename), true); } QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 971c99eea1..eeab6b97d5 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -40,7 +40,7 @@ public: Snapshot(); static QString saveSnapshot(QImage image, const QString& filename); - static void save360Snapshot(const glm::vec3& cameraPosition, const QString& filename); + static void save360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const QString& filename); static QTemporaryFile* saveTempSnapshot(QImage image); static SnapshotMetaData* parseSnapshotData(QString snapshotPath); @@ -61,6 +61,7 @@ private: static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename = QString()); static QString snapshotFilename; + static bool cubemapOutputFormat; static QTimer snapshotTimer; static qint16 snapshotIndex; static bool oldEnabled; @@ -70,6 +71,7 @@ private: static QVariant oldNearClipPlaneDistance; static QVariant oldFarClipPlaneDistance; static QImage imageArray[6]; + static void convertToCubemap(); static void convertToEquirectangular(); }; diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 3b3ac4dfe6..a28f343ad3 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -672,7 +672,7 @@ Menu.menuItemEvent.connect(menuItemEvent); Window.domainConnectionRefused.connect(onDomainConnectionRefused); Window.stillSnapshotTaken.connect(onSnapshotTaken); - Window.equirectangularSnapshotTaken.connect(onSnapshotTaken); + Window.snapshot360Taken.connect(onSnapshotTaken); Window.processingGifStarted.connect(processingGif); Window.connectionAdded.connect(connectionAdded); Window.connectionError.connect(connectionError); diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js index 8e8c0db6c4..5ce03a9292 100644 --- a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js +++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js @@ -194,7 +194,7 @@ Window.domainChanged.connect(onDomainChanged); Window.geometryChanged.connect(resizeViewFinderOverlay); Window.stillSnapshotTaken.connect(onStillSnapshotTaken); - Window.equirectangularSnapshotTaken.connect(onEquirectangularSnapshotTaken); + Window.snapshot360Taken.connect(on360SnapshotTaken); Controller.keyPressEvent.connect(keyPressEvent); HMD.displayModeChanged.connect(onHMDChanged); viewFinderOverlay = false; @@ -407,7 +407,7 @@ }, 250); } } - function onEquirectangularSnapshotTaken() { + function on360SnapshotTaken() { if (monitorShowsCameraView) { setDisplay(true); } @@ -606,7 +606,7 @@ Window.domainChanged.disconnect(onDomainChanged); Window.geometryChanged.disconnect(resizeViewFinderOverlay); Window.stillSnapshotTaken.disconnect(onStillSnapshotTaken); - Window.equirectangularSnapshotTaken.disconnect(onEquirectangularSnapshotTaken); + Window.snapshot360Taken.disconnect(on360SnapshotTaken); addOrRemoveButton(true); if (tablet) { tablet.screenChanged.disconnect(onTabletScreenChanged);