Merge pull request #1025 from OpenSpace/feature/planetlabels

Feature/planetlabels
This commit is contained in:
Alexander Bock
2019-12-16 11:04:21 +01:00
committed by GitHub
33 changed files with 1230 additions and 29 deletions

View File

@@ -63,6 +63,22 @@ local Keybindings = {
GuiPath = "/Rendering",
Local = false
},
{
Key = "l",
Name = "Turn on labels",
Command = "openspace.setPropertyValue('{solarsystem_labels}.Renderable.Enabled', true)",
Documentation = "Turns on visibility for all solar system labels",
GuiPath = "/Rendering",
Local = false
},
{
Key = "Shift+l",
Name = "Turn off labels",
Command = "openspace.setPropertyValue('{solarsystem_labels}.Renderable.Enabled', false)",
Documentation = "Turns off visibility for all solar system labels",
GuiPath = "/Rendering",
Local = false
}
}
asset.onInitialize(function ()

View File

@@ -59,6 +59,24 @@ local Pluto = {
}
}
local PlutoLabel = {
Identifier = "PlutoLabel",
Parent = Pluto.Identifier,
Renderable = {
Enabled = true,
Type = "RenderableLabels",
LabelText = "Pluto",
FontSize = 100.0,
LabelSize = 8.9,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
BlendMode = "Additive",
LabelOrientationOption = "Camera View Direction"
},
GUI = {
Name = "Pluto Label",
Path = "/Solar System/Dwarf Planets/Pluto"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Pluto })
assetHelper.registerSceneGraphNodesAndExport(asset, { Pluto, PlutoLabel })

View File

@@ -1,7 +1,7 @@
local transforms = asset.require('./transforms')
local assetHelper = asset.require('util/asset_helper')
local texturesPath = asset.require('./earth_textures').TexturesPath
local labelsPath = asset.require('./earth_labels').LabelsPath
local labelsPath = asset.require('./earth_globelabels').LabelsPath
asset.request('./trail')
@@ -287,6 +287,45 @@ local Earth = {
}
}
local EarthLabel = {
Identifier = "EarthLabel",
Parent = Earth.Identifier,
-- Transform = {
-- Translation = {
-- Type = "SpiceTranslation",
-- Target = "EARTH",
-- Observer = "EARTH BARYCENTER"
-- },
-- -- Rotation = {
-- -- Type = "SpiceRotation",
-- -- SourceFrame = "IAU_MOON",
-- -- DestinationFrame = "GALACTIC"
-- -- }
-- },
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Earth",
FontSize = 100.0,
LabelSize = 8.6,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
LabelOrientationOption = "Camera View Direction",
BlendMode = "Additive",
EnableFading = true,
FadeStartUnit = "au",
FadeStartDistance = 1.5,
FadeStartSpeed = 1.0,
FadeEndUnit = "au",
FadeEndDistance = 15.0,
FadeEndSpeed = 25.0
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Earth Label",
Path = "/Solar System/Planets/Earth"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Earth })
assetHelper.registerSceneGraphNodesAndExport(asset, { Earth, EarthLabel })

View File

@@ -3,7 +3,7 @@ local assetHelper = asset.require('util/asset_helper')
asset.require("spice/base")
asset.request('./trail')
local kernel = asset.require('../kernels').jup310
local labelsPath = asset.require('../jupiter_labels').LabelsPath
local labelsPath = asset.require('../jupiter_globelabels').LabelsPath

View File

@@ -3,7 +3,7 @@ local assetHelper = asset.require('util/asset_helper')
asset.require("spice/base")
asset.request('./trail')
local kernel = asset.require('../kernels').jup310
local labelsPath = asset.require('../jupiter_labels').LabelsPath
local labelsPath = asset.require('../jupiter_globelabels').LabelsPath
local map_service_configs = asset.localResource("map_service_configs")

View File

@@ -3,7 +3,7 @@ local assetHelper = asset.require('util/asset_helper')
asset.require("spice/base")
asset.request('./trail')
local kernel = asset.require('../kernels').jup310
local labelsPath = asset.require('../jupiter_labels').LabelsPath
local labelsPath = asset.require('../jupiter_globelabels').LabelsPath

View File

@@ -3,7 +3,7 @@ local assetHelper = asset.require('util/asset_helper')
asset.require("spice/base")
asset.request('./trail')
local kernel = asset.require('../kernels').jup310
local labelsPath = asset.require('../jupiter_labels').LabelsPath
local labelsPath = asset.require('../jupiter_globelabels').LabelsPath

View File

@@ -42,6 +42,25 @@ local Jupiter = {
}
}
local JupiterLabel = {
Identifier = "JupiterLabel",
Parent = Jupiter.Identifier,
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Jupiter",
FontSize = 100.0,
LabelSize = 8.6,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
LabelOrientationOption = "Camera View Direction",
BlendMode = "Additive"
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Jupiter Label",
Path = "/Solar System/Planets/Jupiter"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Jupiter })
assetHelper.registerSceneGraphNodesAndExport(asset, { Jupiter, JupiterLabel })

View File

