diff --git a/CMakeLists.txt b/CMakeLists.txt index ac3c0cf925..dfe4464edc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,7 +148,7 @@ if (APPLE) find_library(COCOA_LIBRARY Carbon) find_library(APP_SERVICES_LIBRARY ApplicationServices) mark_as_advanced(CARBON_LIBRARY COCOA_LIBRARY APP_SERVICES_LIBRARY) - target_link_libraries(openspace-core ${CARBON_LIBRARY} ${COREFOUNDATION_LIBRARY} + target_link_libraries(openspace-core PUBLIC ${CARBON_LIBRARY} ${COREFOUNDATION_LIBRARY} ${COCOA_LIBRARY} ${APP_SERVICES_LIBRARY}) end_dependency() endif () diff --git a/data/assets/base.asset b/data/assets/base.asset index 86bdf3cbd6..f0cb420c35 100644 --- a/data/assets/base.asset +++ b/data/assets/base.asset @@ -23,6 +23,8 @@ asset.require('scene/milkyway/milkyway/volume') asset.require('scene/milkyway/constellations/constellation_art') asset.require('scene/milkyway/constellations/constellation_keybinds') +assetHelper.requireAll(asset, 'scene/milkyway/exoplanets') + assetHelper.requireAll(asset, 'scene/digitaluniverse') -- Load default key bindings applicable to most scenes diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset new file mode 100644 index 0000000000..b49f091844 --- /dev/null +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset @@ -0,0 +1,7 @@ +local DataPath = asset.syncedResource({ + Name = "Exoplanet Data Files", + Type = "HttpSynchronization", + Identifier = "exoplanets_data", + Version = 1 +}) +asset.export("DataPath", DataPath) diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset new file mode 100644 index 0000000000..287b29d61e --- /dev/null +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset @@ -0,0 +1,7 @@ +local TexturesPath = asset.syncedResource({ + Name = "Exoplanet Textures", + Type = "HttpSynchronization", + Identifier = "exoplanets_textures", + Version = 1 +}) +asset.export("TexturesPath", TexturesPath) diff --git a/data/assets/scene/milkyway/objects/orionnebula/cluster.asset b/data/assets/scene/milkyway/objects/orionnebula/cluster.asset new file mode 100644 index 0000000000..843ca22825 --- /dev/null +++ b/data/assets/scene/milkyway/objects/orionnebula/cluster.asset @@ -0,0 +1,51 @@ +--orionnebula/cluster.asset +local assetHelper = asset.require('util/asset_helper') +local transforms = asset.require("./transforms") + +local sync = asset.syncedResource({ + Name = "Orion Nebula Star Cluster", + Type = "HttpSynchronization", + Identifier = "orion_nebula_star_cluster", + Version = 1 +}) + +local OrionClusterStars = { + Identifier = "OrionClusterStars", + Parent = transforms.NebulaPosition.Identifier, + Renderable = { + Type = "RenderableStars", + File = sync .. "/oricluster.speck", + Texture = sync .. "/halo.png", + Texture = sync .. "/colorbv.cmap", + MagnitudeExponent = 5.02, + SizeComposition = "Distance Modulus", + RenderMethod = "Texture Based" + }, + GUI = { + Name = "Orion Nebula Star Cluster", + Path = "/Milky Way/Stars" + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { OrionClusterStars }) + +asset.meta = { + Name = "Orion Nebula Star Cluster", + Version = "1.0", + Description = [[ In order to have an accurate depiction of the Orion nebula, we need +to include the star cluster that was birthed from it. We turned to a study of the +cluster's stellar population by Lynne Hillenbrand, who was working at the University of +California, Berkeley at the time. The catalog from her paper contains more than 1500 +stars, about half the stars in the actual cluster. The cluster is very crowded, with a +peak density of 10000 stars per cubic parsec over a wide range of masses from a tenth the +sun's mass up to 50 times its mass. We were presented with one problem: there are no +distances. For the stellar distances, we needed to deduce them by statistical methods. +Knowing the size of the cluster and approximating the shape to be roughly spherical, we +placed each star along a line of sight through this imaginary sphere centered on the +cluster. In this sense, these data are observed data and the view from Earth is accurate. +But the distance of each star has been derived from this educated-guess approach for the +cluster distribution. ]], + Author = "AMNH Digital Universe", + URL = "https://www.amnh.org/research/hayden-planetarium/digital-universe", + License = "custom" +} diff --git a/data/assets/scene/milkyway/objects/orionnebula/nebula.asset b/data/assets/scene/milkyway/objects/orionnebula/nebula.asset new file mode 100644 index 0000000000..24e8c2eaa3 --- /dev/null +++ b/data/assets/scene/milkyway/objects/orionnebula/nebula.asset @@ -0,0 +1,157 @@ +local assetHelper = asset.require('util/asset_helper') +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +local transforms = asset.require('./transforms') + +local center = sunTransforms.SolarSystemBarycenter.Identifier; +local LIGHTS = assetHelper.getDefaultLightSources(center); + +local sync = asset.syncedResource({ + Name = "Orion Nebula Model", + Type = "HttpSynchronization", + Identifier = "orion_nebula_model", + Version = 1 +}) + +local NebulaHolder = { + Identifier = "OrionNebulaHolder", + Parent = transforms.NebulaPosition.Identifier, + Transform = { + Scale = { + Type = "StaticScale", + Scale = 35999998699110400.000000 + }, + Rotation = { + Type = "FixedRotation", + Attached = "OrionNebulaHolder", + XAxis = {1.000000,1.000000,0.510000}, + XAxisOrthogonal = true, + YAxis = "Sun", + YAxisInverted = false + } + }, + GUI = { + Name = "Orion Nebula", + Path = "/Milky Way/Objects", + } +} + +local OrionNebulaModel = { + Identifier = "OrionNebulaModel", + Parent = NebulaHolder.Identifier, + Transform = { + Scale = { + Type = "StaticScale", + Scale = 0.67500000 + } + }, + Renderable = { + Type = "RenderableModel", + Geometry = {{ + Type = "MultiModelGeometry", + GeometryFile = sync .. "/orion_nebula.obj", + ColorTexture = sync .. "/heic0601a_masked.png" + }}, + Opacity = 1.0, + DisableFaceCulling = false, + SpecularIntensity = 0.0, + AmbientIntensity = 0.45, + DiffuseIntensity = 0.0, + RotationVector = { 0.000000, 22.300000, 0.000000 }, + LightSources = LIGHTS; + }, + GUI = { + Name = "Orion Nebula Model", + Path = "/Milky Way/Objects", + Hidden = true + } +} + +local OrionNebulaShocksModel = { + Identifier = "OrionNebulaShocksModel", + Parent = NebulaHolder.Identifier, + Transform = { + Scale = { + Type = "StaticScale", + Scale = 0.67500000 + } + }, + Renderable = { + Type = "RenderableModel", + Geometry = {{ + Type = "MultiModelGeometry", + GeometryFile = sync .. "/orishocks.obj", + ColorTexture = "${DATA}/colors/pink.png" + }}, + Opacity = 1.0, + DisableFaceCulling = false, + SpecularIntensity = 0.0, + AmbientIntensity = 0.19, + DiffuseIntensity = 0.4, + RotationVector = { 0.000000, 22.300000, 0.000000 }, + LightSources = LIGHTS; + }, + GUI = { + Name = "Orion Nebula Shocks", + Path = "/Milky Way/Objects", + Hidden = false + } +} + +local OrionNebulaProplydsModel = { + Identifier = "OrionNebulaProplydsModel", + Parent = NebulaHolder.Identifier, + Transform = { + Scale = { + Type = "StaticScale", + Scale = 0.67500000 + } + }, + Renderable = { + Type = "RenderableModel", + Geometry = {{ + Type = "MultiModelGeometry", + GeometryFile = sync .. "/proplyds.obj", + ColorTexture = "${DATA}/colors/pink.png" + }}, + Opacity = 1.0, + DisableFaceCulling = false, + SpecularIntensity = 0.0, + AmbientIntensity = 1.0, + DiffuseIntensity = 1.0, + RotationVector = { 0.000000, 22.300000, 0.000000 }, + LightSources = LIGHTS; + }, + GUI = { + Name = "Orion Nebula Proplyds", + Path = "/Milky Way/Objects", + Hidden = false + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { + NebulaHolder, + OrionNebulaModel, + OrionNebulaShocksModel, + OrionNebulaProplydsModel +}) + +asset.meta = { + Name = "Orion Nebula Model", + Version = "1.0", + Description = [[ In the Digital Universe model of the Orion Nebula, we depict the +ionization front effectively as a terrain, with a flat Hubble image of the nebula mapped +on the undulating surface. In reality, the ionization front has a slight thickness to +it - about a third of a light year - but is quite thin compared to the overall size of +the nebula, which stretches about ten light years from side to side.

Close into +the center, we see small teardrop-shaped structures with their narrow ends pointing away +from the bright star: these are protoplanetary disks, or proplyds, of dense gas and dust +surrounding young stars. The larger formations that one sees farther away from the center +of the nebula take on a cup-like shape, with the narrow end pointing away from the +nebulas center. These enormous structures are bow shocks that delineate the region where +highspeed winds from the central star slow from supersonic to subsonic speeds. You can +think of an HII region as a sort of tremendous explosion, taking place over millennia, +and the bow shocks are part of the outward rush of material. ]], + Author = "AMNH Digital Universe", + URL = "https://www.amnh.org/research/hayden-planetarium/digital-universe", + License = "custom" +} diff --git a/data/assets/scene/milkyway/objects/orionnebula/orionnebula.asset b/data/assets/scene/milkyway/objects/orionnebula/orionnebula.asset new file mode 100644 index 0000000000..34df0dacc9 --- /dev/null +++ b/data/assets/scene/milkyway/objects/orionnebula/orionnebula.asset @@ -0,0 +1,2 @@ +asset.require('./cluster') +asset.require('./nebula') diff --git a/data/assets/scene/milkyway/objects/orionnebula/transforms.asset b/data/assets/scene/milkyway/objects/orionnebula/transforms.asset new file mode 100644 index 0000000000..15bc241234 --- /dev/null +++ b/data/assets/scene/milkyway/objects/orionnebula/transforms.asset @@ -0,0 +1,26 @@ +local assetHelper = asset.require('util/asset_helper') +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') + +local PARSEC_CONSTANT = 3.0856776E16; + +local NebulaPosition = { + Identifier = "NebulaPosition", + Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Transform = { + Translation = { + Type = "StaticTranslation", + Position = { + -329.915 * PARSEC_CONSTANT, + -183.153 * PARSEC_CONSTANT, + -132.706 * PARSEC_CONSTANT + } + }, + }, + GUI = { + Name = "Orion Nebula Position", + Path = "/Milky Way/Objects", + Hidden = true + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { NebulaPosition }) diff --git a/data/assets/scene/solarsystem/planets/earth/default_layers.asset b/data/assets/scene/solarsystem/planets/earth/default_layers.asset index d1ad5753a3..21410493d5 100644 --- a/data/assets/scene/solarsystem/planets/earth/default_layers.asset +++ b/data/assets/scene/solarsystem/planets/earth/default_layers.asset @@ -7,7 +7,7 @@ local waterMasksPath = "./layers/watermasks" -- Color layers local colorLayer = asset.require(colorLayersPath .. "/esri_viirs_combo") asset.require(colorLayersPath .. "/esri_world_imagery") -asset.require(colorLayersPath .. "/esri_imagery_world_2d") +asset.require(colorLayersPath .. "/esri_imagery_world_2D") asset.require(colorLayersPath .. "/viirs_snpp_temporal") asset.require(colorLayersPath .. "/aqua_modis_temporal") asset.require(colorLayersPath .. "/terra_modis_temporal") diff --git a/data/colors/pink.png b/data/colors/pink.png new file mode 100644 index 0000000000..bcf3e40111 Binary files /dev/null and b/data/colors/pink.png differ diff --git a/data/tasks/exoplanets/csvtobin.task b/data/tasks/exoplanets/csvtobin.task new file mode 100644 index 0000000000..1ae7a44c6b --- /dev/null +++ b/data/tasks/exoplanets/csvtobin.task @@ -0,0 +1,12 @@ +local dataFolder = "${BASE}/modules/exoplanets" +return { + { + Type = "ExoplanetsCsvToBinTask", + + InputCSV = dataFolder .. "/exoplanets.csv", + InputSPECK = "${SYNC}/http/digitaluniverse_exoplanets_speck/1/expl.speck", + TeffToBvFile = "${SYNC}/http/exoplanets_data/1/teff_bv.txt", + OutputBIN = dataFolder .. "/exoplanets_data.bin", + OutputLUT = dataFolder .. "/lookup.txt" + } +} diff --git a/data/web/documentation/scenelicense.hbs b/data/web/documentation/scenelicense.hbs index ee9bce0479..b4b0828d8d 100644 --- a/data/web/documentation/scenelicense.hbs +++ b/data/web/documentation/scenelicense.hbs @@ -4,7 +4,7 @@

Asset - {{name}}

-

{{description}}

+

{{{description}}}

Version - {{version}}

Author - {{author}}

Associated URL - {{url}}

diff --git a/data/web/documentation/script.js b/data/web/documentation/script.js index de1f726e0a..ba8e45eb4b 100644 --- a/data/web/documentation/script.js +++ b/data/web/documentation/script.js @@ -127,6 +127,15 @@ window.onload = function () { } } + if (documentation[i].identifier == "sceneLicense") { + for (var j = 0; j < documentation[i].data.length; j++) { + var escaped = documentation[i].data[j].description.replace( + /\\n/g, "" + ); + documentation[i].data[j].description = escaped; + } + } + } currentDocumentation = documentation[3]; diff --git a/ext/ghoul b/ext/ghoul index 44420f45cb..f568acc5fe 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 44420f45cba1738847046b70b29b25e28c3284ef +Subproject commit f568acc5fee29a5b0c654f183baddcb7a061e7a6 diff --git a/include/openspace/util/distanceconstants.h b/include/openspace/util/distanceconstants.h index 8bb599cc04..e488cce1f9 100644 --- a/include/openspace/util/distanceconstants.h +++ b/include/openspace/util/distanceconstants.h @@ -27,6 +27,8 @@ namespace openspace::distanceconstants { constexpr double EarthRadius = 6371; + constexpr double JupiterRadius = 7.1492E7; + constexpr double SolarRadius = 6.95700E8; constexpr double LightYear = 9.4607304725808E15; constexpr double LightMonth = LightYear / 12; constexpr double LightDay = LightYear / 365; diff --git a/include/openspace/util/memorymanager.h b/include/openspace/util/memorymanager.h index 6d202f15ee..7fa289263c 100644 --- a/include/openspace/util/memorymanager.h +++ b/include/openspace/util/memorymanager.h @@ -26,7 +26,6 @@ #define __OPENSPACE_CORE___MEMORYMANAGER___H__ #include -#include namespace openspace { diff --git a/modules/base/rendering/renderablelabels.cpp b/modules/base/rendering/renderablelabels.cpp index 9ad0172359..c435137a97 100644 --- a/modules/base/rendering/renderablelabels.cpp +++ b/modules/base/rendering/renderablelabels.cpp @@ -206,12 +206,6 @@ documentation::Documentation RenderableLabels::Documentation() { Optional::Yes, LabelColorInfo.description, }, - { - LabelColorInfo.identifier, - new DoubleVector4Verifier, - Optional::Yes, - LabelColorInfo.description, - }, { LabelTextInfo.identifier, new StringVerifier, @@ -397,7 +391,7 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) _labelColor.setViewOption(properties::Property::ViewOptions::Color); if (dictionary.hasKey(LabelColorInfo.identifier)) { - _labelColor = dictionary.value(LabelColorInfo.identifier); + _labelColor = dictionary.value(LabelColorInfo.identifier); } addProperty(_labelColor); diff --git a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp index dd6095e862..54a9dc6649 100644 --- a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp +++ b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp @@ -850,7 +850,7 @@ void RenderableBillboardsCloud::renderBillboards(const RenderData& data, if (_hasPolygon) { glBindTexture(GL_TEXTURE_2D, _pTexture); } - else { + else if (_spriteTexture) { _spriteTexture->bind(); } _program->setUniform(_uniformCache.spriteTexture, textureUnit); @@ -867,7 +867,6 @@ void RenderableBillboardsCloud::renderBillboards(const RenderData& data, global::renderEngine.openglStateCache().resetBlendState(); global::renderEngine.openglStateCache().resetDepthState(); - } void RenderableBillboardsCloud::renderLabels(const RenderData& data, @@ -902,7 +901,7 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data, } glm::vec4 textColor = glm::vec4( - glm::vec3(_textColor), + glm::vec3(_textColor), _textOpacity * fadeInVariable ); diff --git a/modules/exoplanets/CMakeLists.txt b/modules/exoplanets/CMakeLists.txt new file mode 100644 index 0000000000..3a1902cb9f --- /dev/null +++ b/modules/exoplanets/CMakeLists.txt @@ -0,0 +1,55 @@ +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2020 # +# # +# 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(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/exoplanetshelper.h + ${CMAKE_CURRENT_SOURCE_DIR}/exoplanetsmodule.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableorbitdisc.h + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/exoplanetscsvtobintask.h +) +source_group("Header Files" FILES ${HEADER_FILES}) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/exoplanetshelper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/exoplanetsmodule.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/exoplanetsmodule_lua.inl + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableorbitdisc.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/exoplanetscsvtobintask.cpp +) +source_group("Source Files" FILES ${SOURCE_FILES}) + +set(SHADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/orbitdisc_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/orbitdisc_vs.glsl +) +source_group("Shader Files" FILES ${SHADER_FILES}) + +create_new_module( + "Exoplanets" + exoplanets_module + STATIC + ${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES} +) diff --git a/modules/exoplanets/exoplanetshelper.cpp b/modules/exoplanets/exoplanetshelper.cpp new file mode 100644 index 0000000000..62adafc80d --- /dev/null +++ b/modules/exoplanets/exoplanetshelper.cpp @@ -0,0 +1,127 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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 + +namespace openspace::exoplanets { + +std::string_view speckStarName(std::string_view csvName) { + if (csvName == "HD 1237") { return "GJ 3021"; } + if (csvName == "MOA-2009-BLG-387L") { return "MOA 2009-BLG-387L"; } + if (csvName == "HD 126614 A") { return "HD 126614"; } + if (csvName == "epsilon Ret") { return "HD 27442"; } + if (csvName == "PH-1") { return "PH1"; } + if (csvName == "gamma Leo A") { return "gam 1 Leo"; } + if (csvName == "OGLE-2007-BLG-368L") { return "OGLE 2007-BLG-368L"; } + if (csvName == "alpha Ari") { return "alf Ari"; } + if (csvName == "mu Ara") { return "HD 160691"; } + if (csvName == "OGLE-05-169L") { return "OGLE 2005-BLG-169L"; } + if (csvName == "tau Gru") { return "HD 216435"; } + if (csvName == "iota Hor") { return "HR 810"; } + if (csvName == "OGLE-05-071L") { return "OGLE 2005-BLG-71L"; } + if (csvName == "OGLE235-MOA53") { return "OGLE 2003-BLG-235L"; } + if (csvName == "MOA-2008-BLG-310L") { return "MOA 2008-BLG-310L"; } + if (csvName == "KIC 11442793") { return "KOI-351"; } + if (csvName == "OGLE-2006-BLG-109L") { return "OGLE 2006-BLG-109L"; } + if (csvName == "HD 137388") { return "HD 137388 A"; } + if (csvName == "kappa CrB") { return "kap CrB"; } + if (csvName == "XO-2") { return "XO-2 N"; } + if (csvName == "epsilon Tau") { return "eps Tau"; } + if (csvName == "epsilon Eri") { return "eps Eri"; } + if (csvName == "Kepler-448") { return "KOI-12"; } + if (csvName == "omega Ser") { return "ome Ser"; } + if (csvName == "MOA-2010-BLG-477L") { return "MOA 2010-BLG-477L"; } + if (csvName == "GJ 176") { return "HD 285968"; } + if (csvName == "HIP 2247") { return "BD-17 63"; } + if (csvName == "MOA-2009-BLG-266L") { return "MOA 2009-BLG-266L"; } + if (csvName == "Kepler-89") { return "KOI-94"; } + if (csvName == "iota Dra") { return "HIP 75458"; } + if (csvName == "MOA-2007-BLG-400L") { return "MOA 2007-BLG-400L"; } + if (csvName == "upsilon And") { return "ups And"; } + if (csvName == "OGLE-2011-BLG-0251") { return "OGLE 2011-BLG-251L"; } + if (csvName == "OGLE-05-390L") { return "OGLE 2005-BLG-390L"; } + if (csvName == "Kepler-420") { return "KOI-1257"; } + if (csvName == "beta Pic") { return "bet Pic"; } + if (csvName == "gamma Cep") { return "gam Cep"; } + if (csvName == "MOA-2007-BLG-192L") { return "MOA 2007-BLG-192L"; } + if (csvName == "MOA-2009-BLG-319L") { return "MOA 2009-BLG-319L"; } + if (csvName == "omicron CrB") { return "omi CrB"; } + if (csvName == "beta Gem") { return "HD 62509"; } + if (csvName == "epsilon CrB") { return "eps CrB"; } + if (csvName == "omicron UMa") { return "omi UMa"; } + if (csvName == "HD 142022") { return "HD 142022 A"; } + return csvName; +} + +std::string_view csvStarName(std::string_view name) { + if (name == "GJ 3021") { return "HD 1237"; } + if (name == "MOA 2009-BLG-387L") { return "MOA-2009-BLG-387L"; } + if (name == "HD 126614") { return "HD 126614 A"; } + if (name == "HD 27442") { return "epsilon Ret"; } + if (name == "PH1") { return "PH-1"; } + if (name == "gam 1 Leo") { return "gamma Leo A"; } + if (name == "OGLE 2007-BLG-368L") { return "OGLE-2007-BLG-368L"; } + if (name == "alf Ari") { return "alpha Ari"; } + if (name == "HD 160691") { return "mu Ara"; } + if (name == "OGLE 2005-BLG-169L") { return "OGLE-05-169L"; } + if (name == "HD 216435") { return "tau Gru"; } + if (name == "HR 810") { return "iota Hor"; } + if (name == "OGLE 2005-BLG-71L") { return "OGLE-05-071L"; } + if (name == "OGLE 2003-BLG-235L") { return "OGLE235-MOA53"; } + if (name == "MOA 2008-BLG-310L") { return "MOA-2008-BLG-310L"; } + if (name == "KOI-351") { return "KIC 11442793"; } + if (name == "OGLE 2006-BLG-109L") { return "OGLE-2006-BLG-109L"; } + if (name == "HD 137388 A") { return "HD 137388"; } + if (name == "kap CrB") { return "kappa CrB"; } + if (name == "XO-2 N") { return "XO-2"; } + if (name == "eps Tau") { return "epsilon Tau"; } + if (name == "eps Eri") { return "epsilon Eri"; } + if (name == "KOI-12") { return "Kepler-448"; } + if (name == "ome Ser") { return "omega Ser"; } + if (name == "MOA 2010-BLG-477L") { return "MOA-2010-BLG-477L"; } + if (name == "HD 285968") { return "GJ 176"; } + if (name == "BD-17 63") { return "HIP 2247"; } + if (name == "MOA 2009-BLG-266L") { return "MOA-2009-BLG-266L"; } + if (name == "KOI-94") { return "Kepler-89"; } + if (name == "HIP 75458") { return "iota Dra"; } + if (name == "MOA 2007-BLG-400L") { return "MOA-2007-BLG-400L"; } + if (name == "ups And") { return "upsilon And"; } + if (name == "OGLE 2011-BLG-251L") { return "OGLE-2011-BLG-0251"; } + if (name == "OGLE 2005-BLG-390L") { return "OGLE-05-390L"; } + if (name == "KOI-1257") { return "Kepler-420"; } + if (name == "bet Pic") { return "beta Pic"; } + if (name == "gam Cep") { return "gamma Cep"; } + if (name == "MOA 2007-BLG-192L") { return "MOA-2007-BLG-192L"; } + if (name == "MOA 2009-BLG-319L") { return "MOA-2009-BLG-319L"; } + if (name == "omi CrB") { return "omicron CrB"; } + if (name == "HD 62509") { return "beta Gem"; } + if (name == "eps CrB") { return "epsilon CrB"; } + if (name == "omi UMa") { return "omicron UMa"; } + if (name == "HD 142022 A") { return "HD 142022"; } + return name; +} + +} // namespace openspace::exoplanets diff --git a/modules/exoplanets/exoplanetshelper.h b/modules/exoplanets/exoplanetshelper.h new file mode 100644 index 0000000000..948e802c41 --- /dev/null +++ b/modules/exoplanets/exoplanetshelper.h @@ -0,0 +1,85 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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_EXOPLANETS___EXOPLANET_HELPER___H__ +#define __OPENSPACE_MODULE_EXOPLANETS___EXOPLANET_HELPER___H__ + +#include + +namespace openspace::exoplanets { + +struct Exoplanet { + float a; // Orbital semi-major axis in AU + double aUpper; // Upper uncertainty of orbital semi-major axis + double aLower; // Lower uncertainty of orbital semi-major axis + double ua; // Uncertainty of orbital semi-major axis + float bigOm; // Longitude of ascending node in degrees + float bigOmUpper; // Upper uncertainty of longitude of ascending node + float bigOmLower; // Lower uncertainty of longitude of ascending node + float uBigOm; // Uncertainty of longitude of ascending node + bool binary; // Star known to be binary? + float bmv; // B − V color + float ecc; // Orbital eccentricity + float eccUpper; // Upper uncertainty of orbital eccentricity + float eccLower; // Lower uncertainty of orbital eccentricity + float uEcc; // Uncertainty of orbital eccentricity + float i; // Orbital inclination in degrees (for transiting systems only) + float iUpper; // Upper uncertainty of orbital inclination + float iLower; // Lower uncertainty of orbital inclination + float ui; // Uncertainty of orbital inclination + int nComp; // Number of planetary companions known + float om; // Argument of periastron in degrees + float omUpper; // Upper uncertainty of argument of periastron + float omLower; // Lower uncertainty of argument of periastron + float uOm; // Uncertainty of argument of periastron + double per; // Orbital period in days + float perUpper; // Upper uncertainty of period + float perLower; // Lower uncertainty of period + float uPer; // Uncertainty of period + double r; // Radius of the planet in Jupiter radii + double rUpper; // Upper uncertainty of radius of the planet + double rLower; // Lower uncertainty of radius of the planet + double ur; // Uncertainty of radius of the planet + float rStar; // Estimated radius of the star in solar radii + float rStarUpper; // Upper uncertainty of estimated star radius + float rStarLower; // Lower uncertainty of estimated star radius + float urStar; // Uncertainty of estimated star radius + double tt; // Epoch of transit center in HJD-2440000 + float ttUpper; // Upper uncertainty of epoch of transit center + float ttLower; // Lower uncertainty of epoch of transit center + float uTt; // Uncertainty of epoch of transit center + float positionX; // Star position's X-coordinate in parsec + float positionY; // Star position's Y-coordinate in parsec + float positionZ; // Star position's Z-coordinate in parsec +}; + +// Convert csv-file specific names to the corresponding name in the speck data file +std::string_view speckStarName(std::string_view name); + +// Convert speck-file specific names to the corresponding name in the csv data file +std::string_view csvStarName(std::string_view name); + +} // namespace openspace::exoplanets + +#endif // __OPENSPACE_MODULE_EXOPLANETS___EXOPLANETSMODULE___H__ diff --git a/modules/exoplanets/exoplanetsmodule.cpp b/modules/exoplanets/exoplanetsmodule.cpp new file mode 100644 index 0000000000..b23e31f7f0 --- /dev/null +++ b/modules/exoplanets/exoplanetsmodule.cpp @@ -0,0 +1,93 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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 +#include +#include +#include + +#include "exoplanetsmodule_lua.inl" + +namespace openspace { + +using namespace exoplanets; + +ExoplanetsModule::ExoplanetsModule() : OpenSpaceModule(Name) {} + +scripting::LuaLibrary ExoplanetsModule::luaLibrary() const { + scripting::LuaLibrary res; + res.name = "exoplanets"; + res.functions = { + { + "addExoplanetSystem", + &exoplanets::luascriptfunctions::addExoplanetSystem, + {}, + "string", + "Add the exoplanet system specified by the input string, including " + "information about the host star and planets." + }, + { + "removeExoplanetSystem", + &exoplanets::luascriptfunctions::removeExoplanetSystem, + {}, + "string", + "Removes the nodes of the specified exoplanet system from the scene graph." + }, + { + "listAvailableExoplanetSystems", + &exoplanets::luascriptfunctions::listAvailableExoplanetSystems, + {}, + "", + "Prints a list with the names of all exoplanet systems that can be added to " + "the scene graph to the OpenSpace Log. " + } + }; + + return res; +} + +void ExoplanetsModule::internalInitialize(const ghoul::Dictionary&) { + auto fTask = FactoryManager::ref().factory(); + auto fRenderable = FactoryManager::ref().factory(); + ghoul_assert(fTask, "No task factory existed"); + fTask->registerClass("ExoplanetsCsvToBinTask"); + fRenderable->registerClass("RenderableOrbitDisc"); +} + +std::vector ExoplanetsModule::documentations() const { + return { + ExoplanetsCsvToBinTask::documentation() + }; +} + +} // namespace openspace diff --git a/modules/exoplanets/exoplanetsmodule.h b/modules/exoplanets/exoplanetsmodule.h new file mode 100644 index 0000000000..3a9ea264f4 --- /dev/null +++ b/modules/exoplanets/exoplanetsmodule.h @@ -0,0 +1,50 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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_EXOPLANETS___EXOPLANETSMODULE___H__ +#define __OPENSPACE_MODULE_EXOPLANETS___EXOPLANETSMODULE___H__ + +#include + +#include + +namespace openspace { + +class ExoplanetsModule : public OpenSpaceModule { +public: + constexpr static const char* Name = "Exoplanets"; + + ExoplanetsModule(); + virtual ~ExoplanetsModule() = default; + + scripting::LuaLibrary luaLibrary() const override; + std::vector documentations() const override; + +protected: + void internalInitialize(const ghoul::Dictionary&) override; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_EXOPLANETS___EXOPLANETSMODULE___H__ diff --git a/modules/exoplanets/exoplanetsmodule_lua.inl b/modules/exoplanets/exoplanetsmodule_lua.inl new file mode 100644 index 0000000000..dc4efc8345 --- /dev/null +++ b/modules/exoplanets/exoplanetsmodule_lua.inl @@ -0,0 +1,560 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2020 * +* * +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + constexpr const char* _loggerCat = "ExoplanetsModule"; +} // namespace + +namespace openspace::exoplanets::luascriptfunctions { + +constexpr const char* ExoplanetsGuiPath = "/Milky Way/Exoplanets/Exoplanet Systems/"; + +constexpr const char* LookUpTablePath = "${SYNC}/http/exoplanets_data/1/lookup.txt"; +constexpr const char* ExoplanetsDataPath = + "${SYNC}/http/exoplanets_data/1/exoplanets_data.bin"; + +constexpr const char* StarTextureFile = "${SYNC}/http/exoplanets_textures/1/sun.jpg"; +constexpr const char* DiscTextureFile = + "${SYNC}/http/exoplanets_textures/1/disc_texture.png"; + +constexpr const char* BvColormapPath = "${SYNC}/http/stars_colormap/2/colorbv.cmap"; + +std::string starColor(float bv, std::ifstream& colormap) { + const int t = static_cast(round(((bv + 0.4) / (2.0 + 0.4)) * 255)); + std::string color; + for (int i = 0; i < t + 12; i++) { + getline(colormap, color); + } + colormap.close(); + + std::istringstream colorStream(color); + std::string r, g, b; + getline(colorStream, r, ' '); + getline(colorStream, g, ' '); + getline(colorStream, b, ' '); + + return fmt::format("{{ {}, {}, {} }}", r, g, b); +} + +glm::dmat4 computeOrbitPlaneRotationMatrix(float i, float bigom, float om) { + // Exoplanet defined inclination changed to be used as Kepler defined inclination + const glm::dvec3 ascendingNodeAxisRot = glm::dvec3(0.0, 0.0, 1.0); + const glm::dvec3 inclinationAxisRot = glm::dvec3(1.0, 0.0, 0.0); + const glm::dvec3 argPeriapsisAxisRot = glm::dvec3(0.0, 0.0, 1.0); + + const double asc = glm::radians(bigom); + const double inc = glm::radians(i); + const double per = glm::radians(om); + + const glm::dmat4 orbitPlaneRotation = + glm::rotate(asc, glm::dvec3(ascendingNodeAxisRot)) * + glm::rotate(inc, glm::dvec3(inclinationAxisRot)) * + glm::rotate(per, glm::dvec3(argPeriapsisAxisRot)); + + return orbitPlaneRotation; +} + +// Rotate the original coordinate system (where x is pointing to First Point of Aries) +// so that x is pointing from star to the sun. +// Modified from "http://www.opengl-tutorial.org/intermediate-tutorials/ +// tutorial-17-quaternions/ #how-do-i-find-the-rotation-between-2-vectors" +glm::dmat3 exoplanetSystemRotation(glm::dvec3 start, glm::dvec3 end) { + glm::quat rotationQuat; + glm::dvec3 rotationAxis; + const float cosTheta = static_cast(glm::dot(start, end)); + constexpr float Epsilon = 1E-3f; + + if (cosTheta < -1.f + Epsilon) { + // special case when vectors in opposite directions: + // there is no "ideal" rotation axis + // So guess one; any will do as long as it's perpendicular to start vector + rotationAxis = glm::cross(glm::dvec3(0.0, 0.0, 1.0), start); + if (length2(rotationAxis) < 0.01f) { + // bad luck, they were parallel, try again! + rotationAxis = glm::cross(glm::dvec3(1.0, 0.0, 0.0), start); + } + + rotationAxis = glm::normalize(rotationAxis); + rotationQuat = glm::quat(glm::radians(180.f), rotationAxis); + return glm::dmat3(toMat4(rotationQuat)); + } + + rotationAxis = glm::cross(start, end); + + const float s = sqrt((1.f + cosTheta) * 2.f); + const float invs = 1.f / s; + + rotationQuat = glm::quat( + s * 0.5f, + rotationAxis.x * invs, + rotationAxis.y * invs, + rotationAxis.z * invs + ); + + return glm::dmat3(glm::toMat4(rotationQuat)); +} + +// Create an identifier without whitespaces +std::string createIdentifier(std::string name) { + std::replace(name.begin(), name.end(), ' ', '_'); + return name; +} + +int addExoplanetSystem(lua_State* L) { + const int StringLocation = -1; + const std::string starName = luaL_checkstring(L, StringLocation); + + // If user have given name as in EOD, change it to speck-name + const std::string starNameSpeck = std::string(speckStarName(starName)); + + const std::string starIdentifier = createIdentifier(starNameSpeck); + const std::string guiPath = ExoplanetsGuiPath + starNameSpeck; + + SceneGraphNode* existingStarNode = sceneGraphNode(starIdentifier); + if (existingStarNode) { + return ghoul::lua::luaError( + L, + "Adding of exoplanet system failed. The system has already been added." + ); + } + + std::ifstream data(absPath(ExoplanetsDataPath), std::ios::in | std::ios::binary); + + if (!data.good()) { + return ghoul::lua::luaError(L, "Failed to open exoplanets data file"); + } + + std::ifstream lut(absPath(LookUpTablePath)); + if (!lut.good()) { + return ghoul::lua::luaError(L, "Failed to open exoplanets look-up table file"); + } + + // 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. + Exoplanet p; + std::string line; + bool found = false; + + std::vector planetSystem; + std::vector planetNames; + + while (getline(lut, line)) { + std::istringstream ss(line); + std::string name; + getline(ss, name, ','); + + if (name.compare(0, name.length() - 2, starNameSpeck) == 0) { + std::string location_s; + getline(ss, location_s); + long location = std::stol(location_s.c_str()); + + data.seekg(location); + data.read(reinterpret_cast(&p), sizeof(Exoplanet)); + + planetNames.push_back(name); + planetSystem.push_back(p); + found = true; + } + } + + data.close(); + lut.close(); + + if (!found) { + return ghoul::lua::luaError( + L, + "No star with the provided name was found." + ); + } + + bool notEnoughData = isnan(p.positionX) || isnan(p.a) || isnan(p.per); + + if (notEnoughData) { + return ghoul::lua::luaError( + L, + "Insufficient data available for representing the exoplanet system." + ); + } + + const glm::dvec3 starPosition = glm::dvec3( + p.positionX * distanceconstants::Parsec, + p.positionY * distanceconstants::Parsec, + p.positionZ * distanceconstants::Parsec + ); + + const glm::dvec3 sunPosition = glm::dvec3(0.0, 0.0, 0.0); + const glm::dvec3 starToSunVec = glm::normalize(sunPosition - starPosition); + const glm::dvec3 galacticNorth = glm::dvec3(0.0, 0.0, 1.0); + + const glm::dmat3 galaxticToCelestialMatrix = + SpiceManager::ref().positionTransformMatrix("GALACTIC", "J2000", 0.0); + + const glm::dvec3 celestialNorth = glm::normalize( + galaxticToCelestialMatrix * galacticNorth + ); + + // Earth's north vector projected onto the skyplane, the plane perpendicular to the + // viewing vector (starToSunVec) + const float celestialAngle = static_cast(glm::dot( + celestialNorth, + starToSunVec + )); + glm::dvec3 northProjected = glm::normalize( + celestialNorth - (celestialAngle / glm::length(starToSunVec)) * starToSunVec + ); + + const glm::dvec3 beta = glm::normalize(glm::cross(starToSunVec, northProjected)); + + const glm::dmat3 exoplanetSystemRotation = glm::dmat3( + northProjected.x, + northProjected.y, + northProjected.z, + beta.x, + beta.y, + beta.z, + starToSunVec.x, + starToSunVec.y, + starToSunVec.z + ); + + // Star renderable globe, if we have a radius + std::string starGlobeRenderableString; + const float starRadius = p.rStar; + if (!isnan(starRadius)) { + std::ifstream colorMap(absPath(BvColormapPath), std::ios::in); + + if (!colorMap.good()) { + return ghoul::lua::luaError(L, "Failed to open colormap data file"); + } + + const std::string color = starColor(p.bmv, colorMap); + const float radiusInMeter = starRadius * static_cast(distanceconstants::SolarRadius); + + starGlobeRenderableString = "Renderable = {" + "Type = 'RenderableGlobe'," + "Radii = " + std::to_string(radiusInMeter) + "," + "SegmentsPerPatch = 64," + "PerformShading = false," + "Layers = {" + "ColorLayers = {" + "{" + "Identifier = 'StarColor'," + "Type = 'SolidColor'," + "Color = " + color + "," + "BlendMode = 'Normal'," + "Enabled = true" + "}," + "{" + "Identifier = 'StarTexture'," + "FilePath = openspace.absPath('" + StarTextureFile +"')," + "BlendMode = 'Color'," + "Enabled = true" + "}" + "}" + "}" + "},"; + } + + const std::string starParent = "{" + "Identifier = '" + starIdentifier + "'," + "Parent = 'SolarSystemBarycenter'," + "" + starGlobeRenderableString + "" + "Transform = {" + "Rotation = {" + "Type = 'StaticRotation'," + "Rotation = " + ghoul::to_string(exoplanetSystemRotation) + "" + "}," + "Translation = {" + "Type = 'StaticTranslation'," + "Position = " + ghoul::to_string(starPosition) + "" + "}" + "}," + "GUI = {" + "Name = '" + starNameSpeck + " (Star)'," + "Path = '" + guiPath + "'" + "}" + "}"; + + openspace::global::scriptEngine.queueScript( + "openspace.addSceneGraphNode(" + starParent + ");", + openspace::scripting::ScriptEngine::RemoteScripting::Yes + ); + + // Planets + for (size_t i = 0; i < planetSystem.size(); i++) { + Exoplanet planet = planetSystem[i]; + const std::string planetName = planetNames[i]; + + if (isnan(planet.ecc)) { + planet.ecc = 0.f; + } + if (isnan(planet.i)) { + planet.i = 90.f; + } + if (isnan(planet.bigOm)) { + planet.bigOm = 180.f; + } + if (isnan(planet.om)) { + planet.om = 90.f; + } + Time epoch; + std::string sEpoch; + if (!isnan(planet.tt)) { + epoch.setTime("JD " + std::to_string(planet.tt)); + sEpoch = std::string(epoch.ISO8601()); + } + else { + sEpoch = "2009-05-19T07:11:34.080"; + } + + float planetRadius; + std::string enabled; + + const float astronomicalUnit = static_cast(distanceconstants::AstronomicalUnit); + const float solarRadius = static_cast(distanceconstants::SolarRadius); + const float jupiterRadius = static_cast(distanceconstants::JupiterRadius); + + if (isnan(planet.r)) { + if (isnan(planet.rStar)) { + planetRadius = planet.a * 0.001f * astronomicalUnit; + } + else { + planetRadius = planet.rStar * 0.1f * solarRadius; + } + enabled = "false"; + } + else { + planetRadius = static_cast(planet.r) * jupiterRadius; + enabled = "true"; + } + + const float period = static_cast(planet.per * SecondsPerDay); + const float semiMajorAxisInMeter = planet.a * astronomicalUnit; + const float semiMajorAxisInKm = semiMajorAxisInMeter * 0.001f; + + const std::string planetIdentifier = createIdentifier(planetName); + + const std::string planetKeplerTranslation = "{" + "Type = 'KeplerTranslation'," + "Eccentricity = " + std::to_string(planet.ecc) + "," //ECC + "SemiMajorAxis = " + std::to_string(semiMajorAxisInKm) + "," + "Inclination = " + std::to_string(planet.i) + "," //I + "AscendingNode = " + std::to_string(planet.bigOm) + "," //BIGOM + "ArgumentOfPeriapsis = " + std::to_string(planet.om) + "," //OM + "MeanAnomaly = 0.0," + "Epoch = '" + sEpoch + "'," //TT. JD to YYYY MM DD hh:mm:ss + "Period = " + std::to_string(period) + "" + "}"; + + const std::string planetNode = "{" + "Identifier = '" + planetIdentifier + "'," + "Parent = '" + starIdentifier + "'," + "Enabled = true," + "Renderable = {" + "Type = 'RenderableGlobe'," + "Enabled = " + enabled + "," + "Radii = " + std::to_string(planetRadius) + "," //R. in meters. + "SegmentsPerPatch = 64," + "PerformShading = false," + "Layers = {}" + "}," + "Transform = { " + "Translation = " + planetKeplerTranslation + "" + "}," + "GUI = {" + "Name = '" + planetName + "'," + "Path = '" + guiPath + "'" + "}" + "}"; + + int trailResolution = 1000; + + // increase the resolution for highly eccentric orbits + const float eccentricityThreshold = 0.85f; + if (planet.ecc > eccentricityThreshold) { + trailResolution *= 2; + } + + openspace::global::scriptEngine.queueScript( + "openspace.addSceneGraphNode(" + planetNode + ");", + openspace::scripting::ScriptEngine::RemoteScripting::Yes + ); + + const std::string planetTrailNode = "{" + "Identifier = '" + planetIdentifier + "_Trail'," + "Parent = '" + starIdentifier + "'," + "Enabled = true," + "Renderable = {" + "Type = 'RenderableTrailOrbit'," + "Period = " + std::to_string(planet.per) + "," + "Resolution = " + std::to_string(trailResolution) + "," + "Translation = " + planetKeplerTranslation + "," + "Color = { 1, 1, 1 }" + "}," + "GUI = {" + "Name = '" + planetName + " Trail'," + "Path = '" + guiPath + "'" + "}" + "}"; + + openspace::global::scriptEngine.queueScript( + "openspace.addSceneGraphNode(" + planetTrailNode + ");", + openspace::scripting::ScriptEngine::RemoteScripting::Yes + ); + + bool hasUpperAUncertainty = !isnan(planet.aUpper); + bool hasLowerAUncertainty = !isnan(planet.aLower); + + if (hasUpperAUncertainty && hasLowerAUncertainty) { + // Get the orbit plane of the planet trail orbit from the KeplerTranslation + const glm::dmat4 orbitPlaneRotationMatrix = computeOrbitPlaneRotationMatrix( + planet.i, + planet.bigOm, + planet.om + ); + const glm::dmat3 rotation = orbitPlaneRotationMatrix; + + const std::string discNode = "{" + "Identifier = '" + planetIdentifier + "_Disc'," + "Parent = '" + starIdentifier + "'," + "Enabled = true," + "Renderable = {" + "Type = 'RenderableOrbitDisc'," + "Texture = openspace.absPath('" + DiscTextureFile + "')," + "Size = " + std::to_string(semiMajorAxisInMeter) + "," + "Eccentricity = " + std::to_string(planet.ecc) + "," + "Offset = { " + + std::to_string(planet.aLower) + ", " + + std::to_string(planet.aUpper) + + "}," //min / max extend + "Opacity = 0.3" + "}," + "Transform = {" + "Rotation = {" + "Type = 'StaticRotation'," + "Rotation = " + ghoul::to_string(rotation) + "" + "}" + "}," + "GUI = {" + "Name = '" + planetName + " Disc'," + "Path = '" + guiPath + "'" + "}" + "}"; + + openspace::global::scriptEngine.queueScript( + "openspace.addSceneGraphNode(" + discNode + ");", + openspace::scripting::ScriptEngine::RemoteScripting::Yes + ); + } + } + + return 0; +} + +int removeExoplanetSystem(lua_State* L) { + const int StringLocation = -1; + const std::string starName = luaL_checkstring(L, StringLocation); + const std::string starNameSpeck = std::string(speckStarName(starName)); + const std::string starIdentifier = createIdentifier(starNameSpeck); + + openspace::global::scriptEngine.queueScript( + "openspace.removeSceneGraphNode('" + starIdentifier + "');", + scripting::ScriptEngine::RemoteScripting::Yes + ); + + return 0; +} + +int listAvailableExoplanetSystems(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::listAvailableExoplanetSystems"); + + std::ifstream file(absPath(LookUpTablePath)); + + if (!file.good()) { + return ghoul::lua::luaError( + L, + fmt::format("Failed to open file '{}'", LookUpTablePath) + ); + } + + std::vector names; + // As of 2020 there are about 4000 confirmed exoplanets, so use this number + // as a guess for the vector size + const int nExoplanetsGuess = 4000; + names.reserve(nExoplanetsGuess); + + std::string line; + while (getline(file, line)) { + std::stringstream ss(line); + std::string name; + getline(ss, name, ','); + // Remove the last two characters, that specify the planet + name = name.substr(0, name.size() - 2); + + names.push_back(name); + } + + // For easier read, sort by names and remove duplicates + std::sort(names.begin(), names.end()); + names.erase(std::unique(names.begin(), names.end()), names.end()); + + std::string output; + for (auto it = names.begin(); it != names.end(); ++it) { + if (it != names.end()) { + output += *it + ", "; + } + } + + LINFO(fmt::format( + "There is data available for the following {} exoplanet systems: {}", + names.size(), + output + )); + + return 0; +} +} //namespace openspace::exoplanets::luascriptfunctions diff --git a/modules/exoplanets/include.cmake b/modules/exoplanets/include.cmake new file mode 100644 index 0000000000..ffea0ac430 --- /dev/null +++ b/modules/exoplanets/include.cmake @@ -0,0 +1 @@ +set(DEFAULT_MODULE ON) diff --git a/modules/exoplanets/rendering/renderableorbitdisc.cpp b/modules/exoplanets/rendering/renderableorbitdisc.cpp new file mode 100644 index 0000000000..150a4d0e3d --- /dev/null +++ b/modules/exoplanets/rendering/renderableorbitdisc.cpp @@ -0,0 +1,325 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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 +#include +#include +#include +#include +#include +#include + +namespace { + static const openspace::properties::Property::PropertyInfo TextureInfo = { + "Texture", + "Texture", + "This value is the path to a texture on disk that contains a one-dimensional " + "texture which is used for these rings." + }; + + static const openspace::properties::Property::PropertyInfo SizeInfo = { + "Size", + "Size", + "This value specifies the semi-major axis of the orbit in meter." + }; + + static const openspace::properties::Property::PropertyInfo EccentricityInfo = { + "Eccentricity", + "Eccentricity", + "This value determines the eccentricity, that is the deviation from a perfect " + "sphere, for this orbit." + }; + + static const openspace::properties::Property::PropertyInfo OffsetInfo = { + "Offset", + "Offset", + "This value is used to limit the width of the rings. Each of the two values is " + "the lower and the upper uncertainties of the semi-major axis. " + }; +} // namespace + +namespace openspace { + +documentation::Documentation RenderableOrbitDisc::Documentation() { + using namespace documentation; + return { + "Renderable Orbit Disc", + "exoplanets_renderable_orbit_disc", + { + { + "Type", + new StringEqualVerifier("RenderableOrbitDisc"), + Optional::No + }, + { + TextureInfo.identifier, + new StringVerifier, + Optional::No, + TextureInfo.description + }, + { + SizeInfo.identifier, + new DoubleVerifier, + Optional::No, + SizeInfo.description + }, + { + EccentricityInfo.identifier, + new DoubleVerifier, + Optional::No, + EccentricityInfo.description + }, + { + OffsetInfo.identifier, + new DoubleVector2Verifier, + Optional::Yes, + OffsetInfo.description + } + } + }; +} + +RenderableOrbitDisc::RenderableOrbitDisc(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _texturePath(TextureInfo) + , _size(SizeInfo, 1.f, 0.f, 3.0e12f) + , _eccentricity(EccentricityInfo, 0.f, 0.f, 1.f) + , _offset(OffsetInfo, glm::vec2(0.f, 1.f), glm::vec2(0.f), glm::vec2(1.f)) +{ + using ghoul::filesystem::File; + + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableOrbitDisc" + ); + + if (dictionary.hasKey(OffsetInfo.identifier)) { + _offset = dictionary.value(OffsetInfo.identifier); + } + addProperty(_offset); + + _size = static_cast(dictionary.value(SizeInfo.identifier)); + _size = _size + (_offset.value().y * distanceconstants::AstronomicalUnit); + setBoundingSphere(_size); + _size.onChange([&]() { _planeIsDirty = true; }); + addProperty(_size); + + _texturePath = absPath(dictionary.value(TextureInfo.identifier)); + _textureFile = std::make_unique(_texturePath); + + _texturePath.onChange([&]() { _textureIsDirty = true; }); + addProperty(_texturePath); + + _textureFile->setCallback([&](const File&) { _textureIsDirty = true; }); + + _eccentricity = static_cast( + dictionary.value(EccentricityInfo.identifier) + ); + _eccentricity.onChange([&]() { _planeIsDirty = true; }); + addProperty(_eccentricity); + + addProperty(_opacity); +} + +bool RenderableOrbitDisc::isReady() const { + return _shader && _texture; +} + +void RenderableOrbitDisc::initializeGL() { + _shader = global::renderEngine.buildRenderProgram( + "OrbitdiscProgram", + absPath("${BASE}/modules/exoplanets/shaders/orbitdisc_vs.glsl"), + absPath("${BASE}/modules/exoplanets/shaders/orbitdisc_fs.glsl") + ); + + _uniformCache.modelViewProjection = _shader->uniformLocation( + "modelViewProjectionTransform" + ); + _uniformCache.textureOffset = _shader->uniformLocation("textureOffset"); + _uniformCache.opacity = _shader->uniformLocation("opacity"); + _uniformCache.texture = _shader->uniformLocation("discTexture"); + _uniformCache.eccentricity = _shader->uniformLocation("eccentricity"); + _uniformCache.semiMajorAxis = _shader->uniformLocation("semiMajorAxis"); + + glGenVertexArrays(1, &_quad); + glGenBuffers(1, &_vertexPositionBuffer); + + createPlane(); + loadTexture(); +} + +void RenderableOrbitDisc::deinitializeGL() { + glDeleteVertexArrays(1, &_quad); + _quad = 0; + + glDeleteBuffers(1, &_vertexPositionBuffer); + _vertexPositionBuffer = 0; + + _textureFile = nullptr; + _texture = nullptr; + + global::renderEngine.removeRenderProgram(_shader.get()); + _shader = nullptr; +} + +void RenderableOrbitDisc::render(const RenderData& data, RendererTasks&) { + _shader->activate(); + + glm::dmat4 modelTransform = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * + glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); + + glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; + + _shader->setUniform( + _uniformCache.modelViewProjection, + data.camera.projectionMatrix() * glm::mat4(modelViewTransform) + ); + _shader->setUniform(_uniformCache.textureOffset, _offset); + _shader->setUniform(_uniformCache.opacity, _opacity); + _shader->setUniform(_uniformCache.eccentricity, _eccentricity); + _shader->setUniform(_uniformCache.semiMajorAxis, _size); + + ghoul::opengl::TextureUnit unit; + unit.activate(); + _texture->bind(); + _shader->setUniform(_uniformCache.texture, unit); + + glEnablei(GL_BLEND, 0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(false); + glDisable(GL_CULL_FACE); + + glBindVertexArray(_quad); + glDrawArrays(GL_TRIANGLES, 0, 6); + + _shader->deactivate(); + + // Restores GL State + global::renderEngine.openglStateCache().resetBlendState(); + global::renderEngine.openglStateCache().resetDepthState(); + global::renderEngine.openglStateCache().resetPolygonAndClippingState(); +} + +void RenderableOrbitDisc::update(const UpdateData& data) { + if (_shader->isDirty()) { + _shader->rebuildFromFile(); + _uniformCache.modelViewProjection = _shader->uniformLocation( + "modelViewProjectionTransform" + ); + _uniformCache.textureOffset = _shader->uniformLocation("textureOffset"); + _uniformCache.opacity = _shader->uniformLocation("opacity"); + _uniformCache.texture = _shader->uniformLocation("discTexture"); + _uniformCache.eccentricity = _shader->uniformLocation("eccentricity"); + _uniformCache.semiMajorAxis = _shader->uniformLocation("semiMajorAxis"); + } + + if (_planeIsDirty) { + createPlane(); + _planeIsDirty = false; + } + + if (_textureIsDirty) { + loadTexture(); + _textureIsDirty = false; + } +} + +void RenderableOrbitDisc::loadTexture() { + if (!_texturePath.value().empty()) { + std::unique_ptr texture = + ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath)); + + if (texture) { + LDEBUGC( + "RenderableOrbitDisc", + fmt::format("Loaded texture from '{}'", absPath(_texturePath)) + ); + _texture = std::move(texture); + + _texture->uploadTexture(); + _texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + + _textureFile = std::make_unique(_texturePath); + _textureFile->setCallback( + [&](const ghoul::filesystem::File&) { _textureIsDirty = true; } + ); + } + } +} + +void RenderableOrbitDisc::createPlane() { + const GLfloat size = _size * (1.f + _eccentricity); + + struct VertexData { + GLfloat x; + GLfloat y; + GLfloat s; + GLfloat t; + }; + + VertexData data[] = { + { -size, -size, 0.f, 0.f }, + { size, size, 1.f, 1.f }, + { -size, size, 0.f, 1.f }, + { -size, -size, 0.f, 0.f }, + { size, -size, 1.f, 0.f }, + { size, size, 1.f, 1.f }, + }; + + glBindVertexArray(_quad); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer( + 0, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(VertexData), + nullptr + ); + glEnableVertexAttribArray(1); + glVertexAttribPointer( + 1, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(VertexData), + reinterpret_cast(offsetof(VertexData, s)) + ); +} + +} // namespace openspace diff --git a/modules/exoplanets/rendering/renderableorbitdisc.h b/modules/exoplanets/rendering/renderableorbitdisc.h new file mode 100644 index 0000000000..3cae6e64c4 --- /dev/null +++ b/modules/exoplanets/rendering/renderableorbitdisc.h @@ -0,0 +1,82 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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_EXOPLENETS___RENDERABLEORBITDISC___H__ +#define __OPENSPACE_MODULE_EXOPLANETS___RENDERABLEORBITDISC___H__ + +#include +#include +#include +#include +#include +#include + +namespace ghoul::filesystem { class File; } +namespace ghoul::opengl { + class ProgramObject; + class Texture; +} // namespace ghoul::opengl + +namespace openspace { + +namespace documentation { struct Documentation; } + +class RenderableOrbitDisc : public Renderable { +public: + RenderableOrbitDisc(const ghoul::Dictionary& dictionary); + + void initializeGL() override; + void deinitializeGL() override; + + bool isReady() const override; + + void render(const RenderData& data, RendererTasks& rendererTask) override; + void update(const UpdateData& data) override; + + static documentation::Documentation Documentation(); + +private: + void loadTexture(); + void createPlane(); + + properties::StringProperty _texturePath; + properties::FloatProperty _size; + properties::FloatProperty _eccentricity; + properties::Vec2Property _offset; + + std::unique_ptr _shader = nullptr; + UniformCache(modelViewProjection, textureOffset, opacity, + texture, eccentricity, semiMajorAxis) _uniformCache; + std::unique_ptr _texture = nullptr; + std::unique_ptr _textureFile; + + bool _textureIsDirty = false; + bool _planeIsDirty = false; + GLuint _quad = 0; + GLuint _vertexPositionBuffer = 0; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_EXOPLENETS___RENDERABLEORBITDISC___H__ diff --git a/modules/exoplanets/shaders/orbitdisc_fs.glsl b/modules/exoplanets/shaders/orbitdisc_fs.glsl new file mode 100644 index 0000000000..373ea936dc --- /dev/null +++ b/modules/exoplanets/shaders/orbitdisc_fs.glsl @@ -0,0 +1,114 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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 "PowerScaling/powerScaling_fs.hglsl" +#include "fragment.glsl" + +in vec2 vs_st; +in vec4 vs_position; + +uniform sampler1D discTexture; +uniform vec2 textureOffset; +uniform float opacity; +uniform float eccentricity; +uniform float semiMajorAxis; + +const float AstronomicalUnit = 149597870700.0; // m +const float Epsilon = 0.0000001; + +// Compute semi minor axis from major axis, a, and eccentricity, e +float semiMinorAxis(float a, float e) { + return a * sqrt(1.0 - e * e); +} + +// If returned value <= 1, the point is insdie or on the ellipse specified by the input: +// a and b are the semi-major and semi-minor axes, respectively. +// cx is the displacement of the center of the ellipse along the x-axis (for an orbit, +// the y-displacement is always zero) +float ellipseTest(vec2 point, float a, float b, float cx) { + float x = point.x; + float y = point.y; + return (pow(x - cx, 2.0) / (a*a)) + ((y*y) / (b*b)); +} + +Fragment getFragment() { + // Moving the origin to the center + vec2 st = (vs_st - vec2(0.5)) * 2.0; + + float AUpper = semiMajorAxis; + float BUpper = semiMinorAxis(AUpper, eccentricity); + float CUpper = sqrt(AUpper*AUpper - BUpper*BUpper); + float outerApoapsisDistance = AUpper * (1 + eccentricity); + + float ALower = AUpper - AstronomicalUnit * (textureOffset.x + textureOffset.y); + float BLower = semiMinorAxis(ALower, eccentricity); + float CLower = sqrt(ALower*ALower - BLower*BLower); + float innerApoapsisDistance = ALower * (1 + eccentricity); + + // Normalize based on outer apoapsis distance (size of plane) + float AU_n = AUpper / outerApoapsisDistance; + float BU_n = BUpper / outerApoapsisDistance; + float CU_n = CUpper / outerApoapsisDistance; + float AL_n = ALower / outerApoapsisDistance; + float BL_n = BLower / outerApoapsisDistance; + float CL_n = CLower / outerApoapsisDistance; + + if (eccentricity <= Epsilon) { + CU_n = 0.0; + CL_n = 0.0; + } + + float outer = ellipseTest(st, AU_n, BU_n, -CU_n); + float inner = ellipseTest(st, AL_n, BL_n, -CL_n); + if (outer > 1.0 || inner < 1.0) { + // point is outside outer ellipse or inside inner eliipse + discard; + } + + // Remapping the texture coordinates + vec2 dir = normalize(st); + + // Find outer ellipse: where along the direction does the equation == 1? + float denominator = pow(BU_n * dir.x, 2.0) + pow(AU_n * dir.y, 2.0); + float first = -(pow(BU_n, 2.0) * dir.x * CU_n) / denominator; + float second = pow((pow(BU_n, 2.0) * dir.x * CU_n) / denominator, 2.0); + float third = (pow(BU_n * CU_n, 2.0) - pow(AU_n * BU_n, 2.0)) / denominator; + + float scale = first + sqrt(second - third); + + vec2 max = dir * scale; + vec2 min = max * (innerApoapsisDistance / outerApoapsisDistance); + + float distance1 = distance(max, min); + float distance2 = distance(max, st); + float textureCoord = distance2 / distance1; + + vec4 diffuse = texture(discTexture, textureCoord); + diffuse.a *= opacity; + + Fragment frag; + frag.color = diffuse; + frag.depth = vs_position.w; + return frag; +} diff --git a/modules/exoplanets/shaders/orbitdisc_vs.glsl b/modules/exoplanets/shaders/orbitdisc_vs.glsl new file mode 100644 index 0000000000..e998350ce7 --- /dev/null +++ b/modules/exoplanets/shaders/orbitdisc_vs.glsl @@ -0,0 +1,44 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +#include "PowerScaling/powerScaling_vs.hglsl" + +layout(location = 0) in vec2 in_position; +layout(location = 1) in vec2 in_st; + +out vec2 vs_st; +out vec4 vs_position; + +uniform mat4 modelViewProjectionTransform; + +void main() { + vs_st = in_st; + vs_position = z_normalization( + modelViewProjectionTransform * vec4(in_position, 0.0, 1.0) + ); + + gl_Position = vs_position; +} diff --git a/modules/exoplanets/tasks/exoplanetscsvtobintask.cpp b/modules/exoplanets/tasks/exoplanetscsvtobintask.cpp new file mode 100644 index 0000000000..6cb232fb79 --- /dev/null +++ b/modules/exoplanets/tasks/exoplanetscsvtobintask.cpp @@ -0,0 +1,696 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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 +#include +#include + +namespace { + constexpr const char* KeyInputCsv = "InputCSV"; + constexpr const char* KeyInputSpeck = "InputSPECK"; + constexpr const char* KeyOutputBin = "OutputBIN"; + constexpr const char* KeyOutputLut = "OutputLUT"; + constexpr const char* KeyTeffToBv = "TeffToBvFile"; + + constexpr const char* _loggerCat = "CsvToBinTask"; +} // namespace + +namespace openspace::exoplanets { + +ExoplanetsCsvToBinTask::ExoplanetsCsvToBinTask(const ghoul::Dictionary& dictionary) { + openspace::documentation::testSpecificationAndThrow( + documentation(), + dictionary, + "ExoplanetsCsvToBinTask" + ); + + _inputCsvPath = absPath(dictionary.value(KeyInputCsv)); + _inputSpeckPath = absPath(dictionary.value(KeyInputSpeck)); + _outputBinPath = absPath(dictionary.value(KeyOutputBin)); + _outputLutPath = absPath(dictionary.value(KeyOutputLut)); + _teffToBvFilePath = absPath(dictionary.value(KeyTeffToBv)); +} + +std::string ExoplanetsCsvToBinTask::description() { + return fmt::format( + "Extract metadata from csv-file '{}' and write as bin to '{}'", + _inputCsvPath, + _outputBinPath + ); +} + +void ExoplanetsCsvToBinTask::perform(const Task::ProgressCallback& progressCallback) { + std::ifstream csvFile(_inputCsvPath); + if (!csvFile.good()) { + LERROR(fmt::format("Failed to open CSV file '{}'", _inputCsvPath)); + return; + } + + std::ofstream binFile(_outputBinPath, std::ios::out | std::ios::binary); + std::ofstream lutFile(_outputLutPath); + + int version = 1; + binFile.write(reinterpret_cast(&version), sizeof(int)); + + std::string planetRow; + getline(csvFile, planetRow); // The first line, containing the data names + + int total = 0; + while (getline(csvFile, planetRow)) { + ++total; + } + csvFile.clear(); + csvFile.seekg(0); + getline(csvFile, planetRow); // The first line, containing the data names + LINFOC("CSVTOBIN", fmt::format("Loading {} stars", total)); + + auto readFloatData = [](const std::string& str) -> float { + float result; + auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), result); + if (ec == std::errc()) { + return result; + } + return NAN; + }; + + auto readDoubleData = [](const std::string& str) -> double { + double result; + auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), result); + if (ec == std::errc()) { + return result; + } + return NAN; + }; + + auto readIntegerData = [](const std::string& str) -> int { + int result; + auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), result); + if (ec == std::errc()) { + return result; + } + return -1; + }; + + Exoplanet p; + std::string data; + int count = 0; + while (getline(csvFile, planetRow)) { + ++count; + progressCallback(static_cast(count) / static_cast(total)); + + std::istringstream lineStream(planetRow); + + getline(lineStream, data, ','); // A + p.a = readFloatData(data); + + getline(lineStream, data, ','); // AUPPER + p.aUpper = readDoubleData(data); + + getline(lineStream, data, ','); // ALOWER + p.aLower = readDoubleData(data); + + getline(lineStream, data, ','); // UA + p.ua = readDoubleData(data); + + getline(lineStream, data, ','); // AREF + getline(lineStream, data, ','); // AURL + getline(lineStream, data, ','); // AR + getline(lineStream, data, ','); // ARUPPER + getline(lineStream, data, ','); // ARLOWER + getline(lineStream, data, ','); // UAR + getline(lineStream, data, ','); // ARREF + getline(lineStream, data, ','); // ARURL + getline(lineStream, data, ','); // ASTROMETRY + getline(lineStream, data, ','); // B + getline(lineStream, data, ','); // BUPPER + getline(lineStream, data, ','); // BLOWER + getline(lineStream, data, ','); // UB + getline(lineStream, data, ','); // BREF + getline(lineStream, data, ','); // BURL + getline(lineStream, data, ','); // BIGOM + p.bigOm = readFloatData(data); + + getline(lineStream, data, ','); // BIGOMUPPER + p.bigOmUpper = readFloatData(data); + + getline(lineStream, data, ','); // BIGOMLOWER + p.bigOmLower = readFloatData(data); + + getline(lineStream, data, ','); // UBIGOM + p.uBigOm = readFloatData(data); + + getline(lineStream, data, ','); // BIGOMREF + getline(lineStream, data, ','); // BIGOMURL + getline(lineStream, data, ','); // BINARY + p.binary = static_cast(readIntegerData(data)); + + getline(lineStream, data, ','); // BINARYREF + getline(lineStream, data, ','); // BINARYURL + getline(lineStream, data, ','); // BMV + p.bmv = readFloatData(data); + + getline(lineStream, data, ','); // CHI2 + getline(lineStream, data, ','); // COMP + std::string component = data; + + getline(lineStream, data, ','); // DATE + getline(lineStream, data, ','); // DEC + getline(lineStream, data, ','); // DEC_STRING + getline(lineStream, data, ','); // DENSITY + getline(lineStream, data, ','); // DENSITYUPPER + getline(lineStream, data, ','); // DENSITYLOWER + getline(lineStream, data, ','); // UDENSITY + getline(lineStream, data, ','); // DENSITYREF + getline(lineStream, data, ','); // DENSITYURL + getline(lineStream, data, ','); // DEPTH + getline(lineStream, data, ','); // DEPTHUPPER + getline(lineStream, data, ','); // DEPTHLOWER + getline(lineStream, data, ','); // UDEPTH + getline(lineStream, data, ','); // DEPTHREF + getline(lineStream, data, ','); // DEPTHURL + getline(lineStream, data, ','); // DIST + getline(lineStream, data, ','); // DISTUPPER + getline(lineStream, data, ','); // DISTLOWER + getline(lineStream, data, ','); // UDIST + getline(lineStream, data, ','); // DISTREF + getline(lineStream, data, ','); // DISTURL + getline(lineStream, data, ','); // DR + getline(lineStream, data, ','); // DRUPPER + getline(lineStream, data, ','); // DRLOWER + getline(lineStream, data, ','); // UDR + getline(lineStream, data, ','); // DRREF + getline(lineStream, data, ','); // DRURL + getline(lineStream, data, ','); // DVDT + getline(lineStream, data, ','); // DVDTUPPER + getline(lineStream, data, ','); // DVDTLOWER + getline(lineStream, data, ','); // UDVDT + getline(lineStream, data, ','); // DVDTREF + getline(lineStream, data, ','); // DVDTURL + getline(lineStream, data, ','); // EANAME + getline(lineStream, data, ','); // EAURL + getline(lineStream, data, ','); // ECC + p.ecc = readFloatData(data); + + getline(lineStream, data, ','); // ECCUPPER + p.eccUpper = readFloatData(data); + + getline(lineStream, data, ','); // ECCLOWER + p.eccLower = readFloatData(data); + + getline(lineStream, data, ','); // UECC + p.uEcc = readFloatData(data); + + getline(lineStream, data, ','); // ECCREF + getline(lineStream, data, ','); // ECCURL + getline(lineStream, data, ','); // EOD + getline(lineStream, data, ','); // ETDNAME + getline(lineStream, data, ','); // ETDURL + getline(lineStream, data, ','); // FE + getline(lineStream, data, ','); // FEUPPER + getline(lineStream, data, ','); // FELOWER + getline(lineStream, data, ','); // UFE + getline(lineStream, data, ','); // FEREF + getline(lineStream, data, ','); // FEURL + getline(lineStream, data, ','); // FIRSTREF + getline(lineStream, data, ','); // FIRSTURL + getline(lineStream, data, ','); // FREEZE_ECC + getline(lineStream, data, ','); // GAMMA + getline(lineStream, data, ','); // GAMMAUPPER + getline(lineStream, data, ','); // GAMMALOWER + getline(lineStream, data, ','); // UGAMMA + getline(lineStream, data, ','); // GAMMAREF + getline(lineStream, data, ','); // GAMMAURL + getline(lineStream, data, ','); // GL + getline(lineStream, data, ','); // GRAVITY + getline(lineStream, data, ','); // GRAVITYUPPER + getline(lineStream, data, ','); // GRAVITYLOWER + getline(lineStream, data, ','); // UGRAVITY + getline(lineStream, data, ','); // GRAVITYREF + getline(lineStream, data, ','); // GRAVITYURL + getline(lineStream, data, ','); // H + getline(lineStream, data, ','); // HD + getline(lineStream, data, ','); // HIPP + getline(lineStream, data, ','); // HR + getline(lineStream, data, ','); // I + p.i = readFloatData(data); + + getline(lineStream, data, ','); // IUPPER + p.iUpper = readFloatData(data); + + getline(lineStream, data, ','); // ILOWER + p.iLower = readFloatData(data); + + getline(lineStream, data, ','); // UI + p.ui = readFloatData(data); + + getline(lineStream, data, ','); // IREF + getline(lineStream, data, ','); // IURL + getline(lineStream, data, ','); // IMAGING + getline(lineStream, data, ','); // J + getline(lineStream, data, ','); // JSNAME + getline(lineStream, data, ','); // EPEURL + getline(lineStream, data, ','); // K + getline(lineStream, data, ','); // KUPPER + getline(lineStream, data, ','); // KLOWER + getline(lineStream, data, ','); // UK + getline(lineStream, data, ','); // KREF + getline(lineStream, data, ','); // KURL + getline(lineStream, data, ','); // KOI + getline(lineStream, data, ','); // KS + getline(lineStream, data, ','); // KP + getline(lineStream, data, ','); // LAMBDA + getline(lineStream, data, ','); // LAMBDAUPPER + getline(lineStream, data, ','); // LAMBDALOWER + getline(lineStream, data, ','); // ULAMBDA + getline(lineStream, data, ','); // LAMBDAREF + getline(lineStream, data, ','); // LAMBDAURL + getline(lineStream, data, ','); // LOGG + getline(lineStream, data, ','); // LOGGUPPER + getline(lineStream, data, ','); // LOGGLOWER + getline(lineStream, data, ','); // ULOGG + getline(lineStream, data, ','); // LOGGREF + getline(lineStream, data, ','); // LOGGURL; + getline(lineStream, data, ','); // MASS + getline(lineStream, data, ','); // MASSUPPER + getline(lineStream, data, ','); // MASSLOWER + getline(lineStream, data, ','); // UMASS + getline(lineStream, data, ','); // MASSREF + getline(lineStream, data, ','); // MASSURL + getline(lineStream, data, ','); // MICROLENSING + getline(lineStream, data, ','); // MSINI + getline(lineStream, data, ','); // MSINIUPPER + getline(lineStream, data, ','); // MSINILOWER + getline(lineStream, data, ','); // UMSINI + getline(lineStream, data, ','); // MSINIREF + getline(lineStream, data, ','); // MSINIURL + getline(lineStream, data, ','); // MSTAR + getline(lineStream, data, ','); // MSTARUPPER + getline(lineStream, data, ','); // MSTARLOWER + getline(lineStream, data, ','); // UMSTAR + getline(lineStream, data, ','); // MSTARREF + getline(lineStream, data, ','); // MSTARURL + getline(lineStream, data, ','); // MULT + getline(lineStream, data, ','); // NAME + getline(lineStream, data, ','); // NCOMP + p.nComp = readIntegerData(data); + + getline(lineStream, data, ','); // NOBS + getline(lineStream, data, ','); // OM + p.om = readFloatData(data); + + getline(lineStream, data, ','); // OMUPPER + p.omUpper = readFloatData(data); + + getline(lineStream, data, ','); // OMLOWER + p.omLower = readFloatData(data); + + getline(lineStream, data, ','); // UOM + p.uOm = readFloatData(data); + + getline(lineStream, data, ','); // OMREF + getline(lineStream, data, ','); // OMURL + getline(lineStream, data, ','); // ORBREF + getline(lineStream, data, ','); // ORBURL + getline(lineStream, data, ','); // OTHERNAME + getline(lineStream, data, ','); // PAR + getline(lineStream, data, ','); // PARUPPER + getline(lineStream, data, ','); // PARLOWER + getline(lineStream, data, ','); // UPAR + getline(lineStream, data, ','); // PER + p.per = readDoubleData(data); + + getline(lineStream, data, ','); // PERUPPER + p.perUpper = readFloatData(data); + + getline(lineStream, data, ','); // PERLOWER + p.perLower = readFloatData(data); + + getline(lineStream, data, ','); // UPER + p.uPer = readFloatData(data); + + getline(lineStream, data, ','); // PERREF + getline(lineStream, data, ','); // PERURL + getline(lineStream, data, ','); // PLANETDISCMETH + getline(lineStream, data, ','); // R + p.r = readDoubleData(data); + + getline(lineStream, data, ','); // RUPPER + p.rUpper = readDoubleData(data); + + getline(lineStream, data, ','); // RLOWER + p.rLower = readDoubleData(data); + + getline(lineStream, data, ','); //UR + p.ur = readDoubleData(data); + + getline(lineStream, data, ','); // RREF + getline(lineStream, data, ','); // RURL + getline(lineStream, data, ','); // RA + getline(lineStream, data, ','); // RA_STRING + getline(lineStream, data, ','); // RHK + getline(lineStream, data, ','); // RHOSTAR + getline(lineStream, data, ','); // RHOSTARUPPER + getline(lineStream, data, ','); // RHOSTARLOWER + getline(lineStream, data, ','); // URHOSTAR + getline(lineStream, data, ','); // RHOSTARREF + getline(lineStream, data, ','); // RHOSTARURL + getline(lineStream, data, ','); // RMS + getline(lineStream, data, ','); // RR + getline(lineStream, data, ','); // RRUPPER + getline(lineStream, data, ','); // RRLOWER + getline(lineStream, data, ','); // URR + getline(lineStream, data, ','); // RRREF + getline(lineStream, data, ','); // RRURL + getline(lineStream, data, ','); // RSTAR + p.rStar = readFloatData(data); + + getline(lineStream, data, ','); // RSTARUPPER + p.rStarUpper = readFloatData(data); + + getline(lineStream, data, ','); // RSTARLOWER + p.rStarLower = readFloatData(data); + + getline(lineStream, data, ','); // URSTAR + p.urStar = readFloatData(data); + + getline(lineStream, data, ','); // RSTARREF + getline(lineStream, data, ','); // RSTARURL + getline(lineStream, data, ','); // SAO + getline(lineStream, data, ','); // SE + getline(lineStream, data, ','); // SEREF + getline(lineStream, data, ','); // SEURL + getline(lineStream, data, ','); // SEDEPTHJ + getline(lineStream, data, ','); // SEDEPTHJUPPER + getline(lineStream, data, ','); // SEDEPTHJLOWER + getline(lineStream, data, ','); // USEDEPTHJ + getline(lineStream, data, ','); // SEDEPTHJREF + getline(lineStream, data, ','); // SEDEPTHJURL + getline(lineStream, data, ','); // SEDEPTHH + getline(lineStream, data, ','); // SEDEPTHHUPPER + getline(lineStream, data, ','); // SEDEPTHHLOWER + getline(lineStream, data, ','); // USEDEPTHH + getline(lineStream, data, ','); // SEDEPTHHREF + getline(lineStream, data, ','); // SEDEPTHHURL + getline(lineStream, data, ','); // SEDEPTHKS + getline(lineStream, data, ','); // SEDEPTHKSUPPER + getline(lineStream, data, ','); // SEDEPTHKSLOWER + getline(lineStream, data, ','); // USEDEPTHKS + getline(lineStream, data, ','); // SEDEPTHKSREF + getline(lineStream, data, ','); // SEDEPTHKSURL + getline(lineStream, data, ','); // SEDEPTHKP + getline(lineStream, data, ','); // SEDEPTHKPUPPER + getline(lineStream, data, ','); // SEDEPTHKPLOWER + getline(lineStream, data, ','); // USEDEPTHKP + getline(lineStream, data, ','); // SEDEPTHKPREF + getline(lineStream, data, ','); // SEDEPTHKPURL + getline(lineStream, data, ','); // SEDEPTH36 + getline(lineStream, data, ','); // SEDEPTH36UPPER + getline(lineStream, data, ','); // SEDEPTH36LOWER + getline(lineStream, data, ','); // USEDEPTH36 + getline(lineStream, data, ','); // SEDEPTH36REFx + getline(lineStream, data, ','); // SEDEPTH36URLx + getline(lineStream, data, ','); // SEDEPTH45 + getline(lineStream, data, ','); // SEDEPTH45UPPER + getline(lineStream, data, ','); // SEDEPTH45LOWER + getline(lineStream, data, ','); // USEDEPTH45 + getline(lineStream, data, ','); // SEDEPTH45REF + getline(lineStream, data, ','); // SEDEPTH45URL + getline(lineStream, data, ','); // SEDEPTH58 + getline(lineStream, data, ','); // SEDEPTH58UPPER + getline(lineStream, data, ','); // SEDEPTH58LOWER + getline(lineStream, data, ','); // USEDEPTH58 + getline(lineStream, data, ','); // EDEPTH58REF + getline(lineStream, data, ','); // SEDEPTH58URL + getline(lineStream, data, ','); // SEDEPTH80 + getline(lineStream, data, ','); // SEDEPTH80UPPER + getline(lineStream, data, ','); // SEDEPTH80LOWER + getline(lineStream, data, ','); // USEDEPTH80 + getline(lineStream, data, ','); // SEDEPTH80REF + getline(lineStream, data, ','); // SEDEPTH80URL + getline(lineStream, data, ','); // SEP + getline(lineStream, data, ','); // SEPUPPER + getline(lineStream, data, ','); // SEPLOWER + getline(lineStream, data, ','); // USEP + getline(lineStream, data, ','); // SEPREF + getline(lineStream, data, ','); // SEPURL + getline(lineStream, data, ','); // SET + getline(lineStream, data, ','); // SETUPPER + getline(lineStream, data, ','); // SETLOWER + getline(lineStream, data, ','); // USET + getline(lineStream, data, ','); // SETREF + getline(lineStream, data, ','); // SETURL + getline(lineStream, data, ','); // SHK + getline(lineStream, data, ','); // SIMBADNAME + getline(lineStream, data, ','); // SIMBADURL + getline(lineStream, data, ','); // SPECREF + getline(lineStream, data, ','); // SPECURL + getline(lineStream, data, ','); // STAR + std::string speckStarname = std::string(speckStarName(data)); + glm::vec3 position = starPosition(speckStarname); + p.positionX = position[0]; + p.positionY = position[1]; + p.positionZ = position[2]; + + getline(lineStream, data, ','); // STARDISCMETH + getline(lineStream, data, ','); // T0 + getline(lineStream, data, ','); // T0UPPER + getline(lineStream, data, ','); // T0LOWER + getline(lineStream, data, ','); // UT0 + getline(lineStream, data, ','); // T0REF + getline(lineStream, data, ','); // T0URL + getline(lineStream, data, ','); // T14 + getline(lineStream, data, ','); // T14UPPER + getline(lineStream, data, ','); // T14LOWER + getline(lineStream, data, ','); // UT14 + getline(lineStream, data, ','); // T14REF + getline(lineStream, data, ','); // T14URL + getline(lineStream, data, ','); // TEFF + float teff = readFloatData(data); + + getline(lineStream, data, ','); // TEFFUPPER + getline(lineStream, data, ','); // TEFFLOWER + getline(lineStream, data, ','); // UTEFF + getline(lineStream, data, ','); // TEFFREF + getline(lineStream, data, ','); // TEFFURL + getline(lineStream, data, ','); // TIMING + getline(lineStream, data, ','); // TRANSIT + getline(lineStream, data, ','); // TRANSITREF + getline(lineStream, data, ','); // TRANSITURL + getline(lineStream, data, ','); // TREND + getline(lineStream, data, ','); // TT + p.tt = readDoubleData(data); + + getline(lineStream, data, ','); // TTUPPER + p.ttUpper = readFloatData(data); + + getline(lineStream, data, ','); // TTLOWER + p.ttLower = readFloatData(data); + + getline(lineStream, data, ','); // UTT + p.uTt = readFloatData(data); + + getline(lineStream, data, ','); // TTREF + getline(lineStream, data, ','); // TTURL + getline(lineStream, data, ','); // V + getline(lineStream, data, ','); // VREF + getline(lineStream, data, ','); // VURL + getline(lineStream, data, ','); // VSINI + getline(lineStream, data, ','); // VSINIUPPER + getline(lineStream, data, ','); // VSINILOWER + getline(lineStream, data, ','); // UVSINI + getline(lineStream, data, ','); // VSINIREF + getline(lineStream, data, ','); // VSINIURL + getline(lineStream, data, ','); // KEPID + bool isKeplerObject = false; + if (!data.empty()) { + isKeplerObject = true; + } + getline(lineStream, data); // KDE + + if (!isKeplerObject) { + // calculate B-V from Teff if not exsisting + if (std::isnan(p.bmv)) { + p.bmv = bvFromTeff(teff); + } + + // create look-up table + long pos = static_cast(binFile.tellp()); + std::string planetName = speckStarname + " " + component; + lutFile << planetName << "," << pos << std::endl; + binFile.write(reinterpret_cast(&p), sizeof(Exoplanet)); + } + } + + progressCallback(1.f); +} + +glm::vec3 ExoplanetsCsvToBinTask::starPosition(const std::string& starName) { + std::ifstream exoplanetsFile(_inputSpeckPath); + if (!exoplanetsFile) { + LERROR(fmt::format("Error opening file expl.speck")); + } + + glm::vec3 position{ NAN }; + std::string line; + + while (getline(exoplanetsFile, line)) { + bool shouldSkipLine = ( + line.empty() || line[0] == '#' || line.substr(0, 7) == "datavar" || + line.substr(0, 10) == "texturevar" || line.substr(0, 7) == "texture" + ); + + if (shouldSkipLine) { + continue; + } + + std::string data; + std::string name; + std::istringstream linestream(line); + getline(linestream, data, '#'); + getline(linestream, name); + name.erase(0, 1); + + std::string coord; + if (name == starName) { + std::stringstream dataStream(data); + getline(dataStream, coord, ' '); + position[0] = std::stof(coord.c_str(), nullptr); + getline(dataStream, coord, ' '); + position[1] = std::stof(coord.c_str(), nullptr); + getline(dataStream, coord, ' '); + position[2] = std::stof(coord.c_str(), nullptr); + break; + } + } + + // Apply transformation matrix to pos + glm::dmat4 _transformationMatrix = glm::dmat4(1.0); + glm::vec3 transformedPosition = glm::vec3( + _transformationMatrix * glm::dvec4(position, 1.0) + ); + + return transformedPosition; +} + +float ExoplanetsCsvToBinTask::bvFromTeff(float teff) { + if (std::isnan(teff)) { + return NAN; + } + + std::ifstream teffToBvFile(_teffToBvFilePath); + if (!teffToBvFile.good()) { + LERROR(fmt::format("Failed to open teff_bv.txt file")); + return NAN; + } + + float bv = 0.f; + float bvUpper = 0.f; + float bvLower = 0.f; + float teffLower, teffUpper; + std::string row, teffString, bvString; + while (getline(teffToBvFile, row)) { + std::istringstream lineStream(row); + getline(lineStream, teffString, ','); + getline(lineStream, bvString); + + float teffCurrent = std::stof(teffString.c_str(), nullptr); + float bvCurrent = std::stof(bvString.c_str(), nullptr); + + if (teff > teffCurrent) { + teffLower = teffCurrent; + bvLower = bvCurrent; + } + else { + teffUpper = teffCurrent; + bvUpper = bvCurrent; + if (bvLower == 0.f) { + bv = 2.f; + } + else { + float bvDiff = (bvUpper - bvLower); + float teffDiff = (teffUpper - teffLower); + bv = ((bvDiff * (teff - teffLower)) / teffDiff) + bvLower; + } + break; + } + } + return bv; +} + +documentation::Documentation ExoplanetsCsvToBinTask::documentation() { + using namespace documentation; + return { + "ExoplanetsCsvToBinTask", + "exoplanets_csv_to_bin_task", + { + { + "Type", + new StringEqualVerifier("ExoplanetsCsvToBinTask"), + Optional::No, + "" + }, + { + KeyInputCsv, + new StringAnnotationVerifier("A file path to a csv file"), + Optional::No, + "The csv file to extract data from" + }, + { + KeyInputSpeck, + new StringAnnotationVerifier("A file path to a speck file"), + Optional::No, + "The speck file with star locations" + }, + { + KeyOutputBin, + new StringAnnotationVerifier("A valid filepath"), + Optional::No, + "The bin file to export data into" + }, + { + KeyOutputLut, + new StringAnnotationVerifier("A valid filepath"), + Optional::No, + "The txt file to write look-up table into" + }, + { + KeyTeffToBv, + new StringAnnotationVerifier("A valid filepath"), + Optional::No, + "The path to a teff to bv conversion file" + } + } + }; +} + +} // namespace openspace::exoplanets diff --git a/modules/exoplanets/tasks/exoplanetscsvtobintask.h b/modules/exoplanets/tasks/exoplanetscsvtobintask.h new file mode 100644 index 0000000000..9bbebf74ed --- /dev/null +++ b/modules/exoplanets/tasks/exoplanetscsvtobintask.h @@ -0,0 +1,56 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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_EXOPLANETS___EXOPLANETSCSVTOBINTASK___H__ +#define __OPENSPACE_MODULE_EXOPLANETS___EXOPLANETSCSVTOBINTASK___H__ + +#include +#include +#include + +namespace openspace::exoplanets { + +class ExoplanetsCsvToBinTask : public Task { +public: + ExoplanetsCsvToBinTask(const ghoul::Dictionary& dictionary); + std::string description() override; + void perform(const Task::ProgressCallback& progressCallback) override; + static documentation::Documentation documentation(); + +private: + std::string _inputCsvPath; + std::string _inputSpeckPath; + std::string _outputBinPath; + std::string _outputLutPath; + std::string _teffToBvFilePath; + + glm::vec3 starPosition(const std::string& starName); + + // Compute b-v color from teff value using a conversion file + float bvFromTeff(float teff); +}; + +} // namespace openspace::exoplanets + +#endif // __OPENSPACE_MODULE_EXOPLANETS___EXOPLANETSCSVTOBINTASK___H__ diff --git a/modules/globebrowsing/src/renderableglobe.cpp b/modules/globebrowsing/src/renderableglobe.cpp index a623939cc4..e52afba971 100644 --- a/modules/globebrowsing/src/renderableglobe.cpp +++ b/modules/globebrowsing/src/renderableglobe.cpp @@ -51,7 +51,14 @@ #include #include #include +#ifndef __APPLE__ #include +#else +#include +namespace std { + using namespace experimental; +} // namespace std +#endif // __APPLE__ namespace { // Global flags to modify the RenderableGlobe @@ -261,14 +268,22 @@ const Chunk& findChunkNode(const Chunk& node, const Geodetic2& location) { return *n; } -std::pmr::vector> -tilesAndSettingsUnsorted(const LayerGroup& layerGroup, const TileIndex& tileIndex) +#ifndef __APPLE__ +using ChunkTileVector = std::pmr::vector>; +#else // __APPLE__ +using ChunkTileVector = std::vector>; +#endif // __APPLE__ + +ChunkTileVector tilesAndSettingsUnsorted(const LayerGroup& layerGroup, + const TileIndex& tileIndex) { ZoneScoped - std::pmr::vector> tilesAndSettings( - &global::memoryManager.TemporaryMemory - ); +#ifndef __APPLE__ + ChunkTileVector tilesAndSettings(&global::memoryManager.TemporaryMemory); +#else // __APPLE__ + ChunkTileVector tilesAndSettings; +#endif // __APPLE__ for (Layer* layer : layerGroup.activeLayers()) { if (layer->tileProvider()) { tilesAndSettings.emplace_back( @@ -294,8 +309,10 @@ BoundingHeights boundingHeightsForChunk(const Chunk& chunk, const LayerManager& const size_t HeightChannel = 0; const LayerGroup& heightmaps = lm.layerGroup(layergroupid::GroupID::HeightLayers); - std::pmr::vector chunkTileSettingPairs = - tilesAndSettingsUnsorted(heightmaps, chunk.tileIndex); + ChunkTileVector chunkTileSettingPairs = tilesAndSettingsUnsorted( + heightmaps, + chunk.tileIndex + ); bool lastHadMissingData = true; for (const ChunkTileSettingsPair& chunkTileSettingsPair : chunkTileSettingPairs) { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 513db837e4..70f0d93979 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -453,7 +453,7 @@ configure_file( if (APPLE) find_library(APPKIT_LIBRARY AppKit REQUIRED) - target_link_libraries(openspace-core ${APPKIT_LIBRARY}) + target_link_libraries(openspace-core PUBLIC ${APPKIT_LIBRARY}) endif () set_openspace_compile_settings(openspace-core) diff --git a/src/util/time.cpp b/src/util/time.cpp index 203abb7778..e0be6096eb 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -108,8 +108,8 @@ std::string_view Time::ISO8601() const { std::memset(b, 0, S); SpiceManager::ref().dateFromEphemerisTime(_time, b, S, Format); - - return std::string_view(b, S); + + return std::string_view(b, S-1); } void Time::ISO8601(char* buffer) const {