Moving more documentation to use codegen (#1549)

- Make use of more codegen in more classes
- Fix verifier for Color4Verifier
This commit is contained in:
Alexander Bock
2021-03-29 21:50:26 +02:00
committed by GitHub
parent a49c1f435f
commit 612b9bbc7f
44 changed files with 1877 additions and 3279 deletions
@@ -62,36 +62,25 @@ namespace {
"Determines the number of significant digits that are shown in the location text."
};
struct [[codegen::Dictionary(DashboardItemGlobeLocation)]] Parameters {
// [[codegen::verbatim(FontNameInfo.description)]]
std::optional<std::string> fontName;
// [[codegen::verbatim(FontSizeInfo.description)]]
std::optional<float> fontSize;
// [[codegen::verbatim(SignificantDigitsInfo.description)]]
std::optional<int> significantDigits;
};
#include "dashboarditemglobelocation_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation DashboardItemGlobeLocation::Documentation() {
using namespace documentation;
return {
"DashboardItem Globe Location",
"globebrowsing_dashboarditem_globelocation",
{
{
FontNameInfo.identifier,
new StringVerifier,
Optional::Yes,
FontNameInfo.description
},
{
FontSizeInfo.identifier,
new IntVerifier,
Optional::Yes,
FontSizeInfo.description
},
{
SignificantDigitsInfo.identifier,
new IntVerifier,
Optional::Yes,
SignificantDigitsInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "globebrowsing_dashboarditem_globelocation";
return doc;
}
DashboardItemGlobeLocation::DashboardItemGlobeLocation(
@@ -102,30 +91,15 @@ DashboardItemGlobeLocation::DashboardItemGlobeLocation(
, _significantDigits(SignificantDigitsInfo, 4, 1, 12)
, _font(global::fontManager->font(KeyFontMono, 10))
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"DashboardItemGlobeLocation"
);
if (dictionary.hasKey(FontNameInfo.identifier)) {
_fontName = dictionary.value<std::string>(FontNameInfo.identifier);
}
if (dictionary.hasKey(FontSizeInfo.identifier)) {
_fontSize = static_cast<float>(dictionary.value<double>(FontSizeInfo.identifier));
}
if (dictionary.hasKey(SignificantDigitsInfo.identifier)) {
_significantDigits = static_cast<int>(
dictionary.value<double>(SignificantDigitsInfo.identifier)
);
}
const Parameters p = codegen::bake<Parameters>(dictionary);
_fontName = p.fontName.value_or(_fontName);
_fontName.onChange([this]() {
_font = global::fontManager->font(_fontName, _fontSize);
});
addProperty(_fontName);
_fontSize = p.fontSize.value_or(_fontSize);
_fontSize.onChange([this]() {
_font = global::fontManager->font(_fontName, _fontSize);
});
@@ -139,6 +113,7 @@ DashboardItemGlobeLocation::DashboardItemGlobeLocation(
_significantDigits.value()
);
};
_significantDigits = p.significantDigits.value_or(_significantDigits);
_significantDigits.onChange(updateFormatString);
addProperty(_significantDigits);
updateFormatString();
@@ -42,14 +42,14 @@
#include <ghoul/misc/profiling.h>
#include <ghoul/opengl/programobject.h>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <locale>
#include <optional>
namespace {
constexpr const char* _loggerCat = "GlobeLabels";
constexpr const char* KeyLabelsFileName = "FileName";
constexpr const double LabelFadeOutLimitAltitudeMeters = 25000.0;
constexpr const double RangeAngularCoefConst = 0.8;
constexpr const float MinOpacityValueConst = 0.009f;
@@ -163,114 +163,72 @@ namespace {
"Label Alignment Option",
"Labels are aligned horizontally or circularly related to the planet."
};
struct [[codegen::Dictionary(GlobeLabelsComponent)]] Parameters {
// The path to the labels file
std::optional<std::filesystem::path> fileName;
// [[codegen::verbatim(LabelsInfo.description)]]
std::optional<bool> labels;
// [[codegen::verbatim(LabelsEnableInfo.description)]]
std::optional<bool> enable;
// [[codegen::verbatim(LabelsFontSizeInfo.description)]]
std::optional<float> labelsFontSize;
// [[codegen::verbatim(LabelsMinSizeInfo.description)]]
std::optional<int> labelsMinSize;
// [[codegen::verbatim(LabelsMaxSizeInfo.description)]]
std::optional<int> labelsMaxSize;
// [[codegen::verbatim(LabelsSizeInfo.description)]]
std::optional<float> labelsSize;
// [[codegen::verbatim(LabelsMinHeightInfo.description)]]
std::optional<float> labelsMinHeight;
// [[codegen::verbatim(LabelsColorInfo.description)]]
std::optional<glm::vec3> labelsColor [[codegen::color()]];
// [[codegen::verbatim(LabelsOpacityInfo.description)]]
std::optional<float> labelsOpacity [[codegen::inrange(0.f, 1.0)]];
// [[codegen::verbatim(LabelsFadeInStartingDistanceInfo.description)]]
std::optional<float> fadeInStartingDistance;
// [[codegen::verbatim(LabelsFadeOutStartingDistanceInfo.description)]]
std::optional<float> fadeOutStartingDistance;
// [[codegen::verbatim(LabelsFadeInEnabledInfo.description)]]
std::optional<bool> labelsFadeInEnabled;
// [[codegen::verbatim(LabelsFadeOutEnabledInfo.description)]]
std::optional<bool> labelsFadeOutEnabled;
// [[codegen::verbatim(LabelsDisableCullingEnabledInfo.description)]]
std::optional<bool> labelsDisableCullingEnabled;
// [[codegen::verbatim(LabelsDistanceEPSInfo.description)]]
std::optional<float> labelsDistanceEPS;
enum class Alignment {
Horizontally,
Circularly
};
// [[codegen::verbatim(LabelAlignmentOptionInfo.description)]]
std::optional<Alignment> labelAlignmentOption;
};
#include "globelabelscomponent_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation GlobeLabelsComponent::Documentation() {
using namespace documentation;
return {
"GlobeLabels Component",
"globebrowsing_globelabelscomponent",
{
{
LabelsInfo.identifier,
new BoolVerifier,
Optional::Yes,
LabelsInfo.description
},
{
LabelsEnableInfo.identifier,
new BoolVerifier,
Optional::Yes,
LabelsEnableInfo.description
},
{
LabelsFontSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsFontSizeInfo.description
},
{
LabelsMaxSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsMaxSizeInfo.description
},
{
LabelsMinSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsMinSizeInfo.description
},
{
LabelsSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsSizeInfo.description
},
{
LabelsMinHeightInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsMinHeightInfo.description
},
{
LabelsColorInfo.identifier,
new Color3Verifier,
Optional::Yes,
LabelsColorInfo.description
},
{
LabelsOpacityInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsOpacityInfo.description
},
{
LabelsFadeInStartingDistanceInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsFadeInStartingDistanceInfo.description
},
{
LabelsFadeOutStartingDistanceInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsFadeOutStartingDistanceInfo.description
},
{
LabelsFadeInEnabledInfo.identifier,
new BoolVerifier,
Optional::Yes,
LabelsFadeInEnabledInfo.description
},
{
LabelsFadeOutEnabledInfo.identifier,
new BoolVerifier,
Optional::Yes,
LabelsFadeOutEnabledInfo.description
},
{
LabelsDisableCullingEnabledInfo.identifier,
new BoolVerifier,
Optional::Yes,
LabelsDisableCullingEnabledInfo.description
},
{
LabelsDistanceEPSInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LabelsDistanceEPSInfo.description
},
{
LabelAlignmentOptionInfo.identifier,
new StringVerifier,
Optional::Yes,
LabelAlignmentOptionInfo.description
},
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "globebrowsing_globelabelscomponent";
return doc;
}
GlobeLabelsComponent::GlobeLabelsComponent()
@@ -293,7 +251,7 @@ GlobeLabelsComponent::GlobeLabelsComponent()
, _labelsFadeInEnabled(LabelsFadeInEnabledInfo, false)
, _labelsFadeOutEnabled(LabelsFadeOutEnabledInfo, false)
, _labelsDisableCullingEnabled(LabelsDisableCullingEnabledInfo, false)
, _labelsDistaneEPS(LabelsDistanceEPSInfo, 100000.f, 1000.f, 10000000.f)
, _labelsDistanceEPS(LabelsDistanceEPSInfo, 100000.f, 1000.f, 10000000.f)
, _labelAlignmentOption(
LabelAlignmentOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
@@ -312,7 +270,7 @@ GlobeLabelsComponent::GlobeLabelsComponent()
addProperty(_labelsFadeInEnabled);
addProperty(_labelsFadeOutEnabled);
addProperty(_labelsDisableCullingEnabled);
addProperty(_labelsDistaneEPS);
addProperty(_labelsDistanceEPS);
_labelAlignmentOption.addOption(Horizontally, "Horizontally");
_labelAlignmentOption.addOption(Circularly, "Circularly");
@@ -324,125 +282,45 @@ void GlobeLabelsComponent::initialize(const ghoul::Dictionary& dictionary,
globebrowsing::RenderableGlobe* globe)
{
ZoneScoped
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"GlobeLabelsComponent"
);
_globe = globe;
// Reads labels' file and build cache file if necessary
if (dictionary.isEmpty()) {
return;
}
if (!dictionary.hasValue<std::string>(KeyLabelsFileName)) {
const Parameters p = codegen::bake<Parameters>(dictionary);
if (!p.fileName.has_value()) {
return;
}
std::string labelsFile = dictionary.value<std::string>(KeyLabelsFileName);
bool loadSuccess = loadLabelsData(absPath(labelsFile));
const bool loadSuccess = loadLabelsData(absPath(p.fileName->string()));
if (!loadSuccess) {
return;
}
if (dictionary.hasKey(LabelsEnableInfo.identifier)) {
// In case of the label's dic is present but is disabled
_labelsEnabled = dictionary.value<bool>(LabelsEnableInfo.identifier);
}
else {
// Is the labels dic is enable in the configuration file,
// enables the label automatically.
_labelsEnabled = true;
}
if (dictionary.hasKey(LabelsFontSizeInfo.identifier)) {
_labelsFontSize = static_cast<float>(
dictionary.value<double>(LabelsFontSizeInfo.identifier)
);
_labelsFontSize.onChange([this]() { initializeFonts(); });
}
_labelsEnabled = p.enable.value_or(true);
_labelsFontSize = p.labelsFontSize.value_or(_labelsFontSize);
_labelsFontSize.onChange([this]() { initializeFonts(); });
_labelsSize = p.labelsSize.value_or(_labelsSize);
_labelsMinHeight = p.labelsMinHeight.value_or(_labelsMinHeight);
_labelsColor = p.labelsColor.value_or(_labelsColor);
_labelsOpacity = p.labelsOpacity.value_or(_labelsOpacity);
_labelsFadeInEnabled = p.labelsFadeInEnabled.value_or(_labelsFadeInEnabled);
_labelsFadeInDist = p.fadeInStartingDistance.value_or(_labelsFadeInDist);
_labelsFadeOutEnabled = p.labelsFadeOutEnabled.value_or(_labelsFadeOutEnabled);
_labelsFadeOutDist = p.fadeOutStartingDistance.value_or(_labelsFadeOutDist);
_labelsMinSize = p.labelsMinSize.value_or(_labelsMinSize);
_labelsMaxSize = p.labelsMaxSize.value_or(_labelsMaxSize);
_labelsDisableCullingEnabled =
p.labelsDisableCullingEnabled.value_or(_labelsDisableCullingEnabled);
_labelsDistanceEPS = p.labelsDistanceEPS.value_or(_labelsDistanceEPS);
if (dictionary.hasKey(LabelsSizeInfo.identifier)) {
_labelsSize = static_cast<float>(
dictionary.value<double>(LabelsSizeInfo.identifier)
);
}
if (dictionary.hasKey(LabelsMinHeightInfo.identifier)) {
_labelsMinHeight = static_cast<float>(
dictionary.value<double>(LabelsMinHeightInfo.identifier)
);
}
if (dictionary.hasKey(LabelsColorInfo.identifier)) {
_labelsColor = dictionary.value<glm::dvec3>(LabelsColorInfo.identifier);
}
if (dictionary.hasKey(LabelsOpacityInfo.identifier)) {
_labelsOpacity = static_cast<float>(
dictionary.value<double>(LabelsOpacityInfo.identifier)
);
}
if (dictionary.hasKey(LabelsFadeInEnabledInfo.identifier)) {
_labelsFadeInEnabled = dictionary.value<bool>(LabelsFadeInEnabledInfo.identifier);
}
if (dictionary.hasKey(LabelsFadeInStartingDistanceInfo.identifier)) {
_labelsFadeInDist = static_cast<float>(
dictionary.value<double>(LabelsFadeInStartingDistanceInfo.identifier)
);
}
if (dictionary.hasKey(LabelsFadeOutEnabledInfo.identifier)) {
_labelsFadeOutEnabled = dictionary.value<bool>(
LabelsFadeOutEnabledInfo.identifier
);
}
if (dictionary.hasKey(LabelsFadeOutStartingDistanceInfo.identifier)) {
_labelsFadeOutDist = static_cast<float>(
dictionary.value<double>(LabelsFadeOutStartingDistanceInfo.identifier)
);
}
if (dictionary.hasKey(LabelsMinSizeInfo.identifier)) {
_labelsMinSize = static_cast<int>(
dictionary.value<double>(LabelsMinSizeInfo.identifier)
);
}
if (dictionary.hasKey(LabelsMaxSizeInfo.identifier)) {
_labelsMaxSize = static_cast<int>(
dictionary.value<double>(LabelsMaxSizeInfo.identifier)
);
}
if (dictionary.hasKey(LabelsDisableCullingEnabledInfo.identifier)) {
bool disabled = dictionary.value<bool>(
LabelsDisableCullingEnabledInfo.identifier
);
_labelsDisableCullingEnabled = disabled;
}
if (dictionary.hasKey(LabelsDistanceEPSInfo.identifier)) {
_labelsDistaneEPS = static_cast<float>(
dictionary.value<double>(LabelsDistanceEPSInfo.identifier)
);
}
if (dictionary.hasKey(LabelAlignmentOptionInfo.identifier)) {
std::string alignment =
dictionary.value<std::string>(LabelAlignmentOptionInfo.identifier);
if (alignment == "Horizontally") {
_labelAlignmentOption = Horizontally;
}
else if (alignment == "Circularly" ) {
_labelAlignmentOption = Circularly;
}
else {
LERROR("Unknown alignment option: " + alignment);
if (p.labelAlignmentOption.has_value()) {
switch (*p.labelAlignmentOption) {
case Parameters::Alignment::Horizontally:
_labelAlignmentOption = Horizontally;
break;
case Parameters::Alignment::Circularly:
_labelAlignmentOption = Circularly;
break;
default:
throw ghoul::MissingCaseException();
}
}
@@ -732,7 +610,7 @@ void GlobeLabelsComponent::renderLabels(const RenderData& data,
glm::length(locationPositionWorld - data.camera.positionVec3());
if (_labelsDisableCullingEnabled ||
((distToCamera > (distanceCameraToLabelWorld + _labelsDistaneEPS)) &&
((distToCamera > (distanceCameraToLabelWorld + _labelsDistanceEPS)) &&
isLabelInFrustum(VP, locationPositionWorld)))
{
if (_labelAlignmentOption == Circularly) {
@@ -96,7 +96,7 @@ private:
properties::BoolProperty _labelsFadeInEnabled;
properties::BoolProperty _labelsFadeOutEnabled;
properties::BoolProperty _labelsDisableCullingEnabled;
properties::FloatProperty _labelsDistaneEPS;
properties::FloatProperty _labelsDistanceEPS;
properties::OptionProperty _labelAlignmentOption;
private:
+34 -63
View File
@@ -74,51 +74,33 @@ namespace {
"as an offset from the heightmap. Otherwise, it will be an offset from the "
"globe's reference ellipsoid. The default value is 'false'."
};
struct [[codegen::Dictionary(GlobeTranslation)]] Parameters {
// [[codegen::verbatim(GlobeInfo.description)]]
std::string globe
[[codegen::annotation("A valid scene graph node with a RenderableGlobe")]];
// [[codegen::verbatim(LongitudeInfo.description)]]
std::optional<double> longitude;
// [[codegen::verbatim(LatitudeInfo.description)]]
std::optional<double> latitude;
// [[codegen::verbatim(AltitudeInfo.description)]]
std::optional<double> altitude;
// [[codegen::verbatim(UseHeightmapInfo.description)]]
std::optional<bool> useHeightmap;
};
#include "globetranslation_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
documentation::Documentation GlobeTranslation::Documentation() {
using namespace openspace::documentation;
return {
"Globe Translation",
"space_translation_globetranslation",
{
{
GlobeInfo.identifier,
new StringAnnotationVerifier(
"A valid scene graph node with a RenderableGlobe"
),
Optional::No,
GlobeInfo.description
},
{
LongitudeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LongitudeInfo.description
},
{
LatitudeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LatitudeInfo.description,
},
{
AltitudeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
AltitudeInfo.description
},
{
UseHeightmapInfo.identifier,
new BoolVerifier,
Optional::Yes,
UseHeightmapInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "space_translation_globetranslation";
return doc;
}
GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
@@ -128,39 +110,28 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
, _altitude(AltitudeInfo, 0.0, 0.0, 1e12)
, _useHeightmap(UseHeightmapInfo, false)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"GlobeTranslation"
);
_globe = dictionary.value<std::string>(GlobeInfo.identifier);
if (dictionary.hasKey(LongitudeInfo.identifier)) {
_longitude = dictionary.value<double>(LongitudeInfo.identifier);
}
if (dictionary.hasKey(LatitudeInfo.identifier)) {
_latitude = dictionary.value<double>(LatitudeInfo.identifier);
}
if (dictionary.hasKey(AltitudeInfo.identifier)) {
_altitude = dictionary.value<double>(AltitudeInfo.identifier);
}
if (dictionary.hasKey(UseHeightmapInfo.identifier)) {
_useHeightmap = dictionary.value<bool>(UseHeightmapInfo.identifier);
}
const Parameters p = codegen::bake<Parameters>(dictionary);
_globe = p.globe;
_globe.onChange([this]() {
fillAttachedNode();
_positionIsDirty = true;
});
_longitude = p.longitude.value_or(_longitude);
_longitude.onChange([this]() { _positionIsDirty = true; });
_latitude.onChange([this]() { _positionIsDirty = true; });
_altitude.onChange([this]() { _positionIsDirty = true; });
_useHeightmap.onChange([this]() { _positionIsDirty = true; });
addProperty(_longitude);
_latitude = p.latitude.value_or(_latitude);
_latitude.onChange([this]() { _positionIsDirty = true; });
addProperty(_latitude);
_altitude = p.altitude.value_or(_altitude);
_altitude.onChange([this]() { _positionIsDirty = true; });
addProperty(_altitude);
_useHeightmap = p.useHeightmap.value_or(_useHeightmap);
_useHeightmap.onChange([this]() { _positionIsDirty = true; });
addProperty(_useHeightmap);
}
+40 -52
View File
@@ -26,12 +26,9 @@
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <optional>
namespace {
constexpr const char* KeyType = "Type";
constexpr const char* KeyChromaKeyColor = "ChromaKeyColor";
constexpr const char* KeyChromaKeyTolerance = "ChromaKeyTolerance";
constexpr openspace::properties::Property::PropertyInfo ChromaKeyColorInfo = {
"ChromaKeyColor",
"Chroma Key Color",
@@ -50,37 +47,32 @@ namespace {
"Type",
"The type of layer adjustment that is applied to the underlying layer."
};
struct [[codegen::Dictionary(LayerAdjustment)]] Parameters {
enum class Type {
None,
ChromaKey,
TransferFunction
};
// Specifies the type of the adjustment that is applied
std::optional<Type> type;
// Specifies the chroma key used when selecting 'ChromaKey' for the 'Type'
std::optional<glm::vec3> chromaKeyColor [[codegen::color()]];
// Specifies the tolerance to match the color to the chroma key when the
// 'ChromaKey' type is selected for the 'Type'
std::optional<float> chromaKeyTolerance;
};
#include "layeradjustment_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
documentation::Documentation LayerAdjustment::Documentation() {
using namespace documentation;
return {
"LayerAdjustment",
"globebrowsing_layeradjustment",
{
{
KeyType,
new StringInListVerifier({ "None", "ChromaKey", "TransferFunction" }),
Optional::Yes,
"Specifies the type of the adjustment that is applied"
},
{
KeyChromaKeyColor,
new Color3Verifier,
Optional::Yes,
"Specifies the chroma key used when selecting 'ChromaKey' for the 'Type'."
},
{
KeyChromaKeyTolerance,
new DoubleVerifier,
Optional::Yes,
"Specifies the tolerance to match the color to the chroma key when the "
"'ChromaKey' type is selected for the 'Type'."
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "globebrowsing_layeradjustment";
return doc;
}
LayerAdjustment::LayerAdjustment()
@@ -121,31 +113,27 @@ LayerAdjustment::LayerAdjustment()
}
void LayerAdjustment::setValuesFromDictionary(const ghoul::Dictionary& adjustmentDict) {
documentation::testSpecificationAndThrow(
Documentation(),
adjustmentDict,
"LayerAdjustment"
);
const Parameters p = codegen::bake<Parameters>(adjustmentDict);
if (adjustmentDict.hasValue<std::string>(KeyType)) {
std::string dictType = adjustmentDict.value<std::string>(KeyType);
_typeOption = static_cast<int>(
ghoul::from_string<layergroupid::AdjustmentTypeID>(dictType)
);
if (p.type.has_value()) {
switch (*p.type) {
case Parameters::Type::None:
_typeOption = static_cast<int>(layergroupid::AdjustmentTypeID::None);
break;
case Parameters::Type::ChromaKey:
_typeOption = static_cast<int>(layergroupid::AdjustmentTypeID::ChromaKey);
break;
case Parameters::Type::TransferFunction:
_typeOption =
static_cast<int>(layergroupid::AdjustmentTypeID::TransferFunction);
break;
default:
throw ghoul::MissingCaseException();
}
}
if (adjustmentDict.hasValue<glm::dvec3>(KeyChromaKeyColor)) {
glm::vec3 dictChromaKeyColor =
adjustmentDict.value<glm::dvec3>(KeyChromaKeyColor);
_chromaKeyColor = std::move(dictChromaKeyColor);
}
if (adjustmentDict.hasValue<double>(KeyChromaKeyTolerance)) {
float dictChromaKeyTolerance = static_cast<float>(
adjustmentDict.value<double>(KeyChromaKeyTolerance)
);
_chromaKeyTolerance = dictChromaKeyTolerance;
}
_chromaKeyColor = p.chromaKeyColor.value_or(_chromaKeyColor);
_chromaKeyTolerance = p.chromaKeyTolerance.value_or(_chromaKeyTolerance);
}
layergroupid::AdjustmentTypeID LayerAdjustment::type() const {
+77 -105
View File
@@ -79,11 +79,6 @@ namespace {
bool isShadowing = false;
};
constexpr const char* KeyRadii = "Radii";
constexpr const char* KeyLayers = "Layers";
constexpr const char* KeyShadowGroup = "ShadowGroup";
constexpr const char* KeyLabels = "Labels";
const openspace::globebrowsing::AABB3 CullingFrustum{
glm::vec3(-1.f, -1.f, 0.f),
glm::vec3( 1.f, 1.f, 1e35)
@@ -232,6 +227,47 @@ namespace {
"This is the number of currently active layers, if this value reaches the "
"maximum, bad things will happen."
};
struct [[codegen::Dictionary(RenderableGlobe)]] Parameters {
// Specifies the radii for this planet. If the Double version of this is used, all
// three radii are assumed to be equal
std::optional<std::variant<glm::dvec3, double>> radii;
// Specifies whether the planet should be shaded by the primary light source or
// not. If it is disabled, all parts of the planet are illuminated
std::optional<bool> performShading;
// A list of all the layers that should be added
std::map<std::string, ghoul::Dictionary> layers
[[codegen::reference("globebrowsing_layermanager")]];
// Specifies information about planetary labels that can be rendered on the
// object's surface
std::optional<ghoul::Dictionary> labels
[[codegen::reference("globebrowsing_globelabelscomponent")]];
struct ShadowGroup {
struct Source {
std::string name;
double radius;
};
std::vector<Source> sources;
struct Caster {
std::string name;
double radius;
};
std::vector<Caster> casters;
};
std::optional<ShadowGroup> shadowGroup;
std::optional<ghoul::Dictionary> rings
[[codegen::reference("globebrowsing_rings_component")]];
std::optional<ghoul::Dictionary> shadows
[[codegen::reference("globebrowsing_shadows_component")]];
};
#include "renderableglobe_codegen.cpp"
} // namespace
using namespace openspace::properties;
@@ -461,48 +497,9 @@ Chunk::Chunk(const TileIndex& ti)
{}
documentation::Documentation RenderableGlobe::Documentation() {
using namespace documentation;
return {
"RenderableGlobe",
"globebrowsing_renderableglobe",
{
{
KeyRadii,
new OrVerifier({ new DoubleVector3Verifier, new DoubleVerifier }),
Optional::Yes,
"Specifies the radii for this planet. If the Double version of this is "
"used, all three radii are assumed to be equal."
},
{
"PerformShading",
new BoolVerifier,
Optional::Yes,
"Specifies whether the planet should be shaded by the primary light "
"source or not. If it is disabled, all parts of the planet are "
"illuminated."
},
{
KeyLayers,
new TableVerifier({
{
"*",
new ReferencingVerifier("globebrowsing_layermanager"),
Optional::Yes,
"Descriptions of the individual layer groups"
}
}),
Optional::Yes,
"A list of all the layers that should be added"
},
{
KeyLabels,
new ReferencingVerifier("globebrowsing_globelabelscomponent"),
Optional::Yes,
"Specifies information about planetary labels that can be rendered on "
"the object's surface."
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "globebrowsing_renderableglobe";
return doc;
}
RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
@@ -539,75 +536,52 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
, _ringsComponent(dictionary)
, _shadowComponent(dictionary)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_generalProperties.currentLodScaleFactor.setReadOnly(true);
// Read the radii in to its own dictionary
if (dictionary.hasValue<glm::dvec3>(KeyRadii)) {
_ellipsoid = Ellipsoid(dictionary.value<glm::dvec3>(KeyRadii));
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
}
else if (dictionary.hasValue<double>(KeyRadii)) {
const double radius = dictionary.value<double>(KeyRadii);
_ellipsoid = Ellipsoid({ radius, radius, radius });
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
if (p.radii.has_value()) {
if (std::holds_alternative<glm::dvec3>(*p.radii)) {
_ellipsoid = Ellipsoid(std::get<glm::dvec3>(*p.radii));
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
}
else if (std::holds_alternative<double>(*p.radii)) {
const double radius = std::get<double>(*p.radii);
_ellipsoid = Ellipsoid({ radius, radius, radius });
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
}
else {
throw ghoul::MissingCaseException();
}
}
if (dictionary.hasKey("PerformShading")) {
_generalProperties.performShading = dictionary.value<bool>("PerformShading");
}
_generalProperties.performShading =
p.performShading.value_or(_generalProperties.performShading);
// Init layer manager
ghoul::Dictionary layersDictionary;
if (!dictionary.hasValue<ghoul::Dictionary>(KeyLayers)) {
throw ghoul::RuntimeError(std::string(KeyLayers) + " must be specified");
}
layersDictionary = dictionary.value<ghoul::Dictionary>(KeyLayers);
// @TODO (abock, 2021-03-25) The layermanager should be changed to take a
// std::map<std::string, ghoul::Dictionary> instead and then we don't need to get it
// as a bare dictionary anymore and can use the value from the struct directly
ghoul::Dictionary layersDictionary = dictionary.value<ghoul::Dictionary>("Layers");
_layerManager.initialize(layersDictionary);
addProperty(_generalProperties.performShading);
addProperty(_generalProperties.useAccurateNormals);
// ================================================================
// ======== Reads Shadow (Eclipses) Entries in asset file =========
// ================================================================
if (dictionary.hasValue<ghoul::Dictionary>(KeyShadowGroup)) {
ghoul::Dictionary shadowDictionary =
dictionary.value<ghoul::Dictionary>(KeyShadowGroup);
std::vector<std::pair<std::string, double>> sourceArray;
ghoul::Dictionary sources = shadowDictionary.value<ghoul::Dictionary>("Sources");
for (std::string_view k : sources.keys()) {
ghoul::Dictionary source = sources.value<ghoul::Dictionary>(k);
std::string name = source.value<std::string>("Name");
double radius = source.value<double>("Radius");
sourceArray.emplace_back(name, radius);
}
std::vector<std::pair<std::string, double>> casterArray;
ghoul::Dictionary casters = shadowDictionary.value<ghoul::Dictionary>("Casters");
for (std::string_view k : casters.keys()) {
ghoul::Dictionary caster = casters.value<ghoul::Dictionary>(k);
std::string name = caster.value<std::string>("Name");
double radius = caster.value<double>("Radius");
casterArray.emplace_back(name, radius);
}
if (p.shadowGroup.has_value()) {
std::vector<Ellipsoid::ShadowConfiguration> shadowConfArray;
for (const std::pair<std::string, double>& source : sourceArray) {
for (const std::pair<std::string, double>& caster : casterArray) {
for (const Parameters::ShadowGroup::Source& source : p.shadowGroup->sources) {
for (const Parameters::ShadowGroup::Caster& caster : p.shadowGroup->casters) {
Ellipsoid::ShadowConfiguration sc;
sc.source = source;
sc.caster = caster;
sc.source = std::pair<std::string, double>(source.name, source.radius);
sc.caster = std::pair<std::string, double>(source.name, source.radius);
shadowConfArray.push_back(sc);
}
}
_ellipsoid.setShadowConfigurationArray(shadowConfArray);
}
if (!_ellipsoid.shadowConfigurationArray().empty()) {
addProperty(_generalProperties.eclipseShadowsEnabled);
addProperty(_generalProperties.eclipseHardShadows);
}
@@ -667,22 +641,20 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
_localChunkBuffer.resize(2048);
_traversalMemory.resize(512);
// Labels Dictionary
if (dictionary.hasValue<ghoul::Dictionary>(KeyLabels)) {
_labelsDictionary = dictionary.value<ghoul::Dictionary>(KeyLabels);
}
_labelsDictionary = p.labels.value_or(_labelsDictionary);
// Components
if (dictionary.hasValue<ghoul::Dictionary>("Rings")) {
_hasRings = p.rings.has_value();
if (_hasRings) {
_ringsComponent.initialize();
addPropertySubOwner(_ringsComponent);
_hasRings = true;
}
if (dictionary.hasKey("Shadows")) {
_hasShadows = p.shadows.has_value();
if (_hasShadows) {
_shadowComponent.initialize();
addPropertySubOwner(_shadowComponent);
_hasShadows = true;
_generalProperties.shadowMapping = true;
}
_generalProperties.shadowMapping.onChange(notifyShaderRecompilation);
+74 -135
View File
@@ -46,6 +46,7 @@
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <ghoul/io/texture/texturereader.h>
#include <filesystem>
#include <fstream>
#include <cstdlib>
#include <locale>
@@ -155,90 +156,53 @@ namespace {
"The number of samples used during shadow mapping calculation "
"(Percentage Closer Filtering)."
};
struct [[codegen::Dictionary(RingsComponent)]] Parameters {
// [[codegen::verbatim(TextureInfo.description)]]
std::optional<std::filesystem::path> texture;
// [[codegen::verbatim(TextureFwrdInfo.description)]]
std::optional<std::filesystem::path> textureFwrd;
// [[codegen::verbatim(TextureBckwrdInfo.description)]]
std::optional<std::filesystem::path> textureBckwrd;
// [[codegen::verbatim(TextureUnlitInfo.description)]]
std::optional<std::filesystem::path> textureUnlit;
// [[codegen::verbatim(TextureColorInfo.description)]]
std::optional<std::filesystem::path> textureColor;
// [[codegen::verbatim(TextureTransparencyInfo.description)]]
std::optional<std::filesystem::path> textureTransparency;
// [[codegen::verbatim(SizeInfo.description)]]
std::optional<float> size;
// [[codegen::verbatim(OffsetInfo.description)]]
std::optional<glm::vec2> offset;
// [[codegen::verbatim(NightFactorInfo.description)]]
std::optional<float> nightFactor;
// [[codegen::verbatim(ColorFilterInfo.description)]]
std::optional<float> colorFilter;
// [[codegen::verbatim(ZFightingPercentageInfo.description)]]
std::optional<float> zFightingPercentage;
// [[codegen::verbatim(NumberShadowSamplesInfo.description)]]
std::optional<int> numberShadowSamples;
};
#include "ringscomponent_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RingsComponent::Documentation() {
using namespace documentation;
return {
"Rings Component",
"globebrowsing_rings_component",
{
{
TextureInfo.identifier,
new StringVerifier,
Optional::Yes,
TextureInfo.description
},
{
TextureFwrdInfo.identifier,
new StringVerifier,
Optional::Yes,
TextureFwrdInfo.description
},
{
TextureBckwrdInfo.identifier,
new StringVerifier,
Optional::Yes,
TextureBckwrdInfo.description
},
{
TextureUnlitInfo.identifier,
new StringVerifier,
Optional::Yes,
TextureUnlitInfo.description
},
{
TextureColorInfo.identifier,
new StringVerifier,
Optional::Yes,
TextureColorInfo.description
},
{
TextureTransparencyInfo.identifier,
new StringVerifier,
Optional::Yes,
TextureTransparencyInfo.description
},
{
SizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
SizeInfo.description
},
{
OffsetInfo.identifier,
new DoubleVector2Verifier,
Optional::Yes,
OffsetInfo.description
},
{
NightFactorInfo.identifier,
new DoubleVerifier,
Optional::Yes,
NightFactorInfo.description
},
{
ColorFilterInfo.identifier,
new DoubleVerifier,
Optional::Yes,
ColorFilterInfo.description
},
{
ZFightingPercentageInfo.identifier,
new DoubleVerifier,
Optional::Yes,
ZFightingPercentageInfo.description
},
{
NumberShadowSamplesInfo.identifier,
new IntVerifier,
Optional::Yes,
NumberShadowSamplesInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "globebrowsing_rings_component";
return doc;
}
RingsComponent::RingsComponent(const ghoul::Dictionary& dictionary)
@@ -265,14 +229,17 @@ RingsComponent::RingsComponent(const ghoul::Dictionary& dictionary)
// term and rather extract the values directly here. This would require a bit of
// a rewrite in the RenderableGlobe class to not create the RingsComponent in the
// class-initializer list though
// @TODO (abock, 2021-03-25) Righto! The RenderableGlobe passes this dictionary
// in as-is so it would be easy to just pass it directly to the initialize method
// instead
_ringsDictionary = dictionary.value<ghoul::Dictionary>("Rings");
}
documentation::testSpecificationAndThrow(
Documentation(),
_ringsDictionary,
"RingsComponent"
);
documentation::testSpecificationAndThrow(
Documentation(),
_ringsDictionary,
"RingsComponent"
);
}
}
void RingsComponent::initialize() {
@@ -280,106 +247,78 @@ void RingsComponent::initialize() {
using ghoul::filesystem::File;
const Parameters p = codegen::bake<Parameters>(_ringsDictionary);
addProperty(_enabled);
_size = static_cast<float>(_ringsDictionary.value<double>(SizeInfo.identifier));
//setBoundingSphere(_size);
_size = p.size.value_or(_size);
_size.onChange([&]() { _planeIsDirty = true; });
addProperty(_size);
if (_ringsDictionary.hasKey(TextureInfo.identifier)) {
_texturePath = absPath(
_ringsDictionary.value<std::string>(TextureInfo.identifier)
);
if (p.texture.has_value()) {
_texturePath = absPath(p.texture->string());
_textureFile = std::make_unique<File>(_texturePath);
_texturePath.onChange([&]() { loadTexture(); });
addProperty(_texturePath);
_textureFile->setCallback([&](const File&) { _textureIsDirty = true; });
}
if (_ringsDictionary.hasKey(TextureFwrdInfo.identifier)) {
_textureFwrdPath = absPath(
_ringsDictionary.value<std::string>(TextureFwrdInfo.identifier)
);
if (p.textureFwrd.has_value()) {
_textureFwrdPath = absPath(p.textureFwrd->string());
_textureFileForwards = std::make_unique<File>(_textureFwrdPath);
_textureFwrdPath.onChange([&]() { loadTexture(); });
addProperty(_textureFwrdPath);
_textureFileForwards->setCallback([&](const File&) { _textureIsDirty = true; });
}
if (_ringsDictionary.hasKey(TextureBckwrdInfo.identifier)) {
_textureBckwrdPath = absPath(
_ringsDictionary.value<std::string>(TextureBckwrdInfo.identifier)
);
if (p.textureBckwrd.has_value()) {
_textureBckwrdPath = absPath(p.textureBckwrd->string());
_textureFileBackwards = std::make_unique<File>(_textureBckwrdPath);
_textureBckwrdPath.onChange([&]() { loadTexture(); });
addProperty(_textureBckwrdPath);
_textureFileBackwards->setCallback([&](const File&) { _textureIsDirty = true; });
}
if (_ringsDictionary.hasKey(TextureUnlitInfo.identifier)) {
_textureUnlitPath = absPath(
_ringsDictionary.value<std::string>(TextureUnlitInfo.identifier)
);
if (p.textureUnlit.has_value()) {
_textureUnlitPath = absPath(p.textureUnlit->string());
_textureFileUnlit = std::make_unique<File>(_textureUnlitPath);
_textureUnlitPath.onChange([&]() { loadTexture(); });
addProperty(_textureUnlitPath);
_textureFileUnlit->setCallback([&](const File&) { _textureIsDirty = true; });
}
if (_ringsDictionary.hasKey(TextureColorInfo.identifier)) {
_textureColorPath = absPath(
_ringsDictionary.value<std::string>(TextureColorInfo.identifier)
);
if (p.textureColor.has_value()) {
_textureColorPath = absPath(p.textureColor->string());
_textureFileColor = std::make_unique<File>(_textureColorPath);
_textureColorPath.onChange([&]() { loadTexture(); });
addProperty(_textureColorPath);
_textureFileColor->setCallback([&](const File&) { _textureIsDirty = true; });
}
if (_ringsDictionary.hasKey(TextureTransparencyInfo.identifier)) {
_textureTransparencyPath = absPath(
_ringsDictionary.value<std::string>(TextureTransparencyInfo.identifier)
);
if (p.textureTransparency.has_value()) {
_textureTransparencyPath = absPath(p.textureTransparency->string());
_textureFileTransparency = std::make_unique<File>(_textureTransparencyPath);
_textureTransparencyPath.onChange([&]() { loadTexture(); });
addProperty(_textureTransparencyPath);
_textureFileTransparency->setCallback([&](const File&) { _textureIsDirty = true; });
}
if (_ringsDictionary.hasValue<glm::dvec2>(OffsetInfo.identifier)) {
_offset = _ringsDictionary.value<glm::dvec2>(OffsetInfo.identifier);
}
_offset = p.offset.value_or(_offset);
addProperty(_offset);
if (_ringsDictionary.hasValue<double>(NightFactorInfo.identifier)) {
_nightFactor = static_cast<float>(
_ringsDictionary.value<double>(NightFactorInfo.identifier)
);
}
_nightFactor = p.nightFactor.value_or(_nightFactor);
addProperty(_nightFactor);
if (_ringsDictionary.hasValue<double>(ColorFilterInfo.identifier)) {
_colorFilter = static_cast<float>(
_ringsDictionary.value<double>(ColorFilterInfo.identifier)
);
}
_colorFilter = p.colorFilter.value_or(_colorFilter);
addProperty(_colorFilter);
// Shadow Mapping Quality Controls
if (_ringsDictionary.hasKey(ZFightingPercentageInfo.identifier)) {
_zFightingPercentage = static_cast<float>(
_ringsDictionary.value<double>(ZFightingPercentageInfo.identifier)
);
}
_zFightingPercentage = p.zFightingPercentage.value_or(_zFightingPercentage);
addProperty(_zFightingPercentage);
if (_ringsDictionary.hasKey(NumberShadowSamplesInfo.identifier)) {
_nShadowSamples = _ringsDictionary.value<int>(NumberShadowSamplesInfo.identifier);
}
_nShadowSamples = p.numberShadowSamples.value_or(_nShadowSamples);
_nShadowSamples.onChange([this]() { compileShadowShader(); });
addProperty(_nShadowSamples);
addProperty(_colorFilter);
}
bool RingsComponent::isReady() const {
+28 -48
View File
@@ -141,30 +141,23 @@ namespace {
}
}
}
struct [[codegen::Dictionary(ShadowComponent)]] Parameters {
// [[codegen::verbatim(DistanceFractionInfo.description)]]
std::optional<int> distanceFraction;
// [[codegen::verbatim(DepthMapSizeInfo.description)]]
std::optional<glm::ivec2> depthMapSize;
};
#include "shadowcomponent_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation ShadowComponent::Documentation() {
using namespace documentation;
return {
"ShadowsRing Component",
"globebrowsing_shadows_component",
{
{
DistanceFractionInfo.identifier,
new DoubleVerifier,
Optional::Yes,
DistanceFractionInfo.description
},
{
DepthMapSizeInfo.identifier,
new Vector2ListVerifier<double>,
Optional::Yes,
DepthMapSizeInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "globebrowsing_shadows_component";
return doc;
}
ShadowComponent::ShadowComponent(const ghoul::Dictionary& dictionary)
@@ -172,37 +165,30 @@ ShadowComponent::ShadowComponent(const ghoul::Dictionary& dictionary)
, _saveDepthTexture(SaveDepthTextureInfo)
, _distanceFraction(DistanceFractionInfo, 20, 1, 10000)
, _enabled({ "Enabled", "Enabled", "Enable/Disable Shadows" }, true)
, _shadowMapDictionary(dictionary)
{
using ghoul::filesystem::File;
if (dictionary.hasValue<ghoul::Dictionary>("Shadows")) {
// @TODO (abock, 2019-12-16) It would be better to not store the dictionary long
// term and rather extract the values directly here. This would require a bit of
// a rewrite in the RenderableGlobe class to not create the ShadowComponent in the
// class-initializer list though
_shadowMapDictionary = dictionary.value<ghoul::Dictionary>("Shadows");
// @TODO (abock, 2021-03-25) This is not really a nice solution as this key name is
// coded into the RenderableGlobe. Instead, the parent should unpack the dictionary
// and pass the unpacked dictionary in here; Or maybe we don't want a dictionary at
// this state anyway?
if (!dictionary.hasValue<ghoul::Dictionary>("Shadows")) {
return;
}
ghoul::Dictionary d = dictionary.value<ghoul::Dictionary>("Shadows");
const Parameters p = codegen::bake<Parameters>(d);
documentation::testSpecificationAndThrow(
Documentation(),
_shadowMapDictionary,
"ShadowComponent"
);
addProperty(_enabled);
_distanceFraction = p.distanceFraction.value_or(_distanceFraction);
addProperty(_distanceFraction);
if (_shadowMapDictionary.hasKey(DistanceFractionInfo.identifier)) {
_distanceFraction = static_cast<int>(
_shadowMapDictionary.value<double>(DistanceFractionInfo.identifier)
);
}
_saveDepthTexture.onChange([&]() { _executeDepthTextureSave = true; });
if (_shadowMapDictionary.hasKey(DepthMapSizeInfo.identifier)) {
glm::dvec2 depthMapSize =
_shadowMapDictionary.value<glm::dvec2>(DepthMapSizeInfo.identifier);
_shadowDepthTextureWidth = static_cast<int>(depthMapSize.x);
_shadowDepthTextureHeight = static_cast<int>(depthMapSize.y);
if (p.depthMapSize.has_value()) {
_shadowDepthTextureWidth = p.depthMapSize->x;
_shadowDepthTextureHeight = p.depthMapSize->y;
_dynamicDepthTextureRes = false;
}
else {
@@ -212,13 +198,7 @@ ShadowComponent::ShadowComponent(const ghoul::Dictionary& dictionary)
_dynamicDepthTextureRes = true;
}
_saveDepthTexture.onChange([&]() { _executeDepthTextureSave = true; });
_viewDepthMap = false;
addProperty(_enabled);
addProperty(_saveDepthTexture);
addProperty(_distanceFraction);
}
void ShadowComponent::initialize() {
@@ -105,8 +105,6 @@ private:
properties::IntProperty _distanceFraction;
properties::BoolProperty _enabled;
ghoul::Dictionary _shadowMapDictionary;
int _shadowDepthTextureHeight = 4096;
int _shadowDepthTextureWidth = 4096;
bool _dynamicDepthTextureRes = true;