@@ -2,7 +2,7 @@ local transforms = asset.require('./transforms')
local assetHelper = asset.require('util/asset_helper')
asset.require("spice/base")
asset.request('./trail')
local labelsPath = asset.require('./mars_labels').LabelsPath
local labelsPath = asset.require('./mars_globelabels').LabelsPath
@@ -187,4 +187,31 @@ local Mars = {
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Mars })
local MarsLabel = {
Identifier = "MarsLabel",
Parent = Mars.Identifier,
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Mars",
FontSize = 100.0,
LabelSize = 8.5,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
LabelOrientationOption = "Camera View Direction",
BlendMode = "Additive",
TransformationMatrix = {
1.0, 0.0, 0.0, -8.0E6,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 1.0E7,
0.0, 0.0, 0.0, 1.0
},
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Mars Label",
Path = "/Solar System/Planets/Mars"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Mars, MarsLabel })

View File

@@ -1,6 +1,6 @@
local assetHelper = asset.require('util/asset_helper')
local transforms = asset.require('./transforms')
local labelsPath = asset.require('./mercury_labels').LabelsPath
local labelsPath = asset.require('./mercury_globelabels').LabelsPath
asset.require("spice/base")
@@ -223,5 +223,25 @@ local Mercury = {
}
}
local MercuryLabel = {
Identifier = "MercuryLabel",
Parent = Mercury.Identifier,
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Mercury",
FontSize = 100.0,
LabelSize = 8.3,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
LabelOrientationOption = "Camera View Direction",
BlendMode = "Additive"
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Mercury Label",
Path = "/Solar System/Planets/Mercury"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Mercury })
assetHelper.registerSceneGraphNodesAndExport(asset, { Mercury, MercuryLabel })

View File

@@ -40,4 +40,25 @@ local Neptune = {
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Neptune })
local NeptuneLabel = {
Identifier = "NeptuneLabel",
Parent = Neptune.Identifier,
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Neptune",
FontSize = 100.0,
LabelSize = 8.8,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
LabelOrientationOption = "Camera View Direction",
BlendMode = "Additive"
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Neptune Label",
Path = "/Solar System/Planets/Neptune"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Neptune, NeptuneLabel })

View File

@@ -2,7 +2,7 @@ local transforms = asset.require('../transforms')
local assetHelper = asset.require('util/asset_helper')
local kernel = asset.require('../kernels').sat375
asset.request('./trail')
local labelsPath = asset.require('../saturn_labels').LabelsPath
local labelsPath = asset.require('../saturn_globelabels').LabelsPath

View File

@@ -2,7 +2,7 @@ local transforms = asset.require('../transforms')
local assetHelper = asset.require('util/asset_helper')
local kernel = asset.require('../kernels').sat375
asset.request('./trail')
local labelsPath = asset.require('../saturn_labels').LabelsPath
local labelsPath = asset.require('../saturn_globelabels').LabelsPath

View File

@@ -2,7 +2,7 @@ local transforms = asset.require('../transforms')
local assetHelper = asset.require('util/asset_helper')
local kernel = asset.require('../kernels').sat375
asset.request('./trail')
local labelsPath = asset.require('../saturn_labels').LabelsPath
local labelsPath = asset.require('../saturn_globelabels').LabelsPath

View File

@@ -2,7 +2,7 @@ local transforms = asset.require('../transforms')
local assetHelper = asset.require('util/asset_helper')
local kernel = asset.require('../kernels').sat375
asset.request('./trail')
local labelsPath = asset.require('../saturn_labels').LabelsPath
local labelsPath = asset.require('../saturn_globelabels').LabelsPath

View File

@@ -2,7 +2,7 @@ local transforms = asset.require('../transforms')
local assetHelper = asset.require('util/asset_helper')
local kernel = asset.require('../kernels').sat375
asset.request('./trail')
local labelsPath = asset.require('../saturn_labels').LabelsPath
local labelsPath = asset.require('../saturn_globelabels').LabelsPath

View File

@@ -57,6 +57,26 @@ local SaturnRings = {
}
}
local SaturnLabel = {
Identifier = "SaturnLabel",
Parent = Saturn.Identifier,
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Saturn",
FontSize = 100.0,
LabelSize = 8.7,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
BlendMode = "Additive",
LabelOrientationOption = "Camera View Direction"
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Saturn Label",
Path = "/Solar System/Planets/Saturn"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Saturn, SaturnRings })
assetHelper.registerSceneGraphNodesAndExport(asset, { Saturn, SaturnRings, SaturnLabel })

View File

@@ -2,7 +2,7 @@ local transforms = asset.require('../transforms')
local assetHelper = asset.require('util/asset_helper')
local kernel = asset.require('../kernels').sat375
asset.request('./trail')
local labelsPath = asset.require('../saturn_labels').LabelsPath
local labelsPath = asset.require('../saturn_globelabels').LabelsPath

View File

@@ -2,7 +2,7 @@ local transforms = asset.require('../transforms')
local assetHelper = asset.require('util/asset_helper')
local kernel = asset.require('../kernels').sat375
asset.request('./trail')
local labelsPath = asset.require('../saturn_labels').LabelsPath
local labelsPath = asset.require('../saturn_globelabels').LabelsPath
local map_service_configs = asset.localResource("map_service_configs")

