diff --git a/data/scene/atmosphereearth.scene b/data/scene/atmosphereearth.scene index f0daa2545c..6b5738f34f 100644 --- a/data/scene/atmosphereearth.scene +++ b/data/scene/atmosphereearth.scene @@ -24,8 +24,7 @@ function preInitialization() -- 6:20 -> 23:20 day before in UTC ]]-- - - openspace.time.setTime("2016-03-08T22:45:00") + --openspace.time.setTime("2016-03-08T22:45:00") -- Total Lunar Eclipse Jan 31, 2018 at 10:51:13 UTC -- Regions seeing, at least, some parts of the eclipse: North/East Europe, @@ -33,6 +32,9 @@ function preInitialization() -- Pacific, Atlantic, Indian Ocean, Arctic, Antarctica. --openspace.time.setTime("2018-01-31T10:30:00") + + openspace.time.setTime("2017-05-17T08:00:00") + dofile(openspace.absPath('${SCRIPTS}/bind_common_keys.lua')) end @@ -43,7 +45,7 @@ function postInitialization() graphical settings for the renderables. ]]-- openspace.printInfo("Setting default values") - openspace.setPropertyValue("Sun.renderable.enabled", true) + openspace.setPropertyValue("Sun.renderable.enabled", false) openspace.setPropertyValue("SunMarker.renderable.enabled", false) openspace.setPropertyValue("EarthMarker.renderable.enabled", false) openspace.setPropertyValue("Constellation Bounds.renderable.enabled", false) @@ -67,8 +69,8 @@ return { ScenePath = ".", CommonFolder = "common", Camera = { - --Focus = "Earth", - Focus = "Mars", + Focus = "Earth", + --Focus = "Mars", --Position = {526781518487.171326, 257168309890.072144, -1381125204152.817383}, --Rotation = {-0.106166, 0.981574, -0.084545, 0.134513}, --Position = {-21230341452.764542, -75199905816.520981, 126295587136.952240}, @@ -87,8 +89,8 @@ return { --"moon", "lodglobes/earth", - "lodglobes/mars", - "lodglobes/moon", + --"lodglobes/mars", + --"lodglobes/moon", --"toyvolume", --"earth", diff --git a/data/scene/lodglobes/earth/earth.mod b/data/scene/lodglobes/earth/earth.mod index b01abc182a..1c39b6df1b 100644 --- a/data/scene/lodglobes/earth/earth.mod +++ b/data/scene/lodglobes/earth/earth.mod @@ -57,7 +57,7 @@ return { SegmentsPerPatch = 64, Atmosphere = { -- Atmosphere radius in Km - AtmoshereRadius = 6420, + AtmoshereRadius = 6450, PlanetRadius = 6378.1366, PlanetAverageGroundReflectance = 0.1, Rayleigh = { diff --git a/data/scene/milkyway-eso/milkyway-eso.mod b/data/scene/milkyway-eso/milkyway-eso.mod index 86902a48e7..60c6f71696 100644 --- a/data/scene/milkyway-eso/milkyway-eso.mod +++ b/data/scene/milkyway-eso/milkyway-eso.mod @@ -4,7 +4,7 @@ return { Parent = "SolarSystem", Renderable = { Type = "RenderableSphere", - Size = { 10, 20 }, + Size = 10E20, Segments = 40, Texture = "textures/eso0932a_blend.png", Orientation = "Inside/Outside" diff --git a/data/scene/milkyway/milkyway.mod b/data/scene/milkyway/milkyway.mod index 8fa37be7a5..49c07a217c 100644 --- a/data/scene/milkyway/milkyway.mod +++ b/data/scene/milkyway/milkyway.mod @@ -4,7 +4,7 @@ return { Parent = "SolarSystem", Renderable = { Type = "RenderableSphere", - Size = { 10, 22 }, + Size = 10E22, Segments = 40, Texture = "textures/DarkUniverse_mellinger_8k.jpg", Orientation = "Inside/Outside" diff --git a/data/scene/sun/sun.mod b/data/scene/sun/sun.mod index 6905d9de89..11b0e1516d 100644 --- a/data/scene/sun/sun.mod +++ b/data/scene/sun/sun.mod @@ -30,7 +30,7 @@ return { }, PerformShading = false, }, - Transformation = { + Transform = { Translation = { Type = "SpiceTranslation", Body = "SUN", @@ -56,7 +56,7 @@ return { Texture = "textures/sun-glare.png", BlendMode = "Additive" }, - Transformation = { + Transform = { Translation = { Type = "SpiceTranslation", Body = "SUN", diff --git a/data/web/keybindings/keybinding.hbs b/data/web/keybindings/keybinding.hbs index 29773e357e..4873cdef05 100644 --- a/data/web/keybindings/keybinding.hbs +++ b/data/web/keybindings/keybinding.hbs @@ -6,6 +6,7 @@ {{key}} {{#if remoteScripting}}Remote scripting{{else}}Local scripting{{/if}}

{{script}}

+

{{documentation}}

diff --git a/data/web/properties/main.hbs b/data/web/properties/main.hbs index fc56bca0b8..6af37752cd 100644 --- a/data/web/properties/main.hbs +++ b/data/web/properties/main.hbs @@ -18,7 +18,6 @@

OpenSpace Scene Properties

Version: {{version.[0]}}.{{version.[1]}}.{{version.[2]}}

-

Scene name: {{sceneFilename}}

Generated: {{generationTime}}

{{#each propertyOwners}} diff --git a/data/web/properties/script.js b/data/web/properties/script.js index f7302a5e0b..52b8a468fa 100644 --- a/data/web/properties/script.js +++ b/data/web/properties/script.js @@ -53,7 +53,7 @@ window.onload = function () { var data = { propertyOwners: propertyOwners, version: version, - sceneFilename: sceneFilename, + // sceneFilename: sceneFilename, generationTime: generationTime } diff --git a/include/openspace/documentation/documentationengine.h b/include/openspace/documentation/documentationengine.h index 41400602fb..5ab18d9f03 100644 --- a/include/openspace/documentation/documentationengine.h +++ b/include/openspace/documentation/documentationengine.h @@ -26,8 +26,9 @@ #define __OPENSPACE_CORE___DOCUMENTATIONENGINE___H__ #include - +#include #include + #include namespace openspace { @@ -38,7 +39,9 @@ namespace documentation { * produced in the application an write them out as a documentation file for human * consumption. */ -class DocumentationEngine : public ghoul::Singleton { +class DocumentationEngine : public ghoul::Singleton + , public DocumentationGenerator +{ public: /** * This exception is thrown by the addDocumentation method if a provided Documentation @@ -57,16 +60,7 @@ public: Documentation documentation; }; - /** - * Write the collected Documentation%s to disk at the \p filename in the specified - * \p type. A new file is created and silently overwritten in the location that - * \p filename is pointed to. - * \param filename The file that is to be created containing all the Documentation - * information. - * \param type The type of documentation that is written. Currently allowed values are - * \c text and \c html - */ - void writeDocumentation(const std::string& filename, const std::string& type); + DocumentationEngine(); /** * Adds the \p documentation to the list of Documentation%s that are written to a @@ -90,6 +84,8 @@ public: static DocumentationEngine& ref(); private: + std::string generateJson() const override; + /// The list of all Documentation%s that are stored by the DocumentationEngine std::vector _documentations; diff --git a/include/openspace/documentation/documentationgenerator.h b/include/openspace/documentation/documentationgenerator.h new file mode 100644 index 0000000000..ca91bc9eff --- /dev/null +++ b/include/openspace/documentation/documentationgenerator.h @@ -0,0 +1,105 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___DOCUMENTATIONGENERATOR___H__ +#define __OPENSPACE_CORE___DOCUMENTATIONGENERATOR___H__ + +#include +#include + +namespace openspace { + +/* + * This abstract class is used for instances when another class has the ability to + * generate a Handlebar generated documentation file that contains valuable information + * for the user. Instances of this are the DocumentationEngine results, the list of + * Property%s generated by the Scene, or the FactoryEngine results. The documentation is + * generated through the writeDocumentation method. + * + * The concrete subclass needs to overload the generateJson class that will return the + * Json that is parsed by Handlebar to generate the webpage. + * + * A list of Handlebar templates, the variable name for the result of the generateJson + * method, and the Javascript file that contains additional logic is passed in the + * constructor. + */ +class DocumentationGenerator { +public: + /// This struct contains a single Handlebar template, with the name and the filename + struct HandlebarTemplate { + std::string name; ///< The name of the Handlebar template defined in \m filename + std::string filename; ///< The filename referenced in the \m name + }; + + /** + * The constructor that is used to set the member variables later used in the + * writeDocumentation method. + * \param name The name of the written documentation + * \param jsonName The variable name of the value generated by the generateJson + * \param handlebarTemplates A list of Handlebar templates that is added to the + * documentation file + * \param javascriptFilename The path to a Javascript source file that is added to the + * documentation and that can contain additional functionality + * \pre name must not be empty + * \pre jsonName must not be empty + * \pre Each handlebarTemplates' \c name must not be empty + * \pre javascriptFilename must not be empty + */ + DocumentationGenerator(std::string name, std::string jsonName, + std::vector handlebarTemplates, + std::string javascriptFilename); + + /// Default constructor + virtual ~DocumentationGenerator() = default; + + /** + * Create the documentation into the provided filename. Any existing file will be + * silently overwritten. This method will call the generateJson method that can be + * used by concrete subclasses to provide the actual data that is provided in the + * documentation. + * \param filename The filename in which the documentation is written + */ + void writeDocumentation(const std::string& filename); + +protected: + /** + * This abstract method is used by concrete subclasses to provide the actual data that + * is used in the documentation written by this DocumentationGenerator class. The JSON + * string returned by this function will be stored in the variable with the + * \c jsonName as passed in the constructor. + * \return A JSON script that is parsed and stored in the variable passed in the + * DocumentationGenerator constructor + */ + virtual std::string generateJson() const = 0; + +private: + const std::string _name; + const std::string _jsonName; + const std::vector _handlebarTemplates; + const std::string _javascriptFile; +}; + +} // namespace openspace + +#endif // __OPENSPACE_CORE___DOCUMENTATIONGENERATOR___H__ diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index 76ab9b5610..891dfca494 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -25,9 +25,11 @@ #ifndef __OPENSPACE_CORE___INTERACTIONHANDLER___H__ #define __OPENSPACE_CORE___INTERACTIONHANDLER___H__ +#include +#include + #include #include -#include #include #include #include @@ -47,8 +49,7 @@ class SceneGraphNode; namespace interaction { - -class InteractionHandler : public properties::PropertyOwner +class InteractionHandler : public properties::PropertyOwner, public DocumentationGenerator { public: InteractionHandler(); @@ -121,7 +122,6 @@ public: void saveCameraStateToFile(const std::string& filepath); void restoreCameraStateFromFile(const std::string& filepath); - void writeKeyboardDocumentation(const std::string& type, const std::string& file); private: using Synchronized = ghoul::Boolean; @@ -131,6 +131,8 @@ private: Synchronized synchronization; std::string documentation; }; + + std::string generateJson() const override; void setInteractionMode(std::shared_ptr interactionMode); diff --git a/include/openspace/mission/mission.h b/include/openspace/mission/mission.h index 914afb040c..b5dfe70f50 100644 --- a/include/openspace/mission/mission.h +++ b/include/openspace/mission/mission.h @@ -62,26 +62,25 @@ public: * Returns the name of the MissionPhase. * \return The name of the MissionPhase */ - const std::string& name() const; + std::string name() const; /** * Returns the TimeRange of the MissionPhase. * \return The TimeRange of the MissionPhase */ - const TimeRange& timeRange() const; + TimeRange timeRange() const; /** * Returns the description of the MissionPhase. * \return The description of the MissionPhase */ - const std::string& description() const; + std::string description() const; /** * Returns all subphases sorted by start time. * \return All subphases sorted by start time */ - const std::vector& phases() const; - + std::vector phases() const; using Trace = std::vector>; @@ -111,6 +110,7 @@ protected: * \param time The time which the subphases have to cover to be added to the \p trace * \param trace The list of MissionPhase%s that are active during the time \p time * \param maxDepth The maximum depth of levels that will be considered + * \pre maxDepth must not be negative */ void phaseTrace(double time, Trace& trace, int maxDepth) const; @@ -139,7 +139,7 @@ using Mission = MissionPhase; * \pre \p filename must not contain tokens * \pre \p filename must exist */ -Mission missionFromFile(std::string filename); +Mission missionFromFile(const std::string& filename); } // namespace openspace diff --git a/include/openspace/network/parallelconnection.h b/include/openspace/network/parallelconnection.h index db3d000413..f14c871599 100644 --- a/include/openspace/network/parallelconnection.h +++ b/include/openspace/network/parallelconnection.h @@ -30,6 +30,7 @@ #include #include #include +#include //glm includes #include diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index b2abbb7710..b9fe5cf7a3 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -28,20 +28,21 @@ #include #include -#include -#include - -// Forward declare to minimize dependencies namespace ghoul { namespace opengl { + class ProgramObject; class Texture; } class Dictionary; -} +} // namespace ghoul namespace openspace { +struct RenderData; +struct UpdateData; +struct RendererTasks; + namespace documentation { struct Documentation; } // Forward declare to minimize dependencies diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index e690b94c85..bdda2dbb97 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -25,21 +25,13 @@ #ifndef __OPENSPACE_CORE___RENDERENGINE___H__ #define __OPENSPACE_CORE___RENDERENGINE___H__ -#include -#include #include + +#include #include #include #include -#include -#include -#include -#include - -#include - -#include namespace ghoul { namespace fontrendering { @@ -50,17 +42,22 @@ namespace opengl { } class Dictionary; class SharedMemory; -} +} // namespace ghoul namespace openspace { -// Forward declare to minimize dependencies +namespace performance { class PerformanceManager; } +namespace scripting { struct LuaLibrary; } class Camera; -class SyncBuffer; +class RaycasterManager; +class DeferredcasterManager; +class Renderer; class Scene; class SceneManager; class ScreenLog; class ScreenSpaceRenderable; +class Syncable; +class SyncBuffer; class RenderEngine : public properties::PropertyOwner { public: @@ -77,7 +74,7 @@ public: }; RenderEngine(); - ~RenderEngine() = default; + ~RenderEngine(); void initialize(); void initializeGL(); @@ -207,6 +204,7 @@ private: //FrametimeType _frametimeType; + properties::BoolProperty _showDate; properties::BoolProperty _showInfo; properties::BoolProperty _showLog; @@ -215,7 +213,7 @@ private: properties::BoolProperty _applyWarping; properties::BoolProperty _showFrameNumber; properties::BoolProperty _disableMasterRendering; - properties::BoolProperty _disableSceneOnMaster; + properties::BoolProperty _disableSceneTranslationOnMaster; float _globalBlackOutFactor; float _fadeDuration; diff --git a/include/openspace/scene/scene.h b/include/openspace/scene/scene.h index 76f87a3e41..26660b7568 100644 --- a/include/openspace/scene/scene.h +++ b/include/openspace/scene/scene.h @@ -25,6 +25,8 @@ #ifndef __OPENSPACE_CORE___SCENE___H__ #define __OPENSPACE_CORE___SCENE___H__ +#include + #include #include #include @@ -45,7 +47,7 @@ class SceneGraphNode; // Notifications: // SceneGraphFinishedLoading -class Scene { +class Scene : public DocumentationGenerator { public: using UpdateDependencies = ghoul::Boolean; @@ -135,11 +137,6 @@ public: */ const std::map& nodesByName() const; - /** - * Output property documentation to a file. - */ - void writePropertyDocumentation(const std::string& filename, const std::string& type, const std::string& sceneFilename); - /** * Returns the Lua library that contains all Lua functions available to change the * scene graph. The functions contained are @@ -152,7 +149,9 @@ public: static documentation::Documentation Documentation(); -private: +private: + std::string generateJson() const override; + void sortTopologically(); std::unique_ptr _root; diff --git a/include/openspace/scene/scenegraphnode.h b/include/openspace/scene/scenegraphnode.h index 9298e670ae..de8d49b787 100644 --- a/include/openspace/scene/scenegraphnode.h +++ b/include/openspace/scene/scenegraphnode.h @@ -25,16 +25,12 @@ #ifndef __OPENSPACE_CORE___SCENEGRAPHNODE___H__ #define __OPENSPACE_CORE___SCENEGRAPHNODE___H__ -#include -#include -#include -#include #include -#include -#include +#include +#include -#include +#include #include #include #include @@ -43,6 +39,16 @@ namespace ghoul { class Dictionary; } namespace openspace { +class Camera; +struct RenderData; +class Renderable; +struct RendererTasks; +class Rotation; +class Translation; +class Scale; +class Scene; +struct UpdateData; + namespace documentation { struct Documentation; } class SceneGraphNode : public properties::PropertyOwner { diff --git a/include/openspace/scripting/scriptengine.h b/include/openspace/scripting/scriptengine.h index b28a8fb2ba..c35bc3cbb9 100644 --- a/include/openspace/scripting/scriptengine.h +++ b/include/openspace/scripting/scriptengine.h @@ -25,9 +25,11 @@ #ifndef __OPENSPACE_CORE___SCRIPTENGINE___H__ #define __OPENSPACE_CORE___SCRIPTENGINE___H__ -#include +#include #include +#include + #include #include #include @@ -50,9 +52,12 @@ namespace scripting { * openspace namespac prefix in Lua. The same functions can be exposed to * other Lua states by passing them to the #initializeLuaState method. */ -class ScriptEngine : public Syncable { +class ScriptEngine : public Syncable, public DocumentationGenerator { public: using RemoteScripting = ghoul::Boolean; + + ScriptEngine(); + /** * Initializes the internal Lua state and registers a common set of library functions * \throw LuaRuntimeException If the creation of the new Lua state fails @@ -73,8 +78,6 @@ public: bool runScript(const std::string& script); bool runScriptFile(const std::string& filename); - void writeDocumentation(const std::string& filename, const std::string& type) const; - bool writeLog(const std::string& script); virtual void presync(bool isMaster); @@ -106,6 +109,8 @@ private: void addBaseLibrary(); void remapPrintFunction(); + std::string generateJson() const override; + ghoul::lua::LuaState _state; std::set _registeredLibraries; diff --git a/include/openspace/util/factorymanager.h b/include/openspace/util/factorymanager.h index 7b815ca065..900cbbd6ac 100644 --- a/include/openspace/util/factorymanager.h +++ b/include/openspace/util/factorymanager.h @@ -25,6 +25,8 @@ #ifndef __OPENSPACE_CORE___FACTORYMANAGER___H__ #define __OPENSPACE_CORE___FACTORYMANAGER___H__ +#include + #include #include @@ -37,7 +39,7 @@ namespace openspace { * them available through the #addFactory and #factory methods. Each * ghoul::TemplateFactory can only be added once and can be accessed by its type. */ -class FactoryManager { +class FactoryManager : public DocumentationGenerator { public: /// This exception is thrown if the ghoul::TemplateFactory could not be found in the /// #factory method @@ -55,6 +57,8 @@ public: /// The type describing the ghoul::TemplateFactory that could not be found std::string type; }; + + FactoryManager(); /** * Static initializer that initializes the static member. This needs to be done before @@ -104,17 +108,9 @@ public: template ghoul::TemplateFactory* factory() const; - /** - * Writes a documentation for the FactoryMananger that contains all of the registered - * factories and for each factory all registered class names. - * \param file The file to which the documentation will be written - * \param type The type of documentation that will be written - * \pre \p file must not be empty - * \pre \p type must not be empty - */ - void writeDocumentation(const std::string& file, const std::string& type); - private: + std::string generateJson() const override; + /// Singleton member for the Factory Manager static FactoryManager* _manager; diff --git a/include/openspace/util/screenlog.h b/include/openspace/util/screenlog.h index b9769f7b01..f92816cf2a 100644 --- a/include/openspace/util/screenlog.h +++ b/include/openspace/util/screenlog.h @@ -75,7 +75,12 @@ public: * have in order to be stored in the ScreenLog */ ScreenLog(std::chrono::seconds timeToLive, LogLevel logLevel = LogLevel::Info); - + + /** + * Destructor + */ + ~ScreenLog(); + /** * Overwritten ghoul::loggling::Log method that is called whenever a new log message * shall be stored. diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.h b/modules/atmosphere/rendering/atmospheredeferredcaster.h index 150ed09b57..fcc9f80d02 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.h +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.h @@ -29,12 +29,13 @@ #include #include #include +#include //#include namespace ghoul { namespace opengl { - class Texture; + class Texture; class ProgramObject; } } diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index 751cb25587..4d3ae2b0fe 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -28,7 +28,6 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/modelgeometry.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.h - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablepath.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablesphere.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablesphericalgrid.h @@ -47,7 +46,6 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/modelgeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablepath.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablesphere.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablesphericalgrid.cpp diff --git a/modules/base/basemodule.cpp b/modules/base/basemodule.cpp index fc8f383a3d..47af9e3ec5 100644 --- a/modules/base/basemodule.cpp +++ b/modules/base/basemodule.cpp @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -77,7 +76,6 @@ void BaseModule::internalInitialize() { ghoul_assert(fRenderable, "Renderable factory was not created"); fRenderable->registerClass("RenderableModel"); - fRenderable->registerClass("RenderablePath"); fRenderable->registerClass("RenderablePlane"); fRenderable->registerClass("RenderableSphere"); fRenderable->registerClass("RenderableSphericalGrid"); @@ -97,7 +95,7 @@ void BaseModule::internalInitialize() { auto fScale = FactoryManager::ref().factory(); ghoul_assert(fScale, "Scale factory was not created"); - fScale->registerClass ("StaticScale"); + fScale->registerClass("StaticScale"); auto fModelGeometry = FactoryManager::ref().factory(); ghoul_assert(fModelGeometry, "Model geometry factory was not created"); @@ -106,10 +104,16 @@ void BaseModule::internalInitialize() { std::vector BaseModule::documentations() const { return { - StaticScale::Documentation(), - StaticTranslation::Documentation(), + RenderableModel::Documentation(), + RenderablePlane::Documentation(), + RenderableSphere::Documentation(), RenderableTrailOrbit::Documentation(), RenderableTrailTrajectory::Documentation(), + ScreenSpaceFramebuffer::Documentation(), + ScreenSpaceImage::Documentation(), + StaticRotation::Documentation(), + StaticScale::Documentation(), + StaticTranslation::Documentation(), modelgeometry::ModelGeometry::Documentation(), }; } diff --git a/modules/base/rendering/modelgeometry.cpp b/modules/base/rendering/modelgeometry.cpp index b74f44bd59..5b1cc4b287 100644 --- a/modules/base/rendering/modelgeometry.cpp +++ b/modules/base/rendering/modelgeometry.cpp @@ -25,20 +25,24 @@ #include #include +#include #include + #include #include #include +#include #include namespace { const char* _loggerCat = "ModelGeometry"; - const char* keyGeomModelFile = "GeometryFile"; + + const char* KeyName = "Name"; + const char* KeyType = "Type"; + const char* KeyGeomModelFile = "GeometryFile"; const int8_t CurrentCacheVersion = 3; - const char* keyType = "Type"; - const char* keyName = "Name"; -} +} // namespace namespace openspace { namespace modelgeometry { @@ -50,13 +54,13 @@ documentation:: Documentation ModelGeometry::Documentation() { "base_geometry_model", { { - keyType, + KeyType, new StringVerifier, "The type of the Model Geometry that should be generated", Optional::No }, { - keyGeomModelFile, + KeyGeomModelFile, new StringVerifier, "The file that should be loaded in this ModelGeometry. The file can " "contain filesystem tokens or can be specified relatively to the " @@ -71,25 +75,18 @@ documentation:: Documentation ModelGeometry::Documentation() { std::unique_ptr ModelGeometry::createFromDictionary( const ghoul::Dictionary& dictionary) { - if (!dictionary.hasKeyAndValue(keyType)) { + if (!dictionary.hasKeyAndValue(KeyType)) { throw ghoul::RuntimeError("Dictionary did not contain a key 'Type'"); } - std::string geometryType = dictionary.value(keyType); + const std::string geometryType = dictionary.value(KeyType); + auto factory = FactoryManager::ref().factory(); - - std::unique_ptr result = factory->create(geometryType, dictionary); - if (result == nullptr) { - throw ghoul::RuntimeError( - "Failed to create a ModelGeometry object of type '" + geometryType + "'" - ); - } - return result; + return factory->create(geometryType, dictionary);; } ModelGeometry::ModelGeometry(const ghoul::Dictionary& dictionary) : properties::PropertyOwner("ModelGeometry") - , _parent(nullptr) , _mode(GL_TRIANGLES) { documentation::testSpecificationAndThrow( @@ -98,11 +95,7 @@ ModelGeometry::ModelGeometry(const ghoul::Dictionary& dictionary) "ModelGeometry" ); - std::string name; - bool success = dictionary.getValue(keyName, name); - ghoul_assert(success, "Name tag was not present"); - - _file = absPath(dictionary.value(keyGeomModelFile)); + _file = absPath(dictionary.value(KeyGeomModelFile)); } double ModelGeometry::boundingRadius() const { @@ -119,10 +112,6 @@ double ModelGeometry::boundingRadius() const { return maxDist; } - -ModelGeometry::~ModelGeometry() { -} - void ModelGeometry::render() { glBindVertexArray(_vaoID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); @@ -135,39 +124,67 @@ void ModelGeometry::changeRenderMode(const GLenum mode) { } bool ModelGeometry::initialize(Renderable* parent) { - _parent = parent; float maximumDistanceSquared = 0; - for (auto v: _vertices) - { + for (const Vertex& v : _vertices) { maximumDistanceSquared = glm::max( glm::pow(v.location[0], 2.f) + glm::pow(v.location[1], 2.f) + glm::pow(v.location[2], 2.f), maximumDistanceSquared); } - _parent->setBoundingSphere(glm::sqrt(maximumDistanceSquared)); + parent->setBoundingSphere(glm::sqrt(maximumDistanceSquared)); - if (_vertices.empty()) + if (_vertices.empty()) { return false; + } + glGenVertexArrays(1, &_vaoID); glGenBuffers(1, &_vbo); glGenBuffers(1, &_ibo); glBindVertexArray(_vaoID); glBindBuffer(GL_ARRAY_BUFFER, _vbo); - glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(Vertex), _vertices.data(), GL_STATIC_DRAW); + glBufferData( + GL_ARRAY_BUFFER, + _vertices.size() * sizeof(Vertex), + _vertices.data(), + GL_STATIC_DRAW + ); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, location))); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, tex))); - glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, normal))); + glVertexAttribPointer( + 0, + 4, + GL_FLOAT, + GL_FALSE, + sizeof(Vertex), + reinterpret_cast(offsetof(Vertex, location)) + ); + glVertexAttribPointer( + 1, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(Vertex), + reinterpret_cast(offsetof(Vertex, tex)) + ); + glVertexAttribPointer( + 2, + 3, + GL_FLOAT, + GL_FALSE, + sizeof(Vertex), + reinterpret_cast(offsetof(Vertex, normal)) + ); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(int), _indices.data(), GL_STATIC_DRAW); + glBufferData( + GL_ELEMENT_ARRAY_BUFFER, + _indices.size() * sizeof(int), + _indices.data(), + GL_STATIC_DRAW + ); glBindVertexArray(0); @@ -181,37 +198,42 @@ void ModelGeometry::deinitialize() { } bool ModelGeometry::loadObj(const std::string& filename) { - std::string cachedFile = FileSys.cacheManager()->cachedFilename( + const std::string cachedFile = FileSys.cacheManager()->cachedFilename( filename, ghoul::filesystem::CacheManager::Persistent::Yes - ); + ); - bool hasCachedFile = FileSys.fileExists(cachedFile); + const bool hasCachedFile = FileSys.fileExists(cachedFile); if (hasCachedFile) { - LINFO("Cached file '" << cachedFile << "' used for Model file '" << filename << "'"); + LINFO("Cached file '" << cachedFile << "' used for file '" << filename << "'"); - bool success = loadCachedFile(cachedFile); - if (success) + const bool success = loadCachedFile(cachedFile); + if (success) { return true; - else + } + else { FileSys.cacheManager()->removeCacheFile(filename); + } // Intentional fall-through to the 'else' computation to generate the cache // file for the next run } else { - LINFO("Cached file '" << cachedFile << "' used for Model file '" << filename << "' not found"); + LINFO( + "Cached file '" << cachedFile << "' for file '" << filename << "' not found" + ); } LINFO("Loading Model file '" << filename << "'"); - bool success = loadModel(filename); + const bool modelSuccess = loadModel(filename); - if (!success) + if (!modelSuccess) { return false; + } LINFO("Saving cache"); - success = saveCachedFile(cachedFile); + const bool cacheSuccess = saveCachedFile(cachedFile); - return success; + return cacheSuccess; } bool ModelGeometry::saveCachedFile(const std::string& filename) { @@ -271,22 +293,6 @@ bool ModelGeometry::loadCachedFile(const std::string& filename) { } } -bool ModelGeometry::getVertices(std::vector* vertexList) { - vertexList->clear(); - for (auto v : _vertices) - vertexList->push_back(v); - - return !(vertexList->empty()); -} - -bool ModelGeometry::getIndices(std::vector* indexList) { - indexList->clear(); - for (auto i : _indices) - indexList->push_back(i); - - return !(indexList->empty()); -} - void ModelGeometry::setUniforms(ghoul::opengl::ProgramObject&) {} } // namespace modelgeometry diff --git a/modules/base/rendering/modelgeometry.h b/modules/base/rendering/modelgeometry.h index 508b523101..f76685404c 100644 --- a/modules/base/rendering/modelgeometry.h +++ b/modules/base/rendering/modelgeometry.h @@ -27,36 +27,46 @@ #include -#include +#include -namespace ghoul { class Dictionary; } +#include + +namespace ghoul { + class Dictionary; + + namespace opengl { class ProgramObject; } +} // namespace ghoul namespace openspace { -namespace documentation { struct Documentation; } +class Renderable; + +namespace documentation { struct Documentation; } namespace modelgeometry { class ModelGeometry : public properties::PropertyOwner { public: - static std::unique_ptr createFromDictionary( - const ghoul::Dictionary& dictionary - ); - struct Vertex { GLfloat location[4]; GLfloat tex[2]; GLfloat normal[3]; }; + static std::unique_ptr createFromDictionary( + const ghoul::Dictionary& dictionary + ); + ModelGeometry(const ghoul::Dictionary& dictionary); - virtual ~ModelGeometry(); + virtual ~ModelGeometry() = default; + virtual bool initialize(Renderable* parent); virtual void deinitialize(); void render(); + virtual bool loadModel(const std::string& filename) = 0; void changeRenderMode(const GLenum mode); - bool getVertices(std::vector* vertexList); - bool getIndices(std::vector* indexList); + //bool getVertices(std::vector* vertexList); + //bool getIndices(std::vector* indexList); double boundingRadius() const; @@ -65,8 +75,6 @@ public: static documentation::Documentation Documentation(); protected: - Renderable* _parent; - bool loadObj(const std::string& filename); bool loadCachedFile(const std::string& filename); bool saveCachedFile(const std::string& filename); diff --git a/modules/base/rendering/multimodelgeometry.cpp b/modules/base/rendering/multimodelgeometry.cpp index 5428bd5724..ee8ea50aa2 100644 --- a/modules/base/rendering/multimodelgeometry.cpp +++ b/modules/base/rendering/multimodelgeometry.cpp @@ -24,15 +24,9 @@ #include -#include "ghoul/logging/logmanager.h" #include "ghoul/io/model/modelreadermultiformat.h" -#include "ghoul/opengl/vertexbufferobject.h" -#include - -namespace { - const std::string _loggerCat = "MultiModelGeometry"; -} +#include namespace openspace { namespace modelgeometry { @@ -43,25 +37,13 @@ MultiModelGeometry::MultiModelGeometry(const ghoul::Dictionary& dictionary) loadObj(_file); } -bool MultiModelGeometry::initialize(Renderable* parent) { - bool success = ModelGeometry::initialize(parent); - return success; -} - -void MultiModelGeometry::deinitialize() { - ModelGeometry::deinitialize(); -} - bool MultiModelGeometry::loadModel(const std::string& filename) { - ghoul::io::ModelReaderMultiFormat modelReader; - std::vector vertices; std::vector indices; - - modelReader.loadModel(filename, vertices, indices); + ghoul::io::ModelReaderMultiFormat().loadModel(filename, vertices, indices); _vertices.reserve(vertices.size()); - for (const auto & v : vertices) { + for (const ghoul::io::ModelReaderBase::Vertex& v : vertices) { Vertex vv; memcpy(vv.location, v.location, sizeof(GLfloat) * 3); vv.location[3] = 1.0; diff --git a/modules/base/rendering/multimodelgeometry.h b/modules/base/rendering/multimodelgeometry.h index dedd7f256c..57f255f646 100644 --- a/modules/base/rendering/multimodelgeometry.h +++ b/modules/base/rendering/multimodelgeometry.h @@ -38,9 +38,6 @@ class MultiModelGeometry : public ModelGeometry { public: MultiModelGeometry(const ghoul::Dictionary& dictionary); - bool initialize(Renderable* parent) override; - void deinitialize() override; - private: bool loadModel(const std::string& filename); }; diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index 2f92b51d79..97175e9d9c 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -24,129 +24,141 @@ #include -#include #include + +#include +#include #include - -#include -#include -#include -#include - -#include - #include +#include +#include +#include +#include -#define _USE_MATH_DEFINES -#include +#include +#include +#include +#include +#include +#include namespace { - const std::string _loggerCat = "RenderableModel"; - const char* keyGeometry = "Geometry"; + const char* KeyGeometry = "Geometry"; + const char* KeyTexture = "Textures.Color"; + const char* KeyModelTransform = "Rotation.ModelTransform"; + const char* KeyFading = "Shading.Fadeable"; + const char* keyBody = "Body"; const char* keyStart = "StartTime"; const char* keyEnd = "EndTime"; - const char* keyFading = "Shading.Fadeable"; - const char* keyModelTransform = "Rotation.ModelTransform"; - //const std::string keyGhosting = "Shading.Ghosting"; - -} +} // namespace namespace openspace { +documentation::Documentation RenderableModel::Documentation() { + using namespace documentation; + return { + "RenderableModel", + "base_renderable_model", + { + { + KeyGeometry, + new ReferencingVerifier("base_geometry_model"), + "This specifies the model that is rendered by the Renderable.", + Optional::No + }, + { + KeyTexture, + new StringVerifier, + "A color texture that can be applied to the model specified by the " + "Geometry.", + Optional::Yes + }, + { + KeyModelTransform, + new DoubleMatrix3Verifier, + "Specifies a distinct transformation matrix that is applied to the " + "model. If it is not specified, it is equal to the Identity matrix.", + Optional::Yes + }, + { + KeyFading, + new BoolVerifier, + "Specifies whether the model should be periodically fading in and out. " + "If this value is not specified, it will not fade.", + Optional::Yes + } + } + }; +} + RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary) : Renderable(dictionary) + , _geometry(nullptr) , _colorTexturePath("colorTexture", "Color Texture") , _performFade("performFading", "Perform Fading", false) + , _performShading("performShading", "Perform Shading", true) , _fading("fading", "Fade", 0) - , _debugModelRotation("modelrotation", "Model Rotation", glm::vec3(0.f), glm::vec3(0.f), glm::vec3(360.f)) , _programObject(nullptr) , _texture(nullptr) - , _geometry(nullptr) - , _alpha(1.f) - //, _isGhost(false) - , _performShading("performShading", "Perform Shading", true) - , _frameCount(0) + , _modelTransform(1.0) { - std::string name; - bool success = dictionary.getValue(SceneGraphNode::KeyName, name); - ghoul_assert(success, "Name was not passed to RenderableModel"); + ghoul_precondition( + dictionary.hasKeyAndValue(SceneGraphNode::KeyName), + "Name was not passed to RenderableModel" + ); - ghoul::Dictionary geometryDictionary; - success = dictionary.getValue(keyGeometry, geometryDictionary); - if (success) { - geometryDictionary.setValue(SceneGraphNode::KeyName, name); - _geometry = modelgeometry::ModelGeometry::createFromDictionary(geometryDictionary); + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableModel" + ); + + if (dictionary.hasKey(KeyGeometry)) { + std::string name = dictionary.value(SceneGraphNode::KeyName); + ghoul::Dictionary dict = dictionary.value(KeyGeometry); + dict.setValue(SceneGraphNode::KeyName, name); + _geometry = modelgeometry::ModelGeometry::createFromDictionary(dict); } - std::string texturePath = ""; - success = dictionary.getValue("Textures.Color", texturePath); - if (success) - _colorTexturePath = absPath(texturePath); + if (dictionary.hasKey(KeyTexture)) { + _colorTexturePath = absPath(dictionary.value(KeyTexture)); + } + + if (dictionary.hasKey(KeyModelTransform)) { + _modelTransform = dictionary.value(KeyModelTransform); + } + + if (dictionary.hasKey(KeyFading)) { + _performFade = dictionary.value(KeyFading); + } addPropertySubOwner(_geometry.get()); addProperty(_colorTexturePath); _colorTexturePath.onChange(std::bind(&RenderableModel::loadTexture, this)); - addProperty(_debugModelRotation); - - //dictionary.getValue(keySource, _source); - //dictionary.getValue(keyDestination, _destination); - if (dictionary.hasKeyAndValue(keyModelTransform)) - dictionary.getValue(keyModelTransform, _modelTransform); - else - _modelTransform = glm::dmat3(1.f); - dictionary.getValue(keyBody, _target); - - //openspace::SpiceManager::ref().addFrame(_target, _source); - - //setBoundingSphere(pss(1.f, 9.f)); addProperty(_performShading); - - if (dictionary.hasKeyAndValue(keyFading)) { - bool fading; - dictionary.getValue(keyFading, fading); - _performFade = fading; - } addProperty(_performFade); - - //if (dictionary.hasKeyAndValue(keyGhosting)) { - // bool ghosting; - // dictionary.getValue(keyGhosting, ghosting); - // _isGhost = ghosting; - //} } bool RenderableModel::isReady() const { - bool ready = true; - ready &= (_programObject != nullptr); - ready &= (_texture != nullptr); - return ready; + return _programObject && _texture; } bool RenderableModel::initialize() { - bool completeSuccess = true; - if (_programObject == nullptr) { - // NH shader - - RenderEngine& renderEngine = OsEng.renderEngine(); - _programObject = renderEngine.buildRenderProgram("ModelProgram", - "${MODULE_BASE}/shaders/model_vs.glsl", - "${MODULE_BASE}/shaders/model_fs.glsl"); - - if (!_programObject) - return false; - } + _programObject = OsEng.renderEngine().buildRenderProgram( + "ModelProgram", + "${MODULE_BASE}/shaders/model_vs.glsl", + "${MODULE_BASE}/shaders/model_fs.glsl" + ); loadTexture(); + bool completeSuccess = true; completeSuccess &= (_texture != nullptr); completeSuccess &= _geometry->initialize(this); - //completeSuccess &= !_source.empty(); - //completeSuccess &= !_destination.empty(); - return completeSuccess; } @@ -157,10 +169,8 @@ bool RenderableModel::deinitialize() { } _texture = nullptr; - - RenderEngine& renderEngine = OsEng.renderEngine(); if (_programObject) { - renderEngine.removeRenderProgram(_programObject); + OsEng.renderEngine().removeRenderProgram(_programObject); _programObject = nullptr; } @@ -176,30 +186,18 @@ void RenderableModel::render(const RenderData& data) { } else if (!_performFade && _fading < 1.f) { _fading = _fading + 0.01f; - } - - // debug rotation controlled from GUI - glm::mat4 unitMat4(1); - glm::vec3 debugEulerRot = glm::radians(_debugModelRotation.value()); - glm::mat4 rotX = glm::rotate(unitMat4, debugEulerRot.x, glm::vec3(1, 0, 0)); - glm::mat4 rotY = glm::rotate(unitMat4, debugEulerRot.y, glm::vec3(0, 1, 0)); - glm::mat4 rotZ = glm::rotate(unitMat4, debugEulerRot.z, glm::vec3(0, 0, 1)); - glm::dmat4 debugModelRotation = rotX * rotY * rotZ; - // Model transform and view transform needs to be in double precision glm::dmat4 modelTransform = glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation glm::dmat4(data.modelTransform.rotation) * // Spice rotation glm::dmat4(glm::scale(glm::dmat4(_modelTransform), glm::dvec3(data.modelTransform.scale))); - debugModelRotation; // debug model rotation controlled from GUI glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; glm::vec3 directionToSun = glm::normalize(_sunPos - data.modelTransform.translation); glm::vec3 directionToSunViewSpace = glm::mat3(data.camera.combinedViewMatrix()) * directionToSun; - _programObject->setUniform("transparency", _alpha); _programObject->setUniform("directionToSunViewSpace", directionToSunViewSpace); _programObject->setUniform("modelViewTransform", glm::mat4(modelViewTransform)); _programObject->setUniform("projectionTransform", data.camera.projectionMatrix()); @@ -216,7 +214,6 @@ void RenderableModel::render(const RenderData& data) { _geometry->render(); - // disable shader _programObject->deactivate(); } @@ -224,23 +221,6 @@ void RenderableModel::update(const UpdateData& data) { if (_programObject->isDirty()) { _programObject->rebuildFromFile(); } -// double _time = data.time; - - //if (_isGhost){ - // futureTime = openspace::ImageSequencer::ref().getNextCaptureTime(); - // double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - data.time; - // double interval = openspace::ImageSequencer::ref().getIntervalLength(); - // double t = 1.f - remaining / openspace::ImageSequencer::ref().getIntervalLength(); - // if (interval > 60) { - // if (t < 0.8) - // _fading = static_cast(t); - // else if (t >= 0.95) - // _fading = _fading - 0.5f; - // } - // else - // _fading = 0.f; - // _time = futureTime; - //} _sunPos = OsEng.renderEngine().scene()->sceneGraphNode("Sun")->worldPosition(); } @@ -250,7 +230,10 @@ void RenderableModel::loadTexture() { if (_colorTexturePath.value() != "") { _texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath)); if (_texture) { - LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); + LDEBUGC( + "RenderableModel", + "Loaded texture from '" << absPath(_colorTexturePath) << "'" + ); _texture->uploadTexture(); _texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); } diff --git a/modules/base/rendering/renderablemodel.h b/modules/base/rendering/renderablemodel.h index 153964d60a..f169710df7 100644 --- a/modules/base/rendering/renderablemodel.h +++ b/modules/base/rendering/renderablemodel.h @@ -31,15 +31,23 @@ #include #include #include -#include - -#include -#include #include +namespace ghoul { +namespace opengl { + class ProgramObject; + class Texture; +} // namespace opengl +} // namespace ghoul + namespace openspace { +struct RenderData; +struct UpdateData; + +namespace documentation { struct Documentation; } + namespace modelgeometry { class ModelGeometry; } @@ -56,35 +64,24 @@ public: void render(const RenderData& data) override; void update(const UpdateData& data) override; + static documentation::Documentation Documentation(); protected: void loadTexture(); private: + std::unique_ptr _geometry; + properties::StringProperty _colorTexturePath; properties::BoolProperty _performFade; + properties::BoolProperty _performShading; properties::FloatProperty _fading; + std::unique_ptr _programObject; std::unique_ptr _texture; - std::unique_ptr _geometry; - glm::dmat3 _modelTransform; - - float _alpha; - //glm::dmat3 _stateMatrix; - - //std::string _source; - //std::string _destination; - std::string _target; - - //bool _isGhost; - int _frameCount; - glm::dvec3 _sunPos; - - properties::BoolProperty _performShading; - properties::Vec3Property _debugModelRotation; }; } // namespace openspace diff --git a/modules/base/rendering/renderablepath.cpp b/modules/base/rendering/renderablepath.cpp deleted file mode 100644 index 081abb3b9f..0000000000 --- a/modules/base/rendering/renderablepath.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2017 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* TODO for this class: -* In order to add geometry shader (for pretty-draw), -* need to pack each consecutive point pair into a vec2 -* in order to draw quad between them. -*/ - -namespace { - const std::string _loggerCat = "RenderableTrail"; - //constants - const char* keyName = "Name"; - const char* keyBody = "Body"; - const char* keyObserver = "Observer"; - const char* keyFrame = "Frame"; - const char* keyPathModule = "ModulePath"; - const char* keyColor = "RGB"; - const char* keyTimeSteps = "TimeSteps"; - const char* keyPointSteps = "PointSteps"; - const char* keyDrawLine = "DrawLine"; - const char* keRenderDistanceInterval = "RenderDistanceInterval"; -} - -namespace openspace { - -RenderablePath::RenderablePath(const ghoul::Dictionary& dictionary) - : Renderable(dictionary) - , _lineWidth("lineWidth", "Line Width", 2.f, 1.f, 20.f) - , _drawLine("drawline", "Draw Line", false) - , _programObject(nullptr) - , _successfullDictionaryFetch(true) - , _vaoID(0) - , _vBufferID(0) - , _needsSweep(true) - , _start(0.0) - , _stop(0.0) -{ - _successfullDictionaryFetch &= dictionary.getValue(keyBody, _target); - _successfullDictionaryFetch &= dictionary.getValue(keyObserver, _observer); - _successfullDictionaryFetch &= dictionary.getValue(keyFrame, _frame); - _successfullDictionaryFetch &= dictionary.getValue(keyTimeSteps, _increment); - - float fPointSteps; // Dictionary can not pick out ints... - if (!dictionary.getValue(keyPointSteps, fPointSteps)) - fPointSteps = 4; - _pointSteps = static_cast(fPointSteps); - - glm::vec3 color(0.f); - if (dictionary.hasKeyAndValue(keyColor)) - dictionary.getValue(keyColor, color); - _lineColor = color; - - bool drawLine = false; - if (dictionary.hasKeyAndValue(keyDrawLine)) - dictionary.getValue(keyDrawLine, drawLine); - _drawLine = drawLine; - addProperty(_drawLine); - addProperty(_lineWidth); - _distanceFade = 1.0; -} - -bool RenderablePath::initialize() { - if (!_successfullDictionaryFetch) { - LERROR("The following keys need to be set in the Dictionary. Cannot initialize!"); - LERROR(keyBody << ": " << _target); - LERROR(keyObserver << ": " << _observer); - LERROR(keyFrame << ": " << _frame); - return false; - } - - bool completeSuccess = true; - - - RenderEngine& renderEngine = OsEng.renderEngine(); - _programObject = renderEngine.buildRenderProgram("PathProgram", - "${MODULE_BASE}/shaders/path_vs.glsl", - "${MODULE_BASE}/shaders/path_fs.glsl"); - if (!_programObject) - return false; - - bool intervalSet = hasTimeInterval(); - if (intervalSet) { - completeSuccess &= getInterval(_start, _stop); - } - - return completeSuccess; -} - -bool RenderablePath::deinitialize() { - glDeleteVertexArrays(1, &_vaoID); - _vaoID = 0; - - glDeleteBuffers(1, &_vBufferID); - _vBufferID = 0; - - RenderEngine& renderEngine = OsEng.renderEngine(); - if (_programObject) { - renderEngine.removeRenderProgram(_programObject); - _programObject = nullptr; - } - - return true; -} - -bool RenderablePath::isReady() const { - return (_programObject != nullptr) && _successfullDictionaryFetch; -} - -void RenderablePath::render(const RenderData& data) { - double time = openspace::Time::ref().j2000Seconds(); - if (_start > time || _stop < time) - return; - - - size_t nPointsToDraw = _vertexArray.size();// (time - _start) / (_stop - _start) * (_vertexArray.size()) + 1 + 0.5; - - _programObject->activate(); - - // Calculate variables to be used as uniform variables in shader - glm::dvec3 bodyPosition = data.modelTransform.translation; - - // Model transform and view transform needs to be in double precision - glm::dmat4 modelTransform = - glm::translate(glm::dmat4(1.0), bodyPosition); // Translation - glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; - - _programObject->setUniform("modelViewTransform", glm::mat4(modelViewTransform)); - _programObject->setUniform("projectionTransform", data.camera.projectionMatrix()); - _programObject->setUniform("pointSteps", _pointSteps); - _programObject->setUniform("color", _lineColor); - - if (_drawLine) { - glLineWidth(_lineWidth); - glBindVertexArray(_vaoID); - glDrawArrays(GL_LINE_STRIP, 0, static_cast(nPointsToDraw)); - glBindVertexArray(0); - glLineWidth(1.f); - } - - glEnable(GL_PROGRAM_POINT_SIZE); - - glBindVertexArray(_vaoID); - glDrawArrays(GL_POINTS, 0, static_cast(nPointsToDraw)); - glBindVertexArray(0); - - glDisable(GL_PROGRAM_POINT_SIZE); - - _programObject->deactivate(); -} - -void RenderablePath::update(const UpdateData& data) { - if (data.isTimeJump) - _needsSweep = true; - - if (_needsSweep) { - calculatePath(_observer); - sendToGPU(); - _needsSweep = false; - } - - if (_programObject->isDirty()) - _programObject->rebuildFromFile(); -} - -void RenderablePath::calculatePath(std::string observer) { - double interval = (_stop - _start); - int segments = static_cast(interval /_increment); - - if (segments == 0) - return; - - double lightTime; -// bool correctPosition = true; - - double currentTime = _start; - _vertexArray.resize(segments); - - //psc pscPos; - //float r, g, b; - //float g = _lineColor[1]; - //float b = _lineColor[2]; - glm::vec3 position; - for (int i = 0; i < segments; i++) { - position = - glm::vec3(SpiceManager::ref().targetPosition(_target, observer, _frame, {}, currentTime, lightTime)); - - // Convert from 100 m to m - position *= 10e2; - - //pscPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); - //pscPos[3] += 3; - - //if (!correctPosition) { - // r = 1.f; - // g = b = 0.5f; - //} - //else if ((i % 8) == 0) { - // r = _lineColor[0]; - // g = _lineColor[1]; - // b = _lineColor[2]; - //} - //else { - // r = g = b = 0.6f; - //} - //add position - _vertexArray[i] = { position[0], position[1], position[2], 1.0f }; - //add color for position - //_vertexArray[i + 1] = { r, g, b, a }; - currentTime += _increment; - } - _lastPosition = glm::vec4(position, 1.0f); - - glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glBufferSubData(GL_ARRAY_BUFFER, 0, _vertexArray.size() * sizeof(VertexInfo), &_vertexArray[0]); -} - -void RenderablePath::sendToGPU() { - glGenVertexArrays(1, &_vaoID); - glGenBuffers(1, &_vBufferID); - - glBindVertexArray(_vaoID); - - glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glBufferData(GL_ARRAY_BUFFER, _vertexArray.size() * sizeof(VertexInfo), NULL, GL_STREAM_DRAW); // orphaning the buffer, sending NULL data. - glBufferSubData(GL_ARRAY_BUFFER, 0, _vertexArray.size() * sizeof(VertexInfo), &_vertexArray[0]); - - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); - //glEnableVertexAttribArray(1); - //glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexInfo) * 2, (void*)(sizeof(VertexInfo))); - - glBindVertexArray(0); -} - -} // namespace openspace diff --git a/modules/base/rendering/renderablepath.h b/modules/base/rendering/renderablepath.h deleted file mode 100644 index 44c7dfb1b8..0000000000 --- a/modules/base/rendering/renderablepath.h +++ /dev/null @@ -1,94 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2017 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#ifndef __OPENSPACE_MODULE_BASE___RENDERABLEPATH___H__ -#define __OPENSPACE_MODULE_BASE___RENDERABLEPATH___H__ - -#include -#include -#include - -#include - -namespace ghoul { - namespace opengl { - class ProgramObject; - class Texture; - } -} - -namespace openspace { - -class RenderablePath : public Renderable { -public: - RenderablePath(const ghoul::Dictionary& dictionary); - - bool initialize() override; - bool deinitialize() override; - - bool isReady() const override; - - void render(const RenderData& data) override; - void update(const UpdateData& data) override; - - void calculatePath(std::string observer); -private: - struct VertexInfo { - float x, y, z, e; - //float r, g, b, a; - }; - void sendToGPU(); - void addPosition(glm::vec3 pos); - void addColor(glm::vec4 col); - - glm::vec3 _lineColor; - glm::vec4 _lastPosition; - properties::FloatProperty _lineWidth; - properties::BoolProperty _drawLine; - - std::unique_ptr _programObject; - - bool _successfullDictionaryFetch; - - std::string _target; - std::string _observer; - std::string _frame; - - GLuint _vaoID; - GLuint _vBufferID; - - bool _needsSweep; - - std::vector _vertexArray; - - float _increment; - double _start; - double _stop; - float _distanceFade; - int _pointSteps; -}; - -} // namespace openspace - -#endif // __OPENSPACE_MODULE_BASE___RENDERABLEPATH___H__ diff --git a/modules/base/rendering/renderableplane.cpp b/modules/base/rendering/renderableplane.cpp index 25e80ffd59..1398d290b2 100644 --- a/modules/base/rendering/renderableplane.cpp +++ b/modules/base/rendering/renderableplane.cpp @@ -22,14 +22,14 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include #include -#include -#include -#include +#include +#include +#include #include -#include +#include +#include #include #include @@ -38,108 +38,106 @@ #include namespace { - static const std::string _loggerCat = "RenderablePlane"; - - const char* keyFieldlines = "Fieldlines"; - const char* keyFilename = "File"; - const char* keyHints = "Hints"; - const char* keyShaders = "Shaders"; - const char* keyVertexShader = "VertexShader"; - const char* keyFragmentShader = "FragmentShader"; -} + const char* KeySize = "Size"; + const char* KeyBillboard = "Billboard"; + const char* KeyBlendMode = "BlendMode"; + const char* KeyTexture = "Texture"; +} // namespace namespace openspace { +documentation::Documentation RenderablePlane::Documentation() { + using namespace documentation; + return { + "Renderable Plane", + "base_renderable_plane", + { + { + KeySize, + new DoubleVerifier, + "Specifies the size of the square plane in meters.", + Optional::No + }, + { + KeyBillboard, + new BoolVerifier, + "Specifies whether the plane is a billboard, which means that it is " + "always facing the camera. If this is false, it can be oriented using " + "other transformations. The default is 'false'.", + Optional::Yes + }, + { + KeyBlendMode, + new StringInListVerifier({ "Normal", "Additive" }), + "Specifies the blend mode that is applied to this plane. The default " + "value is 'Normal'.", + Optional::Yes + }, + { + KeyTexture, + new StringVerifier, + "Specifies the texture that is applied to this plane. This image has to " + "be a square image.", + Optional::No + } + } + }; +} + + RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _texturePath("texture", "Texture") , _billboard("billboard", "Billboard", false) - , _projectionListener("projectionListener", "DisplayProjections", false) , _size("size", "Size", 10, 0, std::pow(10, 25)) - , _origin(Origin::Center) , _shader(nullptr) - , _textureIsDirty(false) , _texture(nullptr) , _blendMode(BlendMode::Normal) , _quad(0) , _vertexPositionBuffer(0) + , _planeIsDirty(false) + , _textureIsDirty(false) { - dictionary.getValue("Size", _size); + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderablePlane" + ); - if (dictionary.hasKey("Name")) { - dictionary.getValue("Name", _nodeName); + _size = dictionary.value(KeySize); + + if (dictionary.hasKey(KeyBillboard)) { + _billboard = dictionary.value(KeyBillboard); } - std::string origin; - if (dictionary.getValue("Origin", origin)) { - if (origin == "LowerLeft") { - _origin = Origin::LowerLeft; + if (dictionary.hasKey(KeyBlendMode)) { + const std::string v = dictionary.value(KeyBlendMode); + if (v == "Normal") { + _blendMode = BlendMode::Normal; } - else if (origin == "LowerRight") { - _origin = Origin::LowerRight; - } - else if (origin == "UpperLeft") { - _origin = Origin::UpperLeft; - } - else if (origin == "UpperRight") { - _origin = Origin::UpperRight; - } - else if (origin == "Center") { - _origin = Origin::Center; - } - } - - // Attempt to get the billboard value - bool billboard = false; - if (dictionary.getValue("Billboard", billboard)) { - _billboard = billboard; - } - if (dictionary.hasKey("ProjectionListener")){ - bool projectionListener = false; - if (dictionary.getValue("ProjectionListener", projectionListener)) { - _projectionListener = projectionListener; - } - } - - std::string blendMode; - if (dictionary.getValue("BlendMode", blendMode)) { - if (blendMode == "Additive") { + else if (v == "Additive") { _blendMode = BlendMode::Additive; setRenderBin(Renderable::RenderBin::Transparent); } } - - std::string texturePath = ""; - bool success = dictionary.getValue("Texture", texturePath); - if (success) { - _texturePath = absPath(texturePath); - _textureFile = new ghoul::filesystem::File(_texturePath); - } + _texturePath = absPath(dictionary.value(KeyTexture)); + _textureFile = std::make_unique(_texturePath); addProperty(_billboard); addProperty(_texturePath); - _texturePath.onChange(std::bind(&RenderablePlane::loadTexture, this)); - _textureFile->setCallback([&](const ghoul::filesystem::File&) { _textureIsDirty = true; }); + _texturePath.onChange([this]() {loadTexture(); }); + _textureFile->setCallback( + [this](const ghoul::filesystem::File&) { _textureIsDirty = true; } + ); addProperty(_size); - //_size.onChange(std::bind(&RenderablePlane::createPlane, this)); _size.onChange([this](){ _planeIsDirty = true; }); setBoundingSphere(_size); } -RenderablePlane::~RenderablePlane() { - delete _textureFile; - _textureFile = nullptr; -} - bool RenderablePlane::isReady() const { - bool ready = true; - if (!_shader) - ready &= false; - if(!_texture) - ready &= false; - return ready; + return _shader && _texture; } bool RenderablePlane::initialize() { @@ -147,17 +145,10 @@ bool RenderablePlane::initialize() { glGenBuffers(1, &_vertexPositionBuffer); // generate buffer createPlane(); - if (_shader == nullptr) { - // Plane Program - - RenderEngine& renderEngine = OsEng.renderEngine(); - _shader = renderEngine.buildRenderProgram("PlaneProgram", - "${MODULE_BASE}/shaders/plane_vs.glsl", - "${MODULE_BASE}/shaders/plane_fs.glsl" - ); - if (!_shader) - return false; - } + _shader = OsEng.renderEngine().buildRenderProgram("PlaneProgram", + "${MODULE_BASE}/shaders/plane_vs.glsl", + "${MODULE_BASE}/shaders/plane_fs.glsl" + ); loadTexture(); @@ -171,16 +162,8 @@ bool RenderablePlane::deinitialize() { glDeleteBuffers(1, &_vertexPositionBuffer); _vertexPositionBuffer = 0; - if (!_projectionListener){ - // its parents job to kill texture - // iff projectionlistener - _texture = nullptr; - } - - delete _textureFile; _textureFile = nullptr; - RenderEngine& renderEngine = OsEng.renderEngine(); if (_shader) { renderEngine.removeRenderProgram(_shader); @@ -191,44 +174,35 @@ bool RenderablePlane::deinitialize() { } void RenderablePlane::render(const RenderData& data) { - glm::mat4 scaleTransform = glm::mat4(1.0); - - // Activate shader _shader->activate(); - if (_projectionListener){ - //get parent node-texture and set with correct dimensions - SceneGraphNode* textureNode = OsEng.renderEngine().scene()->sceneGraphNode(_nodeName)->parent(); - if (textureNode != nullptr){ - RenderablePlanetProjection* t = static_cast(textureNode->renderable()); - _texture = std::unique_ptr(&(t->baseTexture())); - unsigned int h = _texture->height(); - unsigned int w = _texture->width(); - float scale = static_cast(h) / static_cast(w); - scaleTransform = glm::scale(glm::mat4(1.0), glm::vec3(1.f, scale, 1.f)); - } - } + //if (_projectionListener){ + // //get parent node-texture and set with correct dimensions + // SceneGraphNode* textureNode = OsEng.renderEngine().scene()->sceneGraphNode(_nodeName)->parent(); + // if (textureNode != nullptr){ + // RenderablePlanetProjection* t = static_cast(textureNode->renderable()); + // _texture = std::unique_ptr(&(t->baseTexture())); + // unsigned int h = _texture->height(); + // unsigned int w = _texture->width(); + // float scale = static_cast(h) / static_cast(w); + // scaleTransform = glm::scale(glm::mat4(1.0), glm::vec3(1.f, scale, 1.f)); + // } + //} // Model transform and view transform needs to be in double precision - glm::dmat4 rotationTransform; - if (_billboard) - rotationTransform = glm::inverse(glm::dmat4(data.camera.viewRotationMatrix())); - else - rotationTransform = glm::dmat4(data.modelTransform.rotation); + const glm::dmat4 rotationTransform = _billboard ? + glm::inverse(glm::dmat4(data.camera.viewRotationMatrix())) : + glm::dmat4(data.modelTransform.rotation); - glm::dmat4 modelTransform = + const glm::dmat4 modelTransform = glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * rotationTransform * glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale))) * - glm::dmat4(scaleTransform); - glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; + glm::dmat4(1.0); + const glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; _shader->setUniform("modelViewProjectionTransform", data.camera.projectionMatrix() * glm::mat4(modelViewTransform)); - //_shader->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); - //_shader->setUniform("ModelTransform", transform); - //setPscUniforms(*_shader.get(), data.camera, data.position); - ghoul::opengl::TextureUnit unit; unit.activate(); _texture->bind(); @@ -276,9 +250,14 @@ void RenderablePlane::update(const UpdateData&) { void RenderablePlane::loadTexture() { if (_texturePath.value() != "") { - std::unique_ptr texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath)); + std::unique_ptr texture = + ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath)); + if (texture) { - LDEBUG("Loaded texture from '" << absPath(_texturePath) << "'"); + LDEBUGC( + "RenderablePlane", + "Loaded texture from '" << absPath(_texturePath) << "'" + ); texture->uploadTexture(); // Textures of planets looks much smoother with AnisotropicMipMap rather than linear @@ -286,19 +265,15 @@ void RenderablePlane::loadTexture() { _texture = std::move(texture); - delete _textureFile; - _textureFile = new ghoul::filesystem::File(_texturePath); + _textureFile = std::make_unique(_texturePath); _textureFile->setCallback([&](const ghoul::filesystem::File&) { _textureIsDirty = true; }); } } } void RenderablePlane::createPlane() { - // ============================ - // GEOMETRY (quad) - // ============================ const GLfloat size = _size; - const GLfloat vertex_data[] = { + const GLfloat vertexData[] = { // x y z w s t -size, -size, 0.f, 0.f, 0.f, 0.f, size, size, 0.f, 0.f, 1.f, 1.f, @@ -308,13 +283,28 @@ void RenderablePlane::createPlane() { size, size, 0.f, 0.f, 1.f, 1.f, }; - glBindVertexArray(_quad); // bind array - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); // bind buffer - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glBindVertexArray(_quad); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(0)); + glVertexAttribPointer( + 0, + 4, + GL_FLOAT, + GL_FALSE, + sizeof(GLfloat) * 6, + reinterpret_cast(0) + ); + glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(sizeof(GLfloat) * 4)); + glVertexAttribPointer( + 1, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(GLfloat) * 6, + reinterpret_cast(sizeof(GLfloat) * 4) + ); } } // namespace openspace diff --git a/modules/base/rendering/renderableplane.h b/modules/base/rendering/renderableplane.h index a14e340f9e..aad6a2b2e9 100644 --- a/modules/base/rendering/renderableplane.h +++ b/modules/base/rendering/renderableplane.h @@ -29,35 +29,31 @@ #include #include -#include +#include + +#include namespace ghoul { - namespace filesystem { - class File; - } - namespace opengl { - class ProgramObject; - class Texture; - } +namespace filesystem { class File; } + +namespace opengl { + class ProgramObject; + class Texture; } +} // namespace ghoul namespace openspace { - struct LinePoint; + +struct RenderData; +struct UpdateData; + +namespace documentation { struct Documentation; } + +struct LinePoint; class RenderablePlane : public Renderable { - - enum class Origin { - LowerLeft, LowerRight, UpperLeft, UpperRight, Center - }; - public: - enum class BlendMode : int { - Normal = 0, - Additive - }; - RenderablePlane(const ghoul::Dictionary& dictionary); - ~RenderablePlane(); bool initialize() override; bool deinitialize() override; @@ -67,27 +63,32 @@ public: void render(const RenderData& data) override; void update(const UpdateData& data) override; + static documentation::Documentation Documentation(); + private: + enum class BlendMode : int { + Normal = 0, + Additive + }; + void loadTexture(); void createPlane(); properties::StringProperty _texturePath; properties::BoolProperty _billboard; - properties::BoolProperty _projectionListener; properties::FloatProperty _size; - Origin _origin; - std::string _nodeName; - - bool _planeIsDirty; - std::unique_ptr _shader; - bool _textureIsDirty; std::unique_ptr _texture; + std::unique_ptr _textureFile; + BlendMode _blendMode; - ghoul::filesystem::File* _textureFile; + GLuint _quad; GLuint _vertexPositionBuffer; + + bool _planeIsDirty; + bool _textureIsDirty; }; } // namespace openspace diff --git a/modules/base/rendering/renderablesphere.cpp b/modules/base/rendering/renderablesphere.cpp index 3383aa594b..25ca8c0494 100644 --- a/modules/base/rendering/renderablesphere.cpp +++ b/modules/base/rendering/renderablesphere.cpp @@ -24,38 +24,77 @@ #include +#include +#include #include #include -#include -#include -#include - #include +#include + +#include +#include +#include +#include +#include #define _USE_MATH_DEFINES #include namespace { - static const std::string _loggerCat = "RenderableSphere"; - - const char* keySize = "Size"; - const char* keySegments = "Segments"; - const char* keyTexture = "Texture"; - const char* keyOrientation = "Orientation"; + const char* KeySize = "Size"; + const char* KeySegments = "Segments"; + const char* KeyTexture = "Texture"; + const char* KeyOrientation = "Orientation"; enum Orientation { Outside = 1, Inside = 2 }; -} +} // namespace namespace openspace { +documentation::Documentation RenderableSphere::Documentation() { + using namespace documentation; + return { + "RenderableSphere", + "base_renderable_sphere", + { + { + KeySize, + new DoubleVerifier, + "Specifies the radius of the sphere in meters.", + Optional::No + }, + { + KeySegments, + new IntVerifier, + "Specifies the number of segments the sphere is separated in.", + Optional::No + }, + { + KeyTexture, + new StringVerifier, + "Specifies the texture that is applied to the sphere.", + Optional::No + }, + { + KeyOrientation, + new StringInListVerifier({ "Inside", "Outside", "Inside/Outside" }), + "Specifies whether the texture is applied to the inside of the sphere, " + "the outside of the sphere, or both. The default value is 'Outside'.", + Optional::Yes + } + } + }; +} + + RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _texturePath("texture", "Texture") , _orientation("orientation", "Orientation") - , _size("size", "Size", glm::vec2(1.f, 1.f), glm::vec2(0.f), glm::vec2(100.f)) + , _size("size", "Size", 1.f, 0.f, std::pow(10.f, 45)) , _segments("segments", "Segments", 8, 4, 100) , _transparency("transparency", "Transparency", 1.f, 0.f, 1.f) , _shader(nullptr) @@ -63,67 +102,68 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary) , _sphere(nullptr) , _sphereIsDirty(false) { - if (dictionary.hasKeyAndValue(keySize)) { - glm::vec2 size; - dictionary.getValue(keySize, size); - _size = size; - } + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableSphere" + ); - if (dictionary.hasKeyAndValue(keySegments)) { - int segments; - dictionary.getValue(keySegments, segments); - _segments = segments; - } - - if (dictionary.hasKeyAndValue(keyTexture)) { - std::string texture; - dictionary.getValue(keyTexture, texture); - _texturePath = absPath(texture); - } + _size = dictionary.value(KeySize); + _segments = static_cast(dictionary.value(KeySegments)); + _texturePath = absPath(dictionary.value(KeyTexture)); _orientation.addOption(Outside, "Outside"); _orientation.addOption(Inside, "Inside"); - _orientation.addOption(Outside | Inside, "Outside + Inside"); + _orientation.addOption(Outside | Inside, "Inside/Outside"); - if (dictionary.hasKeyAndValue(keyOrientation)) { - std::string orientation; - dictionary.getValue(keyOrientation, orientation); - if (orientation == "Outside") - _orientation = Outside; - else if (orientation == "Inside") + if (dictionary.hasKey(KeyOrientation)) { + const std::string v = dictionary.value(KeyOrientation); + if (v == "Inside") { _orientation = Inside; - else + } + else if (v == "Outside") { + _orientation = Outside; + } + else if (v == "Inside/Outside") { _orientation = Outside | Inside; + } + else { + ghoul_assert(false, "Missing 'case' label"); + } + } + else { + _orientation = Outside; } - addProperty(_orientation); + addProperty(_size); _size.onChange([this](){ _sphereIsDirty = true; }); + addProperty(_segments); _segments.onChange([this](){ _sphereIsDirty = true; }); addProperty(_transparency); - addProperty(_texturePath); - _texturePath.onChange(std::bind(&RenderableSphere::loadTexture, this)); + _texturePath.onChange([this]() {loadTexture(); }); + + + setRenderBin(Renderable::RenderBin::Transparent); } bool RenderableSphere::isReady() const { - return (_sphere != nullptr) && (_shader != nullptr) && (_texture != nullptr); + return _shader && _texture; } bool RenderableSphere::initialize() { - delete _sphere; - _sphere = new PowerScaledSphere(_size.value(), _segments); + _sphere = std::make_unique( + PowerScaledScalar::CreatePSS(_size), _segments + ); _sphere->initialize(); // pscstandard - RenderEngine& renderEngine = OsEng.renderEngine(); - _shader = renderEngine.buildRenderProgram("Sphere", + _shader = OsEng.renderEngine().buildRenderProgram("Sphere", "${MODULE_BASE}/shaders/sphere_vs.glsl", "${MODULE_BASE}/shaders/sphere_fs.glsl"); - if (!_shader) - return false; loadTexture(); @@ -131,28 +171,21 @@ bool RenderableSphere::initialize() { } bool RenderableSphere::deinitialize() { - delete _sphere; - _sphere = nullptr; - _texture = nullptr; - RenderEngine& renderEngine = OsEng.renderEngine(); if (_shader) { - renderEngine.removeRenderProgram(_shader); + OsEng.renderEngine().removeRenderProgram(_shader); _shader = nullptr; } - return true; } void RenderableSphere::render(const RenderData& data) { - glm::mat4 transform = glm::mat4(1.0); transform = glm::rotate(transform, static_cast(M_PI_2), glm::vec3(1, 0, 0)); - // Activate shader using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; _shader->activate(); @@ -171,20 +204,40 @@ void RenderableSphere::render(const RenderData& data) { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); + + bool usingFramebufferRenderer = + OsEng.renderEngine().rendererImplementation() == RenderEngine::RendererImplementation::Framebuffer; + + bool usingABufferRenderer = + OsEng.renderEngine().rendererImplementation() == RenderEngine::RendererImplementation::ABuffer; + + if (usingABufferRenderer) { + _shader->setUniform("additiveBlending", true); + } + + if (usingFramebufferRenderer) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + } _sphere->render(); + if (usingFramebufferRenderer) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + _shader->setIgnoreUniformLocationError(IgnoreError::No); _shader->deactivate(); } void RenderableSphere::update(const UpdateData&) { - if (_shader->isDirty()) + if (_shader->isDirty()) { _shader->rebuildFromFile(); + } if (_sphereIsDirty) { - delete _sphere; - _sphere = new PowerScaledSphere(_size.value(), _segments); + _sphere = std::make_unique( + PowerScaledScalar::CreatePSS(_size), _segments + ); _sphere->initialize(); _sphereIsDirty = false; } @@ -194,7 +247,10 @@ void RenderableSphere::loadTexture() { if (_texturePath.value() != "") { std::unique_ptr texture = ghoul::io::TextureReader::ref().loadTexture(_texturePath); if (texture) { - LDEBUG("Loaded texture from '" << absPath(_texturePath) << "'"); + LDEBUGC( + "RenderableSphere", + "Loaded texture from '" << absPath(_texturePath) << "'" + ); texture->uploadTexture(); // Textures of planets looks much smoother with AnisotropicMipMap rather than linear diff --git a/modules/base/rendering/renderablesphere.h b/modules/base/rendering/renderablesphere.h index e697ca7f5a..8f74d6fe96 100644 --- a/modules/base/rendering/renderablesphere.h +++ b/modules/base/rendering/renderablesphere.h @@ -26,19 +26,26 @@ #define __OPENSPACE_MODULE_BASE___RENDERABLESPHERE___H__ #include -#include #include #include #include #include -#include -#include -#include + +namespace ghoul { +namespace opengl { + class ProgramObject; + class Texture; +} +} // namespace ghoul namespace openspace { class PowerScaledSphere; +struct RenderData; +struct UpdateData; + +namespace documentation { struct Documentation; } class RenderableSphere : public Renderable { public: @@ -52,13 +59,15 @@ public: void render(const RenderData& data) override; void update(const UpdateData& data) override; + static documentation::Documentation Documentation(); + private: void loadTexture(); properties::StringProperty _texturePath; properties::OptionProperty _orientation; - properties::Vec2Property _size; + properties::FloatProperty _size; properties::IntProperty _segments; properties::FloatProperty _transparency; @@ -66,7 +75,7 @@ private: std::unique_ptr _shader; std::unique_ptr _texture; - PowerScaledSphere* _sphere; + std::unique_ptr _sphere; bool _sphereIsDirty; }; diff --git a/modules/base/rendering/renderablesphericalgrid.cpp b/modules/base/rendering/renderablesphericalgrid.cpp index 7a3ad7d2e6..f167f514aa 100644 --- a/modules/base/rendering/renderablesphericalgrid.cpp +++ b/modules/base/rendering/renderablesphericalgrid.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #define _USE_MATH_DEFINES @@ -61,7 +62,8 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio staticGrid = dictionary.getValue(KeyGridParentsRotation, _parentsRotation); } - dictionary.getValue(KeyGridSegments, _segments); + _segments = static_cast(dictionary.value(KeyGridSegments)); + //dictionary.getValue(KeyGridSegments, _segments); /*glm::vec2 radius; diff --git a/modules/base/rendering/renderablesphericalgrid.h b/modules/base/rendering/renderablesphericalgrid.h index f5290bc1d5..b4dabab32a 100644 --- a/modules/base/rendering/renderablesphericalgrid.h +++ b/modules/base/rendering/renderablesphericalgrid.h @@ -32,6 +32,7 @@ #include namespace openspace { + class RenderableSphericalGrid : public Renderable{ public: RenderableSphericalGrid(const ghoul::Dictionary& dictionary); diff --git a/modules/base/rendering/renderabletrail.cpp b/modules/base/rendering/renderabletrail.cpp index 4dd118eb1b..159dc60c61 100644 --- a/modules/base/rendering/renderabletrail.cpp +++ b/modules/base/rendering/renderabletrail.cpp @@ -29,6 +29,9 @@ #include #include #include +#include + +#include namespace { const char* KeyTranslation = "Translation"; diff --git a/modules/base/rendering/renderabletrail.h b/modules/base/rendering/renderabletrail.h index c8a73fdb10..f96f5d7bed 100644 --- a/modules/base/rendering/renderabletrail.h +++ b/modules/base/rendering/renderabletrail.h @@ -73,6 +73,8 @@ class Translation; */ class RenderableTrail : public Renderable { public: + ~RenderableTrail() = default; + bool initialize() override; bool deinitialize() override; diff --git a/modules/base/rendering/renderabletrailorbit.cpp b/modules/base/rendering/renderabletrailorbit.cpp index 2f21fd320a..47a723d301 100644 --- a/modules/base/rendering/renderabletrailorbit.cpp +++ b/modules/base/rendering/renderabletrailorbit.cpp @@ -27,6 +27,9 @@ #include #include #include +#include + +#include #include diff --git a/modules/base/rendering/renderabletrailtrajectory.cpp b/modules/base/rendering/renderabletrailtrajectory.cpp index 25f5fc686d..889bdf3a14 100644 --- a/modules/base/rendering/renderabletrailtrajectory.cpp +++ b/modules/base/rendering/renderabletrailtrajectory.cpp @@ -28,6 +28,7 @@ #include #include #include +#include // This class creates the entire trajectory at once and keeps it in memory the entire // time. This means that there is no need for updating the trail at runtime, but also that diff --git a/modules/base/rendering/renderabletrailtrajectory.h b/modules/base/rendering/renderabletrailtrajectory.h index 2e02ee6f3a..62f600d5a4 100644 --- a/modules/base/rendering/renderabletrailtrajectory.h +++ b/modules/base/rendering/renderabletrailtrajectory.h @@ -32,6 +32,8 @@ #include #include +#include + namespace openspace { namespace documentation { struct Documentation; } diff --git a/modules/base/rendering/screenspaceframebuffer.cpp b/modules/base/rendering/screenspaceframebuffer.cpp index e41c126ae8..1f4d6fe118 100644 --- a/modules/base/rendering/screenspaceframebuffer.cpp +++ b/modules/base/rendering/screenspaceframebuffer.cpp @@ -23,6 +23,8 @@ ****************************************************************************************/ #include + +#include #include #include #include @@ -34,11 +36,27 @@ namespace openspace { +documentation::Documentation ScreenSpaceFramebuffer::Documentation() { + using namespace documentation; + return { + "ScreenSpace Framebuffer", + "base_screenspace_framebuffer", + {}, + Exhaustive::Yes + }; +} + ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictionary) : ScreenSpaceRenderable(dictionary) , _size("size", "Size", glm::vec4(0), glm::vec4(0), glm::vec4(2000)) , _framebuffer(nullptr) { + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "ScreenSpaceFramebuffer" + ); + _id = id(); setName("ScreenSpaceFramebuffer" + std::to_string(_id)); diff --git a/modules/base/rendering/screenspaceframebuffer.h b/modules/base/rendering/screenspaceframebuffer.h index 33a04a3655..772e19e99b 100644 --- a/modules/base/rendering/screenspaceframebuffer.h +++ b/modules/base/rendering/screenspaceframebuffer.h @@ -34,6 +34,9 @@ #include namespace openspace { + +namespace documentation { struct Documentation; } + /** * @brief Creates a texture by rendering to a framebuffer, this is then used on a screen space plane. * @details This class lets you ass renderfunctions that should render to a framebuffer with an attached texture. @@ -54,6 +57,8 @@ public: void addRenderFunction(std::shared_ptr> renderFunction); void removeAllRenderFunctions(); + static documentation::Documentation Documentation(); + private: void createFragmentbuffer(); static int id(); diff --git a/modules/base/rendering/screenspaceimage.cpp b/modules/base/rendering/screenspaceimage.cpp index 6b2e4e44bb..7d81e60faa 100644 --- a/modules/base/rendering/screenspaceimage.cpp +++ b/modules/base/rendering/screenspaceimage.cpp @@ -24,6 +24,9 @@ #include +#include +#include + #include #include #include @@ -36,39 +39,66 @@ namespace { const char* KeyName = "Name"; const char* KeyTexturePath = "TexturePath"; const char* KeyUrl = "URL"; -} +} // namespace namespace openspace { +documentation::Documentation ScreenSpaceImage::Documentation() { + using namespace openspace::documentation; + return { + "ScreenSpace Image", + "base_screenspace_image", + { + { + KeyName, + new StringVerifier, + "Specifies the GUI name of the ScreenspaceImage", + Optional::Yes + }, + { + KeyTexturePath, + new StringVerifier, + "Specifies the image that is shown on the screenspace-aligned plane. If " + "this value is set and the URL is not, the disk image is used.", + Optional::Yes + } + } + }; +} + ScreenSpaceImage::ScreenSpaceImage(const ghoul::Dictionary& dictionary) : ScreenSpaceRenderable(dictionary) , _downloadImage(false) , _textureIsDirty(false) , _texturePath("texturePath", "Texture path", "") { - std::string name; - if (dictionary.getValue(KeyName, name)) { - setName(name); - } else { + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "ScreenSpaceImage" + ); + + if (dictionary.hasKey(KeyName)) { + setName(dictionary.value(KeyName)); + } + else { static int id = 0; setName("ScreenSpaceImage " + std::to_string(id)); ++id; } - addProperty(_texturePath); - std::string texturePath; if (dictionary.getValue(KeyTexturePath, texturePath)) { - _texturePath = texturePath; - _texturePath.onChange([this]() { _textureIsDirty = true; }); + _texturePath = dictionary.value(KeyTexturePath); } if (dictionary.getValue(KeyUrl, _url)) { _downloadImage = true; } -} -ScreenSpaceImage::~ScreenSpaceImage() {} + _texturePath.onChange([this]() { _textureIsDirty = true; }); + addProperty(_texturePath); +} bool ScreenSpaceImage::initialize() { _originalViewportSize = OsEng.windowWrapper().currentWindowResolution(); diff --git a/modules/base/rendering/screenspaceimage.h b/modules/base/rendering/screenspaceimage.h index 4788e6df72..9130627ee9 100644 --- a/modules/base/rendering/screenspaceimage.h +++ b/modules/base/rendering/screenspaceimage.h @@ -33,11 +33,12 @@ #include namespace openspace { + +namespace documentation { struct Documentation; } class ScreenSpaceImage : public ScreenSpaceRenderable { public: ScreenSpaceImage(const ghoul::Dictionary& dictionary); - ~ScreenSpaceImage(); bool initialize() override; bool deinitialize() override; @@ -45,6 +46,8 @@ public: void update() override; bool isReady() const override; + static documentation::Documentation Documentation(); + protected: void loadTexture(); void updateTexture(); diff --git a/modules/base/scale/staticscale.cpp b/modules/base/scale/staticscale.cpp index 5e53730ea8..6eb819e419 100644 --- a/modules/base/scale/staticscale.cpp +++ b/modules/base/scale/staticscale.cpp @@ -38,11 +38,13 @@ documentation::Documentation StaticScale::Documentation() { return { "Static Scaling", "base_scale_static", - {{ - KeyValue, - new DoubleVerifier, - "The scaling factor by which the scenegraph node is scaled." - }} + { + { + KeyValue, + new DoubleVerifier, + "The scaling factor by which the scenegraph node is scaled." + } + } }; } diff --git a/modules/debugging/rendering/renderabledebugplane.h b/modules/debugging/rendering/renderabledebugplane.h index b007cef5dd..6a5aaafb6d 100644 --- a/modules/debugging/rendering/renderabledebugplane.h +++ b/modules/debugging/rendering/renderabledebugplane.h @@ -28,6 +28,7 @@ #include #include +#include #include namespace ghoul { diff --git a/modules/fieldlines/rendering/renderablefieldlines.cpp b/modules/fieldlines/rendering/renderablefieldlines.cpp index 060701141a..9a61c48b46 100644 --- a/modules/fieldlines/rendering/renderablefieldlines.cpp +++ b/modules/fieldlines/rendering/renderablefieldlines.cpp @@ -28,10 +28,12 @@ #include #include #include +#include #include #include #include +#include #include diff --git a/modules/galaxy/rendering/galaxyraycaster.h b/modules/galaxy/rendering/galaxyraycaster.h index dcd34063e6..b65e08eff6 100644 --- a/modules/galaxy/rendering/galaxyraycaster.h +++ b/modules/galaxy/rendering/galaxyraycaster.h @@ -44,7 +44,7 @@ namespace ghoul { namespace openspace { -class RenderData; +struct RenderData; class RaycastData; class GalaxyRaycaster : public VolumeRaycaster { diff --git a/modules/galaxy/rendering/renderablegalaxy.cpp b/modules/galaxy/rendering/renderablegalaxy.cpp index 812dc33619..b3f8bae0df 100644 --- a/modules/galaxy/rendering/renderablegalaxy.cpp +++ b/modules/galaxy/rendering/renderablegalaxy.cpp @@ -41,6 +41,8 @@ #include #include +#include + #include diff --git a/modules/globebrowsing/chunk/chunk.cpp b/modules/globebrowsing/chunk/chunk.cpp index 5e140bfc3b..2d2adf6c4f 100644 --- a/modules/globebrowsing/chunk/chunk.cpp +++ b/modules/globebrowsing/chunk/chunk.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace openspace { diff --git a/modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.cpp b/modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.cpp index e7ce4379d7..73624a9e26 100644 --- a/modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.cpp +++ b/modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace openspace { namespace globebrowsing { diff --git a/modules/globebrowsing/chunk/chunklevelevaluator/projectedareaevaluator.cpp b/modules/globebrowsing/chunk/chunklevelevaluator/projectedareaevaluator.cpp index a92a9c62e8..31514dc6c5 100644 --- a/modules/globebrowsing/chunk/chunklevelevaluator/projectedareaevaluator.cpp +++ b/modules/globebrowsing/chunk/chunklevelevaluator/projectedareaevaluator.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace openspace { namespace globebrowsing { diff --git a/modules/globebrowsing/chunk/culling/frustumculler.cpp b/modules/globebrowsing/chunk/culling/frustumculler.cpp index 03410a4dd0..090d91ba4a 100644 --- a/modules/globebrowsing/chunk/culling/frustumculler.cpp +++ b/modules/globebrowsing/chunk/culling/frustumculler.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace openspace { namespace globebrowsing { diff --git a/modules/globebrowsing/chunk/culling/horizonculler.cpp b/modules/globebrowsing/chunk/culling/horizonculler.cpp index 5e7e09b989..c7c62a89bd 100644 --- a/modules/globebrowsing/chunk/culling/horizonculler.cpp +++ b/modules/globebrowsing/chunk/culling/horizonculler.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace openspace { namespace globebrowsing { diff --git a/modules/globebrowsing/globes/pointglobe.cpp b/modules/globebrowsing/globes/pointglobe.cpp index 7e1887a3e2..eff28b2f52 100644 --- a/modules/globebrowsing/globes/pointglobe.cpp +++ b/modules/globebrowsing/globes/pointglobe.cpp @@ -29,6 +29,9 @@ #include #include #include +#include + +#include namespace openspace { namespace globebrowsing { diff --git a/modules/globebrowsing/globes/pointglobe.h b/modules/globebrowsing/globes/pointglobe.h index b52c151821..9750444785 100644 --- a/modules/globebrowsing/globes/pointglobe.h +++ b/modules/globebrowsing/globes/pointglobe.h @@ -27,6 +27,8 @@ #include +#include + namespace ghoul { namespace opengl { class ProgramObject; } } diff --git a/modules/globebrowsing/other/distanceswitch.cpp b/modules/globebrowsing/other/distanceswitch.cpp index 18f4644643..063286ad92 100644 --- a/modules/globebrowsing/other/distanceswitch.cpp +++ b/modules/globebrowsing/other/distanceswitch.cpp @@ -24,6 +24,7 @@ #include #include +#include namespace openspace { namespace globebrowsing { diff --git a/modules/globebrowsing/rendering/chunkrenderer.cpp b/modules/globebrowsing/rendering/chunkrenderer.cpp index 60f9b8e81f..10cd20767c 100644 --- a/modules/globebrowsing/rendering/chunkrenderer.cpp +++ b/modules/globebrowsing/rendering/chunkrenderer.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace { const char* keyFrame = "Frame"; diff --git a/modules/iswa/rendering/datacygnet.cpp b/modules/iswa/rendering/datacygnet.cpp index aebb3bedd1..b706741c1b 100644 --- a/modules/iswa/rendering/datacygnet.cpp +++ b/modules/iswa/rendering/datacygnet.cpp @@ -30,6 +30,8 @@ #include #include +#include + namespace { const std::string _loggerCat = "DataCygnet"; } diff --git a/modules/iswa/rendering/dataplane.cpp b/modules/iswa/rendering/dataplane.cpp index 8df05c92a5..df06111031 100644 --- a/modules/iswa/rendering/dataplane.cpp +++ b/modules/iswa/rendering/dataplane.cpp @@ -25,6 +25,8 @@ #include #include +#include + namespace { const std::string _loggerCat = "DataPlane"; } diff --git a/modules/iswa/rendering/datasphere.cpp b/modules/iswa/rendering/datasphere.cpp index 28ec37e580..a899cf36bf 100644 --- a/modules/iswa/rendering/datasphere.cpp +++ b/modules/iswa/rendering/datasphere.cpp @@ -26,6 +26,8 @@ #include #include +#include + #ifdef WIN32 #define _USE_MATH_DEFINES #include diff --git a/modules/iswa/rendering/iswacygnet.cpp b/modules/iswa/rendering/iswacygnet.cpp index 39f595ae71..491eeda6ac 100644 --- a/modules/iswa/rendering/iswacygnet.cpp +++ b/modules/iswa/rendering/iswacygnet.cpp @@ -28,6 +28,10 @@ #include #include #include +#include +#include + +#include namespace { const std::string _loggerCat = "IswaCygnet"; diff --git a/modules/iswa/rendering/textureplane.cpp b/modules/iswa/rendering/textureplane.cpp index e6106e7e38..a8cdb47310 100644 --- a/modules/iswa/rendering/textureplane.cpp +++ b/modules/iswa/rendering/textureplane.cpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace { const std::string _loggerCat = "TexturePlane"; diff --git a/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h index 95f4ecb656..4def71f6a0 100644 --- a/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h +++ b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h @@ -49,8 +49,8 @@ namespace ghoul { namespace openspace { -class RenderData; -class RaycastData; +struct RenderData; +struct RaycastData; class KameleonVolumeRaycaster : public VolumeRaycaster { public: diff --git a/modules/multiresvolume/rendering/multiresvolumeraycaster.h b/modules/multiresvolume/rendering/multiresvolumeraycaster.h index c08a75e0c4..3c598ffd84 100644 --- a/modules/multiresvolume/rendering/multiresvolumeraycaster.h +++ b/modules/multiresvolume/rendering/multiresvolumeraycaster.h @@ -48,7 +48,7 @@ namespace ghoul { namespace openspace { -class RenderData; +struct RenderData; class RaycastData; class MultiresVolumeRaycaster : public VolumeRaycaster { diff --git a/modules/newhorizons/rendering/renderablecrawlingline.cpp b/modules/newhorizons/rendering/renderablecrawlingline.cpp index 8ff7e4c9fd..9b26b94903 100644 --- a/modules/newhorizons/rendering/renderablecrawlingline.cpp +++ b/modules/newhorizons/rendering/renderablecrawlingline.cpp @@ -24,12 +24,17 @@ #include +#include #include #include #include #include #include -#include +#include + +#include + +#include namespace { const char* KeySource = "Source"; diff --git a/modules/newhorizons/rendering/renderablecrawlingline.h b/modules/newhorizons/rendering/renderablecrawlingline.h index 1f350834e5..c31b2981c7 100644 --- a/modules/newhorizons/rendering/renderablecrawlingline.h +++ b/modules/newhorizons/rendering/renderablecrawlingline.h @@ -28,6 +28,7 @@ #include #include +#include namespace openspace { diff --git a/modules/newhorizons/rendering/renderablefov.cpp b/modules/newhorizons/rendering/renderablefov.cpp index fc264a4516..ffea6bb70f 100644 --- a/modules/newhorizons/rendering/renderablefov.cpp +++ b/modules/newhorizons/rendering/renderablefov.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include diff --git a/modules/newhorizons/rendering/renderablefov.h b/modules/newhorizons/rendering/renderablefov.h index fbcda8be87..29e8ce3cde 100644 --- a/modules/newhorizons/rendering/renderablefov.h +++ b/modules/newhorizons/rendering/renderablefov.h @@ -34,6 +34,7 @@ #include #include +#include namespace ghoul { namespace opengl { diff --git a/modules/newhorizons/rendering/renderablemodelprojection.cpp b/modules/newhorizons/rendering/renderablemodelprojection.cpp index 20900c9790..150ddafd6e 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.cpp +++ b/modules/newhorizons/rendering/renderablemodelprojection.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/modules/newhorizons/rendering/renderablemodelprojection.h b/modules/newhorizons/rendering/renderablemodelprojection.h index ac85b7df0d..4dec2aba5b 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.h +++ b/modules/newhorizons/rendering/renderablemodelprojection.h @@ -34,6 +34,8 @@ #include #include +#include + namespace ghoul { namespace opengl { class ProgramObject; diff --git a/modules/newhorizons/rendering/renderableplaneprojection.cpp b/modules/newhorizons/rendering/renderableplaneprojection.cpp index 5c9dd95685..a9a3917f3b 100644 --- a/modules/newhorizons/rendering/renderableplaneprojection.cpp +++ b/modules/newhorizons/rendering/renderableplaneprojection.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include diff --git a/modules/newhorizons/rendering/renderableplaneprojection.h b/modules/newhorizons/rendering/renderableplaneprojection.h index d1963b18e6..310833b9e8 100644 --- a/modules/newhorizons/rendering/renderableplaneprojection.h +++ b/modules/newhorizons/rendering/renderableplaneprojection.h @@ -27,6 +27,8 @@ #include +#include + #include namespace ghoul { diff --git a/modules/newhorizons/rendering/renderableshadowcylinder.h b/modules/newhorizons/rendering/renderableshadowcylinder.h index 9e214a3581..394680c48f 100644 --- a/modules/newhorizons/rendering/renderableshadowcylinder.h +++ b/modules/newhorizons/rendering/renderableshadowcylinder.h @@ -33,10 +33,10 @@ #include +#include + namespace ghoul { -namespace opengl { -class ProgramObject; -} +namespace opengl { class ProgramObject; } } namespace openspace { diff --git a/modules/newhorizons/util/projectioncomponent.cpp b/modules/newhorizons/util/projectioncomponent.cpp index 68d4fb1313..676c071a0a 100644 --- a/modules/newhorizons/util/projectioncomponent.cpp +++ b/modules/newhorizons/util/projectioncomponent.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/modules/onscreengui/src/guiorigincomponent.cpp b/modules/onscreengui/src/guiorigincomponent.cpp index 80032549bc..7c732583a8 100644 --- a/modules/onscreengui/src/guiorigincomponent.cpp +++ b/modules/onscreengui/src/guiorigincomponent.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index 0cec68472b..50dc8a5ac8 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -22,17 +22,17 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -// openspace +#include + +#include +#include #include #include -#include #include #include -// ghoul #include -// std #include #define _USE_MATH_DEFINES #include @@ -41,13 +41,12 @@ #include "SpiceZpr.h" namespace { - const std::string _loggerCat = "RenderableConstellationBounds"; + const char* KeyVertexFile = "File"; + const char* KeyConstellationFile = "ConstellationFile"; + const char* KeyReferenceFrame = "ReferenceFrame"; - const char* keyVertexFile = "File"; - const char* keyConstellationFile = "ConstellationFile"; - const char* keyReferenceFrame = "ReferenceFrame"; - const char* defaultReferenceFrame = "J2000"; + const char* DefaultReferenceFrame = "J2000"; float deg2rad(float deg) { return static_cast((deg / 360.f) * 2.f * M_PI); @@ -56,12 +55,45 @@ namespace { // 360 degrees / 24h = 15 degrees/h return deg2rad(rightAscension * 15); } -} +} // namespace namespace openspace { +documentation::Documentation RenderableConstellationBounds::Documentation() { + using namespace documentation; + return { + "RenderableConstellationBounds", + "space_renderable_constellationbounds", + { + { + KeyVertexFile, + new StringVerifier, + "Specifies the file containing the bounds information about the " + "constellation locations.", + Optional::No + }, + { + KeyConstellationFile, + new StringVerifier, + "Specifies the file that contains the mapping between constellation " + "abbreviations and full name of the constellation. If the file is " + "omitted, the abbreviations are used as the full names.", + Optional::Yes + }, + { + KeyReferenceFrame, + new StringVerifier, + "The reference frame in which the constellation points are stored in. " + "Defaults to J2000< / code>", + Optional::Yes + } + } + }; +} + + RenderableConstellationBounds::RenderableConstellationBounds( - const ghoul::Dictionary& dictionary) + const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _vertexFilename("") , _constellationFilename("") @@ -71,66 +103,64 @@ RenderableConstellationBounds::RenderableConstellationBounds( , _vao(0) , _vbo(0) { - bool success = dictionary.getValue(keyVertexFile, _vertexFilename); - if (!success) { - LERROR("RenderableConstellationBounds did not contain a key '" << - keyVertexFile << "'"); + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableConstellationBounds" + ); + + _vertexFilename = dictionary.value(KeyVertexFile); + + if (dictionary.hasKey(KeyConstellationFile)) { + _constellationFilename = dictionary.value(KeyConstellationFile); } - dictionary.getValue(keyConstellationFile, _constellationFilename); - - success = dictionary.getValue(keyReferenceFrame, _originReferenceFrame); - if (!success) { - _originReferenceFrame = defaultReferenceFrame; + if (dictionary.hasKey(KeyReferenceFrame)) { + _originReferenceFrame = dictionary.value(KeyReferenceFrame); + } + else { + _originReferenceFrame = DefaultReferenceFrame; } addProperty(_distance); addProperty(_constellationSelection); _constellationSelection.onChange( - std::bind(&RenderableConstellationBounds::selectionPropertyHasChanged, this) + [this]() { selectionPropertyHasChanged(); } ); } bool RenderableConstellationBounds::initialize() { - RenderEngine& renderEngine = OsEng.renderEngine(); - _program = renderEngine.buildRenderProgram("ConstellationBounds", + _program = OsEng.renderEngine().buildRenderProgram("ConstellationBounds", "${MODULE_SPACE}/shaders/constellationbounds_vs.glsl", "${MODULE_SPACE}/shaders/constellationbounds_fs.glsl"); - if (!_program) - return false; - bool loadSuccess = loadVertexFile(); - if (!loadSuccess) + if (!loadSuccess) { return false; + } loadSuccess = loadConstellationFile(); - if (!loadSuccess) + if (!loadSuccess) { return false; + } fillSelectionProperty(); - if (_vao == 0) { - glGenVertexArrays(1, &_vao); - LDEBUG("Generating Vertex Array id '" << _vao << "'"); - } - if (_vbo == 0) { - glGenBuffers(1, &_vbo); - LDEBUG("Generating Vertex Buffer Object id '" << _vbo << "'"); - } - + glGenVertexArrays(1, &_vao); glBindVertexArray(_vao); + + glGenBuffers(1, &_vbo); glBindBuffer(GL_ARRAY_BUFFER, _vbo); - glBufferData(GL_ARRAY_BUFFER, - _vertexValues.size() * 3 * sizeof(float), - &_vertexValues[0], - GL_STATIC_DRAW - ); + glBufferData( + GL_ARRAY_BUFFER, + _vertexValues.size() * 3 * sizeof(float), + &_vertexValues[0], + GL_STATIC_DRAW + ); GLint positionAttrib = _program->attributeLocation("in_position"); glEnableVertexAttribArray(positionAttrib); glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); return true; @@ -142,9 +172,8 @@ bool RenderableConstellationBounds::deinitialize() { glDeleteVertexArrays(1, &_vao); _vao = 0; - RenderEngine& renderEngine = OsEng.renderEngine(); if (_program) { - renderEngine.removeRenderProgram(_program); + OsEng.renderEngine().removeRenderProgram(_program); _program = nullptr; } @@ -152,7 +181,7 @@ bool RenderableConstellationBounds::deinitialize() { } bool RenderableConstellationBounds::isReady() const { - return (_vao != 0) && (_vbo != 0) && (_program != nullptr); + return (_vao != 0) && (_vbo != 0) && _program; } void RenderableConstellationBounds::render(const RenderData& data) { @@ -168,7 +197,6 @@ void RenderableConstellationBounds::render(const RenderData& data) { for (const ConstellationBound& bound : _constellationBounds) { if (bound.isEnabled) { glDrawArrays( - //GL_LINE_STRIP, GL_LINE_LOOP, static_cast(bound.startIndex), static_cast(bound.nVertices) @@ -188,46 +216,49 @@ void RenderableConstellationBounds::update(const UpdateData& data) { } bool RenderableConstellationBounds::loadVertexFile() { - if (_vertexFilename.empty()) - return false; - - std::string fileName = absPath(_vertexFilename); - std::ifstream file(fileName); - if (!file.good()) { - LERROR("Could not open file '" << fileName << "' for reading"); + if (_vertexFilename.empty()) { return false; } + std::string fileName = absPath(_vertexFilename); + std::ifstream file; + file.exceptions(std::ifstream::goodbit); + file.open(fileName); + ConstellationBound currentBound; currentBound.constellationAbbreviation = ""; std::string currentLine; int currentLineNumber = 1; - float ra; - float dec; - std::string constellationName; - double rectangularValues[3]; - // Overview of the reading algorithm: // We keep an active ConstellationBound (currentBound) and update it until we read // a new constellation name, at which point the currentBound is stored away, a new, // empty ConstellationBound is created and set at the currentBound while (file.good()) { std::getline(file, currentLine); - if (currentLine.empty()) + if (currentLine.empty()) { continue; + } // @CHECK: Is this the best way of doing this? ---abock std::stringstream s(currentLine); + float ra; s >> ra; + + float dec; s >> dec; + + std::string constellationName; s >> constellationName; if (!s.good()) { // If this evaluates to true, the stream was not completely filled, which // means that the line was incomplete, so there was an error - LERROR("Error reading file '" << fileName << "' at line #" << currentLineNumber); + LERRORC( + "RenderableConstellationBounds", + "Error reading file '" << fileName << "' at line #" << currentLineNumber + ); break; } @@ -254,6 +285,7 @@ bool RenderableConstellationBounds::loadVertexFile() { // Convert the (right ascension, declination) to rectangular coordinates) // The 1.0 is the distance of the celestial sphere, we will scale that in the // render function + double rectangularValues[3]; radrec_c(1.0, ra, dec, rectangularValues); // Add the new vertex to our list of vertices @@ -277,39 +309,43 @@ bool RenderableConstellationBounds::loadVertexFile() { } bool RenderableConstellationBounds::loadConstellationFile() { - if (_constellationFilename.empty()) + if (_constellationFilename.empty()) { return true; - - std::string fileName = absPath(_constellationFilename); - std::ifstream file(fileName); - if (!file.good()) { - LERROR("Could not open file '" << fileName << "' for reading"); - return false; } + std::ifstream file; + file.exceptions(std::ifstream::goodbit); + file.open(absPath(_constellationFilename)); + std::string line; int index = 0; while (file.good()) { - std::getline(file, line); - if (line.empty()) + std::getline(file, line); + if (line.empty()) { continue; + } std::string abbreviation; std::stringstream s(line); s >> abbreviation; - auto it = std::find_if(_constellationBounds.begin(), _constellationBounds.end(), + auto it = std::find_if( + _constellationBounds.begin(), + _constellationBounds.end(), [abbreviation](const ConstellationBound& bound) { return bound.constellationAbbreviation == abbreviation; - }); + } + ); if (it == _constellationBounds.end()) { - LERROR("Could not find constellation '" << abbreviation << "' in list"); + LERRORC( + "RenderableConstellationBounds", + "Could not find constellation '" << abbreviation << "' in list" + ); return false; } // Update the constellations full name s >> it->constellationFullName; - ++index; } @@ -329,18 +365,21 @@ void RenderableConstellationBounds::selectionPropertyHasChanged() { const std::vector& values = _constellationSelection; // If no values are selected (the default), we want to show all constellations if (values.size() == 0) { - for (ConstellationBound& b : _constellationBounds) + for (ConstellationBound& b : _constellationBounds) { b.isEnabled = true; + } } else { // In the worst case, this algorithm runs with 2 * nConstellations, which is // acceptable as the number of constellations is < 100 // First disable all constellations - for (ConstellationBound& b : _constellationBounds) + for (ConstellationBound& b : _constellationBounds) { b.isEnabled = false; + } // then re-enable the ones for which we have indices - for (int value : values) + for (int value : values) { _constellationBounds[value].isEnabled = true; + } } } diff --git a/modules/space/rendering/renderableconstellationbounds.h b/modules/space/rendering/renderableconstellationbounds.h index d000c0c3d5..406d36fd5b 100644 --- a/modules/space/rendering/renderableconstellationbounds.h +++ b/modules/space/rendering/renderableconstellationbounds.h @@ -34,6 +34,8 @@ namespace openspace { +namespace documentation { struct Documentation; } + /** * This class renders the constellation bounds as defined in * http://cdsarc.u-strasbg.fr/viz-bin/Cat?cat=VI%2F49. It contains the bounds on the @@ -42,14 +44,6 @@ namespace openspace { * The bounds are drawn as lines on a sphere with variable radius, set by the * _distance property. Currently, all constellation bounds are lines, which * leads to artifacts if the radius is very small. - * Renderable configuration attributes: - * File [string] (required): The file that contains the bounds and the - * abbreviations for the different constellations - * ConstellationFile [string]: The file that contains the mapping between - * abbreviations and full names. If the file is omitted, the abbreviations are used as the - * full names. - * ReferenceFrame [string]: The reference frame in which the points contained - * in the File are stored in. Defaults to J2000 */ class RenderableConstellationBounds : public Renderable { public: @@ -63,6 +57,8 @@ public: void render(const RenderData& data) override; void update(const UpdateData& data) override; + static documentation::Documentation Documentation(); + private: /// Stores the constellation bounds struct ConstellationBound { @@ -106,7 +102,7 @@ private: /// The list of all loaded constellation bounds std::vector _constellationBounds; - typedef std::array Vertex; + using Vertex = std::array; std::vector _vertexValues; ///< A list of all vertices of all bounds /// The radius of the celestial sphere onto which the bounds are drawn diff --git a/modules/space/rendering/renderableplanet.cpp b/modules/space/rendering/renderableplanet.cpp index 4a908b3040..86112565d8 100644 --- a/modules/space/rendering/renderableplanet.cpp +++ b/modules/space/rendering/renderableplanet.cpp @@ -22,9 +22,11 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -// open space includes #include +#include +#include + #include #include #include @@ -39,6 +41,7 @@ #include #include #include +#include #include #include @@ -48,21 +51,76 @@ namespace { + const char* KeyGeometry = "Geometry"; + const char* KeyRadius = "Radius"; + const char* KeyColorTexture = "Textures.Color"; + const char* KeyNightTexture = "Textures.Night"; + const char* KeyHeightTexture = "Textures.Height"; + const char* KeyShading = "PerformShading"; + + + static const std::string _loggerCat = "RenderablePlanet"; const char* keyFrame = "Frame"; - const char* keyGeometry = "Geometry"; - const char* keyRadius = "Radius"; - const char* keyShading = "PerformShading"; const char* keyShadowGroup = "Shadow_Group"; const char* keyShadowSource = "Source"; const char* keyShadowCaster = "Caster"; -// const char* keyPlanetRadius = "PlanetRadius"; const char* keyBody = "Body"; -} +} // namespace namespace openspace { +documentation::Documentation RenderablePlanet::Documentation() { + using namespace documentation; + return { + "RenderablePlanet", + "space_renderable_planet", + { + { + KeyGeometry, + new ReferencingVerifier("space_geometry_planet"), + "Specifies the planet geometry that is used for this RenderablePlanet.", + Optional::No + }, + { + KeyRadius, + new DoubleVerifier, + "Specifies the radius of the planet. If this value is not specified, it " + "will try to query the SPICE library for radius values.", + Optional::Yes + }, + { + KeyColorTexture, + new StringVerifier, + "Specifies the color texture that is used for this RenderablePlanet.", + Optional::Yes + }, + { + KeyHeightTexture, + new StringVerifier, + "Specifies the height texture that is used for this RenderablePlanet.", + Optional::Yes + }, + { + KeyNightTexture, + new StringVerifier, + "Specifies the texture that is used for the night side of this " + "RenderablePlanet.", + Optional::Yes + }, + { + KeyShading, + new BoolVerifier, + "Specifies whether the planet should be rendered shaded by the Sun. If " + "this value is 'false', any existing night texture will not be used. " + "This value defaults to 'true'.", + Optional::Yes + } + } + }; +} + RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _colorTexturePath("colorTexture", "Color Texture") @@ -74,118 +132,85 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary) , _heightExaggeration("heightExaggeration", "Height Exaggeration", 1.f, 0.f, 10.f) , _geometry(nullptr) , _performShading("performShading", "Perform Shading", true) - , _rotation("rotation", "Rotation", 0, 0, 360) , _alpha(1.f) , _planetRadius(0.f) , _hasNightTexture(false) , _hasHeightTexture(false) , _shadowEnabled(false) { - std::string name; - bool success = dictionary.getValue(SceneGraphNode::KeyName, name); - ghoul_assert( - success, - std::string("RenderablePlanet need the '") + SceneGraphNode::KeyName + - "' be specified" + ghoul_precondition( + dictionary.hasKeyAndValue(SceneGraphNode::KeyName), + "RenderablePlanet needs the name to be specified" ); - ghoul::Dictionary geometryDictionary; - success = dictionary.getValue(keyGeometry, geometryDictionary); + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderablePlanet" + ); + const std::string name = dictionary.value(SceneGraphNode::KeyName); - glm::dvec3 radius; - bool accutareRadius = false; - try { - SpiceManager::ref().getValue(name, "RADII", radius); - accutareRadius = true; - } catch (const SpiceManager::SpiceException& e) { - accutareRadius = false; + ghoul::Dictionary geomDict = dictionary.value(KeyGeometry); + + if (dictionary.hasKey(KeyRadius)) { + // If the user specified a radius, we want to use this + _planetRadius = dictionary.value(KeyRadius); } - - if (accutareRadius) { + else if (SpiceManager::ref().hasValue(name, "RADII") ) { + // If the user didn't specfify a radius, but Spice has a radius, we can use this + glm::dvec3 radius; + SpiceManager::ref().getValue(name, "RADII", radius); radius *= 1000.0; // Spice gives radii in KM. std::swap(radius[1], radius[2]); // z is equivalent to y in our coordinate system - geometryDictionary.setValue(keyRadius, radius); + geomDict.setValue(KeyRadius, radius); + + _planetRadius = (radius.x + radius.y + radius.z) / 3.0; + } + else { + LERRORC("RenderablePlanet", "Missing radius specification"); } - if (success) { - //geometryDictionary.setValue(SceneGraphNode::KeyName, name); - _geometry = planetgeometry::PlanetGeometry::createFromDictionary(geometryDictionary); - - float planetRadius; - if (accutareRadius) { - _planetRadius = (radius[0] + radius[1] + radius[2]) / 3.0; - } else if (geometryDictionary.getValue(keyRadius, planetRadius)) { - _planetRadius = planetRadius; - } - else { - LWARNING("No Radius value specified for " << name << " planet."); - } + _geometry = planetgeometry::PlanetGeometry::createFromDictionary(geomDict); + + if (dictionary.hasKey(KeyColorTexture)) { + _colorTexturePath = absPath(dictionary.value(KeyColorTexture)); } - //=============================================================== - //======== Reads Body and Frame Entries in mod file ============= - //=============================================================== - dictionary.getValue(keyFrame, _frame); - dictionary.getValue(keyBody, _target); - - - //============================================================ - //======== Reads the Texture Entries in mod file ============= - //============================================================ - // TODO: textures need to be replaced by a good system similar to the geometry as soon - // as the requirements are fixed (ab) - std::string texturePath = ""; - success = dictionary.getValue("Textures.Color", texturePath); - if (success) - _colorTexturePath = absPath(texturePath); - - std::string nightTexturePath = ""; - dictionary.getValue("Textures.Night", nightTexturePath); - if (nightTexturePath != ""){ + if (dictionary.hasKey(KeyNightTexture)) { _hasNightTexture = true; - _nightTexturePath = absPath(nightTexturePath); + _nightTexturePath = absPath(dictionary.value(KeyNightTexture)); } - - std::string heightMapTexturePath = ""; - dictionary.getValue("Textures.Height", heightMapTexturePath); - if (heightMapTexturePath != "") { + + if (dictionary.hasKey(KeyHeightTexture)) { _hasHeightTexture = true; - _heightMapTexturePath = absPath(heightMapTexturePath); + _heightMapTexturePath = absPath(dictionary.value(KeyHeightTexture)); + } + + if (dictionary.hasKey(KeyShading)) { + _performShading = dictionary.value(KeyShading); } addPropertySubOwner(_geometry.get()); + auto loadTextureCallback = [this]() {loadTexture(); }; addProperty(_colorTexturePath); - _colorTexturePath.onChange(std::bind(&RenderablePlanet::loadTexture, this)); + _colorTexturePath.onChange(loadTextureCallback); addProperty(_nightTexturePath); - _nightTexturePath.onChange(std::bind(&RenderablePlanet::loadTexture, this)); + _nightTexturePath.onChange(loadTextureCallback); addProperty(_heightMapTexturePath); - _heightMapTexturePath.onChange(std::bind(&RenderablePlanet::loadTexture, this)); + _heightMapTexturePath.onChange(loadTextureCallback); addProperty(_heightExaggeration); - - - //========================================================= - //======== Shading and Rotation as Properties ============= - //========================================================= - if (dictionary.hasKeyAndValue(keyShading)) { - bool shading; - dictionary.getValue(keyShading, shading); - _performShading = shading; - } - addProperty(_performShading); - // Mainly for debugging purposes @AA - addProperty(_rotation); //================================================================ //======== Reads Shadow (Eclipses) Entries in mod file =========== //================================================================ ghoul::Dictionary shadowDictionary; - success = dictionary.getValue(keyShadowGroup, shadowDictionary); + bool success = dictionary.getValue(keyShadowGroup, shadowDictionary); bool disableShadows = false; if (success) { std::vector< std::pair > sourceArray; @@ -259,9 +284,6 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary) } } -RenderablePlanet::~RenderablePlanet() { -} - bool RenderablePlanet::initialize() { RenderEngine& renderEngine = OsEng.renderEngine(); @@ -280,8 +302,6 @@ bool RenderablePlanet::initialize() { "shadowNightProgram", "${MODULE_SPACE}/shaders/shadow_nighttexture_vs.glsl", "${MODULE_SPACE}/shaders/shadow_nighttexture_fs.glsl"); - if (!_programObject) - return false; } else if (_programObject == nullptr && _shadowEnabled) { // shadow program @@ -289,8 +309,6 @@ bool RenderablePlanet::initialize() { "shadowProgram", "${MODULE_SPACE}/shaders/shadow_vs.glsl", "${MODULE_SPACE}/shaders/shadow_fs.glsl"); - if (!_programObject) - return false; } else if (_programObject == nullptr && _hasNightTexture) { // Night texture program @@ -298,8 +316,6 @@ bool RenderablePlanet::initialize() { "nightTextureProgram", "${MODULE_SPACE}/shaders/nighttexture_vs.glsl", "${MODULE_SPACE}/shaders/nighttexture_fs.glsl"); - if (!_programObject) - return false; } else if (_programObject == nullptr) { // pscstandard @@ -307,8 +323,6 @@ bool RenderablePlanet::initialize() { "pscstandard", "${MODULE_SPACE}/shaders/renderableplanet_vs.glsl", "${MODULE_SPACE}/shaders/renderableplanet_fs.glsl"); - if (!_programObject) - return false; } using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; @@ -336,7 +350,7 @@ bool RenderablePlanet::initialize() { } bool RenderablePlanet::deinitialize() { - if(_geometry) { + if (_geometry) { _geometry->deinitialize(); _geometry = nullptr; } @@ -347,9 +361,9 @@ bool RenderablePlanet::deinitialize() { _programObject = nullptr; } - _geometry = nullptr; - _texture = nullptr; - _nightTexture = nullptr; + _geometry = nullptr; + _texture = nullptr; + _nightTexture = nullptr; return true; } diff --git a/modules/space/rendering/renderableplanet.h b/modules/space/rendering/renderableplanet.h index fe9137a7e0..5162ca70ff 100644 --- a/modules/space/rendering/renderableplanet.h +++ b/modules/space/rendering/renderableplanet.h @@ -52,6 +52,8 @@ namespace planetgeometry { class PlanetGeometry; } +namespace documentation { struct Documentation; } + class RenderablePlanet : public Renderable { public: // Shadow structure @@ -69,8 +71,7 @@ public: }; public: - explicit RenderablePlanet(const ghoul::Dictionary& dictionary); - ~RenderablePlanet(); + RenderablePlanet(const ghoul::Dictionary& dictionary); bool initialize() override; bool deinitialize() override; @@ -79,6 +80,8 @@ public: void render(const RenderData& data) override; void update(const UpdateData& data) override; + static documentation::Documentation Documentation(); + protected: void loadTexture(); private: @@ -96,14 +99,11 @@ private: std::unique_ptr _geometry; properties::BoolProperty _performShading; - properties::IntProperty _rotation; float _alpha; std::vector< ShadowConf > _shadowConfArray; float _planetRadius; glm::dmat3 _stateMatrix; - std::string _frame; - std::string _target; bool _hasNightTexture; bool _hasHeightTexture; bool _shadowEnabled; diff --git a/modules/space/rendering/renderablerings.cpp b/modules/space/rendering/renderablerings.cpp index ac5d88e822..b77287111d 100644 --- a/modules/space/rendering/renderablerings.cpp +++ b/modules/space/rendering/renderablerings.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/modules/space/rendering/renderablestars.h b/modules/space/rendering/renderablestars.h index 7a8244f2cd..896b2fafc4 100644 --- a/modules/space/rendering/renderablestars.h +++ b/modules/space/rendering/renderablestars.h @@ -31,6 +31,8 @@ #include #include +#include + namespace ghoul { namespace filesystem { class File; } namespace opengl { @@ -40,7 +42,8 @@ namespace opengl { } // namespace ghoul namespace openspace { -namespace documentation { struct Documentation; } + + namespace documentation { struct Documentation; } class RenderableStars : public Renderable { public: diff --git a/modules/space/rendering/simplespheregeometry.cpp b/modules/space/rendering/simplespheregeometry.cpp index d574196014..0bc1369ba1 100644 --- a/modules/space/rendering/simplespheregeometry.cpp +++ b/modules/space/rendering/simplespheregeometry.cpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace { const std::string _loggerCat = "SimpleSphereGeometry"; diff --git a/modules/space/spacemodule.cpp b/modules/space/spacemodule.cpp index 9fe3f5c77a..00c3361e3a 100644 --- a/modules/space/spacemodule.cpp +++ b/modules/space/spacemodule.cpp @@ -82,9 +82,12 @@ void SpaceModule::internalInitialize() { std::vector SpaceModule::documentations() const { return { + RenderableConstellationBounds::Documentation(), + RenderablePlanet::Documentation(), + RenderableRings::Documentation(), + RenderableStars::Documentation(), SpiceRotation::Documentation(), SpiceTranslation::Documentation(), - RenderableRings::Documentation(), planetgeometry::PlanetGeometry::Documentation() }; } diff --git a/modules/toyvolume/rendering/toyvolumeraycaster.h b/modules/toyvolume/rendering/toyvolumeraycaster.h index 08569987bf..badfe4430a 100644 --- a/modules/toyvolume/rendering/toyvolumeraycaster.h +++ b/modules/toyvolume/rendering/toyvolumeraycaster.h @@ -41,8 +41,8 @@ namespace ghoul { namespace openspace { -class RenderData; -class RaycastData; +struct RenderData; +struct RaycastData; class ToyVolumeRaycaster : public VolumeRaycaster { public: diff --git a/openspace.cfg b/openspace.cfg index d3a103d3fd..ad2bb2000f 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -63,30 +63,13 @@ return { }, CapabilitiesVerbosity = "Full" }, - LuaDocumentation = { - Type = "html", - File = "${DOCUMENTATION}/LuaScripting.html" - }, - PropertyDocumentation = { - Type = "html", - File = "${DOCUMENTATION}/Properties.html" - }, - ScriptLog = { - Type = "text", - File = "${BASE_PATH}/ScriptLog.txt" - }, - KeyboardShortcuts = { - Type = "html", - File = "${DOCUMENTATION}/KeyboardMapping.html" - }, - Documentation = { - Type = "html", - File = "${DOCUMENTATION}/Documentation.html" - }, - FactoryDocumentation = { - Type = "html", - File = "${DOCUMENTATION}/FactoryDocumentation.html" - }, + LuaDocumentation = "${DOCUMENTATION}/LuaScripting.html", + PropertyDocumentation = "${DOCUMENTATION}/Properties.html", + ScriptLog = "${BASE_PATH}/ScriptLog.txt", + KeyboardShortcuts = "${DOCUMENTATION}/KeyboardMapping.html", + Documentation = "${DOCUMENTATION}/Documentation.html", + FactoryDocumentation = "${DOCUMENTATION}/FactoryDocumentation.html", + ShutdownCountdown = 3, -- OnScreenTextScaling = "framebuffer", -- PerSceneCache = true, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d952dde714..35f60de8ef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/documentation/core_registration.cpp ${OPENSPACE_BASE_DIR}/src/documentation/documentation.cpp ${OPENSPACE_BASE_DIR}/src/documentation/documentationengine.cpp + ${OPENSPACE_BASE_DIR}/src/documentation/documentationgenerator.cpp ${OPENSPACE_BASE_DIR}/src/documentation/verifier.cpp ${OPENSPACE_BASE_DIR}/src/engine/configurationmanager.cpp ${OPENSPACE_BASE_DIR}/src/engine/configurationmanager_doc.inl @@ -167,6 +168,7 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/documentation/core_registration.h ${OPENSPACE_BASE_DIR}/include/openspace/documentation/documentation.h ${OPENSPACE_BASE_DIR}/include/openspace/documentation/documentationengine.h + ${OPENSPACE_BASE_DIR}/include/openspace/documentation/documentationgenerator.h ${OPENSPACE_BASE_DIR}/include/openspace/documentation/verifier.h ${OPENSPACE_BASE_DIR}/include/openspace/documentation/verifier.inl ${OPENSPACE_BASE_DIR}/include/openspace/engine/configurationmanager.h diff --git a/src/documentation/documentationengine.cpp b/src/documentation/documentationengine.cpp index 2f48183dd1..92f48e26ae 100644 --- a/src/documentation/documentationengine.cpp +++ b/src/documentation/documentationengine.cpp @@ -38,13 +38,11 @@ #include namespace { - const std::string MainTemplateFilename = "${OPENSPACE_DATA}/web/documentation/main.hbs"; - const std::string DocumentationTemplateFilename = "${OPENSPACE_DATA}/web/documentation/documentation.hbs"; - const std::string HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; - const std::string JsFilename = "${OPENSPACE_DATA}/web/documentation/script.js"; - const std::string BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; - const std::string CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; -} + const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/documentation/main.hbs"; + const char* DocumentationTemplateFilename = + "${OPENSPACE_DATA}/web/documentation/documentation.hbs"; + const char* JsFilename = "${OPENSPACE_DATA}/web/documentation/script.js"; +} // namespace namespace openspace { namespace documentation { @@ -61,6 +59,19 @@ DocumentationEngine::DuplicateDocumentationException::DuplicateDocumentationExce , documentation(std::move(documentation)) {} +DocumentationEngine::DocumentationEngine() + : DocumentationGenerator( + "Documentation", + "documentation", + { + { "mainTemplate", MainTemplateFilename }, + { "documentationTemplate", DocumentationTemplateFilename } + }, + JsFilename + ) +{} + + DocumentationEngine& DocumentationEngine::ref() { if (_instance == nullptr) { _instance = new DocumentationEngine; @@ -113,7 +124,10 @@ std::string generateTextDocumentation(const Documentation& d, int& indentLevel) } else if (tv) { // We have a TableVerifier, so we need to recurse ++indentLevel; - result += generateTextDocumentation({ "", "", tv->documentations }, indentLevel); + result += generateTextDocumentation( + { "", "", tv->documentations }, + indentLevel + ); result = result.substr(0, result.size() - 2); --indentLevel; } @@ -256,124 +270,30 @@ std::string generateHtmlDocumentation(const Documentation& d) { return html.str(); } -void DocumentationEngine::writeDocumentation(const std::string& f, const std::string& t) { - if (t == "text") { - std::ofstream file; - file.exceptions(~std::ofstream::goodbit); - file.open(f); +std::string DocumentationEngine::generateJson() const { + std::stringstream json; + json << "["; - for (const Documentation& d : _documentations) { - int indent = 0; - file << documentation::generateTextDocumentation(d, indent) << "\n\n"; + for (const Documentation& d : _documentations) { + json << generateJsonDocumentation(d); + if (&d != &_documentations.back()) { + json << ", "; } } - else if (t == "html") { - std::ifstream handlebarsInput(absPath(HandlebarsFilename)); - std::ifstream jsInput(absPath(JsFilename)); - std::string jsContent; - std::back_insert_iterator jsInserter(jsContent); + json << "]"; - std::copy(std::istreambuf_iterator{handlebarsInput}, std::istreambuf_iterator(), jsInserter); - std::copy(std::istreambuf_iterator{jsInput}, std::istreambuf_iterator(), jsInserter); - - std::ifstream bootstrapInput(absPath(BootstrapFilename)); - std::ifstream cssInput(absPath(CssFilename)); - - std::string cssContent; - std::back_insert_iterator cssInserter(cssContent); - - std::copy(std::istreambuf_iterator{bootstrapInput}, std::istreambuf_iterator(), cssInserter); - std::copy(std::istreambuf_iterator{cssInput}, std::istreambuf_iterator(), cssInserter); - - std::ifstream mainTemplateInput(absPath(MainTemplateFilename)); - std::string mainTemplateContent{ std::istreambuf_iterator{mainTemplateInput}, - std::istreambuf_iterator{}}; - - std::ifstream documentationTemplateInput(absPath(DocumentationTemplateFilename)); - std::string documentationTemplateContent{ std::istreambuf_iterator{documentationTemplateInput}, - std::istreambuf_iterator{} }; - - std::ofstream file; - file.exceptions(~std::ofstream::goodbit); - file.open(f); - - std::stringstream json; - json << "["; - - for (const Documentation& d : _documentations) { - json << generateJsonDocumentation(d); - if (&d != &_documentations.back()) { - json << ", "; - } + std::string jsonString = ""; + for (const char& c : json.str()) { + if (c == '\'') { + jsonString += "\\'"; } - - json << "]"; - - std::string jsonString = ""; - for (const char& c : json.str()) { - if (c == '\'') { - jsonString += "\\'"; - } else { - jsonString += c; - } + else { + jsonString += c; } - - std::stringstream html; - html << "\n" - << "\n" - << "\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\n" - << "\t\n" - << "\t\tDocumentation\n" - << "\t\n" - << "\t\n" - << "\t\n" - << "\n"; - - file << html.str(); - -/* - Use this for generating documentation in raw html: - - html << "\n" - << "\t\n\n" - << "\t\n" - << "\t\t\n" - << "\t\t\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\t\t\n" - << "\t\t\t\n" - << "\t\t\t\n" - << "\t\t\t\n" - << "\t\t\t\n" - << "\t\t\n" - << "\t\n" - << "\t\n"; - - for (const Documentation& d : _documentations) { - html << generateHtmlDocumentation(d); - - html << "\t\n"; - } - - html << "\t\n" - << "
Documentation
Name
KeyOptionalTypeRestrictionsDocumentation

\n"; -*/ } + + return jsonString; } void DocumentationEngine::addDocumentation(Documentation doc) { diff --git a/src/documentation/documentationgenerator.cpp b/src/documentation/documentationgenerator.cpp new file mode 100644 index 0000000000..ac27f90b67 --- /dev/null +++ b/src/documentation/documentationgenerator.cpp @@ -0,0 +1,152 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include + +namespace { + const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; + const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; + const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; +} // namespace + +namespace openspace { + +DocumentationGenerator::DocumentationGenerator(std::string name, + std::string jsonName, + std::vector handlebarTemplates, + std::string javascriptFilename) + : _name(std::move(name)) + , _jsonName(std::move(jsonName)) + , _handlebarTemplates(std::move(handlebarTemplates)) + , _javascriptFile(std::move(javascriptFilename)) +{ + ghoul_precondition(!_name.empty(), "name must not be empty"); + ghoul_precondition(!_jsonName.empty(), "jsonName must not be empty"); + for (const HandlebarTemplate& t : _handlebarTemplates) { + ghoul_precondition(!t.name.empty(), "name must not be empty"); + ghoul_precondition(!t.filename.empty(), "filename must not be empty"); + } + ghoul_precondition(!_javascriptFile.empty(), "javascriptFilename must not be empty"); +} + +void DocumentationGenerator::writeDocumentation(const std::string& filename) { + std::ifstream handlebarsInput; + handlebarsInput.exceptions(~std::ofstream::goodbit); + handlebarsInput.open(absPath(HandlebarsFilename)); + const std::string handlebarsContent = std::string( + std::istreambuf_iterator(handlebarsInput), + std::istreambuf_iterator() + ); + + std::ifstream jsInput; + jsInput.exceptions(~std::ofstream::goodbit); + jsInput.open(absPath(_javascriptFile)); + const std::string jsContent = std::string( + std::istreambuf_iterator(jsInput), + std::istreambuf_iterator() + ); + + std::ifstream bootstrapInput; + bootstrapInput.exceptions(~std::ofstream::goodbit); + bootstrapInput.open(absPath(BootstrapFilename)); + const std::string bootstrapContent = std::string( + std::istreambuf_iterator(bootstrapInput), + std::istreambuf_iterator() + ); + + std::ifstream cssInput; + cssInput.exceptions(~std::ofstream::goodbit); + cssInput.open(absPath(CssFilename)); + const std::string cssContent = std::string( + std::istreambuf_iterator(cssInput), + std::istreambuf_iterator() + ); + + std::ofstream file; + file.exceptions(~std::ofstream::goodbit); + file.open(filename); + + std::string json = generateJson(); + // We probably should escape backslashes here? + + file << "" << '\n' + << "" << '\n' + << "\t" << "" << '\n'; + + for (const HandlebarTemplate& t : _handlebarTemplates) { + const char* Type = "text/x-handlebars-template"; + file << "\t\t" + << "" << '\n'; + } + + const std::string Version = + "[" + + std::to_string(OPENSPACE_VERSION_MAJOR) + "," + + std::to_string(OPENSPACE_VERSION_MINOR) + "," + + std::to_string(OPENSPACE_VERSION_PATCH) + + "]"; + + std::string generationTime; + try { + generationTime = Time::now().ISO8601(); + } + catch (...) {} + + file + << "\t" << "" << '\n' + << "\t" << "" << '\n' + << "\t\t" << "" << _name << "" << '\n' + << "\t" << "" << '\n' + << "\t" << "" << '\n' + << "\t" << "" << '\n' + << "" << '\n'; +} + +} // namespace openspace diff --git a/src/engine/configurationmanager_doc.inl b/src/engine/configurationmanager_doc.inl index a00228b045..e47a9d9c39 100644 --- a/src/engine/configurationmanager_doc.inl +++ b/src/engine/configurationmanager_doc.inl @@ -141,143 +141,49 @@ documentation::Documentation ConfigurationManager::Documentation() { }, { ConfigurationManager::KeyLuaDocumentation, - new TableVerifier({ - { - ConfigurationManager::PartType, - new StringInListVerifier( - // List from ScriptEngine::writeDocumentation - { "text", "html" } - ), - "The type of documentation that will be written." - }, - { - ConfigurationManager::PartFile, - new StringVerifier, - "The filename that will be created on startup containing the " - "documentation of available Lua functions. Any existing file " - "will be silently overwritten." - } - }), - "Descriptions of whether and where to create a documentation file that " - "describes the available Lua functions that can be executed in scene " - "files or per console.", + new StringVerifier, + "The filename that will be created on startup containing the documentation " + "of available Lua functions that can be executed in scene files or per " + "console. Any existing file will be silently overwritten.", Optional::Yes }, { ConfigurationManager::KeyPropertyDocumentation, - new TableVerifier({ - { - ConfigurationManager::PartType, - new StringInListVerifier( - // List taken from Scene::writePropertyDocumentation - { "text", "html" } - ), - "The type of property documentation file that is created." - }, - { - ConfigurationManager::PartFile, - new StringVerifier, - "The file that will be created on startup containing a list of " - "all properties in the scene. Any existing file will be silently " - "overwritten." - } - }), - "Descriptions of whether and where to create a list of all properties " - "that were created in the current scene.", + new StringVerifier, + "The file that will be created on startup containing a list of all " + "properties in the scene. Any existing file will be silently overwritten.", Optional::Yes }, { ConfigurationManager::KeyScriptLog, - new TableVerifier({ - { - ConfigurationManager::PartType, - new StringInListVerifier( - // List taken from ScriptEngine::writeLog - { "text" } - ), - "The type of logfile that will be created." - }, - { - ConfigurationManager::PartFile, - new StringVerifier, - "The file that will be created on startup containing the log of " - "all Lua scripts that are executed. Any existing file (including " - "the results from previous runs) will be silently overwritten." - } - }), - "Contains a log of all Lua scripts that were executed in the last " - "session.", + new StringVerifier, + "The file that will be created on startup containing the log of all Lua " + "scripts that are executed in the last session. Any existing file (including " + "the results from previous runs) will be silently overwritten.", Optional::Yes }, { ConfigurationManager::KeyKeyboardShortcuts, - new TableVerifier({ - { - ConfigurationManager::PartType, - new StringInListVerifier( - // List from InteractionHandler::writeKeyboardDocumentation - { "text", "html" } - ), - "The type of keyboard binding documentation that should be " - "written." - }, - { - ConfigurationManager::PartFile, - new StringVerifier, - "The file that will be created on startup containing the list of " - "all keyboard bindings with their respective Lua scripts. Any " - "previous file in this location will be silently overritten." - } - }), - "Contains the collection of all keyboard shortcuts that were collected " - "during startup. For each key, it mentions which scripts will be " - "executed in the current session.", + new StringVerifier, + "The file that will be created on startup containing the list of all " + "keyboard bindings with their respective Lua scripts. For each key, it " + "mentions which scripts will be executed in the current session.", Optional::Yes }, { ConfigurationManager::KeyDocumentation, - new TableVerifier({ - { - ConfigurationManager::PartType, - new StringInListVerifier( - // List from DocumentationEngine::writeDocumentation - { "text", "html" } - ), - "The type of documentation that should be written." - }, - { - ConfigurationManager::PartFile, - new StringVerifier, - "The file that will be created on startup containing this " - "documentation. Any previous file in this location will be silently " - "overritten." - } - }), - "This defines the location and type of this documentation file.", + new StringVerifier, + "The file that will be created on startup containing this documentation. Any " + "previous file in this location will be silently overwritten.", Optional::Yes }, { ConfigurationManager::KeyFactoryDocumentation, - new TableVerifier({ - { - ConfigurationManager::PartType, - new StringInListVerifier( - // List from FactoryManager::writeDocumentation - { "text", "html" } - ), - "The type of documentation that should be written." - }, - { - ConfigurationManager::PartFile, - new StringVerifier, - "The file that will be created on startup containing the factory " - "documentation. Any previous file in this location will be silently " - "overritten." - } - }), - "This defines the location and type of the factory documentation file, which " - "shows the different types of objects that can be created in the current " - "application configuration.", + new StringVerifier, + "The file that will be created on startup containing the factory " + "documentation which shows the different types of objects that can be " + "created in the current application configuration. Any previous file in this " + "location will be silently overritten.", Optional::Yes }, { diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 33ada3f73a..9a96c49899 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -589,43 +589,21 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) { } // Write keyboard documentation. - { - const std::string KeyboardShortcutsType = - ConfigurationManager::KeyKeyboardShortcuts + "." + - ConfigurationManager::PartType; - - const std::string KeyboardShortcutsFile = - ConfigurationManager::KeyKeyboardShortcuts + "." + - ConfigurationManager::PartFile; - - std::string type, file; - const bool hasType = configurationManager().getValue(KeyboardShortcutsType, type); - const bool hasFile = configurationManager().getValue(KeyboardShortcutsFile, file); - - if (hasType && hasFile) { - file = absPath(file); - interactionHandler().writeKeyboardDocumentation(type, file); - } + if (configurationManager().hasKey(ConfigurationManager::KeyKeyboardShortcuts)) { + interactionHandler().writeDocumentation( + absPath(configurationManager().value( + ConfigurationManager::KeyKeyboardShortcuts + )) + ); } // If a PropertyDocumentationFile was specified, generate it now. - { - const std::string KeyPropertyDocumentationType = - ConfigurationManager::KeyPropertyDocumentation + '.' + - ConfigurationManager::PartType; - - const std::string KeyPropertyDocumentationFile = - ConfigurationManager::KeyPropertyDocumentation + '.' + - ConfigurationManager::PartFile; - - std::string type, file; - const bool hasType = configurationManager().getValue(KeyPropertyDocumentationType, type); - const bool hasFile = configurationManager().getValue(KeyPropertyDocumentationFile, file); - - if (hasType && hasFile) { - file = absPath(file); - scene->writePropertyDocumentation(file, type, scenePath); - } + if (configurationManager().hasKey(ConfigurationManager::KeyPropertyDocumentation)) { + scene->writeDocumentation( + absPath(configurationManager().value( + ConfigurationManager::KeyPropertyDocumentation + )) + ); } _syncEngine->addSyncables(Time::ref().getSyncables()); @@ -646,72 +624,30 @@ void OpenSpaceEngine::deinitialize() { void OpenSpaceEngine::writeDocumentation() { // If a LuaDocumentationFile was specified, generate it now - const std::string LuaDocumentationType = - ConfigurationManager::KeyLuaDocumentation + "." + ConfigurationManager::PartType; - const std::string LuaDocumentationFile = - ConfigurationManager::KeyLuaDocumentation + "." + ConfigurationManager::PartFile; - - const bool hasLuaDocType = configurationManager().hasKey(LuaDocumentationType); - const bool hasLuaDocFile = configurationManager().hasKey(LuaDocumentationFile); - if (hasLuaDocType && hasLuaDocFile) { - std::string luaDocumentationType = configurationManager().value( - LuaDocumentationType - ); - std::string luaDocumentationFile = configurationManager().value( - LuaDocumentationFile - ); - + if (configurationManager().hasKey(ConfigurationManager::KeyLuaDocumentation)) { _scriptEngine->writeDocumentation( - absPath(luaDocumentationFile), - luaDocumentationType + absPath(configurationManager().value( + ConfigurationManager::KeyLuaDocumentation + )) ); } // If a general documentation was specified, generate it now - const std::string DocumentationType = - ConfigurationManager::KeyDocumentation + '.' + ConfigurationManager::PartType; - const std::string DocumentationFile = - ConfigurationManager::KeyDocumentation + '.' + ConfigurationManager::PartFile; - - const bool hasDocumentationType = configurationManager().hasKey(DocumentationType); - const bool hasDocumentationFile = configurationManager().hasKey(DocumentationFile); - if (hasDocumentationType && hasDocumentationFile) { - std::string documentationType = configurationManager().value( - DocumentationType - ); - std::string documentationFile = configurationManager().value( - DocumentationFile - ); - + if (configurationManager().hasKey(ConfigurationManager::KeyDocumentation)) { DocEng.writeDocumentation( - absPath(documentationFile), - documentationType + absPath(configurationManager().value( + ConfigurationManager::KeyDocumentation + )) ); } - const std::string FactoryDocumentationType = - ConfigurationManager::KeyFactoryDocumentation + '.' + - ConfigurationManager::PartType; - - const std::string FactoryDocumentationFile = - ConfigurationManager::KeyFactoryDocumentation + '.' + - ConfigurationManager::PartFile; - - bool hasFactoryDocumentationType = configurationManager().hasKey( - FactoryDocumentationType - ); - bool hasFactoryDocumentationFile = configurationManager().hasKey( - FactoryDocumentationFile - ); - if (hasFactoryDocumentationType && hasFactoryDocumentationFile) { - std::string type = configurationManager().value( - FactoryDocumentationType + // If a factory documentation was specified, generate it now + if (configurationManager().hasKey(ConfigurationManager::KeyFactoryDocumentation)) { + FactoryManager::ref().writeDocumentation( + absPath(configurationManager().value( + ConfigurationManager::KeyFactoryDocumentation + )) ); - std::string file = configurationManager().value( - FactoryDocumentationFile - ); - - FactoryManager::ref().writeDocumentation(absPath(file), type); } } diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 81d3a029a9..82d8311d1a 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -59,10 +59,7 @@ namespace { const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/keybindings/main.hbs"; const char* KeybindingTemplateFilename = "${OPENSPACE_DATA}/web/keybindings/keybinding.hbs"; - const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; const char* JsFilename = "${OPENSPACE_DATA}/web/keybindings/script.js"; - const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; - const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; } // namespace #include "interactionhandler_lua.inl" @@ -73,6 +70,15 @@ namespace interaction { // InteractionHandler InteractionHandler::InteractionHandler() : properties::PropertyOwner("Interaction") + , DocumentationGenerator( + "Documentation", + "keybindings", + { + { "keybindingTemplate", KeybindingTemplateFilename }, + { "mainTemplate", MainTemplateFilename } + }, + JsFilename + ) , _origin("origin", "Origin", "") , _rotationalFriction("rotationalFriction", "Rotational Friction", true) , _horizontalFriction("horizontalFriction", "Horizontal Friction", true) @@ -433,133 +439,36 @@ void InteractionHandler::bindKey(Key key, KeyModifier modifier, } -void InteractionHandler::writeKeyboardDocumentation(const std::string& type, - const std::string& file) -{ - if (type == "text") { - std::ofstream f; - f.exceptions(~std::ofstream::goodbit); - f.open(absPath(file)); - - for (const auto& p : _keyLua) { - std::string remoteScriptingInfo; - bool remoteScripting = p.second.synchronization; - - if (!remoteScripting) { - remoteScriptingInfo = " (LOCAL)"; - } - f << std::to_string(p.first) << ": " - << p.second.command << remoteScriptingInfo << '\n' - << p.second.documentation << '\n'; +std::string InteractionHandler::generateJson() const { + std::stringstream json; + json << "["; + bool first = true; + for (const auto& p : _keyLua) { + if (!first) { + json << ","; + } + first = false; + json << "{"; + json << "\"key\": \"" << std::to_string(p.first) << "\","; + json << "\"script\": \"" << p.second.command << "\","; + json << "\"remoteScripting\": " << (p.second.synchronization ? "true," : "false,"); + json << "\"documentation\": \"" << p.second.documentation << "\""; + json << "}"; + } + json << "]"; + + std::string jsonString = ""; + for (const char& c : json.str()) { + if (c == '\'') { + jsonString += "\\'"; + } else { + jsonString += c; } } - else if (type == "html") { - std::ofstream f; - f.exceptions(~std::ofstream::goodbit); - f.open(absPath(file)); - std::ifstream handlebarsInput(absPath(HandlebarsFilename)); - std::ifstream jsInput(absPath(JsFilename)); - - std::string jsContent; - std::back_insert_iterator jsInserter(jsContent); - - std::copy(std::istreambuf_iterator{handlebarsInput}, std::istreambuf_iterator(), jsInserter); - std::copy(std::istreambuf_iterator{jsInput}, std::istreambuf_iterator(), jsInserter); - - std::ifstream bootstrapInput(absPath(BootstrapFilename)); - std::ifstream cssInput(absPath(CssFilename)); - - std::string cssContent; - std::back_insert_iterator cssInserter(cssContent); - - std::copy(std::istreambuf_iterator{bootstrapInput}, std::istreambuf_iterator(), cssInserter); - std::copy(std::istreambuf_iterator{cssInput}, std::istreambuf_iterator(), cssInserter); - - std::ifstream mainTemplateInput(absPath(MainTemplateFilename)); - std::string mainTemplateContent{ std::istreambuf_iterator{mainTemplateInput}, - std::istreambuf_iterator{} }; - - std::ifstream keybindingTemplateInput(absPath(KeybindingTemplateFilename)); - std::string keybindingTemplateContent{ std::istreambuf_iterator{keybindingTemplateInput}, - std::istreambuf_iterator{} }; - - std::stringstream json; - json << "["; - bool first = true; - for (const auto& p : _keyLua) { - if (!first) { - json << ","; - } - first = false; - json << "{"; - json << "\"key\": \"" << std::to_string(p.first) << "\","; - json << "\"script\": \"" << p.second.command << "\","; - json << "\"remoteScripting\": " << (p.second.synchronization ? "true," : "false,"); - json << "\"documentation\": \"" << p.second.documentation << "\""; - json << "}"; - } - json << "]"; - - std::string jsonString = ""; - for (const char& c : json.str()) { - if (c == '\'') { - jsonString += "\\'"; - } else { - jsonString += c; - } - } - - std::string generationTime; - try { - generationTime = Time::now().ISO8601(); - } - catch (...) {} - - std::stringstream html; - html << "\n" - << "\n" - << "\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\n" - << "\t\n" - << "\t\tDocumentation\n" - << "\t\n" - << "\t\n" - << "\t\n" - << "\n"; - - f << html.str(); - - - /* - for (const auto& p : _keyLua) { - html << "\t\t\n" - << "\t\t\t" << std::to_string(p.first) << "\n" - << "\t\t\t" << p.second.first << "\n" - << "\t\t\t" << (p.second.second ? "Yes" : "No") << "\n" - << "\t\t\n"; - }*/ - } - else { - throw ghoul::RuntimeError( - "Unsupported keyboard documentation type '" + type + "'", - "InteractionHandler" - ); - } + return jsonString; } + scripting::LuaLibrary InteractionHandler::luaLibrary() { return{ diff --git a/src/interaction/interactionmode.cpp b/src/interaction/interactionmode.cpp index c8f2c333f2..42992093a1 100644 --- a/src/interaction/interactionmode.cpp +++ b/src/interaction/interactionmode.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/src/mission/mission.cpp b/src/mission/mission.cpp index a73edd6397..107d486aae 100644 --- a/src/mission/mission.cpp +++ b/src/mission/mission.cpp @@ -137,19 +137,19 @@ MissionPhase::MissionPhase(const ghoul::Dictionary& dict) { } } -const std::string & MissionPhase::name() const { +std::string MissionPhase::name() const { return _name; } -const TimeRange & MissionPhase::timeRange() const { +TimeRange MissionPhase::timeRange() const { return _timeRange; } -const std::string & MissionPhase::description() const { +std::string MissionPhase::description() const { return _description; } -const std::vector& MissionPhase::phases() const { +std::vector MissionPhase::phases() const { return _subphases; } @@ -163,6 +163,8 @@ MissionPhase::Trace MissionPhase::phaseTrace(double time, int maxDepth) const { } void MissionPhase::phaseTrace(double time, Trace& trace, int maxDepth) const { + ghoul_assert(maxDepth >= 0, "maxDepth must not be negative"); + if (maxDepth == 0) { return; } @@ -180,7 +182,7 @@ void MissionPhase::phaseTrace(double time, Trace& trace, int maxDepth) const { } } -Mission missionFromFile(std::string filename) { +Mission missionFromFile(const std::string& filename) { ghoul_assert(!filename.empty(), "filename must not be empty"); ghoul_assert(!FileSys.containsToken(filename), "filename must not contain tokens"); ghoul_assert(FileSys.fileExists(filename), "filename must exist"); diff --git a/src/performance/performancemanager.cpp b/src/performance/performancemanager.cpp index 57bc4de704..5945eb1148 100644 --- a/src/performance/performancemanager.cpp +++ b/src/performance/performancemanager.cpp @@ -31,6 +31,9 @@ #include #include +#include +#include + namespace { const std::string _loggerCat = "PerformanceManager"; diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 745e974a81..e5b7584dac 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -27,6 +27,7 @@ #ifdef OPENSPACE_MODULE_NEWHORIZONS_ENABLED #include #endif +#include #include #include @@ -39,11 +40,16 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include +#include #include #include @@ -91,1211 +97,1226 @@ namespace { namespace openspace { - RenderEngine::RenderEngine() - : properties::PropertyOwner("RenderEngine") - , _camera(nullptr) - , _scene(nullptr) - , _raycasterManager(nullptr) - , _deferredcasterManager(nullptr) - , _performanceMeasurements("performanceMeasurements", "Performance Measurements") - , _performanceManager(nullptr) - , _renderer(nullptr) - , _rendererImplementation(RendererImplementation::Invalid) - , _log(nullptr) - , _frametimeType( - "frametimeType", - "Type of the frametime display", - properties::OptionProperty::DisplayType::Dropdown - ) - , _showInfo("showInfo", "Show Render Information", true) - , _showLog("showLog", "Show the OnScreen log", true) - , _takeScreenshot("takeScreenshot", "Take Screenshot") - , _shouldTakeScreenshot(false) - , _applyWarping("applyWarpingScreenshot", "Apply Warping to Screenshots", false) - , _showFrameNumber("showFrameNumber", "Show Frame Number", false) - , _disableMasterRendering("disableMasterRendering", "Disable Master Rendering", false) - , _disableSceneOnMaster("disableSceneOnMaster", "Disable Scene on Master", false) - , _globalBlackOutFactor(1.f) - , _fadeDuration(2.f) - , _currentFadeTime(0.f) - , _fadeDirection(0) - , _nAaSamples("nAaSamples", "Number of Antialiasing samples", 8, 1, 16) - , _frameNumber(0) - { - _performanceMeasurements.onChange([this]() { - if (_performanceMeasurements) { - if (!_performanceManager) { - _performanceManager = std::make_unique(); - } - } - else { - _performanceManager = nullptr; +RenderEngine::RenderEngine() + : properties::PropertyOwner("RenderEngine") + , _camera(nullptr) + , _scene(nullptr) + , _raycasterManager(nullptr) + , _deferredcasterManager(nullptr) + , _performanceMeasurements("performanceMeasurements", "Performance Measurements") + , _performanceManager(nullptr) + , _renderer(nullptr) + , _rendererImplementation(RendererImplementation::Invalid) + , _log(nullptr) + , _frametimeType( + "frametimeType", + "Type of the frametime display", + properties::OptionProperty::DisplayType::Dropdown + ) + , _showDate("showDate", "Show Date Information", true) + , _showInfo("showInfo", "Show Render Information", true) + , _showLog("showLog", "Show the OnScreen log", true) + , _takeScreenshot("takeScreenshot", "Take Screenshot") + , _shouldTakeScreenshot(false) + , _applyWarping("applyWarpingScreenshot", "Apply Warping to Screenshots", false) + , _showFrameNumber("showFrameNumber", "Show Frame Number", false) + , _disableMasterRendering("disableMasterRendering", "Disable Master Rendering", false) + , _disableSceneTranslationOnMaster( + "disableSceneTranslationOnMaster", + "Disable Scene Translation on Master", + false + ) + , _globalBlackOutFactor(1.f) + , _fadeDuration(2.f) + , _currentFadeTime(0.f) + , _fadeDirection(0) + , _nAaSamples("nAaSamples", "Number of Antialiasing samples", 8, 1, 16) + , _frameNumber(0) +{ + _performanceMeasurements.onChange([this]() { + if (_performanceMeasurements) { + if (!_performanceManager) { + _performanceManager = std::make_unique(); } + } + }); + addProperty(_performanceMeasurements); - }); - addProperty(_performanceMeasurements); + _frametimeType.addOption( + static_cast(FrametimeType::DtTimeAvg), + "Average Deltatime" + ); + _frametimeType.addOption( + static_cast(FrametimeType::FPS), + "Frames per second" + ); + _frametimeType.addOption( + static_cast(FrametimeType::FPSAvg), + "Average frames per second" + ); + addProperty(_frametimeType); + + addProperty(_showDate); + addProperty(_showInfo); + addProperty(_showLog); + + _nAaSamples.onChange([this](){ + if (_renderer) { + _renderer->setNAaSamples(_nAaSamples); + } + }); + addProperty(_nAaSamples); + addProperty(_applyWarping); + + _takeScreenshot.onChange([this](){ + _shouldTakeScreenshot = true; + }); + addProperty(_takeScreenshot); + + addProperty(_showFrameNumber); + + addProperty(_disableSceneTranslationOnMaster); + addProperty(_disableMasterRendering); +} - _frametimeType.addOption( - static_cast(FrametimeType::DtTimeAvg), - "Average Deltatime" - ); - _frametimeType.addOption( - static_cast(FrametimeType::FPS), - "Frames per second" - ); - _frametimeType.addOption( - static_cast(FrametimeType::FPSAvg), - "Average frames per second" - ); - addProperty(_frametimeType); +/** + * Destructor + */ +RenderEngine::~RenderEngine() {} - addProperty(_showInfo); - addProperty(_showLog); +void RenderEngine::setRendererFromString(const std::string& renderingMethod) { + _rendererImplementation = rendererFromString(renderingMethod); - _nAaSamples.onChange([this]() { - if (_renderer) { - _renderer->setNAaSamples(_nAaSamples); - } - }); - addProperty(_nAaSamples); - addProperty(_applyWarping); - - _takeScreenshot.onChange([this]() { - _shouldTakeScreenshot = true; - }); - addProperty(_takeScreenshot); - - addProperty(_showFrameNumber); - - addProperty(_disableMasterRendering); - addProperty(_disableSceneOnMaster); + std::unique_ptr newRenderer = nullptr; + switch (_rendererImplementation) { + case RendererImplementation::Framebuffer: + newRenderer = std::make_unique(); + break; + case RendererImplementation::ABuffer: + newRenderer = std::make_unique(); + break; + case RendererImplementation::Invalid: + LFATAL("Rendering method '" << renderingMethod << "' not among the available " + << "rendering methods"); } - void RenderEngine::setRendererFromString(const std::string& renderingMethod) { - _rendererImplementation = rendererFromString(renderingMethod); + setRenderer(std::move(newRenderer)); +} - std::unique_ptr newRenderer = nullptr; - switch (_rendererImplementation) { - case RendererImplementation::Framebuffer: - newRenderer = std::make_unique(); - break; - case RendererImplementation::ABuffer: - newRenderer = std::make_unique(); - break; - case RendererImplementation::Invalid: - LFATAL("Rendering method '" << renderingMethod << "' not among the available " - << "rendering methods"); +void RenderEngine::initialize() { + _frameNumber = 0; + std::string renderingMethod = DefaultRenderingMethod; + + // If the user specified a rendering method that he would like to use, use that + auto& confManager = OsEng.configurationManager(); + if (confManager.hasKeyAndValue(KeyRenderingMethod)) { + renderingMethod = confManager.value(KeyRenderingMethod); + } + else { + using Version = ghoul::systemcapabilities::Version; + + // The default rendering method has a requirement of OpenGL 4.3, so if we are + // below that, we will fall back to frame buffer operation + if (OpenGLCap.openGLVersion() < Version{ 4,3,0 }) { + LINFO("Falling back to framebuffer implementation due to OpenGL limitations"); + renderingMethod = "Framebuffer"; } - - setRenderer(std::move(newRenderer)); } - void RenderEngine::initialize() { - _frameNumber = 0; - std::string renderingMethod = DefaultRenderingMethod; + if (confManager.hasKey(ConfigurationManager::KeyDisableMasterRendering)) { + _disableMasterRendering = confManager.value( + ConfigurationManager::KeyDisableMasterRendering + ); + } - // If the user specified a rendering method that he would like to use, use that - auto& confManager = OsEng.configurationManager(); - if (confManager.hasKeyAndValue(KeyRenderingMethod)) { - renderingMethod = confManager.value(KeyRenderingMethod); - } - else { - using Version = ghoul::systemcapabilities::Version; + if (confManager.hasKey(ConfigurationManager::KeyDisableSceneOnMaster)) { + _disableSceneTranslationOnMaster = confManager.value( + ConfigurationManager::KeyDisableSceneOnMaster + ); + } - // The default rendering method has a requirement of OpenGL 4.3, so if we are - // below that, we will fall back to frame buffer operation - if (OpenGLCap.openGLVersion() < Version{ 4,3,0 }) { - LINFO("Falling back to framebuffer implementation due to OpenGL limitations"); - renderingMethod = "Framebuffer"; - } - } + _raycasterManager = std::make_unique(); + _deferredcasterManager = std::make_unique(); + _nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples(); - if (confManager.hasKey(ConfigurationManager::KeyDisableMasterRendering)) { - _disableMasterRendering = confManager.value( - ConfigurationManager::KeyDisableMasterRendering - ); - } - - if (confManager.hasKey(ConfigurationManager::KeyDisableSceneOnMaster)) { - _disableSceneOnMaster = confManager.value( - ConfigurationManager::KeyDisableSceneOnMaster - ); - } - - _raycasterManager = std::make_unique(); - _deferredcasterManager = std::make_unique(); - _nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples(); - - LINFO("Seting renderer from string: " << renderingMethod); - setRendererFromString(renderingMethod); + LINFO("Seting renderer from string: " << renderingMethod); + setRendererFromString(renderingMethod); #ifdef GHOUL_USE_DEVIL - ghoul::io::TextureReader::ref().addReader(std::make_shared()); + ghoul::io::TextureReader::ref().addReader( + std::make_shared() + ); #endif // GHOUL_USE_DEVIL #ifdef GHOUL_USE_FREEIMAGE - ghoul::io::TextureReader::ref().addReader(std::make_shared()); + ghoul::io::TextureReader::ref().addReader( + std::make_shared() + ); #endif // GHOUL_USE_FREEIMAGE #ifdef GHOUL_USE_SOIL - ghoul::io::TextureReader::ref().addReader(std::make_shared()); - ghoul::io::TextureWriter::ref().addWriter(std::make_shared()); + ghoul::io::TextureReader::ref().addReader( + std::make_shared() + ); + ghoul::io::TextureWriter::ref().addWriter( + std::make_shared() + ); #endif // GHOUL_USE_SOIL - ghoul::io::TextureReader::ref().addReader(std::make_shared()); + ghoul::io::TextureReader::ref().addReader( + std::make_shared() + ); - MissionManager::initialize(); + MissionManager::initialize(); +} + +void RenderEngine::initializeGL() { + // TODO: Fix the power scaled coordinates in such a way that these + // values can be set to more realistic values + + // set the close clip plane and the far clip plane to extreme values while in + // development + OsEng.windowWrapper().setNearFarClippingPlane(0.001f, 1000.f); + + try { + const float fontSizeBig = 50.f; + _fontBig = OsEng.fontManager().font(KeyFontMono, fontSizeBig); + const float fontSizeTime = 15.f; + _fontDate = OsEng.fontManager().font(KeyFontMono, fontSizeTime); + const float fontSizeMono = 10.f; + _fontInfo = OsEng.fontManager().font(KeyFontMono, fontSizeMono); + const float fontSizeLight = 8.f; + _fontLog = OsEng.fontManager().font(KeyFontLight, fontSizeLight); + } catch (const ghoul::fontrendering::Font::FreeTypeException& e) { + LERROR(e.what()); + throw; } - void RenderEngine::initializeGL() { - // TODO: Fix the power scaled coordinates in such a way that these - // values can be set to more realistic values + LINFO("Initializing Log"); + std::unique_ptr log = std::make_unique(ScreenLogTimeToLive); + _log = log.get(); + ghoul::logging::LogManager::ref().addLog(std::move(log)); - // set the close clip plane and the far clip plane to extreme values while in - // development - OsEng.windowWrapper().setNearFarClippingPlane(0.001f, 1000.f); + LINFO("Finished initializing GL"); +} + +void RenderEngine::deinitialize() { + for (std::shared_ptr ssr : _screenSpaceRenderables) { + ssr->deinitialize(); + } + MissionManager::deinitialize(); +} + +void RenderEngine::updateScene() { + _scene->update({ + { glm::dvec3(0), glm::dmat3(1), 1.0 }, + Time::ref().j2000Seconds(), + Time::ref().deltaTime(), + Time::ref().paused(), + Time::ref().timeJumped(), + _performanceManager != nullptr + }); + + LTRACE("RenderEngine::updateSceneGraph(end)"); +} + +void RenderEngine::updateShaderPrograms() { + for (ghoul::opengl::ProgramObject* program : _programs) { try { - const float fontSizeBig = 50.f; - _fontBig = OsEng.fontManager().font(KeyFontMono, fontSizeBig); - const float fontSizeTime = 15.f; - _fontDate = OsEng.fontManager().font(KeyFontMono, fontSizeTime); - const float fontSizeMono = 10.f; - _fontInfo = OsEng.fontManager().font(KeyFontMono, fontSizeMono); - const float fontSizeLight = 8.f; - _fontLog = OsEng.fontManager().font(KeyFontLight, fontSizeLight); - } - catch (const ghoul::fontrendering::Font::FreeTypeException& e) { - LERROR(e.what()); - throw; - } - - LINFO("Initializing Log"); - std::unique_ptr log = std::make_unique(ScreenLogTimeToLive); - _log = log.get(); - ghoul::logging::LogManager::ref().addLog(std::move(log)); - - LINFO("Finished initializing GL"); - } - - void RenderEngine::deinitialize() { - for (auto screenspacerenderable : _screenSpaceRenderables) { - screenspacerenderable->deinitialize(); - } - - MissionManager::deinitialize(); - } - - void RenderEngine::updateScene() { - _scene->update({ - { glm::dvec3(0), glm::dmat3(1), 1.0 }, - Time::ref().j2000Seconds(), - Time::ref().deltaTime(), - Time::ref().paused(), - Time::ref().timeJumped(), - _performanceManager != nullptr - }); - - LTRACE("RenderEngine::updateSceneGraph(end)"); - } - - void RenderEngine::updateShaderPrograms() { - for (ghoul::opengl::ProgramObject* program : _programs) { - try { - if (program->isDirty()) { - program->rebuildFromFile(); - } - } - catch (const ghoul::opengl::ShaderObject::ShaderCompileError& e) { - LERRORC(e.component, e.what()); + if (program->isDirty()) { + program->rebuildFromFile(); } } - } - - void RenderEngine::updateRenderer() { - bool windowResized = OsEng.windowWrapper().windowHasResized(); - - if (windowResized) { - _renderer->setResolution(renderingResolution()); - - ghoul::fontrendering::FontRenderer::defaultRenderer().setFramebufferSize( - fontResolution() - ); - } - - _renderer->update(); - } - - void RenderEngine::updateScreenSpaceRenderables() { - for (auto& screenspacerenderable : _screenSpaceRenderables) { - screenspacerenderable->update(); + catch (const ghoul::opengl::ShaderObject::ShaderCompileError& e) { + LERRORC(e.component, e.what()); } } +} - glm::ivec2 RenderEngine::renderingResolution() const { - if (OsEng.windowWrapper().isRegularRendering()) { - return OsEng.windowWrapper().currentWindowResolution(); - } - else { - return OsEng.windowWrapper().currentDrawBufferResolution(); - } - } +void RenderEngine::updateRenderer() { + bool windowResized = OsEng.windowWrapper().windowHasResized(); - glm::ivec2 RenderEngine::fontResolution() const { - std::string value; - bool hasValue = OsEng.configurationManager().getValue( - ConfigurationManager::KeyOnScreenTextScaling, - value + if (windowResized) { + _renderer->setResolution(renderingResolution()); + + ghoul::fontrendering::FontRenderer::defaultRenderer().setFramebufferSize( + fontResolution() ); - if (hasValue && value == "framebuffer") { - return OsEng.windowWrapper().currentWindowResolution(); - } - else { - // The default is to use the window size - return OsEng.windowWrapper().currentWindowSize(); - } } + _renderer->update(); +} - void RenderEngine::updateFade() { - // Temporary fade funtionality - const float fadedIn = 1.0; - const float fadedOut = 0.0; - // Don't restart the fade if you've already done it in that direction - const bool isFadedIn = (_fadeDirection > 0 && _globalBlackOutFactor == fadedIn); - const bool isFadedOut = (_fadeDirection < 0 && _globalBlackOutFactor == fadedOut); - if (isFadedIn || isFadedOut) { +void RenderEngine::updateScreenSpaceRenderables() { + for (std::shared_ptr& ssr : _screenSpaceRenderables) { + ssr->update(); + } +} + +glm::ivec2 RenderEngine::renderingResolution() const { + if (OsEng.windowWrapper().isRegularRendering()) { + return OsEng.windowWrapper().currentWindowResolution(); + } + else { + return OsEng.windowWrapper().currentDrawBufferResolution(); + } +} + +glm::ivec2 RenderEngine::fontResolution() const { + std::string value; + bool hasValue = OsEng.configurationManager().getValue( + ConfigurationManager::KeyOnScreenTextScaling, + value + ); + if (hasValue && value == "framebuffer") { + return OsEng.windowWrapper().currentWindowResolution(); + } + else { + // The default is to use the window size + return OsEng.windowWrapper().currentWindowSize(); + } +} + +void RenderEngine::updateFade() { + // Temporary fade funtionality + const float fadedIn = 1.0; + const float fadedOut = 0.0; + // Don't restart the fade if you've already done it in that direction + const bool isFadedIn = (_fadeDirection > 0 && _globalBlackOutFactor == fadedIn); + const bool isFadedOut = (_fadeDirection < 0 && _globalBlackOutFactor == fadedOut); + if (isFadedIn || isFadedOut) { + _fadeDirection = 0; + } + + if (_fadeDirection != 0) { + if (_currentFadeTime > _fadeDuration) { + _globalBlackOutFactor = _fadeDirection > 0 ? fadedIn : fadedOut; _fadeDirection = 0; } - - if (_fadeDirection != 0) { - if (_currentFadeTime > _fadeDuration) { - _globalBlackOutFactor = _fadeDirection > 0 ? fadedIn : fadedOut; - _fadeDirection = 0; - } - else { - if (_fadeDirection < 0) { - _globalBlackOutFactor = glm::smoothstep( - 1.f, - 0.f, - _currentFadeTime / _fadeDuration - ); - } - else { - _globalBlackOutFactor = glm::smoothstep( - 0.f, - 1.f, - _currentFadeTime / _fadeDuration - ); - } - _currentFadeTime += static_cast( - OsEng.windowWrapper().averageDeltaTime() - ); - } - } - } - - - - void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix, - const glm::mat4& projectionMatrix) - { - LTRACE("RenderEngine::render(begin)"); - WindowWrapper& wrapper = OsEng.windowWrapper(); - - if (_disableSceneOnMaster && wrapper.isMaster()) { - _camera->sgctInternal.setViewMatrix(viewMatrix); - } else { - _camera->sgctInternal.setViewMatrix(viewMatrix * sceneMatrix); - } - _camera->sgctInternal.setProjectionMatrix(projectionMatrix); - - - if (!(wrapper.isMaster() && _disableMasterRendering) && !wrapper.isGuiWindow()) { - _renderer->render(_globalBlackOutFactor, _performanceManager != nullptr); - } - - // Print some useful information on the master viewport - if (wrapper.isMaster() && wrapper.isSimpleRendering()) { - renderInformation(); - } - - glm::vec2 penPosition = glm::vec2( - OsEng.windowWrapper().viewportPixelCoordinates().y / 2 - 50, - OsEng.windowWrapper().viewportPixelCoordinates().w / 3 - ); - - if (_showFrameNumber) { - RenderFontCr(*_fontBig, penPosition, "%i", _frameNumber); - } - - _frameNumber++; - - for (auto& screenSpaceRenderable : _screenSpaceRenderables) { - if (screenSpaceRenderable->isEnabled() && screenSpaceRenderable->isReady()) { - screenSpaceRenderable->render(); - } - } - LTRACE("RenderEngine::render(end)"); - } - - void RenderEngine::renderShutdownInformation(float timer, float fullTime) { - timer = timer < 0.f ? 0.f : timer; - - auto size = ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( - *_fontDate, - "Shutdown in: %.2fs/%.2fs", - timer, - fullTime - ); - - glm::vec2 penPosition = glm::vec2( - OsEng.windowWrapper().viewportPixelCoordinates().y - size.boundingBox.x, - OsEng.windowWrapper().viewportPixelCoordinates().w - size.boundingBox.y - ); - penPosition.y -= _fontDate->height(); - - RenderFontCr( - *_fontDate, - penPosition, - "Shutdown in: %.2fs/%.2fs", - timer, - fullTime - ); - } - - void RenderEngine::postDraw() { - if (Time::ref().timeJumped()) { - Time::ref().setTimeJumped(false); - } - - if (_shouldTakeScreenshot) { - OsEng.windowWrapper().takeScreenshot(_applyWarping); - _shouldTakeScreenshot = false; - } - - if (_performanceManager) { - _performanceManager->storeScenePerformanceMeasurements( - scene()->allSceneGraphNodes() - ); - } - } - - Scene* RenderEngine::scene() { - return _scene; - } - - RaycasterManager& RenderEngine::raycasterManager() { - return *_raycasterManager; - } - - DeferredcasterManager& RenderEngine::deferredcasterManager() { - return *_deferredcasterManager; - } - - void RenderEngine::setScene(Scene* scene) { - _scene = scene; - if (_renderer) { - _renderer->setScene(scene); - } - } - - void RenderEngine::setCamera(Camera* camera) { - _camera = camera; - if (_renderer) { - _renderer->setCamera(camera); - } - } - - Camera* RenderEngine::camera() const { - return _camera; - } - - Renderer* RenderEngine::renderer() const { - return _renderer.get(); - } - - RenderEngine::RendererImplementation RenderEngine::rendererImplementation() const { - return _rendererImplementation; - } - - float RenderEngine::globalBlackOutFactor() { - return _globalBlackOutFactor; - } - - void RenderEngine::setGlobalBlackOutFactor(float opacity) { - _globalBlackOutFactor = opacity; - } - - void RenderEngine::startFading(int direction, float fadeDuration) { - _fadeDirection = direction; - _fadeDuration = fadeDuration; - _currentFadeTime = 0.f; - } - - /** - * Build a program object for rendering with the used renderer - */ - std::unique_ptr RenderEngine::buildRenderProgram( - std::string name, std::string vsPath, - std::string fsPath, const ghoul::Dictionary& data) - { - - ghoul::Dictionary dict = data; - - // set path to the current renderer's main fragment shader - dict.setValue("rendererData", _rendererData); - // parameterize the main fragment shader program with specific contents. - // fsPath should point to a shader file defining a Fragment getFragment() function - // instead of a void main() setting glFragColor, glFragDepth, etc. - dict.setValue("fragmentPath", fsPath); - - using namespace ghoul::opengl; - std::unique_ptr program = ProgramObject::Build( - name, - vsPath, - RenderFsPath, - dict - ); - - if (program) { - _programs.push_back(program.get()); - } - return program; - } - - /** - * Build a program object for rendering with the used renderer - */ - std::unique_ptr RenderEngine::buildRenderProgram( - std::string name, std::string vsPath, - std::string fsPath, std::string csPath, - const ghoul::Dictionary& data) - { - ghoul::Dictionary dict = data; - dict.setValue("rendererData", _rendererData); - - // parameterize the main fragment shader program with specific contents. - // fsPath should point to a shader file defining a Fragment getFragment() function - // instead of a void main() setting glFragColor, glFragDepth, etc. - dict.setValue("fragmentPath", fsPath); - - using namespace ghoul::opengl; - std::unique_ptr program = ProgramObject::Build( - name, - vsPath, - RenderFsPath, - csPath, - dict - ); - - if (program) { - _programs.push_back(program.get()); - } - return program; - } - - void RenderEngine::removeRenderProgram( - const std::unique_ptr& program) - { - if (!program) { - return; - } - - auto it = std::find( - _programs.begin(), - _programs.end(), - program.get() - ); - - if (it != _programs.end()) { - _programs.erase(it); - } - } - - /** - * Set renderer data - * Called from the renderer, whenever it needs to update - * the dictionary of all rendering programs. - */ - void RenderEngine::setRendererData(const ghoul::Dictionary& data) { - _rendererData = data; - for (ghoul::opengl::ProgramObject* program : _programs) { - ghoul::Dictionary dict = program->dictionary(); - dict.setValue("rendererData", _rendererData); - program->setDictionary(dict); - } - } - - - /** - * Set resolve data - * Called from the renderer, whenever it needs to update - * the dictionary of all post rendering programs. - */ - void RenderEngine::setResolveData(const ghoul::Dictionary& data) { - _resolveData = data; - for (ghoul::opengl::ProgramObject* program : _programs) { - ghoul::Dictionary dict = program->dictionary(); - dict.setValue("resolveData", _resolveData); - program->setDictionary(dict); - } - } - - /** - * Set raycasting uniforms on the program object, and setup raycasting. - */ - void RenderEngine::preRaycast(ghoul::opengl::ProgramObject& programObject) { - _renderer->preRaycast(programObject); - } - - /** - * Tear down raycasting for the specified program object. - */ - void RenderEngine::postRaycast(ghoul::opengl::ProgramObject& programObject) { - _renderer->postRaycast(programObject); - } - - /** - * Set renderer - */ - void RenderEngine::setRenderer(std::unique_ptr renderer) { - if (_renderer) { - _renderer->deinitialize(); - } - - _renderer = std::move(renderer); - _renderer->setResolution(renderingResolution()); - _renderer->setNAaSamples(_nAaSamples); - _renderer->initialize(); - _renderer->setCamera(_camera); - _renderer->setScene(_scene); - } - - scripting::LuaLibrary RenderEngine::luaLibrary() { - return{ - "", - { - { - "setRenderer", - &luascriptfunctions::setRenderer, - "string", - "Sets the renderer (ABuffer or FrameBuffer)" - }, - { - "toggleFade", - &luascriptfunctions::toggleFade, - "number", - "Toggles fading in or out" - }, - { - "fadeIn", - &luascriptfunctions::fadeIn, - "number", - "" - }, - //also temporary @JK - { - "fadeOut", - &luascriptfunctions::fadeOut, - "number", - "" - }, - { - "registerScreenSpaceRenderable", - &luascriptfunctions::registerScreenSpaceRenderable, - "table", - "Will create a ScreenSpaceRenderable from a lua Table and register it in the RenderEngine" - }, - { - "unregisterScreenSpaceRenderable", - &luascriptfunctions::unregisterScreenSpaceRenderable, - "string", - "Given a ScreenSpaceRenderable name this script will remove it from the renderengine" - }, - }, - }; - } - - bool RenderEngine::doesPerformanceMeasurements() const { - return _performanceManager != nullptr; - } - - performance::PerformanceManager* RenderEngine::performanceManager() { - return _performanceManager.get(); - } - - void RenderEngine::registerScreenSpaceRenderable(std::shared_ptr s) - { - s->initialize(); - _screenSpaceRenderables.push_back(s); - } - - void RenderEngine::unregisterScreenSpaceRenderable( - std::shared_ptr s) - { - auto it = std::find( - _screenSpaceRenderables.begin(), - _screenSpaceRenderables.end(), - s - ); - - if (it != _screenSpaceRenderables.end()) { - s->deinitialize(); - _screenSpaceRenderables.erase(it); - } - } - - void RenderEngine::unregisterScreenSpaceRenderable(std::string name) { - auto s = screenSpaceRenderable(name); - if (s) { - unregisterScreenSpaceRenderable(s); - } - } - - std::shared_ptr RenderEngine::screenSpaceRenderable( - std::string name) - { - for (auto s : _screenSpaceRenderables) { - if (s->name() == name) { - return s; - } - } - return nullptr; - } - - std::vector RenderEngine::screenSpaceRenderables() const { - std::vector res(_screenSpaceRenderables.size()); - std::transform( - _screenSpaceRenderables.begin(), - _screenSpaceRenderables.end(), - res.begin(), - [](std::shared_ptr p) { return p.get(); } - ); - return res; - } - - RenderEngine::RendererImplementation RenderEngine::rendererFromString( - const std::string& impl) - { - const std::map RenderingMethods = { - { "ABuffer", RendererImplementation::ABuffer }, - { "Framebuffer", RendererImplementation::Framebuffer } - }; - - if (RenderingMethods.find(impl) != RenderingMethods.end()) { - return RenderingMethods.at(impl); - } - else { - return RendererImplementation::Invalid; - } - } - - std::string RenderEngine::progressToStr(int size, double t) { - std::string progress = "|"; - int g = static_cast((t * (size - 1)) + 1); - g = std::max(g, 0); - for (int i = 0; i < g; i++) { - progress.append("-"); - } - progress.append(">"); - for (int i = 0; i < size - g; i++) { - progress.append(" "); - } - progress.append("|"); - return progress; - } - - void RenderEngine::renderInformation() { - // TODO: Adjust font_size properly when using retina screen - using ghoul::fontrendering::RenderFont; - - if (_fontDate) { - glm::vec2 penPosition = glm::vec2( - 10.f, - fontResolution().y - //OsEng.windowWrapper().viewportPixelCoordinates().w - ); - penPosition.y -= _fontDate->height(); - - if (_showInfo && _fontDate) { - RenderFontCr( - *_fontDate, - penPosition, - "Date: %s", - Time::ref().UTC().c_str() + if (_fadeDirection < 0) { + _globalBlackOutFactor = glm::smoothstep( + 1.f, + 0.f, + _currentFadeTime / _fadeDuration ); } - if (_showInfo && _fontInfo) { + else { + _globalBlackOutFactor = glm::smoothstep( + 0.f, + 1.f, + _currentFadeTime / _fadeDuration + ); + } + _currentFadeTime += static_cast( + OsEng.windowWrapper().averageDeltaTime() + ); + } + } +} + +void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix, + const glm::mat4& projectionMatrix) +{ + LTRACE("RenderEngine::render(begin)"); + WindowWrapper& wrapper = OsEng.windowWrapper(); + + if (_disableSceneTranslationOnMaster && wrapper.isMaster()) { + _camera->sgctInternal.setViewMatrix(viewMatrix); + } + else { + _camera->sgctInternal.setViewMatrix(viewMatrix * sceneMatrix); + } + _camera->sgctInternal.setProjectionMatrix(projectionMatrix); + + + if (!(wrapper.isMaster() && _disableMasterRendering) && !wrapper.isGuiWindow()) { + _renderer->render(_globalBlackOutFactor, _performanceManager != nullptr); + } + + // Print some useful information on the master viewport + if (wrapper.isMaster() && wrapper.isSimpleRendering()) { + renderInformation(); + } + + if (_showFrameNumber) { + const glm::vec2 penPosition = glm::vec2( + fontResolution().x / 2 - 50, + fontResolution().y / 3 + ); + + RenderFont(*_fontBig, penPosition, "%i", _frameNumber); + } + + _frameNumber++; + + for (std::shared_ptr& ssr : _screenSpaceRenderables) { + if (ssr->isEnabled() && ssr->isReady()) { + ssr->render(); + } + } + LTRACE("RenderEngine::render(end)"); +} + +void RenderEngine::renderShutdownInformation(float timer, float fullTime) { + timer = timer < 0.f ? 0.f : timer; + + auto size = ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_fontDate, + "Shutdown in: %.2fs/%.2fs", + timer, + fullTime + ); + + glm::vec2 penPosition = glm::vec2( + fontResolution().x - size.boundingBox.x - 10, + fontResolution().y - size.boundingBox.y + ); + penPosition.y -= _fontDate->height(); + + RenderFontCr( + *_fontDate, + penPosition, + "Shutdown in: %.2fs/%.2fs", + timer, + fullTime + ); +} + +void RenderEngine::postDraw() { + if (Time::ref().timeJumped()) { + Time::ref().setTimeJumped(false); + } + + if (_shouldTakeScreenshot) { + OsEng.windowWrapper().takeScreenshot(_applyWarping); + _shouldTakeScreenshot = false; + } + + if (_performanceManager) { + _performanceManager->storeScenePerformanceMeasurements( + scene()->allSceneGraphNodes() + ); + } +} + +Scene* RenderEngine::scene() { + return _scene; +} + +RaycasterManager& RenderEngine::raycasterManager() { + return *_raycasterManager; +} + +DeferredcasterManager& RenderEngine::deferredcasterManager() { + return *_deferredcasterManager; +} + +void RenderEngine::setScene(Scene* scene) { + _scene = scene; + if (_renderer) { + _renderer->setScene(scene); + } +} + +void RenderEngine::setCamera(Camera* camera) { + _camera = camera; + if (_renderer) { + _renderer->setCamera(camera); + } +} + +Camera* RenderEngine::camera() const { + return _camera; +} + +Renderer* RenderEngine::renderer() const { + return _renderer.get(); +} + +RenderEngine::RendererImplementation RenderEngine::rendererImplementation() const { + return _rendererImplementation; +} + +float RenderEngine::globalBlackOutFactor() { + return _globalBlackOutFactor; +} + +void RenderEngine::setGlobalBlackOutFactor(float opacity) { + _globalBlackOutFactor = opacity; +} + +void RenderEngine::startFading(int direction, float fadeDuration) { + _fadeDirection = direction; + _fadeDuration = fadeDuration; + _currentFadeTime = 0.f; +} + +/** +* Build a program object for rendering with the used renderer +*/ +std::unique_ptr RenderEngine::buildRenderProgram( + std::string name, std::string vsPath, + std::string fsPath, const ghoul::Dictionary& data) +{ + + ghoul::Dictionary dict = data; + + // set path to the current renderer's main fragment shader + dict.setValue("rendererData", _rendererData); + // parameterize the main fragment shader program with specific contents. + // fsPath should point to a shader file defining a Fragment getFragment() function + // instead of a void main() setting glFragColor, glFragDepth, etc. + dict.setValue("fragmentPath", fsPath); + + using namespace ghoul::opengl; + std::unique_ptr program = ProgramObject::Build( + name, + vsPath, + RenderFsPath, + dict + ); + + if (program) { + _programs.push_back(program.get()); + } + return program; +} + +/** +* Build a program object for rendering with the used renderer +*/ +std::unique_ptr RenderEngine::buildRenderProgram( + std::string name, std::string vsPath, + std::string fsPath, std::string csPath, + const ghoul::Dictionary& data) +{ + ghoul::Dictionary dict = data; + dict.setValue("rendererData", _rendererData); + + // parameterize the main fragment shader program with specific contents. + // fsPath should point to a shader file defining a Fragment getFragment() function + // instead of a void main() setting glFragColor, glFragDepth, etc. + dict.setValue("fragmentPath", fsPath); + + using namespace ghoul::opengl; + std::unique_ptr program = ProgramObject::Build( + name, + vsPath, + RenderFsPath, + csPath, + dict + ); + + if (program) { + _programs.push_back(program.get()); + } + return program; +} + +void RenderEngine::removeRenderProgram( + const std::unique_ptr& program) +{ + if (!program) { + return; + } + + auto it = std::find( + _programs.begin(), + _programs.end(), + program.get() + ); + + if (it != _programs.end()) { + _programs.erase(it); + } +} + +/** +* Set renderer data +* Called from the renderer, whenever it needs to update +* the dictionary of all rendering programs. +*/ +void RenderEngine::setRendererData(const ghoul::Dictionary& data) { + _rendererData = data; + for (ghoul::opengl::ProgramObject* program : _programs) { + ghoul::Dictionary dict = program->dictionary(); + dict.setValue("rendererData", _rendererData); + program->setDictionary(dict); + } +} + + +/** +* Set resolve data +* Called from the renderer, whenever it needs to update +* the dictionary of all post rendering programs. +*/ +void RenderEngine::setResolveData(const ghoul::Dictionary& data) { + _resolveData = data; + for (ghoul::opengl::ProgramObject* program : _programs) { + ghoul::Dictionary dict = program->dictionary(); + dict.setValue("resolveData", _resolveData); + program->setDictionary(dict); + } +} + +/** +* Set raycasting uniforms on the program object, and setup raycasting. +*/ +void RenderEngine::preRaycast(ghoul::opengl::ProgramObject& programObject) { + _renderer->preRaycast(programObject); +} + +/** +* Tear down raycasting for the specified program object. +*/ +void RenderEngine::postRaycast(ghoul::opengl::ProgramObject& programObject) { + _renderer->postRaycast(programObject); +} + +/** +* Set renderer +*/ +void RenderEngine::setRenderer(std::unique_ptr renderer) { + if (_renderer) { + _renderer->deinitialize(); + } + + _renderer = std::move(renderer); + _renderer->setResolution(renderingResolution()); + _renderer->setNAaSamples(_nAaSamples); + _renderer->initialize(); + _renderer->setCamera(_camera); + _renderer->setScene(_scene); +} + +scripting::LuaLibrary RenderEngine::luaLibrary() { + return{ + "", + { + { + "setRenderer", + &luascriptfunctions::setRenderer, + "string", + "Sets the renderer (ABuffer or FrameBuffer)" + }, + { + "toggleFade", + &luascriptfunctions::toggleFade, + "number", + "Toggles fading in or out" + }, + { + "fadeIn", + &luascriptfunctions::fadeIn, + "number", + "" + }, + //also temporary @JK + { + "fadeOut", + &luascriptfunctions::fadeOut, + "number", + "" + }, + { + "registerScreenSpaceRenderable", + &luascriptfunctions::registerScreenSpaceRenderable, + "table", + "Will create a ScreenSpaceRenderable from a lua Table and register it in the RenderEngine" + }, + { + "unregisterScreenSpaceRenderable", + &luascriptfunctions::unregisterScreenSpaceRenderable, + "string", + "Given a ScreenSpaceRenderable name this script will remove it from the renderengine" + }, + }, + }; +} + +bool RenderEngine::doesPerformanceMeasurements() const { + return _performanceManager != nullptr; +} + +performance::PerformanceManager* RenderEngine::performanceManager() { + return _performanceManager.get(); +} + +void RenderEngine::registerScreenSpaceRenderable(std::shared_ptr s) +{ + s->initialize(); + _screenSpaceRenderables.push_back(s); +} + +void RenderEngine::unregisterScreenSpaceRenderable( + std::shared_ptr s) +{ + auto it = std::find( + _screenSpaceRenderables.begin(), + _screenSpaceRenderables.end(), + s + ); + + if (it != _screenSpaceRenderables.end()) { + s->deinitialize(); + _screenSpaceRenderables.erase(it); + } +} + +void RenderEngine::unregisterScreenSpaceRenderable(std::string name) { + std::shared_ptr s = screenSpaceRenderable(name); + if (s) { + unregisterScreenSpaceRenderable(s); + } +} + +std::shared_ptr RenderEngine::screenSpaceRenderable( + std::string name) +{ + for (auto s : _screenSpaceRenderables) { + if (s->name() == name) { + return s; + } + } + return nullptr; +} + +std::vector RenderEngine::screenSpaceRenderables() const { + std::vector res(_screenSpaceRenderables.size()); + std::transform( + _screenSpaceRenderables.begin(), + _screenSpaceRenderables.end(), + res.begin(), + [](std::shared_ptr p) { return p.get(); } + ); + return res; +} + +RenderEngine::RendererImplementation RenderEngine::rendererFromString( + const std::string& impl) +{ + const std::map RenderingMethods = { + { "ABuffer", RendererImplementation::ABuffer }, + { "Framebuffer", RendererImplementation::Framebuffer } + }; + + if (RenderingMethods.find(impl) != RenderingMethods.end()) { + return RenderingMethods.at(impl); + } + else { + return RendererImplementation::Invalid; + } +} + +std::string RenderEngine::progressToStr(int size, double t) { + std::string progress = "|"; + int g = static_cast((t * (size - 1)) + 1); + g = std::max(g, 0); + for (int i = 0; i < g; i++) { + progress.append("-"); + } + progress.append(">"); + for (int i = 0; i < size - g; i++) { + progress.append(" "); + } + progress.append("|"); + return progress; +} + +void RenderEngine::renderInformation() { + // TODO: Adjust font_size properly when using retina screen + using ghoul::fontrendering::RenderFont; + + if (_fontDate) { + glm::vec2 penPosition = glm::vec2( + 10.f, + fontResolution().y + //OsEng.windowWrapper().viewportPixelCoordinates().w + ); + + if (_showDate && _fontDate) { + penPosition.y -= _fontDate->height(); + RenderFontCr( + *_fontDate, + penPosition, + "Date: %s", + Time::ref().UTC().c_str() + ); + } + else { + penPosition.y -= _fontInfo->height(); + } + if (_showInfo && _fontInfo) { + RenderFontCr( + *_fontInfo, + penPosition, + "Simulation increment (s): %.3f", + Time::ref().deltaTime() + ); + + FrametimeType frametimeType = FrametimeType(_frametimeType.value()); + switch (frametimeType) { + case FrametimeType::DtTimeAvg: RenderFontCr( *_fontInfo, penPosition, - "Simulation increment (s): %.3f", - Time::ref().deltaTime() + "Avg. Frametime: %.5f", + OsEng.windowWrapper().averageDeltaTime() ); + break; + case FrametimeType::FPS: + RenderFontCr( + *_fontInfo, + penPosition, + "FPS: %3.2f", + 1.0 / OsEng.windowWrapper().deltaTime() + ); + break; + case FrametimeType::FPSAvg: + RenderFontCr( + *_fontInfo, + penPosition, + "Avg. FPS: %3.2f", + 1.0 / OsEng.windowWrapper().averageDeltaTime() + ); + break; + default: + RenderFontCr( + *_fontInfo, + penPosition, + "Avg. Frametime: %.5f", + OsEng.windowWrapper().averageDeltaTime() + ); + break; + } - FrametimeType frametimeType = FrametimeType(_frametimeType.value()); - switch (frametimeType) { - case FrametimeType::DtTimeAvg: - RenderFontCr( - *_fontInfo, - penPosition, - "Avg. Frametime: %.5f", - OsEng.windowWrapper().averageDeltaTime() - ); - break; - case FrametimeType::FPS: - RenderFontCr( - *_fontInfo, - penPosition, - "FPS: %3.2f", - 1.0 / OsEng.windowWrapper().deltaTime() - ); - break; - case FrametimeType::FPSAvg: - RenderFontCr( - *_fontInfo, - penPosition, - "Avg. FPS: %3.2f", - 1.0 / OsEng.windowWrapper().averageDeltaTime() - ); - break; - default: - RenderFontCr( - *_fontInfo, - penPosition, - "Avg. Frametime: %.5f", - OsEng.windowWrapper().averageDeltaTime() - ); - break; - } + ParallelConnection::Status status = OsEng.parallelConnection().status(); + size_t nConnections = OsEng.parallelConnection().nConnections(); + const std::string& hostName = OsEng.parallelConnection().hostName(); - ParallelConnection::Status status = OsEng.parallelConnection().status(); - size_t nConnections = OsEng.parallelConnection().nConnections(); - const std::string& hostName = OsEng.parallelConnection().hostName(); + std::string connectionInfo = ""; + int nClients = static_cast(nConnections); + if (status == ParallelConnection::Status::Host) { + nClients--; + if (nClients == 1) { + connectionInfo = "Hosting session with 1 client"; + } + else { + connectionInfo = + "Hosting session with " + std::to_string(nClients) + " clients"; + } + } + else if (status == ParallelConnection::Status::ClientWithHost) { + nClients--; + connectionInfo = "Session hosted by '" + hostName + "'"; + } + else if (status == ParallelConnection::Status::ClientWithoutHost) { + connectionInfo = "Host is disconnected"; + } - std::string connectionInfo = ""; - int nClients = static_cast(nConnections); - if (status == ParallelConnection::Status::Host) { - nClients--; - if (nClients == 1) { - connectionInfo = "Hosting session with 1 client"; - } - else { - connectionInfo = - "Hosting session with " + std::to_string(nClients) + " clients"; - } + if (status == ParallelConnection::Status::ClientWithHost || + status == ParallelConnection::Status::ClientWithoutHost) { + connectionInfo += "\n"; + if (nClients > 2) { + std::string c = std::to_string(nClients - 1); + connectionInfo += "You and " + c + " more clients are tuned in"; } - else if (status == ParallelConnection::Status::ClientWithHost) { - nClients--; - connectionInfo = "Session hosted by '" + hostName + "'"; + else if (nClients == 2) { + std::string c = std::to_string(nClients - 1); + connectionInfo += "You and " + c + " more client are tuned in"; } - else if (status == ParallelConnection::Status::ClientWithoutHost) { - connectionInfo = "Host is disconnected"; + else if (nClients == 1) { + connectionInfo += "You are the only client"; } + } - if (status == ParallelConnection::Status::ClientWithHost || - status == ParallelConnection::Status::ClientWithoutHost) { - connectionInfo += "\n"; - if (nClients > 2) { - std::string c = std::to_string(nClients - 1); - connectionInfo += "You and " + c + " more clients are tuned in"; - } - else if (nClients == 2) { - std::string c = std::to_string(nClients - 1); - connectionInfo += "You and " + c + " more client are tuned in"; - } - else if (nClients == 1) { - connectionInfo += "You are the only client"; - } - } - - if (connectionInfo != "") { - RenderFontCr( - *_fontInfo, - penPosition, - connectionInfo.c_str() - ); - } + if (connectionInfo != "") { + RenderFontCr( + *_fontInfo, + penPosition, + connectionInfo.c_str() + ); + } #ifdef OPENSPACE_MODULE_NEWHORIZONS_ENABLED - bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons") != nullptr ? true : false; - double currentTime = Time::ref().j2000Seconds(); + bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons"); + double currentTime = Time::ref().j2000Seconds(); - if (MissionManager::ref().hasCurrentMission()) { + if (MissionManager::ref().hasCurrentMission()) { - const Mission& mission = MissionManager::ref().currentMission(); + const Mission& mission = MissionManager::ref().currentMission(); - if (mission.phases().size() > 0) { - static const glm::vec4 nextMissionColor(0.7, 0.3, 0.3, 1); - //static const glm::vec4 missionProgressColor(0.4, 1.0, 1.0, 1); - static const glm::vec4 currentMissionColor(0.0, 0.5, 0.5, 1); - static const glm::vec4 missionProgressColor = currentMissionColor;// (0.4, 1.0, 1.0, 1); - static const glm::vec4 currentLeafMissionColor = missionProgressColor; - static const glm::vec4 nonCurrentMissionColor(0.3, 0.3, 0.3, 1); + if (mission.phases().size() > 0) { + static const glm::vec4 nextMissionColor(0.7, 0.3, 0.3, 1); + //static const glm::vec4 missionProgressColor(0.4, 1.0, 1.0, 1); + static const glm::vec4 currentMissionColor(0.0, 0.5, 0.5, 1); + static const glm::vec4 missionProgressColor = currentMissionColor;// (0.4, 1.0, 1.0, 1); + static const glm::vec4 currentLeafMissionColor = missionProgressColor; + static const glm::vec4 nonCurrentMissionColor(0.3, 0.3, 0.3, 1); - // Add spacing - RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, " "); + // Add spacing + RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, " "); - auto phaseTrace = mission.phaseTrace(currentTime); + auto phaseTrace = mission.phaseTrace(currentTime); - if (phaseTrace.size()) { - const MissionPhase& phase = phaseTrace.back().get(); - std::string title = "Current Mission Phase: " + phase.name(); - RenderFontCr(*_fontInfo, penPosition, missionProgressColor, title.c_str()); - double remaining = phase.timeRange().end - currentTime; - float t = static_cast(1.0 - remaining / phase.timeRange().duration()); + if (phaseTrace.size()) { + const MissionPhase& phase = phaseTrace.back().get(); + std::string title = "Current Mission Phase: " + phase.name(); + RenderFontCr(*_fontInfo, penPosition, missionProgressColor, title.c_str()); + double remaining = phase.timeRange().end - currentTime; + float t = static_cast(1.0 - remaining / phase.timeRange().duration()); + std::string progress = progressToStr(25, t); + //RenderFontCr(*_fontInfo, penPosition, missionProgressColor, + // "%.0f s %s %.1f %%", remaining, progress.c_str(), t * 100); + } + else { + RenderFontCr(*_fontInfo, penPosition, nextMissionColor, "Next Mission:"); + double remaining = mission.timeRange().start - currentTime; + RenderFontCr(*_fontInfo, penPosition, nextMissionColor, + "%.0f s", remaining); + } + + bool showAllPhases = false; + + typedef std::pair PhaseWithDepth; + std::stack S; + int pixelIndentation = 20; + S.push({ &mission, 0 }); + while (!S.empty()) { + const MissionPhase* phase = S.top().first; + int depth = S.top().second; + S.pop(); + + bool isCurrentPhase = phase->timeRange().includes(currentTime); + + penPosition.x += depth * pixelIndentation; + if (isCurrentPhase) { + double remaining = phase->timeRange().end - currentTime; + float t = static_cast(1.0 - remaining / phase->timeRange().duration()); std::string progress = progressToStr(25, t); - //RenderFontCr(*_fontInfo, penPosition, missionProgressColor, - // "%.0f s %s %.1f %%", remaining, progress.c_str(), t * 100); + RenderFontCr(*_fontInfo, penPosition, currentMissionColor, + "%s %s %.1f %%", + phase->name().c_str(), + progress.c_str(), + t * 100 + ); } else { - RenderFontCr(*_fontInfo, penPosition, nextMissionColor, "Next Mission:"); - double remaining = mission.timeRange().start - currentTime; - RenderFontCr(*_fontInfo, penPosition, nextMissionColor, - "%.0f s", remaining); + RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, phase->name().c_str()); } + penPosition.x -= depth * pixelIndentation; - bool showAllPhases = false; - - typedef std::pair PhaseWithDepth; - std::stack S; - int pixelIndentation = 20; - S.push({ &mission, 0 }); - while (!S.empty()) { - const MissionPhase* phase = S.top().first; - int depth = S.top().second; - S.pop(); - - bool isCurrentPhase = phase->timeRange().includes(currentTime); - - penPosition.x += depth * pixelIndentation; - if (isCurrentPhase) { - double remaining = phase->timeRange().end - currentTime; - float t = static_cast(1.0 - remaining / phase->timeRange().duration()); - std::string progress = progressToStr(25, t); - RenderFontCr(*_fontInfo, penPosition, currentMissionColor, - "%s %s %.1f %%", - phase->name().c_str(), - progress.c_str(), - t * 100 - ); - } - else { - RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, phase->name().c_str()); - } - penPosition.x -= depth * pixelIndentation; - - if (isCurrentPhase || showAllPhases) { - // phases are sorted increasingly by start time, and will be popped - // last-in-first-out from the stack, so add them in reversed order. - int indexLastPhase = static_cast(phase->phases().size()) - 1; - for (int i = indexLastPhase; 0 <= i; --i) { - S.push({ &phase->phases()[i], depth + 1 }); - } + if (isCurrentPhase || showAllPhases) { + // phases are sorted increasingly by start time, and will be popped + // last-in-first-out from the stack, so add them in reversed order. + int indexLastPhase = static_cast(phase->phases().size()) - 1; + for (int i = indexLastPhase; 0 <= i; --i) { + S.push({ &phase->phases()[i], depth + 1 }); } } } } + } - if (openspace::ImageSequencer::ref().isReady()) { - penPosition.y -= 25.f; + if (openspace::ImageSequencer::ref().isReady()) { + penPosition.y -= 25.f; - glm::vec4 targetColor(0.00, 0.75, 1.00, 1); + glm::vec4 targetColor(0.00, 0.75, 1.00, 1); - if (hasNewHorizons) { - try { - double lt; - glm::dvec3 p = - SpiceManager::ref().targetPosition("PLUTO", "NEW HORIZONS", "GALACTIC", {}, currentTime, lt); - psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); - float a, b; - glm::dvec3 radii; - SpiceManager::ref().getValue("PLUTO", "RADII", radii); - a = static_cast(radii.x); - b = static_cast(radii.y); - float radius = (a + b) / 2.f; - float distToSurf = glm::length(nhPos.vec3()) - radius; + if (hasNewHorizons) { + try { + double lt; + glm::dvec3 p = + SpiceManager::ref().targetPosition("PLUTO", "NEW HORIZONS", "GALACTIC", {}, currentTime, lt); + psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); + float a, b; + glm::dvec3 radii; + SpiceManager::ref().getValue("PLUTO", "RADII", radii); + a = static_cast(radii.x); + b = static_cast(radii.y); + float radius = (a + b) / 2.f; + float distToSurf = glm::length(nhPos.vec3()) - radius; - RenderFont(*_fontInfo, - penPosition, - "Distance to Pluto: % .1f (KM)", - distToSurf - ); - penPosition.y -= _fontInfo->height(); - } - catch (...) { - // @CLEANUP: This is bad as it will discard all exceptions - // without telling us about it! ---abock - } + RenderFont(*_fontInfo, + penPosition, + "Distance to Pluto: % .1f (KM)", + distToSurf + ); + penPosition.y -= _fontInfo->height(); } + catch (...) { + // @CLEANUP: This is bad as it will discard all exceptions + // without telling us about it! ---abock + } + } - double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - currentTime; - float t = static_cast(1.0 - remaining / openspace::ImageSequencer::ref().getIntervalLength()); + double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - currentTime; + float t = static_cast(1.0 - remaining / openspace::ImageSequencer::ref().getIntervalLength()); - std::string str = SpiceManager::ref().dateFromEphemerisTime( - ImageSequencer::ref().getNextCaptureTime(), - "YYYY MON DD HR:MN:SC" + std::string str = SpiceManager::ref().dateFromEphemerisTime( + ImageSequencer::ref().getNextCaptureTime(), + "YYYY MON DD HR:MN:SC" + ); + + glm::vec4 active(0.6, 1, 0.00, 1); + glm::vec4 brigther_active(0.9, 1, 0.75, 1); + + if (remaining > 0) { + + std::string progress = progressToStr(25, t); + brigther_active *= (1 - t); + + RenderFontCr(*_fontInfo, + penPosition, + active * t + brigther_active, + "Next instrument activity:" ); - glm::vec4 active(0.6, 1, 0.00, 1); - glm::vec4 brigther_active(0.9, 1, 0.75, 1); + RenderFontCr(*_fontInfo, + penPosition, + active * t + brigther_active, + "%.0f s %s %.1f %%", + remaining, progress.c_str(), t * 100 + ); - if (remaining > 0) { + RenderFontCr(*_fontInfo, + penPosition, + active, + "Data acquisition time: %s", + str.c_str() + ); + } + std::pair nextTarget = ImageSequencer::ref().getNextTarget(); + std::pair currentTarget = ImageSequencer::ref().getCurrentTarget(); - std::string progress = progressToStr(25, t); - brigther_active *= (1 - t); + if (currentTarget.first > 0.0) { + int timeleft = static_cast(nextTarget.first - currentTime); - RenderFontCr(*_fontInfo, - penPosition, - active * t + brigther_active, - "Next instrument activity:" - ); + int hour = timeleft / 3600; + int second = timeleft % 3600; + int minute = second / 60; + second = second % 60; - RenderFontCr(*_fontInfo, - penPosition, - active * t + brigther_active, - "%.0f s %s %.1f %%", - remaining, progress.c_str(), t * 100 - ); + std::string hh, mm, ss; - RenderFontCr(*_fontInfo, - penPosition, - active, - "Data acquisition time: %s", - str.c_str() - ); - } - std::pair nextTarget = ImageSequencer::ref().getNextTarget(); - std::pair currentTarget = ImageSequencer::ref().getCurrentTarget(); + if (hour < 10) + hh.append("0"); + if (minute < 10) + mm.append("0"); + if (second < 10) + ss.append("0"); - if (currentTarget.first > 0.0) { - int timeleft = static_cast(nextTarget.first - currentTime); + hh.append(std::to_string(hour)); + mm.append(std::to_string(minute)); + ss.append(std::to_string(second)); - int hour = timeleft / 3600; - int second = timeleft % 3600; - int minute = second / 60; - second = second % 60; - - std::string hh, mm, ss; - - if (hour < 10) - hh.append("0"); - if (minute < 10) - mm.append("0"); - if (second < 10) - ss.append("0"); - - hh.append(std::to_string(hour)); - mm.append(std::to_string(minute)); - ss.append(std::to_string(second)); - - RenderFontCr(*_fontInfo, - penPosition, - targetColor, - "Data acquisition adjacency: [%s:%s:%s]", - hh.c_str(), mm.c_str(), ss.c_str() - ); + RenderFontCr(*_fontInfo, + penPosition, + targetColor, + "Data acquisition adjacency: [%s:%s:%s]", + hh.c_str(), mm.c_str(), ss.c_str() + ); #if 0 - // Why is it (2) in the original? ---abock - //std::pair> incidentTargets = ImageSequencer::ref().getIncidentTargetList(0); - //std::pair> incidentTargets = ImageSequencer::ref().getIncidentTargetList(2); - std::string space; - glm::vec4 color; - size_t isize = incidentTargets.second.size(); - for (size_t p = 0; p < isize; p++) { - double t = static_cast(p + 1) / static_cast(isize + 1); - t = (p > isize / 2) ? 1 - t : t; - t += 0.3; - color = (p == isize / 2) ? targetColor : glm::vec4(t, t, t, 1); + // Why is it (2) in the original? ---abock + //std::pair> incidentTargets = ImageSequencer::ref().getIncidentTargetList(0); + //std::pair> incidentTargets = ImageSequencer::ref().getIncidentTargetList(2); + std::string space; + glm::vec4 color; + size_t isize = incidentTargets.second.size(); + for (size_t p = 0; p < isize; p++) { + double t = static_cast(p + 1) / static_cast(isize + 1); + t = (p > isize / 2) ? 1 - t : t; + t += 0.3; + color = (p == isize / 2) ? targetColor : glm::vec4(t, t, t, 1); + RenderFont(*_fontInfo, + penPosition, + color, + "%s%s", + space.c_str(), incidentTargets.second[p].c_str() + ); + for (int k = 0; k < incidentTargets.second[p].size() + 2; k++) + space += " "; + } +#endif + penPosition.y -= _fontInfo->height(); + std::map activeMap = ImageSequencer::ref().getActiveInstruments(); + glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1); + glm::vec4 notFiring(0.5, 0.5, 0.5, 1); + + RenderFontCr(*_fontInfo, + penPosition, + active, + "Active Instruments:" + ); + + for (auto t : activeMap) { + if (t.second == false) { RenderFont(*_fontInfo, penPosition, - color, - "%s%s", - space.c_str(), incidentTargets.second[p].c_str() + glm::vec4(0.3, 0.3, 0.3, 1), + "| |" + ); + RenderFontCr(*_fontInfo, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + " %5s", + t.first.c_str() ); - - for (int k = 0; k < incidentTargets.second[p].size() + 2; k++) - space += " "; } -#endif - penPosition.y -= _fontInfo->height(); - - std::map activeMap = ImageSequencer::ref().getActiveInstruments(); - glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1); - glm::vec4 notFiring(0.5, 0.5, 0.5, 1); - - RenderFontCr(*_fontInfo, - penPosition, - active, - "Active Instruments:" - ); - - for (auto activeInstrument : activeMap) { - if (activeInstrument.second == false) { + else { + RenderFont(*_fontInfo, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + "|" + ); + if (t.first == "NH_LORRI") { RenderFont(*_fontInfo, penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - "| |" - ); - RenderFontCr(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - " %5s", - activeInstrument.first.c_str() - ); - - } - else { - RenderFont(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - "|" - ); - if (activeInstrument.first == "NH_LORRI") { - RenderFont(*_fontInfo, - penPosition, - firing, - " + " - ); - } - RenderFont(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - " |" - ); - RenderFontCr(*_fontInfo, - penPosition, - active, - " %5s", - activeInstrument.first.c_str() + firing, + " + " ); } + RenderFont(*_fontInfo, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + " |" + ); + RenderFontCr(*_fontInfo, + penPosition, + active, + " %5s", + t.first.c_str() + ); } } } } + } #endif - } + } +} + +void RenderEngine::renderScreenLog() { + if (!_showLog) { + return; } - void RenderEngine::renderScreenLog() { - if (!_showLog) { - return; + _log->removeExpiredEntries(); + + const int max = 10; + const int category_length = 20; + const int msg_length = 140; + std::chrono::seconds fade(5); + + auto entries = _log->entries(); + auto lastEntries = + entries.size() > max ? + std::make_pair(entries.rbegin(), entries.rbegin() + max) : + std::make_pair(entries.rbegin(), entries.rend()); + + + size_t nr = 1; + auto now = std::chrono::steady_clock::now(); + for (auto& it = lastEntries.first; it != lastEntries.second; ++it) { + const ScreenLog::LogEntry* e = &(*it); + + std::chrono::duration diff = now - e->timeStamp; + + float alpha = 1; + std::chrono::duration ttf = ScreenLogTimeToLive - fade; + if (diff > ttf) { + auto d = (diff - ttf).count(); + auto t = static_cast(d) / static_cast(fade.count()); + float p = 0.8f - t; + alpha = (p <= 0.f) ? 0.f : pow(p, 0.3f); } - _log->removeExpiredEntries(); + // Since all log entries are ordered, once one exceeds alpha, all have + if (alpha <= 0.0) + break; - const int max = 10; - const int category_length = 20; - const int msg_length = 140; - std::chrono::seconds fade(5); + const std::string lvl = "(" + ghoul::logging::stringFromLevel(e->level) + ")"; + const std::string& message = e->message.substr(0, msg_length); + nr += std::count(message.begin(), message.end(), '\n'); - auto entries = _log->entries(); - auto lastEntries = - entries.size() > max ? - std::make_pair(entries.rbegin(), entries.rbegin() + max) : - std::make_pair(entries.rbegin(), entries.rend()); + const glm::vec4 White(0.9f, 0.9f, 0.9f, 1.0f); + RenderFont( + *_fontLog, + glm::vec2(10.f, _fontLog->pointSize() * nr * 2), + White * alpha, + "%-14s %s%s", // Format + e->timeString.c_str(), // Time string + e->category.substr(0, category_length).c_str(), // Category string + e->category.length() > 20 ? "..." : ""); // Pad category with "..." - size_t nr = 1; - auto now = std::chrono::steady_clock::now(); - for (auto& it = lastEntries.first; it != lastEntries.second; ++it) { - const ScreenLog::LogEntry* e = &(*it); + const glm::vec4 Red(1.f, 0.f, 0.f, 1.f); + const glm::vec4 Yellow(1.f, 1.f, 0.f, 1.f); + const glm::vec4 Green(0.f, 1.f, 0.f, 1.f); + const glm::vec4 Blue(0.f, 0.f, 1.f, 1.f); - std::chrono::duration diff = now - e->timeStamp; - - float alpha = 1; - std::chrono::duration ttf = ScreenLogTimeToLive - fade; - if (diff > ttf) { - auto d = (diff - ttf).count(); - auto t = static_cast(d) / static_cast(fade.count()); - float p = 0.8f - t; - alpha = (p <= 0.f) ? 0.f : pow(p, 0.3f); - } - - // Since all log entries are ordered, once one exceeds alpha, all have - if (alpha <= 0.0) - break; - - const std::string lvl = "(" + ghoul::logging::stringFromLevel(e->level) + ")"; - const std::string& message = e->message.substr(0, msg_length); - nr += std::count(message.begin(), message.end(), '\n'); - - const glm::vec4 White(0.9f, 0.9f, 0.9f, 1.0f); - - RenderFont( - *_fontLog, - glm::vec2(10.f, _fontLog->pointSize() * nr * 2), - White * alpha, - "%-14s %s%s", // Format - e->timeString.c_str(), // Time string - e->category.substr(0, category_length).c_str(), // Category string - e->category.length() > 20 ? "..." : ""); // Pad category with "..." - - const glm::vec4 Red(1.f, 0.f, 0.f, 1.f); - const glm::vec4 Yellow(1.f, 1.f, 0.f, 1.f); - const glm::vec4 Green(0.f, 1.f, 0.f, 1.f); - const glm::vec4 Blue(0.f, 0.f, 1.f, 1.f); - - glm::vec4 color(glm::uninitialize); - switch (e->level) { - case ghoul::logging::LogLevel::Debug: - color = Green; - break; - case ghoul::logging::LogLevel::Warning: - color = Yellow; - break; - case ghoul::logging::LogLevel::Error: - color = Red; - break; - case ghoul::logging::LogLevel::Fatal: - color = Blue; - break; - default: - color = White; - break; - } - - // const float font_with_light = 5; - RenderFont( - *_fontLog, - glm::vec2(static_cast(10 + 39 * _fontLog->pointSize()), _fontLog->pointSize() * nr * 2), - color * alpha, - "%s", // Format - lvl.c_str()); // Pad category with "..." if exceeds category_length - - RenderFont(*_fontLog, - glm::vec2(static_cast(10 + 53 * _fontLog->pointSize()), _fontLog->pointSize() * nr * 2), - White * alpha, - "%s", // Format - message.c_str()); // Pad category with "..." if exceeds category_length - ++nr; + glm::vec4 color(glm::uninitialize); + switch (e->level) { + case ghoul::logging::LogLevel::Debug: + color = Green; + break; + case ghoul::logging::LogLevel::Warning: + color = Yellow; + break; + case ghoul::logging::LogLevel::Error: + color = Red; + break; + case ghoul::logging::LogLevel::Fatal: + color = Blue; + break; + default: + color = White; + break; } + + // const float font_with_light = 5; + RenderFont( + *_fontLog, + glm::vec2(static_cast(10 + 39 * _fontLog->pointSize()), _fontLog->pointSize() * nr * 2), + color * alpha, + "%s", // Format + lvl.c_str()); // Pad category with "..." if exceeds category_length + + RenderFont(*_fontLog, + glm::vec2(static_cast(10 + 53 * _fontLog->pointSize()), _fontLog->pointSize() * nr * 2), + White * alpha, + "%s", // Format + message.c_str()); // Pad category with "..." if exceeds category_length + ++nr; } +} - std::vector RenderEngine::getSyncables() { - if (_camera) { - return _camera->getSyncables(); - } - else { - return std::vector(); - } +std::vector RenderEngine::getSyncables() { + if (_camera) { + return _camera->getSyncables(); } - - void RenderEngine::sortScreenspaceRenderables() { - std::sort( - _screenSpaceRenderables.begin(), - _screenSpaceRenderables.end(), - [](auto j, auto i) { - return i->depth() > j->depth(); - } - ); + else { + return std::vector(); } +} -}// namespace openspace +void RenderEngine::sortScreenspaceRenderables() { + std::sort( + _screenSpaceRenderables.begin(), + _screenSpaceRenderables.end(), + [](const std::shared_ptr& j, + const std::shared_ptr& i) + { + return i->depth() > j->depth(); + } + ); +} + +}// namespace openspace \ No newline at end of file diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index f04461bf0b..0b03377d3c 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -31,7 +31,7 @@ #include #include #include - +#include #ifdef WIN32 #define _USE_MATH_DEFINES diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index 4778aee872..5147d0bde0 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -74,18 +74,27 @@ namespace { const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/properties/main.hbs"; const char* PropertyOwnerTemplateFilename = "${OPENSPACE_DATA}/web/properties/propertyowner.hbs"; const char* PropertyTemplateFilename = "${OPENSPACE_DATA}/web/properties/property.hbs"; - const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; const char* JsFilename = "${OPENSPACE_DATA}/web/properties/script.js"; - const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; - const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; } // namespace namespace openspace { -Scene::Scene() {} - -Scene::~Scene() {} +Scene::Scene() + : DocumentationGenerator( + "Documented", + "propertyOwners", + { + { "mainTemplate", MainTemplateFilename }, + { "propertyOwnerTemplate", PropertyOwnerTemplateFilename }, + { "propertyTemplate", PropertyTemplateFilename } + }, + JsFilename + ) +{} +Scene::~Scene(){ +} + void Scene::setRoot(std::unique_ptr root) { if (_root) { removeNode(_root.get()); @@ -266,165 +275,71 @@ const std::vector& Scene::allSceneGraphNodes() const { return _topologicallySortedNodes; } -void Scene::writePropertyDocumentation(const std::string& filename, const std::string& type, const std::string& sceneFilename) { - LDEBUG("Writing documentation for properties"); - if (type == "text") { - std::ofstream file; - file.exceptions(~std::ofstream::goodbit); - file.open(filename); - - using properties::Property; - for (SceneGraphNode* node : allSceneGraphNodes()) { - std::vector properties = node->propertiesRecursive(); - if (!properties.empty()) { - file << node->name() << std::endl; - - for (Property* p : properties) { - file << p->fullyQualifiedIdentifier() << ": " << - p->guiName() << std::endl; - } - - file << std::endl; - } - } - } - else if (type == "html") { - std::ofstream file; - file.exceptions(~std::ofstream::goodbit); - file.open(filename); - - - std::ifstream handlebarsInput(absPath(HandlebarsFilename)); - std::ifstream jsInput(absPath(JsFilename)); - - std::string jsContent; - std::back_insert_iterator jsInserter(jsContent); - - std::copy(std::istreambuf_iterator{handlebarsInput}, std::istreambuf_iterator(), jsInserter); - std::copy(std::istreambuf_iterator{jsInput}, std::istreambuf_iterator(), jsInserter); - - std::ifstream bootstrapInput(absPath(BootstrapFilename)); - std::ifstream cssInput(absPath(CssFilename)); - - std::string cssContent; - std::back_insert_iterator cssInserter(cssContent); - - std::copy(std::istreambuf_iterator{bootstrapInput}, std::istreambuf_iterator(), cssInserter); - std::copy(std::istreambuf_iterator{cssInput}, std::istreambuf_iterator(), cssInserter); - - std::ifstream mainTemplateInput(absPath(MainTemplateFilename)); - std::string mainTemplateContent{ std::istreambuf_iterator{mainTemplateInput}, - std::istreambuf_iterator{} }; - - std::ifstream propertyOwnerTemplateInput(absPath(PropertyOwnerTemplateFilename)); - std::string propertyOwnerTemplateContent{ std::istreambuf_iterator{propertyOwnerTemplateInput}, - std::istreambuf_iterator{} }; - - std::ifstream propertyTemplateInput(absPath(PropertyTemplateFilename)); - std::string propertyTemplateContent{ std::istreambuf_iterator{propertyTemplateInput}, - std::istreambuf_iterator{} }; - - // Create JSON - std::function createJson = - [&createJson](properties::PropertyOwner* owner) -> std::string - { - std::stringstream json; - json << "{"; - json << "\"name\": \"" << owner->name() << "\","; - - json << "\"properties\": ["; - auto properties = owner->properties(); - for (properties::Property* p : properties) { - json << "{"; - json << "\"id\": \"" << p->identifier() << "\","; - json << "\"type\": \"" << p->className() << "\","; - json << "\"fullyQualifiedId\": \"" << p->fullyQualifiedIdentifier() << "\","; - json << "\"guiName\": \"" << p->guiName() << "\""; - json << "}"; - if (p != properties.back()) { - json << ","; - } - } - json << "],"; - - json << "\"propertyOwners\": ["; - auto propertyOwners = owner->propertySubOwners(); - for (properties::PropertyOwner* o : propertyOwners) { - json << createJson(o); - if (o != propertyOwners.back()) { - json << ","; - } - } - json << "]"; - json << "}"; - - return json.str(); - }; - - +std::string Scene::generateJson() const { + std::function createJson = + [&createJson](properties::PropertyOwner* owner) -> std::string + { std::stringstream json; - json << "["; - std::vector nodes = allSceneGraphNodes(); - if (!nodes.empty()) { - json << std::accumulate( - std::next(nodes.begin()), - nodes.end(), - createJson(*nodes.begin()), - [createJson](std::string a, SceneGraphNode* n) { - return a + "," + createJson(n); - } - ); - } + json << "{"; + json << "\"name\": \"" << owner->name() << "\","; - json << "]"; - - std::string jsonString = ""; - for (const char& c : json.str()) { - if (c == '\'') { - jsonString += "\\'"; - } else { - jsonString += c; + json << "\"properties\": ["; + auto properties = owner->properties(); + for (properties::Property* p : properties) { + json << "{"; + json << "\"id\": \"" << p->identifier() << "\","; + json << "\"type\": \"" << p->className() << "\","; + json << "\"fullyQualifiedId\": \"" << p->fullyQualifiedIdentifier() << "\","; + json << "\"guiName\": \"" << p->guiName() << "\""; + json << "}"; + if (p != properties.back()) { + json << ","; } } + json << "],"; - std::string generationTime; - try { - generationTime = Time::now().ISO8601(); + json << "\"propertyOwners\": ["; + auto propertyOwners = owner->propertySubOwners(); + for (properties::PropertyOwner* o : propertyOwners) { + json << createJson(o); + if (o != propertyOwners.back()) { + json << ","; + } } - catch (...) {} + json << "]"; + json << "}"; - std::stringstream html; - html << "\n" - << "\n" - << "\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\n" - << "\t\n" - << "\t\tDocumentation\n" - << "\t\n" - << "\t\n" - << "\t\n" - << "\n"; - file << html.str(); + return json.str(); + }; + + + std::stringstream json; + json << "["; + std::vector nodes = allSceneGraphNodes(); + if (!nodes.empty()) { + json << std::accumulate( + std::next(nodes.begin()), + nodes.end(), + createJson(*nodes.begin()), + [createJson](std::string a, SceneGraphNode* n) { + return a + "," + createJson(n); + } + ); } - else - LERROR("Undefined type '" << type << "' for Property documentation"); + + json << "]"; + + std::string jsonString = ""; + for (const char& c : json.str()) { + if (c == '\'') { + jsonString += "\\'"; + } + else { + jsonString += c; + } + } + + return jsonString; } scripting::LuaLibrary Scene::luaLibrary() { diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index 4362054249..79baf099e8 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -24,9 +24,21 @@ #include +#include +#include +#include + +#include #include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include @@ -36,13 +48,6 @@ #include #include -#include -#include -#include - -#include -#include - #include #include diff --git a/src/scripting/scriptengine.cpp b/src/scripting/scriptengine.cpp index ddbd6fac4f..ffd76288e0 100644 --- a/src/scripting/scriptengine.cpp +++ b/src/scripting/scriptengine.cpp @@ -40,31 +40,37 @@ #include "scriptengine_lua.inl" -namespace { - const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/main.hbs"; - const char* ScriptingTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/scripting.hbs"; - const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; - const char* JsFilename = "${OPENSPACE_DATA}/web/luascripting/script.js"; - const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; - const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; -} - -namespace openspace { - -namespace scripting { - namespace { const std::string _loggerCat = "ScriptEngine"; - + const char* LuaGlobalNamespace = "_G"; const char* PrintFunctionName = "print"; //const lua_CFunction _printFunctionReplacement = luascriptfunctions::printInfo; - + const int TableOffset = -3; // -1 (top) -1 (first argument) -1 (second argument) -} + + const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/main.hbs"; + const char* ScriptingTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/scripting.hbs"; + const char* JsFilename = "${OPENSPACE_DATA}/web/luascripting/script.js"; +} // namespace + +namespace openspace { +namespace scripting { std::string ScriptEngine::OpenSpaceLibraryName = "openspace"; +ScriptEngine::ScriptEngine() + : DocumentationGenerator( + "Script Documentation", + "scripting", + { + { "mainTemplate", MainTemplateFilename }, + { "scriptingTemplate", ScriptingTemplateFilename } + }, + JsFilename + ) +{} + void ScriptEngine::initialize() { LDEBUG("Adding base library"); addBaseLibrary(); @@ -496,255 +502,62 @@ std::vector ScriptEngine::allLuaFunctions() const { return result; } -void ScriptEngine::writeDocumentation(const std::string& filename, const std::string& type) const { - auto concatenate = [](std::string library, std::string function) { - std::string total = "openspace."; - if (!library.empty()) { - total += std::move(library) + "."; +std::string ScriptEngine::generateJson() const { + // Create JSON + std::stringstream json; + json << "["; + + bool first = true; + for (const LuaLibrary& l : _registeredLibraries) { + if (!first) { + json << ","; } - total += std::move(function); - return total; - }; + first = false; - LDEBUG("Writing Lua documentation of type '" << type << - "' to file '" << filename << "'"); - if (type == "text") { - // Settings - const unsigned int lineWidth = 80; - static const std::string whitespace = " \t"; - static const std::string padding = " "; + json << "{"; + json << "\"library\": \"" << l.name << "\","; + json << "\"functions\": ["; - // The additional space between the longest function name and the descriptions - - std::ofstream file; - file.exceptions(~std::ofstream::goodbit); - file.open(filename); - - file << "Available commands:\n"; - // Now write out the functions - for (const LuaLibrary& l : _registeredLibraries) { - for (const LuaLibrary::Function& f : l.functions) { - std::string name = concatenate(l.name, f.name); - file << padding << name << "(" << f.argumentText << ")" << std::endl; - } - } - file << std::endl; - - // Now write out the functions definitions - for (const LuaLibrary& library : _registeredLibraries) { - for (const LuaLibrary::Function& function : library.functions) { - std::string name = concatenate(library.name, function.name); - file << name << "(" << function.argumentText << "):" << std::endl; - - std::string remainingHelptext = function.helpText; - while (!remainingHelptext.empty()) { - const size_t length = remainingHelptext.length(); - const size_t paddingLength = padding.length(); - - if ((length + paddingLength) > lineWidth) { - size_t lastSpace = remainingHelptext.find_last_of( - whitespace, - lineWidth - 1 - paddingLength - ); - if (lastSpace == remainingHelptext.npos) { - lastSpace = lineWidth; - } - - file << padding << remainingHelptext.substr(0, lastSpace) << '\n'; - - size_t firstNotSpace = remainingHelptext.find_first_not_of( - whitespace, - lastSpace - ); - if (firstNotSpace == remainingHelptext.npos) { - firstNotSpace = lastSpace; - } - remainingHelptext = remainingHelptext.substr(firstNotSpace); - } - else { - file << padding << remainingHelptext << std::endl; - remainingHelptext = ""; - } - } - file << std::endl; - } - } - } - else if (type == "html") { - std::ifstream handlebarsInput(absPath(HandlebarsFilename)); - std::ifstream jsInput(absPath(JsFilename)); - - std::string jsContent; - std::back_insert_iterator jsInserter(jsContent); - - std::copy(std::istreambuf_iterator{handlebarsInput}, std::istreambuf_iterator(), jsInserter); - std::copy(std::istreambuf_iterator{jsInput}, std::istreambuf_iterator(), jsInserter); - - std::ifstream bootstrapInput(absPath(BootstrapFilename)); - std::ifstream cssInput(absPath(CssFilename)); - - std::string cssContent; - std::back_insert_iterator cssInserter(cssContent); - - std::copy(std::istreambuf_iterator{bootstrapInput}, std::istreambuf_iterator(), cssInserter); - std::copy(std::istreambuf_iterator{cssInput}, std::istreambuf_iterator(), cssInserter); - - std::ifstream mainTemplateInput(absPath(MainTemplateFilename)); - std::string mainTemplateContent{ std::istreambuf_iterator{mainTemplateInput}, - std::istreambuf_iterator{} }; - - std::ifstream scriptingTemplateInput(absPath(ScriptingTemplateFilename)); - std::string scriptingTemplateContent{ std::istreambuf_iterator{scriptingTemplateInput}, - std::istreambuf_iterator{} }; - - std::ofstream file; - file.exceptions(~std::ofstream::goodbit); - file.open(filename); - - // Create JSON - std::stringstream json; - json << "["; - - bool first = true; - for (const LuaLibrary& l : _registeredLibraries) { - if (!first) { + for (const LuaLibrary::Function& f : l.functions) { + json << "{"; + json << "\"name\": \"" << f.name << "\", "; + json << "\"arguments\": \"" << f.argumentText << "\", "; + json << "\"help\": \"" << f.helpText << "\""; + json << "}"; + if (&f != &l.functions.back()) { json << ","; } - first = false; - - json << "{"; - json << "\"library\": \"" << l.name << "\","; - json << "\"functions\": ["; - - for (const LuaLibrary::Function& f : l.functions) { - json << "{"; - json << "\"name\": \"" << f.name << "\", "; - json << "\"arguments\": \"" << f.argumentText << "\", "; - json << "\"help\": \"" << f.helpText << "\""; - json << "}"; - if (&f != &l.functions.back()) { - json << ","; - } - } - json << "]}"; - } - json << "]"; + json << "]}"; - std::string jsonString = ""; - for (const char& c : json.str()) { - if (c == '\'') { - jsonString += "\\'"; - } - else { - jsonString += c; - } - } - - std::stringstream html; - html << "\n" - << "\n" - << "\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\n" - << "\t\n" - << "\t\tDocumentation\n" - << "\t\n" - << "\t\n" - << "\t\n" - << "\n"; - - file << html.str(); - - /* - - html << "\n" - << "\t\n" - << "\t\tScript Log\n" - << "\t\n" - << "\n" - << "\n" - << "\t\n\n" - << "\t\n" - << "\t\t\n" - << "\t\t\t\n" - << "\t\t\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\t\t\n" - << "\t\t\t\n" - << "\t\t\t\n" - << "\t\t\n" - << "\t\n" - << "\t\n"; - - - - for (const LuaLibrary& l : _registeredLibraries) { - html << "\t\n"; - - if (l.name.empty()) { - html << "\t\t\n"; - } - else { - html << "\t\t\n"; - } - html << "\t\t\n" - << "\t\"; - - for (const LuaLibrary::Function& f : l.functions) { - html << "\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\n"; - } - - html << "\t\n"; - } - - html << "\t\n" - << "
Script Log
LibraryFunctions
NameArgumentsHelp
openspaceopenspace." << l.name << "
" << f.name << "" << f.argumentText << "" << f.helpText << "
\n" - << ""; - - file << html.str(); -*/ } - else { - throw ghoul::RuntimeError("Undefined type '" + type + "' for Lua documentation"); + json << "]"; + + std::string jsonString = ""; + for (const char& c : json.str()) { + if (c == '\'') { + jsonString += "\\'"; + } + else { + jsonString += c; + } } + + return jsonString; } bool ScriptEngine::writeLog(const std::string& script) { - const std::string KeyScriptLogType = - ConfigurationManager::KeyScriptLog + '.' + ConfigurationManager::PartType; - const std::string KeyScriptLogFile = - ConfigurationManager::KeyScriptLog + '.' + ConfigurationManager::PartFile; - // Check that logging is enabled and initialize if necessary if (!_logFileExists) { // If a ScriptLogFile was specified, generate it now - const bool hasType = OsEng.configurationManager() - .hasKey(KeyScriptLogType); - const bool hasFile = OsEng.configurationManager() - .hasKey(KeyScriptLogFile); - if (hasType && hasFile) { - OsEng.configurationManager() - .getValue(KeyScriptLogType, _logType); - OsEng.configurationManager() - .getValue(KeyScriptLogFile, _logFilename); + const bool hasFile = OsEng.configurationManager().hasKey( + ConfigurationManager::KeyScriptLog + ); + if (hasFile) { + OsEng.configurationManager().getValue( + ConfigurationManager::KeyScriptLog, + _logFilename + ); _logFilename = absPath(_logFilename); _logFileExists = true; @@ -762,32 +575,21 @@ bool ScriptEngine::writeLog(const std::string& script) { return false; } } else { - LDEBUG("No script log specified in 'openspace.cfg.' To log, set '" - << KeyScriptLogType << " and " - << KeyScriptLogFile - << " in configuration table."); _logScripts = false; return false; } } - if (_logType == "text") { - // Simple text output to logfile - std::ofstream file(_logFilename, std::ofstream::app); - if (!file.good()) { - LERROR("Could not open file '" << _logFilename << "' for logging scripts"); - return false; - } - - file << script << std::endl; - file.close(); - } - else { - LERROR("Undefined type '" << _logType << "' for script documentation"); - _logScripts = false; + // Simple text output to logfile + std::ofstream file(_logFilename, std::ofstream::app); + if (!file.good()) { + LERROR("Could not open file '" << _logFilename << "' for logging scripts"); return false; } + file << script << std::endl; + file.close(); + return true; } diff --git a/src/util/factorymanager.cpp b/src/util/factorymanager.cpp index 3c13b6fcc8..118b43ac35 100644 --- a/src/util/factorymanager.cpp +++ b/src/util/factorymanager.cpp @@ -35,10 +35,7 @@ namespace { const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/factories/main.hbs"; const char* FactoryTemplateFilename = "${OPENSPACE_DATA}/web/factories/factory.hbs"; - const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; const char* JsFilename = "${OPENSPACE_DATA}/web/factories/script.js"; - const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; - const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; } // namespace namespace openspace { @@ -52,6 +49,18 @@ FactoryManager::FactoryNotFoundError::FactoryNotFoundError(std::string t) ghoul_assert(!type.empty(), "Type must not be empty"); } +FactoryManager::FactoryManager() + : DocumentationGenerator( + "Factory Documentation", + "factories", + { + { "mainTemplate", MainTemplateFilename }, + { "factoryTemplate", FactoryTemplateFilename } + }, + JsFilename + ) +{} + void FactoryManager::initialize() { ghoul_assert(!_manager, "Factory Manager must not have been initialized"); _manager = new FactoryManager; @@ -79,151 +88,34 @@ void FactoryManager::addFactory(std::unique_ptr fact _factories.push_back({ std::move(factory), std::move(name) }); } -void FactoryManager::writeDocumentation(const std::string& file, const std::string& type) { - if (type == "text") { - std::ofstream f; - f.exceptions(~std::ofstream::goodbit); - f.open(file); +std::string FactoryManager::generateJson() const { + std::stringstream json; - for (const FactoryInfo& factoryInfo : _factories) { - f << factoryInfo.name << '\n'; + json << "["; + for (const FactoryInfo& factoryInfo : _factories) { + json << "{"; + json << "\"name\": \"" << factoryInfo.name << "\","; + json << "\"classes\": ["; - ghoul::TemplateFactoryBase* factory = factoryInfo.factory.get(); - for (const std::string& c : factory->registeredClasses()) { - f << '\t' << c << '\n'; - } - f << "\n\n"; - } - - } - else if (type == "html") { - std::ifstream handlebarsInput(absPath(HandlebarsFilename)); - std::ifstream jsInput(absPath(JsFilename)); - - std::string jsContent; - std::back_insert_iterator jsInserter(jsContent); - - std::copy(std::istreambuf_iterator{handlebarsInput}, std::istreambuf_iterator(), jsInserter); - std::copy(std::istreambuf_iterator{jsInput}, std::istreambuf_iterator(), jsInserter); - - std::ifstream bootstrapInput(absPath(BootstrapFilename)); - std::ifstream cssInput(absPath(CssFilename)); - - std::string cssContent; - std::back_insert_iterator cssInserter(cssContent); - - std::copy(std::istreambuf_iterator{bootstrapInput}, std::istreambuf_iterator(), cssInserter); - std::copy(std::istreambuf_iterator{cssInput}, std::istreambuf_iterator(), cssInserter); - - std::ifstream mainTemplateInput(absPath(MainTemplateFilename)); - std::string mainTemplateContent{ std::istreambuf_iterator{mainTemplateInput}, - std::istreambuf_iterator{} }; - - std::ifstream factoryTemplateInput(absPath(FactoryTemplateFilename)); - std::string factoryTemplateContent{ std::istreambuf_iterator{factoryTemplateInput}, - std::istreambuf_iterator{} }; - - std::stringstream json; - - json << "["; - for (const FactoryInfo& factoryInfo : _factories) { - json << "{"; - json << "\"name\": \"" << factoryInfo.name << "\","; - json << "\"classes\": ["; - - ghoul::TemplateFactoryBase* factory = factoryInfo.factory.get(); - const std::vector& registeredClasses = factory->registeredClasses(); - for (const std::string& c : registeredClasses) { - json << "\"" << c << "\""; - if (&c != ®isteredClasses.back()) { - json << ","; - } - } - - json << "]}"; - if (&factoryInfo != &_factories.back()) { + ghoul::TemplateFactoryBase* factory = factoryInfo.factory.get(); + const std::vector& registeredClasses = factory->registeredClasses(); + for (const std::string& c : registeredClasses) { + json << "\"" << c << "\""; + if (&c != ®isteredClasses.back()) { json << ","; } } - json << "]"; - - // I did not check the output of this for correctness ---abock - std::string jsonText = json.str(); - - std::ofstream f; - f.exceptions(~std::ofstream::goodbit); - f.open(file); - - std::string jsonString = ""; - for (const char& c : json.str()) { - if (c == '\'') { - jsonString += "\\'"; - } else { - jsonString += c; - } + json << "]}"; + if (&factoryInfo != &_factories.back()) { + json << ","; } - - std::stringstream html; - html << "\n" - << "\n" - << "\t\n" - << "\t\t\n" - << "\t\t\n" - << "\t\n" - << "\t\n" - << "\t\tDocumentation\n" - << "\t\n" - << "\t\n" - << "\t\n" - << "\n"; - - f << html.str(); - - /* - html << "\n" - << "\t\n" - << "\t\tFactories\n" - << "\t\n" - << "\n" - << "\n" - << "\t\n\n" - << "\t\n" - << "\t\t\n" - << "\t\t\t\n" - << "\t\t\t\n" - << "\t\t\n" - << "\t\n" - << "\t\n"; - - for (const FactoryInfo& factoryInfo : _factories) { - html << "\t\t\n" - << "\t\t\t\n"; - - ghoul::TemplateFactoryBase* factory = factoryInfo.factory.get(); - for (const std::string& c : factory->registeredClasses()) { - html << "\t\t\t\n"; - } - html << "\t\n"; - - } - - html << "\t\n" - << "
Factories
TypeObject
" << factoryInfo.name << "
" << c << "
\n" - << ";"; - f << html.str(); - */ } + + json << "]"; + + // I did not check the output of this for correctness ---abock + return json.str(); } } // namespace openspace diff --git a/src/util/screenlog.cpp b/src/util/screenlog.cpp index d6fff903f4..94861dacd3 100644 --- a/src/util/screenlog.cpp +++ b/src/util/screenlog.cpp @@ -34,7 +34,9 @@ ScreenLog::ScreenLog(std::chrono::seconds timeToLive, LogLevel logLevel) : _timeToLive(std::move(timeToLive)) , _logLevel(logLevel) {} - + +ScreenLog::~ScreenLog() {} + void ScreenLog::removeExpiredEntries() { auto t = std::chrono::steady_clock::now(); auto ttl = _timeToLive; diff --git a/tests/test_sceneloader.inl b/tests/test_sceneloader.inl index 8291958824..04c3a0fb32 100644 --- a/tests/test_sceneloader.inl +++ b/tests/test_sceneloader.inl @@ -28,6 +28,7 @@ #include #include #include +#include #include #include