diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset index 0d2ab171e8..934d276c5c 100644 --- a/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset @@ -4,6 +4,14 @@ local DataPath = asset.syncedResource({ Identifier = "exoplanets_data", Version = 2 }) + +asset.onInitialize(function () + local p = "Modules.Exoplanets.DataFolder"; + if(openspace.getPropertyValue(p) == "") then + openspace.setPropertyValueSingle(p, DataPath) + end +end) + asset.export("DataPath", DataPath) asset.meta = { diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset index 9efd63b65c..c2898923b3 100644 --- a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset @@ -1,4 +1,5 @@ -asset.require('./../habitable_zones/habitable_zone_textures') +local habitableZoneTextures = + asset.require('./../habitable_zones/habitable_zone_textures').TexturesPath local TexturesPath = asset.syncedResource({ Name = "Exoplanet Textures", @@ -6,6 +7,37 @@ local TexturesPath = asset.syncedResource({ Identifier = "exoplanets_textures", Version = 2 }) + +asset.onInitialize(function () + local starTexture = TexturesPath .. "/sun.jpg" + local noDataTexture = TexturesPath .. "/grid-32.png" + local discTexture = TexturesPath .. "/disc_bw_texture.png" + + local hzTexture = habitableZoneTextures .. "/hot_to_cold_faded.png" + + -- Set the default textures used for the exoplanet system creation + -- (Check if already set, to not override value in config file) + local p = "Modules.Exoplanets.StarTexture"; + if(openspace.getPropertyValue(p) == "") then + openspace.setPropertyValueSingle(p, starTexture) + end + + p = "Modules.Exoplanets.NoDataTexture"; + if(openspace.getPropertyValue(p) == "") then + openspace.setPropertyValueSingle(p, noDataTexture) + end + + p = "Modules.Exoplanets.OrbitDiscTexture"; + if(openspace.getPropertyValue(p) == "") then + openspace.setPropertyValueSingle(p, discTexture) + end + + p = "Modules.Exoplanets.HabitableZoneTexture"; + if(openspace.getPropertyValue(p) == "") then + openspace.setPropertyValueSingle(p, hzTexture) + end +end) + asset.export("TexturesPath", TexturesPath) asset.meta = { diff --git a/modules/exoplanets/exoplanetsmodule.cpp b/modules/exoplanets/exoplanetsmodule.cpp index b962f758e1..18904a32cf 100644 --- a/modules/exoplanets/exoplanetsmodule.cpp +++ b/modules/exoplanets/exoplanetsmodule.cpp @@ -38,11 +38,166 @@ #include "exoplanetsmodule_lua.inl" +namespace { + constexpr const openspace::properties::Property::PropertyInfo DataFolderInfo = { + "DataFolder", + "Data Folder", + "The path to the folder containing the exoplanets data and lookup table" + }; + + constexpr const openspace::properties::Property::PropertyInfo StarTextureInfo = { + "StarTexture", + "Star Texture", + "The path to a grayscale image that is used for the host star surfaces" + }; + + constexpr const openspace::properties::Property::PropertyInfo NoDataTextureInfo = { + "NoDataTexture", + "No Data Star Texture", + "A path to a texture that is used to represent that there is missing data about " + "the star. For example no color information" + }; + + constexpr const openspace::properties::Property::PropertyInfo OrbitDiscTextureInfo = + { + "OrbitDiscTexture", + "Orbit Disc Texture", + "A path to a 1-dimensional image used as a transfer function for the " + "exoplanets' orbit uncertainty disc" + }; + + constexpr const openspace::properties::Property::PropertyInfo + HabitableZoneTextureInfo = + { + "HabitableZoneTexture", + "Habitable Zone Texture", + "A path to a 1-dimensional image used as a transfer function for the " + "habitable zone disc" + }; + + constexpr const openspace::properties::Property::PropertyInfo + ShowComparisonCircleInfo = + { + "ShowComparisonCircle", + "Show Comparison Circle", + "If true, the 1 AU size comparison circle is enabled per default when an " + "exoplanet system is created" + }; + + constexpr const openspace::properties::Property::PropertyInfo + ShowHabitableZoneInfo = + { + "ShowHabitableZone", + "Show Habitable Zone", + "If true, the habitable zone disc is enabled per default when an " + "exoplanet system is created" + }; + + constexpr const openspace::properties::Property::PropertyInfo UseOptimisticZoneInfo = + { + "UseOptimisticZone", + "Use Optimistic Zone Boundaries", + "If true, the habitable zone is computed with optimistic boundaries per default " + "when an exoplanet system is created" + }; + + constexpr const char ExoplanetsDataFileName[] = "exoplanets_data.bin"; + constexpr const char LookupTableFileName[] = "lookup.txt"; + + struct [[codegen::Dictionary(ExoplanetsModule)]] Parameters { + // [[codegen::verbatim(DataFolderInfo.description)]] + std::optional dataFolder; + + // [[codegen::verbatim(StarTextureInfo.description)]] + std::optional starTexture; + + // [[codegen::verbatim(NoDataTextureInfo.description)]] + std::optional noDataTexture; + + // [[codegen::verbatim(OrbitDiscTextureInfo.description)]] + std::optional orbitDiscTexture; + + // [[codegen::verbatim(HabitableZoneTextureInfo.description)]] + std::optional habitableZoneTexture; + + // [[codegen::verbatim(ShowComparisonCircleInfo.description)]] + std::optional showComparisonCircle; + + // [[codegen::verbatim(ShowHabitableZoneInfo.description)]] + std::optional showHabitableZone; + + // [[codegen::verbatim(UseOptimisticZoneInfo.description)]] + std::optional useOptimisticZone; + }; +#include "exoplanetsmodule_codegen.cpp" +} // namespace + namespace openspace { using namespace exoplanets; -ExoplanetsModule::ExoplanetsModule() : OpenSpaceModule(Name) {} +ExoplanetsModule::ExoplanetsModule() + : OpenSpaceModule(Name) + , _exoplanetsDataFolder(DataFolderInfo) + , _starTexturePath(StarTextureInfo) + , _noDataTexturePath(NoDataTextureInfo) + , _orbitDiscTexturePath(OrbitDiscTextureInfo) + , _habitableZoneTexturePath(HabitableZoneTextureInfo) + , _showComparisonCircle(ShowComparisonCircleInfo, false) + , _showHabitableZone(ShowHabitableZoneInfo, true) + , _useOptimisticZone(UseOptimisticZoneInfo, true) +{ + _exoplanetsDataFolder.setReadOnly(true); + + addProperty(_exoplanetsDataFolder); + addProperty(_starTexturePath); + addProperty(_noDataTexturePath); + addProperty(_orbitDiscTexturePath); + addProperty(_habitableZoneTexturePath); + addProperty(_showComparisonCircle); + addProperty(_showHabitableZone); + addProperty(_useOptimisticZone); +} + +std::string ExoplanetsModule::exoplanetsDataPath() const { + return absPath( + fmt::format("{}/{}", _exoplanetsDataFolder, ExoplanetsDataFileName) + ); +}; + +std::string ExoplanetsModule::lookUpTablePath() const { + return absPath( + fmt::format("{}/{}", _exoplanetsDataFolder, LookupTableFileName) + ); +}; + +std::string ExoplanetsModule::starTexturePath() const { + return _starTexturePath; +} + +std::string ExoplanetsModule::noDataTexturePath() const { + return _noDataTexturePath; +} + +std::string ExoplanetsModule::orbitDiscTexturePath() const { + return _orbitDiscTexturePath; +} + +std::string ExoplanetsModule::habitableZoneTexturePath() const { + return _habitableZoneTexturePath; +} + +bool ExoplanetsModule::showComparisonCircle() const { + return _showComparisonCircle; +} + +bool ExoplanetsModule::showHabitableZone() const { + return _showHabitableZone; +} + +bool ExoplanetsModule::useOptimisticZone() const { + return _useOptimisticZone; +} scripting::LuaLibrary ExoplanetsModule::luaLibrary() const { scripting::LuaLibrary res; @@ -83,7 +238,18 @@ scripting::LuaLibrary ExoplanetsModule::luaLibrary() const { return res; } -void ExoplanetsModule::internalInitialize(const ghoul::Dictionary&) { +void ExoplanetsModule::internalInitialize(const ghoul::Dictionary& dict) { + const Parameters p = codegen::bake(dict); + _exoplanetsDataFolder = p.dataFolder.value_or(_exoplanetsDataFolder); + _starTexturePath = p.starTexture.value_or(_starTexturePath); + _noDataTexturePath = p.noDataTexture.value_or(_noDataTexturePath); + _orbitDiscTexturePath = p.orbitDiscTexture.value_or(_orbitDiscTexturePath); + _habitableZoneTexturePath = p.habitableZoneTexture.value_or(_habitableZoneTexturePath); + + _showComparisonCircle = p.showComparisonCircle.value_or(_showComparisonCircle); + _showHabitableZone = p.showHabitableZone.value_or(_showHabitableZone); + _useOptimisticZone = p.useOptimisticZone.value_or(_useOptimisticZone); + auto fTask = FactoryManager::ref().factory(); auto fRenderable = FactoryManager::ref().factory(); ghoul_assert(fTask, "No task factory existed"); diff --git a/modules/exoplanets/exoplanetsmodule.h b/modules/exoplanets/exoplanetsmodule.h index 76058f99b5..13eb62d492 100644 --- a/modules/exoplanets/exoplanetsmodule.h +++ b/modules/exoplanets/exoplanetsmodule.h @@ -28,6 +28,8 @@ #include #include +#include +#include namespace openspace { @@ -38,11 +40,30 @@ public: ExoplanetsModule(); virtual ~ExoplanetsModule() = default; + std::string exoplanetsDataPath() const; + std::string lookUpTablePath() const; + std::string starTexturePath() const; + std::string noDataTexturePath() const; + std::string orbitDiscTexturePath() const; + std::string habitableZoneTexturePath() const; + bool showComparisonCircle() const; + bool showHabitableZone() const; + bool useOptimisticZone() const; + scripting::LuaLibrary luaLibrary() const override; std::vector documentations() const override; protected: - void internalInitialize(const ghoul::Dictionary&) override; + void internalInitialize(const ghoul::Dictionary& dict) override; + + properties::StringProperty _exoplanetsDataFolder; + properties::StringProperty _starTexturePath; + properties::StringProperty _noDataTexturePath; + properties::StringProperty _orbitDiscTexturePath; + properties::StringProperty _habitableZoneTexturePath; + properties::BoolProperty _showComparisonCircle; + properties::BoolProperty _showHabitableZone; + properties::BoolProperty _useOptimisticZone; }; } // namespace openspace diff --git a/modules/exoplanets/exoplanetsmodule_lua.inl b/modules/exoplanets/exoplanetsmodule_lua.inl index a92408f154..bedbb0ca23 100644 --- a/modules/exoplanets/exoplanetsmodule_lua.inl +++ b/modules/exoplanets/exoplanetsmodule_lua.inl @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -40,47 +41,42 @@ namespace { constexpr const char _loggerCat[] = "ExoplanetsModule"; + + constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/"; + + // Lua cannot handle backslashes, so replace these with forward slashes + std::string formatPathToLua(const std::string& path) { + std::string resPath = path; + std::replace(resPath.begin(), resPath.end(), '\\', '/'); + return resPath; + } } // namespace namespace openspace::exoplanets::luascriptfunctions { -constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/"; - -constexpr const char LookUpTablePath[] = "${SYNC}/http/exoplanets_data/2/lookup.txt"; -constexpr const char ExoplanetsDataPath[] = - "${SYNC}/http/exoplanets_data/2/exoplanets_data.bin"; - -constexpr const char StarTextureFile[] = "${SYNC}/http/exoplanets_textures/2/sun.jpg"; -constexpr const char NoDataTextureFile[] = - "${SYNC}/http/exoplanets_textures/2/grid-32.png"; -constexpr const char DiscTextureFile[] = - "${SYNC}/http/exoplanets_textures/2/disc_bw_texture.png"; -constexpr const char HabitableZoneTextureFile[] = - "${SYNC}/http/habitable_zone_textures/1/hot_to_cold_faded.png"; - constexpr const float AU = static_cast(distanceconstants::AstronomicalUnit); constexpr const float SolarRadius = static_cast(distanceconstants::SolarRadius); constexpr const float JupiterRadius = static_cast(distanceconstants::JupiterRadius); ExoplanetSystem findExoplanetSystemInData(std::string_view starName) { - ExoplanetSystem system; + const ExoplanetsModule* module = global::moduleEngine->module(); - std::ifstream data(absPath(ExoplanetsDataPath), std::ios::in | std::ios::binary); + const std::string binPath = module->exoplanetsDataPath(); + std::ifstream data(absPath(binPath), std::ios::in | std::ios::binary); if (!data.good()) { - LERROR(fmt::format( - "Failed to open exoplanets data file: '{}'", absPath(ExoplanetsDataPath) - )); + LERROR(fmt::format("Failed to open exoplanets data file: '{}'", binPath)); return ExoplanetSystem(); } - std::ifstream lut(absPath(LookUpTablePath)); + const std::string lutPath = module->lookUpTablePath(); + std::ifstream lut(absPath(lutPath)); if (!lut.good()) { - LERROR(fmt::format( - "Failed to open exoplanets look-up table: '{}'", absPath(LookUpTablePath) - )); + LERROR(fmt::format("Failed to open exoplanets look-up table: '{}'", lutPath)); return ExoplanetSystem(); } + ExoplanetSystem system; + // 1. search lut for the starname and return the corresponding location // 2. go to that location in the data file // 3. read sizeof(exoplanet) bytes into an exoplanet object. @@ -167,6 +163,8 @@ void createExoplanetSystem(const std::string& starName) { return; } + const ExoplanetsModule* module = global::moduleEngine->module(); + const glm::dvec3 starPos = static_cast(starPosInParsec) * distanceconstants::Parsec; const glm::dmat3 exoplanetSystemRotation = computeSystemRotation(starPos); @@ -182,6 +180,7 @@ void createExoplanetSystem(const std::string& starName) { if (!std::isnan(bv)) { const glm::vec3 color = starColor(bv); + const std::string starTexture = module->starTexturePath(); colorLayers = "{" "Identifier = 'StarColor'," @@ -192,18 +191,17 @@ void createExoplanetSystem(const std::string& starName) { "}," "{" "Identifier = 'StarTexture'," - "FilePath = " + - fmt::format("openspace.absPath('{}')", StarTextureFile) + "," + "FilePath = openspace.absPath('" + formatPathToLua(starTexture) + "')," "BlendMode = 'Color'," "Enabled = true" "}"; } else { + const std::string noDataTexture = module->noDataTexturePath(); colorLayers = "{" "Identifier = 'NoDataStarTexture'," - "FilePath = " + - fmt::format("openspace.absPath('{}')", NoDataTextureFile) + "," + "FilePath = openspace.absPath('" + formatPathToLua(noDataTexture) + "')," "BlendMode = 'Color'," "Enabled = true" "}"; @@ -313,7 +311,6 @@ void createExoplanetSystem(const std::string& starName) { const std::string planetNode = "{" "Identifier = '" + planetIdentifier + "'," "Parent = '" + starIdentifier + "'," - "Enabled = true," "Renderable = {" "Type = 'RenderableGlobe'," "Enabled = " + enabled + "," @@ -342,7 +339,6 @@ void createExoplanetSystem(const std::string& starName) { const std::string planetTrailNode = "{" "Identifier = '" + planetIdentifier + "_Trail'," "Parent = '" + starIdentifier + "'," - "Enabled = true," "Renderable = {" "Type = 'RenderableTrailOrbit'," "Period = " + std::to_string(planet.per) + "," @@ -376,13 +372,16 @@ void createExoplanetSystem(const std::string& starName) { const float lowerOffset = static_cast(planet.aLower / planet.a); const float upperOffset = static_cast(planet.aUpper / planet.a); + const std::string discTexture = module->orbitDiscTexturePath(); + const std::string discNode = "{" "Identifier = '" + planetIdentifier + "_Disc'," "Parent = '" + starIdentifier + "'," - "Enabled = true," "Renderable = {" "Type = 'RenderableOrbitDisc'," - "Texture = openspace.absPath('" + DiscTextureFile + "')," + "Texture = openspace.absPath('" + + formatPathToLua(discTexture) + + "')," "Size = " + std::to_string(semiMajorAxisInMeter) + "," "Eccentricity = " + std::to_string(planet.ecc) + "," "Offset = { " + @@ -410,7 +409,6 @@ void createExoplanetSystem(const std::string& starName) { } } - float meanInclination = 0.f; for (const ExoplanetDataEntry& p : system.planetsData) { meanInclination += p.i; @@ -419,14 +417,16 @@ void createExoplanetSystem(const std::string& starName) { const glm::dmat4 rotation = computeOrbitPlaneRotationMatrix(meanInclination); const glm::dmat3 meanOrbitPlaneRotationMatrix = static_cast(rotation); - // 1 AU Size Comparison Ring - const std::string ringIdentifier = starIdentifier + "_1AU_Ring"; - const std::string ring = "{" - "Identifier = '" + starIdentifier + "_1AU_Ring'," + bool isCircleEnabled = module->showComparisonCircle(); + const std::string isCircleEnabledString = isCircleEnabled ? "true" : "false"; + + // 1 AU Size Comparison Circle + const std::string circle = "{" + "Identifier = '" + starIdentifier + "_1AU_Circle'," "Parent = '" + starIdentifier + "'," - "Enabled = false," "Renderable = {" "Type = 'RenderableRadialGrid'," + "Enabled = " + isCircleEnabledString + "," "OuterRadius = " + std::to_string(AU) + "," "CircleSegments = 64," "LineWidth = 2.0," @@ -438,13 +438,13 @@ void createExoplanetSystem(const std::string& starName) { "}" "}," "GUI = {" - "Name = '1 AU Size Comparison Ring'," + "Name = '1 AU Size Comparison Circle'," "Path = '" + guiPath + "'" "}" "}"; openspace::global::scriptEngine->queueScript( - "openspace.addSceneGraphNode(" + ring + ");", + "openspace.addSceneGraphNode(" + circle + ");", scripting::ScriptEngine::RemoteScripting::Yes ); @@ -463,16 +463,24 @@ void createExoplanetSystem(const std::string& starName) { "the greenhouse effect would not be able to maintain surface temperature " "above freezing anywhere on the planet."; + const std::string hzTexture = module->habitableZoneTexturePath(); + + bool isHzEnabled = module->showHabitableZone(); + const std::string isHzEnabledString = isHzEnabled ? "true" : "false"; + + bool useOptimistic = module->useOptimisticZone(); + const std::string useOptimisticString = useOptimistic ? "true" : "false"; + const std::string zoneDiscNode = "{" "Identifier = '" + starIdentifier + "_HZ_Disc'," "Parent = '" + starIdentifier + "'," - "Enabled = true," "Renderable = {" "Type = 'RenderableHabitableZone'," - "Texture = openspace.absPath('" + HabitableZoneTextureFile + "')," + "Enabled = " + isHzEnabledString + "," + "Texture = openspace.absPath('" + formatPathToLua(hzTexture) + "')," "Luminosity = " + std::to_string(system.starData.luminosity) + "," "EffectiveTemperature = " + std::to_string(system.starData.teff) + "," - "Optimistic = true," + "Optimistic = " + useOptimisticString + "," "Opacity = 0.07" "}," "Transform = {" @@ -545,21 +553,25 @@ int removeExoplanetSystem(lua_State* L) { } std::vector hostStarsWithSufficientData() { + const ExoplanetsModule* module = global::moduleEngine->module(); + + const std::string lutPath = module->lookUpTablePath(); + std::ifstream lookupTableFile(absPath(lutPath)); + if (!lookupTableFile.good()) { + LERROR(fmt::format("Failed to open lookup table file '{}'", lutPath)); + return {}; + } + + const std::string binPath = module->exoplanetsDataPath(); + std::ifstream data(absPath(binPath), std::ios::in | std::ios::binary); + if (!data.good()) { + LERROR(fmt::format("Failed to open data file '{}'", binPath)); + return {}; + } + std::vector names; std::string line; - std::ifstream lookupTableFile(absPath(LookUpTablePath)); - if (!lookupTableFile.good()) { - LERROR(fmt::format("Failed to open lookup table file '{}'", LookUpTablePath)); - return {}; - } - - std::ifstream data(absPath(ExoplanetsDataPath), std::ios::in | std::ios::binary); - if (!data.good()) { - LERROR(fmt::format("Failed to open data file '{}'", ExoplanetsDataPath)); - return {}; - } - // Read number of lines int nExoplanets = 0; while (std::getline(lookupTableFile, line)) { diff --git a/openspace.cfg b/openspace.cfg index 2eba4ff450..a37a89ff7d 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -167,6 +167,11 @@ ModuleConfigurations = { }, Space = { ShowExceptions = false + }, + Exoplanets = { + ShowComparisonCircle = false, + ShowHabitableZone = true, + UseOptimisticZone = true } }