View File

@@ -42,6 +42,25 @@ local Uranus = {
}
}
local UranusLabel = {
Identifier = "UranusLabel",
Parent = Uranus.Identifier,
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Uranus",
FontSize = 100.0,
LabelSize = 8.7,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
LabelOrientationOption = "Camera View Direction",
BlendMode = "Additive"
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Neptune Label",
Path = "/Solar System/Planets/Uranus"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Uranus })
assetHelper.registerSceneGraphNodesAndExport(asset, { Uranus, UranusLabel })

View File

@@ -2,7 +2,7 @@ local assetHelper = asset.require('util/asset_helper')
local transforms = asset.require('./transforms')
asset.require("spice/base")
asset.request('./trail')
local labelsPath = asset.require('./venus_labels').LabelsPath
local labelsPath = asset.require('./venus_globelabels').LabelsPath
local mapServiceConfigs = asset.localResource("map_service_configs")
@@ -82,6 +82,26 @@ local Venus = {
}
}
local VenusLabel = {
Identifier = "VenusLabel",
Parent = Venus.Identifier,
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Venus",
FontSize = 100.0,
LabelSize = 8.4,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
LabelOrientationOption = "Camera View Direction",
BlendMode = "Additive"
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Venus Label",
Path = "/Solar System/Planets/Venus"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Venus })
assetHelper.registerSceneGraphNodesAndExport(asset, { Venus, VenusLabel })

View File

@@ -27,4 +27,32 @@ local Sun = {
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Sun })
local SunLabel = {
Identifier = "SunLabel",
Parent = Sun.Identifier,
Renderable = {
Enabled = false,
Type = "RenderableLabels",
LabelText = "Sun",
FontSize = 100.0,
LabelSize = 13.127,
LabelMaxSize = 100.0,
LabelMinSize = 1.0,
LabelOrientationOption = "Camera View Direction",
BlendMode = "Additive",
EnableFading = true,
FadeStartUnit = "Pm",
FadeStartDistance = 2.841,
FadeStartSpeed = 1.375,
FadeEndUnit = "pc",
FadeEndDistance = 1.326,
FadeEndSpeed = 1.0
},
Tag = { "solarsystem_labels" },
GUI = {
Name = "Sun Label",
Path = "/Solar System/Sun"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Sun, SunLabel })

View File

@@ -41,6 +41,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableboxgrid.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablecartesianaxes.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablelabels.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablenodeline.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.h
@@ -89,6 +90,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableboxgrid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablecartesianaxes.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablelabels.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablenodeline.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.cpp

View File

@@ -38,6 +38,7 @@
#include <modules/base/lightsource/cameralightsource.h>
#include <modules/base/lightsource/scenegraphlightsource.h>
#include <modules/base/rendering/renderablecartesianaxes.h>
#include <modules/base/rendering/renderablelabels.h>
#include <modules/base/rendering/renderablemodel.h>
#include <modules/base/rendering/renderablenodeline.h>
#include <modules/base/rendering/renderablesphere.h>
@@ -123,6 +124,7 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
fRenderable->registerClass<RenderableBoxGrid>("RenderableBoxGrid");
fRenderable->registerClass<RenderableCartesianAxes>("RenderableCartesianAxes");
fRenderable->registerClass<RenderableLabels>("RenderableLabels");
fRenderable->registerClass<RenderableModel>("RenderableModel");
fRenderable->registerClass<RenderableNodeLine>("RenderableNodeLine");
fRenderable->registerClass<RenderablePlaneImageLocal>("RenderablePlaneImageLocal");
@@ -191,6 +193,7 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
DashboardItemVelocity::Documentation(),
RenderableBoxGrid::Documentation(),
RenderableLabels::Documentation(),
RenderableModel::Documentation(),
RenderableNodeLine::Documentation(),
RenderablePlane::Documentation(),

View File

@@ -0,0 +1,816 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2019 *
* *
* 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 <modules/base/rendering/RenderableLabels.h>
#include <modules/base/basemodule.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/misc/crc32.h>
#include <ghoul/misc/templatefactory.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/misc/defer.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <ghoul/glm.h>
#include <glm/gtx/string_cast.hpp>
namespace {
constexpr const char* _loggerCat = "base::RenderableLabels";
constexpr const char* MeterUnit = "m";
constexpr const char* KilometerUnit = "Km";
constexpr const char* MegameterUnit = "Mm";
constexpr const char* GigameterUnit = "Gm";
constexpr const char* AstronomicalUnit = "au";
constexpr const char* TerameterUnit = "Tm";
constexpr const char* PetameterUnit = "Pm";
constexpr const char* ParsecUnit = "pc";
constexpr const char* KiloparsecUnit = "Kpc";
constexpr const char* MegaparsecUnit = "Mpc";
constexpr const char* GigaparsecUnit = "Gpc";
constexpr const char* GigalightyearUnit = "Gly";
enum BlendMode {
BlendModeNormal = 0,
BlendModeAdditive
};
constexpr const int ViewDirection = 0;
constexpr const int NormalDirection = 1;
constexpr double PARSEC = 0.308567756E17;
constexpr openspace::properties::Property::PropertyInfo BlendModeInfo = {
"BlendMode",
"Blending Mode",
"This determines the blending mode that is applied to this plane."
};
constexpr openspace::properties::Property::PropertyInfo LabelColorInfo = {
"LabelColor",
"Label Color",
"The label color for the astronomical object."
};
constexpr openspace::properties::Property::PropertyInfo FontSizeInfo = {
"FontSize",
"Font Size",
"The font size for the astronomical object labels."
};
constexpr openspace::properties::Property::PropertyInfo LabelSizeInfo = {
"LabelSize",
"Label Size",
"The label size for the astronomical object labels."
};
constexpr openspace::properties::Property::PropertyInfo LabelTextInfo = {
"LabelText",
"Label Text",
"The text that will be displayed on screen."
};
constexpr openspace::properties::Property::PropertyInfo LabelMinSizeInfo = {
"LabelMinSize",
"Label Min Size",
"The minimal size (in pixels) of the labels for the astronomical "
"objects being rendered."
};
constexpr openspace::properties::Property::PropertyInfo LabelMaxSizeInfo = {
"LabelMaxSize",
"Label Max Size",
"The maximum size (in pixels) of the labels for the astronomical "
"objects being rendered."
};
constexpr openspace::properties::Property::PropertyInfo TransformationMatrixInfo = {
"TransformationMatrix",
"Transformation Matrix",
"Transformation matrix to be applied to each astronomical object."
};
constexpr openspace::properties::Property::PropertyInfo LabelOrientationOptionInfo = {
"LabelOrientationOption",
"Label Orientation Option",
"Label orientation rendering mode."
};
constexpr openspace::properties::Property::PropertyInfo EnableFadingEffectInfo = {
"EnableFading",
"Enable/Disable Fade-in effect",
"Enable/Disable the Fade-in effect."
};
constexpr openspace::properties::Property::PropertyInfo PixelSizeControlInfo = {
"EnablePixelSizeControl",
"Enable pixel size control.",
"Enable pixel size control for rectangular projections."
};
constexpr openspace::properties::Property::PropertyInfo FadeStartUnitOptionInfo = {
"FadeStartUnit",
"Fade-In/-Out Start Unit.",
"Unit for fade-in/-out starting position calculation."
};
constexpr openspace::properties::Property::PropertyInfo FadeEndUnitOptionInfo = {
"FadeEndUnit",
"Fade-In/-Out End Unit.",
"Unit for fade-in/-out ending position calculation."
};
constexpr openspace::properties::Property::PropertyInfo FadeStartDistInfo = {
"FadeStartDistance",
"Fade-In/-Out starting distance.",
"Fade-In/-Out starting distance."
};
constexpr openspace::properties::Property::PropertyInfo FadeEndDistInfo = {
"FadeEndDistance",
"Fade-In/-Out ending distance.",
"Fade-In/-Out ending distance."
};
constexpr openspace::properties::Property::PropertyInfo FadeStartSpeedInfo = {
"FadeStartSpeed",
"Fade-In/-Out starting speed.",
"Fade-In/-Out starting speed."
};
constexpr openspace::properties::Property::PropertyInfo FadeEndSpeedInfo = {
"FadeEndSpeed",
"Fade-In/-Out ending speed.",
"Fade-In/-Out ending speed."
};
} // namespace
namespace openspace {
documentation::Documentation RenderableLabels::Documentation() {
using namespace documentation;
return {
"Renderable Labels",
"base_renderable_labels",
{
{
BlendModeInfo.identifier,
new StringInListVerifier({ "Normal", "Additive" }),
Optional::Yes,
BlendModeInfo.description, // + " The default value is 'Normal'.",
},
{
LabelOrientationOptionInfo.identifier,
new StringInListVerifier(
{ "Camera View Direction", "Camera Position Normal" }
),
Optional::Yes,
LabelOrientationOptionInfo.description,
},
{
LabelColorInfo.identifier,
new DoubleVector4Verifier,
Optional::Yes,
LabelColorInfo.description,
},
{
LabelColorInfo.identifier,
new DoubleVector4Verifier,
Optional::Yes,
LabelColorInfo.description,
},
{
LabelTextInfo.identifier,
new StringVerifier,
Optional::No,
LabelTextInfo.description
},
{
FontSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
FontSizeInfo.description
},
{
LabelSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelSizeInfo.description
},
{
LabelMinSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelMinSizeInfo.description
},
{
LabelMaxSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelMaxSizeInfo.description
},
{
EnableFadingEffectInfo.identifier,
new BoolVerifier,
Optional::Yes,
EnableFadingEffectInfo.description
},
{
PixelSizeControlInfo.identifier,
new BoolVerifier,
Optional::Yes,
PixelSizeControlInfo.description
},
{
FadeStartUnitOptionInfo.identifier,
new StringInListVerifier(
{ "m", "Km", "Mm", "Gm", "au", "Tm", "Pm", "pc", "Kpc", "Mpc",
"Gpc", "Gly"}
),
Optional::Yes,
FadeStartUnitOptionInfo.description,
},
{
FadeEndUnitOptionInfo.identifier,
new StringInListVerifier(
{"m", "Km", "Mm", "Gm", "au", "Tm", "Pm", "pc", "Kpc", "Mpc",
"Gpc", "Gly"}
),
Optional::Yes,
FadeEndUnitOptionInfo.description,
},
{
FadeStartDistInfo.identifier,
new DoubleVerifier,
Optional::Yes,
FadeStartDistInfo.description
},
{
FadeEndDistInfo.identifier,
new DoubleVerifier,
Optional::Yes,
FadeEndDistInfo.description
},
{
FadeStartSpeedInfo.identifier,
new DoubleVerifier,
Optional::Yes,
FadeStartSpeedInfo.description
},
{
FadeEndSpeedInfo.identifier,
new DoubleVerifier,
Optional::Yes,
FadeEndSpeedInfo.description
},
}
};
}
RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
, _labelColor(
LabelColorInfo,
glm::vec4(1.f, 1.f, 1.f, 1.f),
glm::vec4(0.f),
glm::vec4(1.f)
)
, _labelSize(LabelSizeInfo, 8.f, 0.5f, 30.f)
, _fontSize(FontSizeInfo, 50.f, 1.f, 100.f)
, _labelMinSize(LabelMinSizeInfo, 8.f, 0.5f, 24.f)
, _labelMaxSize(LabelMaxSizeInfo, 20.f, 0.5f, 100.f)
, _pixelSizeControl(PixelSizeControlInfo, false)
, _enableFadingEffect(EnableFadingEffectInfo, false)
, _labelText(LabelTextInfo)
, _fadeStartDistance(FadeStartDistInfo, 1.f, 0.f, 100.f)
, _fadeEndDistance(FadeEndDistInfo, 1.f, 0.f, 100.f)
, _fadeStartSpeed(FadeStartSpeedInfo, 1.f, 1.f, 100.f)
, _fadeEndSpeed(FadeEndSpeedInfo, 1.f, 1.f, 100.f)
, _labelOrientationOption(
LabelOrientationOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
)
, _fadeStartUnitOption(
FadeStartUnitOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
)
, _fadeEndUnitOption(
FadeEndUnitOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableLabels"
);
registerUpdateRenderBinFromOpacity();
_blendMode.addOptions({
{ BlendModeNormal, "Normal" },
{ BlendModeAdditive, "Additive"}
});
_blendMode.onChange([&]() {
switch (_blendMode) {
case BlendModeNormal:
setRenderBinFromOpacity();
break;
case BlendModeAdditive:
setRenderBin(Renderable::RenderBin::Transparent);
break;
default:
throw ghoul::MissingCaseException();
}
});
if (dictionary.hasKey(BlendModeInfo.identifier)) {
const std::string v = dictionary.value<std::string>(BlendModeInfo.identifier);
if (v == "Normal") {
_blendMode = BlendModeNormal;
}
else if (v == "Additive") {
_blendMode = BlendModeAdditive;
}
}
addProperty(_blendMode);
_labelOrientationOption.addOption(ViewDirection, "Camera View Direction");
_labelOrientationOption.addOption(NormalDirection, "Camera Position Normal");
_labelOrientationOption = NormalDirection;
if (dictionary.hasKeyAndValue<std::string>(LabelOrientationOptionInfo.identifier)) {
const std::string o = dictionary.value<std::string>(
LabelOrientationOptionInfo.identifier
);
if (o == "Camera View Direction") {
_labelOrientationOption = ViewDirection;
}
else if (o == "Camera Position Normal") {
_labelOrientationOption = NormalDirection;
}
}
if (dictionary.hasKey(LabelTextInfo.identifier)) {
_labelText = dictionary.value<std::string>(LabelTextInfo.identifier);
}
addProperty(_labelText);
addProperty(_labelOrientationOption);
_labelColor.setViewOption(properties::Property::ViewOptions::Color);
if (dictionary.hasKey(LabelColorInfo.identifier)) {
_labelColor = dictionary.value<glm::vec4>(LabelColorInfo.identifier);
}
addProperty(_labelColor);
if (dictionary.hasKey(FontSizeInfo.identifier)) {
_fontSize = dictionary.value<float>(FontSizeInfo.identifier);
}
_fontSize.onChange([&]() {
_font = global::fontManager.font(
"Mono",
_fontSize,
ghoul::fontrendering::FontManager::Outline::Yes,
ghoul::fontrendering::FontManager::LoadGlyphs::No
);
});
addProperty(_fontSize);
if (dictionary.hasKey(LabelSizeInfo.identifier)) {
_labelSize = dictionary.value<float>(LabelSizeInfo.identifier);
}
addProperty(_labelSize);
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
_labelMinSize = dictionary.value<float>(LabelMinSizeInfo.identifier);
}
addProperty(_labelMinSize);
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
_labelMaxSize = dictionary.value<float>(LabelMaxSizeInfo.identifier);
}
addProperty(_labelMaxSize);
if (dictionary.hasKey(TransformationMatrixInfo.identifier)) {
_transformationMatrix = dictionary.value<glm::dmat4>(
TransformationMatrixInfo.identifier
);
}
if (dictionary.hasKey(PixelSizeControlInfo.identifier)) {
_pixelSizeControl = dictionary.value<bool>(PixelSizeControlInfo.identifier);
addProperty(_pixelSizeControl);
}
if (dictionary.hasKey(EnableFadingEffectInfo.identifier)) {
_enableFadingEffect = dictionary.value<bool>(EnableFadingEffectInfo.identifier);
}
addProperty(_enableFadingEffect);
if (dictionary.hasKey(FadeStartDistInfo.identifier)) {
_fadeStartDistance = dictionary.value<float>(FadeStartDistInfo.identifier);
}
addProperty(_fadeStartDistance);
_fadeStartUnitOption.addOption(Meter, MeterUnit);
_fadeStartUnitOption.addOption(Kilometer, KilometerUnit);
_fadeStartUnitOption.addOption(Megameter, MegameterUnit);
_fadeStartUnitOption.addOption(Gigameter, GigameterUnit);
_fadeStartUnitOption.addOption(AU, AstronomicalUnit);
_fadeStartUnitOption.addOption(Terameter, TerameterUnit);
_fadeStartUnitOption.addOption(Petameter, PetameterUnit);
_fadeStartUnitOption.addOption(Parsec, ParsecUnit);
_fadeStartUnitOption.addOption(Kiloparsec, KiloparsecUnit);
_fadeStartUnitOption.addOption(Megaparsec, MegaparsecUnit);
_fadeStartUnitOption.addOption(Gigaparsec, GigaparsecUnit);
_fadeStartUnitOption.addOption(GigalightYears, GigalightyearUnit);
_fadeStartUnitOption = AU;
if (dictionary.hasKey(FadeStartUnitOptionInfo.identifier)) {
std::string unit = dictionary.value<std::string>(
FadeStartUnitOptionInfo.identifier
);
if (unit == MeterUnit) {
_fadeStartUnitOption = Meter;
}
else if (unit == KilometerUnit) {
_fadeStartUnitOption = Kilometer;
}
else if (unit == MegameterUnit) {
_fadeStartUnitOption = Megameter;
}
else if (unit == GigameterUnit) {
_fadeStartUnitOption = Gigameter;
}
else if (unit == AstronomicalUnit) {
_fadeStartUnitOption = AU;
}
else if (unit == TerameterUnit) {
_fadeStartUnitOption = Terameter;
}
else if (unit == PetameterUnit) {
_fadeStartUnitOption = Petameter;
}
else if (unit == ParsecUnit) {
_fadeStartUnitOption = Parsec;
}
else if (unit == KiloparsecUnit) {
_fadeStartUnitOption = Kiloparsec;
}
else if (unit == MegaparsecUnit) {
_fadeStartUnitOption = Megaparsec;
}
else if (unit == GigaparsecUnit) {
_fadeStartUnitOption = Gigaparsec;
}
else if (unit == GigalightyearUnit) {
_fadeStartUnitOption = GigalightYears;
}
else {
LWARNING(
"No unit given for RenderableLabels. Using kilometer as units."
);
_fadeStartUnitOption = Kilometer;
}
}
addProperty(_fadeStartUnitOption);
if (dictionary.hasKey(FadeStartSpeedInfo.identifier)) {
_fadeStartSpeed = dictionary.value<float>(FadeStartSpeedInfo.identifier);
}
addProperty(_fadeStartSpeed);
if (dictionary.hasKey(FadeEndDistInfo.identifier)) {
_fadeEndDistance = dictionary.value<float>(FadeEndDistInfo.identifier);
}
addProperty(_fadeEndDistance);
_fadeEndUnitOption.addOption(Meter, MeterUnit);
_fadeEndUnitOption.addOption(Kilometer, KilometerUnit);
_fadeEndUnitOption.addOption(Megameter, MegameterUnit);
_fadeEndUnitOption.addOption(Gigameter, GigameterUnit);
_fadeEndUnitOption.addOption(AU, AstronomicalUnit);
_fadeEndUnitOption.addOption(Terameter, TerameterUnit);
_fadeEndUnitOption.addOption(Petameter, PetameterUnit);
_fadeEndUnitOption.addOption(Parsec, ParsecUnit);
_fadeEndUnitOption.addOption(Kiloparsec, KiloparsecUnit);
_fadeEndUnitOption.addOption(Megaparsec, MegaparsecUnit);
_fadeEndUnitOption.addOption(Gigaparsec, GigaparsecUnit);
_fadeEndUnitOption.addOption(GigalightYears, GigalightyearUnit);
_fadeEndUnitOption = AU;
if (dictionary.hasKey(FadeEndUnitOptionInfo.identifier)) {
std::string unit = dictionary.value<std::string>(
FadeEndUnitOptionInfo.identifier
);
if (unit == MeterUnit) {
_fadeEndUnitOption = Meter;
}
else if (unit == KilometerUnit) {
_fadeEndUnitOption = Kilometer;
}
else if (unit == MegameterUnit) {
_fadeEndUnitOption = Megameter;
}
else if (unit == GigameterUnit) {
_fadeEndUnitOption = Gigameter;
}
else if (unit == AstronomicalUnit) {
_fadeEndUnitOption = AU;
}
else if (unit == TerameterUnit) {
_fadeEndUnitOption = Terameter;
}
else if (unit == PetameterUnit) {
_fadeEndUnitOption = Petameter;
}
else if (unit == ParsecUnit) {
_fadeEndUnitOption = Parsec;
}
else if (unit == KiloparsecUnit) {
_fadeEndUnitOption = Kiloparsec;
}
else if (unit == MegaparsecUnit) {
_fadeEndUnitOption = Megaparsec;
}
else if (unit == GigaparsecUnit) {
_fadeEndUnitOption = Gigaparsec;
}
else if (unit == GigalightyearUnit) {
_fadeEndUnitOption = GigalightYears;
}
else {
LWARNING(
"No unit given for RenderableLabels. Using kilometer as units."
);
_fadeEndUnitOption = Kilometer;
}
}
addProperty(_fadeEndUnitOption);
if (dictionary.hasKey(FadeEndSpeedInfo.identifier)) {
_fadeEndSpeed = dictionary.value<float>(FadeEndSpeedInfo.identifier);
}
addProperty(_fadeEndSpeed);
}
bool RenderableLabels::isReady() const {
return true;
}
void RenderableLabels::initialize() {
bool success = true;// loadData();
if (!success) {
throw ghoul::RuntimeError("Error loading objects labels data.");
}
setRenderBin(Renderable::RenderBin::Transparent);
}
void RenderableLabels::initializeGL() {
if (_font == nullptr) {
//size_t _fontSize = 50;
_font = global::fontManager.font(
"Mono",
_fontSize,
ghoul::fontrendering::FontManager::Outline::Yes,
ghoul::fontrendering::FontManager::LoadGlyphs::No
);
}
}
void RenderableLabels::deinitializeGL() {}
void RenderableLabels::render(const RenderData& data, RendererTasks&) {
//bool additiveBlending = (_blendMode == BlendModeAdditive);
//if (additiveBlending) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
//}
float fadeInVariable = 1.f;
if (_enableFadingEffect) {
float distanceNodeToCamera = glm::distance(
data.camera.positionVec3(),
data.modelTransform.translation
);
float sUnit = getUnit(_fadeStartUnitOption);
float eUnit = getUnit(_fadeEndUnitOption);
float startX = _fadeStartDistance * sUnit;
float endX = _fadeEndDistance * eUnit;
//fadeInVariable = changedPerlinSmoothStepFunc(distanceNodeToCamera, startX, endX);
fadeInVariable = linearSmoothStepFunc(
distanceNodeToCamera,
startX,
endX,
sUnit,
eUnit
);
}
glm::dmat4 modelMatrix(1.0);
glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix;
glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix());
glm::dmat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
glm::dvec3 cameraViewDirectionWorld = -data.camera.viewDirectionWorldSpace();
glm::dvec3 cameraUpDirectionWorld = data.camera.lookUpVectorWorldSpace();
glm::dvec3 orthoRight = glm::normalize(
glm::cross(cameraUpDirectionWorld, cameraViewDirectionWorld)
);
if (orthoRight == glm::dvec3(0.0)) {
glm::dvec3 otherVector(
cameraUpDirectionWorld.y,
cameraUpDirectionWorld.x,
cameraUpDirectionWorld.z
);
orthoRight = glm::normalize(glm::cross(otherVector, cameraViewDirectionWorld));
}
glm::dvec3 orthoUp = glm::normalize(glm::cross(cameraViewDirectionWorld, orthoRight));
renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp, fadeInVariable);
//if (additiveBlending) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(true);
//}
}
void RenderableLabels::update(const UpdateData&) {
}
void RenderableLabels::setLabelText(const std::string & newText) {
_labelText = newText;
}
void RenderableLabels::renderLabels(const RenderData& data,
const glm::dmat4& modelViewProjectionMatrix,
const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp, float fadeInVariable)
{
glm::vec4 textColor = _labelColor;
textColor.a *= fadeInVariable;
textColor.a *= _opacity;
ghoul::fontrendering::FontRenderer::ProjectedLabelsInformation labelInfo;
labelInfo.orthoRight = orthoRight;
labelInfo.orthoUp = orthoUp;
labelInfo.minSize = static_cast<int>(_labelMinSize);
labelInfo.maxSize = static_cast<int>(_labelMaxSize);
labelInfo.cameraPos = data.camera.positionVec3();
labelInfo.cameraLookUp = data.camera.lookUpVectorWorldSpace();
labelInfo.renderType = _labelOrientationOption;
labelInfo.mvpMatrix = modelViewProjectionMatrix;
labelInfo.scale = powf(10.f, _labelSize);
labelInfo.enableDepth = true;
labelInfo.enableFalseDepth = false;
// We don't use spice rotation and scale
glm::vec3 transformedPos(
_transformationMatrix * glm::dvec4(data.modelTransform.translation, 1.0)
);
ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render(
*_font,
transformedPos,
_labelText,
textColor,
labelInfo
);
}
float RenderableLabels::changedPerlinSmoothStepFunc(float x, float startX,
float endX) const
{
float f1 = 6.f * powf((x - startX), 5.f) - 15.f * powf((x - startX), 4.f) +
10.f * powf((x - startX), 3.f);
float f2 = -6.f * powf((x - endX), 5.f) + 15.f * powf((x - endX), 4.f) -
10.f * powf((x - endX), 3.f) + 1.f;
float f3 = 1.f;
if (x <= startX) {
return std::clamp(f1, 0.f, 1.f);
}
else if (x > startX && x < endX) {
return f3;
}
else if (x >= endX) {
return std::clamp(f2, 0.f, 1.f);
}
}
float RenderableLabels::linearSmoothStepFunc(float x, float startX, float endX,
float sUnit, float eUnit) const
{
float sdiv = 1.f / (sUnit * _fadeStartSpeed);
float ediv = -1.f / (eUnit * _fadeEndSpeed);
float f1 = sdiv * (x - startX) + 1.f;
float f2 = ediv * (x - endX) + 1.f;
float f3 = 1.f;
if (x <= startX) {
return std::clamp(f1, 0.f, 1.f);
}
else if (x > startX && x < endX) {
return f3;
}
else if (x >= endX) {
return std::clamp(f2, 0.f, 1.f);
}
}
float RenderableLabels::getUnit(int unit) const {
float scale = 0.f;
switch (static_cast<Unit>(unit)) {
case Meter:
scale = 1.f;
break;
case Kilometer:
scale = 1e3;
break;
case Megameter:
scale = 1e6;
break;
case Gigameter:
scale = 1e9;
break;
case AU:
scale = 149597870700.f;
break;
case Terameter:
scale = 1e12;
break;
case Petameter:
scale = 1e15;
break;
case Parsec:
scale = static_cast<float>(PARSEC);
break;
case Kiloparsec:
scale = static_cast<float>(1e3 * PARSEC);
break;
case Megaparsec:
scale = static_cast<float>(1e6 * PARSEC);
break;
case Gigaparsec:
scale = static_cast<float>(1e9 * PARSEC);
break;
case GigalightYears:
scale = static_cast<float>(306391534.73091 * PARSEC);
break;
}
return scale;
}
} // namespace openspace

View File

@@ -0,0 +1,134 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2019 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___RENDERABLELABELS___H__
#define __OPENSPACE_MODULE_BASE___RENDERABLELABELS___H__
#include <openspace/rendering/renderable.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/vector/vec2property.h>
#include <openspace/properties/vector/vec4property.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/opengl/uniformcache.h>
namespace ghoul::filesystem { class File; }
namespace ghoul::fontrendering { class Font; }
namespace ghoul::opengl {
class ProgramObject;
class Texture;
} // namespace ghoul::opengl
namespace openspace {
struct RenderData;
struct UpdateData;
namespace documentation { struct Documentation; }
struct LinePoint;
class RenderableLabels : public Renderable {
public:
RenderableLabels(const ghoul::Dictionary& dictionary);
void initialize() override;
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();
void setLabelText(const std::string & newText);
protected:
properties::OptionProperty _blendMode;
private:
enum Unit {
Meter = 0,
Kilometer,
Megameter,
Gigameter,
AU,
Terameter,
Petameter,
Parsec,
Kiloparsec,
Megaparsec,
Gigaparsec,
GigalightYears
};
void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
const glm::dvec3& orthoRight, const glm::dvec3& orthoUp, float fadeInVariable);
float changedPerlinSmoothStepFunc(float x, float startX, float endX) const;
float linearSmoothStepFunc(float x, float startX, float endX, float sUnit,
float eUnit) const;
float getUnit(int unit) const;
properties::Vec4Property _labelColor;
properties::FloatProperty _labelSize;
properties::FloatProperty _fontSize;
properties::FloatProperty _labelMinSize;
properties::FloatProperty _labelMaxSize;
properties::BoolProperty _pixelSizeControl;
properties::BoolProperty _enableFadingEffect;
properties::StringProperty _labelText;
properties::FloatProperty _fadeStartDistance;
properties::FloatProperty _fadeEndDistance;
properties::FloatProperty _fadeStartSpeed;
properties::FloatProperty _fadeEndSpeed;
properties::OptionProperty _labelOrientationOption;
properties::OptionProperty _fadeStartUnitOption;
properties::OptionProperty _fadeEndUnitOption;
std::shared_ptr<ghoul::fontrendering::Font> _font;
std::string _speckFile;
std::string _colorMapFile;
std::string _labelFile;
std::string _colorOptionString;
std::string _datavarSizeOptionString;
// Data may require some type of transformation prior the spice transformation being
// applied.
glm::dmat4 _transformationMatrix = glm::dmat4(1.0);
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___RENDERABLELABELS___H__

View File

@@ -42,7 +42,6 @@
#include <ghoul/opengl/textureunit.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/glm.h>
#include <glm/gtx/string_cast.hpp>
#include <array>