Merge branch 'master' into feature/model-animation

* Resolve conflicts
This commit is contained in:
Malin Ejdbo
2021-03-30 16:31:25 +02:00
71 changed files with 2203 additions and 3431 deletions
@@ -179,7 +179,8 @@ namespace {
// A list of objects that cast light on this atmosphere
std::vector<CasterElement> casters;
};
// Declares shadow groups, meaning which nodes are considered in shadow calculations
// Declares shadow groups, meaning which nodes are considered in shadow
// calculations
std::optional<ShadowGroup> shadowGroup;
// [[codegen::verbatim(AtmosphereHeightInfo.description)]]
@@ -360,7 +361,7 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
_mieScatteringExtinctionPropCoefficient.onChange(updateWithCalculation);
addProperty(_mieScatteringExtinctionPropCoefficient);
if (p.debug.has_value()) {
_preCalculatedTexturesScale =
p.debug->preCalculatedTextureScale.value_or(_preCalculatedTexturesScale);
+1 -1
View File
@@ -55,7 +55,7 @@ namespace {
struct [[codegen::Dictionary(DashboardItemDate)]] Parameters {
// [[codegen::verbatim(FormatStringInfo.description)]]
std::optional<std::string> formatString;
// [[codegen::verbatim(TimeFormatInfo.description)]]
std::optional<std::string> timeFormat;
};
@@ -132,7 +132,8 @@ namespace {
DtAvg [[codegen::key("Average Deltatime")]],
DtExtremes [[codegen::key("Deltatime extremes")]],
DtStandardDeviation [[codegen::key("Deltatime standard deviation")]],
DtCoefficientOfVariation [[codegen::key("Deltatime coefficient of variation")]],
DtCoefficientOfVariation
[[codegen::key("Deltatime coefficient of variation")]],
FPS [[codegen::key("Frames per second")]],
FPSAvg [[codegen::key("Average frames per second")]]
};
@@ -187,7 +188,8 @@ DashboardItemFramerate::DashboardItemFramerate(const ghoul::Dictionary& dictiona
_frametimeType = static_cast<int>(FrametimeType::DtStandardDeviation);
break;
case Parameters::Type::DtCoefficientOfVariation:
_frametimeType = static_cast<int>(FrametimeType::DtCoefficientOfVariation);
_frametimeType =
static_cast<int>(FrametimeType::DtCoefficientOfVariation);
break;
case Parameters::Type::FPS:
_frametimeType = static_cast<int>(FrametimeType::FPS);
+44 -51
View File
@@ -30,6 +30,7 @@
#include <openspace/util/updatestructures.h>
#include <ghoul/opengl/programobject.h>
#include <numeric>
#include <optional>
// This class is using a VBO ring buffer + a constantly updated point as follows:
// Structure of the array with a _resolution of 16. FF denotes the floating position that
@@ -104,36 +105,32 @@ namespace {
"Opaque, Transparent, or Overlay rendering step. Default is Transparent."
};
struct [[codegen::Dictionary(RenderableTrailOrbit)]] Parameters {
// [[codegen::verbatim(PeriodInfo.description)]]
double period;
// [[codegen::verbatim(ResolutionInfo.description)]]
int resolution;
enum class RenderableType {
Background,
Opaque,
PreDeferredTransparent,
PostDeferredTransparent,
Overlay
};
// [[codegen::verbatim(RenderableTypeInfo.description)]]
std::optional<RenderableType> renderableType;
};
#include "renderabletrailorbit_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RenderableTrailOrbit::Documentation() {
using namespace documentation;
documentation::Documentation doc {
"RenderableTrailOrbit",
"base_renderable_renderabletrailorbit",
{
{
PeriodInfo.identifier,
new DoubleVerifier,
Optional::No,
PeriodInfo.description
},
{
ResolutionInfo.identifier,
new IntVerifier,
Optional::No,
ResolutionInfo.description
},
{
RenderableTypeInfo.identifier,
new StringVerifier,
Optional::Yes,
RenderableTypeInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "base_renderable_renderabletrailorbit";
// Insert the parents documentation entries until we have a verifier that can deal
// with class hierarchy
@@ -152,46 +149,42 @@ RenderableTrailOrbit::RenderableTrailOrbit(const ghoul::Dictionary& dictionary)
, _period(PeriodInfo, 0.0, 0.0, 1e9)
, _resolution(ResolutionInfo, 10000, 1, 1000000)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableTrailOrbit"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
_translation->onParameterChange([this]() { _needsFullSweep = true; });
// Period is in days
using namespace std::chrono;
const long long sph = duration_cast<seconds>(hours(24)).count();
_period = dictionary.value<double>(PeriodInfo.identifier) * sph;
_period = p.period * duration_cast<seconds>(hours(24)).count();
_period.onChange([&] { _needsFullSweep = true; _indexBufferDirty = true; });
addProperty(_period);
_resolution = static_cast<int>(dictionary.value<double>(ResolutionInfo.identifier));
_resolution = p.resolution;
_resolution.onChange([&] { _needsFullSweep = true; _indexBufferDirty = true; });
addProperty(_resolution);
// We store the vertices with (excluding the wrapping) decending temporal order
_primaryRenderInformation.sorting = RenderInformation::VertexSorting::NewestFirst;
if (dictionary.hasKey(RenderableTypeInfo.identifier)) {
std::string renderType = dictionary.value<std::string>(
RenderableTypeInfo.identifier
);
if (renderType == "Background") {
setRenderBin(Renderable::RenderBin::Background);
}
else if (renderType == "Opaque") {
setRenderBin(Renderable::RenderBin::Opaque);
}
else if (renderType == "PreDeferredTransparent") {
setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
}
else if (renderType == "PostDeferredTransparent") {
setRenderBin(Renderable::RenderBin::PostDeferredTransparent);
}
else if (renderType == "Overlay") {
setRenderBin(Renderable::RenderBin::Overlay);
if (p.renderableType.has_value()) {
switch (*p.renderableType) {
case Parameters::RenderableType::Background:
setRenderBin(Renderable::RenderBin::Background);
break;
case Parameters::RenderableType::Opaque:
setRenderBin(Renderable::RenderBin::Opaque);
break;
case Parameters::RenderableType::PreDeferredTransparent:
setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
break;
case Parameters::RenderableType::PostDeferredTransparent:
setRenderBin(Renderable::RenderBin::PostDeferredTransparent);
break;
case Parameters::RenderableType::Overlay:
setRenderBin(Renderable::RenderBin::Overlay);
break;
default:
throw ghoul::MissingCaseException();
}
}
else {
@@ -29,6 +29,7 @@
#include <openspace/scene/translation.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/updatestructures.h>
#include <optional>
// This class creates the entire trajectory at once and keeps it in memory the entire
// time. This means that there is no need for updating the trail at runtime, but also that
@@ -81,49 +82,31 @@ namespace {
"If this value is set to 'true', the entire trail will be rendered; if it is "
"'false', only the trail until the current time in the application will be shown."
};
struct [[codegen::Dictionary(RenderableTrailTrajectory)]] Parameters {
// [[codegen::verbatim(StartTimeInfo.description)]]
std::string startTime [[codegen::annotation("A valid date in ISO 8601 format")]];
// [[codegen::verbatim(EndTimeInfo.description)]]
std::string endTime [[codegen::annotation("A valid date in ISO 8601 format")]];
// [[codegen::verbatim(SampleIntervalInfo.description)]]
double sampleInterval;
// [[codegen::verbatim(TimeSubSampleInfo.description)]]
std::optional<int> timeStampSubsampleFactor;
// [[codegen::verbatim(RenderFullPathInfo.description)]]
std::optional<bool> showFullTrail;
};
#include "renderabletrailtrajectory_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RenderableTrailTrajectory::Documentation() {
using namespace documentation;
documentation::Documentation doc {
"RenderableTrailTrajectory",
"base_renderable_renderabletrailtrajectory",
{
{
StartTimeInfo.identifier,
new StringAnnotationVerifier("A valid date in ISO 8601 format"),
Optional::No,
StartTimeInfo.description
},
{
EndTimeInfo.identifier,
new StringAnnotationVerifier("A valid date in ISO 8601 format"),
Optional::No,
EndTimeInfo.description
},
{
SampleIntervalInfo.identifier,
new DoubleVerifier,
Optional::No,
SampleIntervalInfo.description
},
{
TimeSubSampleInfo.identifier,
new IntVerifier,
Optional::Yes,
TimeSubSampleInfo.description
},
{
RenderFullPathInfo.identifier,
new BoolVerifier,
Optional::Yes,
RenderFullPathInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "base_renderable_renderabletrailtrajectory";
// @TODO cleanup
// Insert the parents documentation entries until we have a verifier that can deal
@@ -146,37 +129,28 @@ RenderableTrailTrajectory::RenderableTrailTrajectory(const ghoul::Dictionary& di
, _timeStampSubsamplingFactor(TimeSubSampleInfo, 1, 1, 1000000000)
, _renderFullTrail(RenderFullPathInfo, false)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableTrailTrajectory"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
_translation->onParameterChange([this]() { _needsFullSweep = true; });
_startTime = dictionary.value<std::string>(StartTimeInfo.identifier);
_startTime = p.startTime;
_startTime.onChange([this] { _needsFullSweep = true; });
addProperty(_startTime);
_endTime = dictionary.value<std::string>(EndTimeInfo.identifier);
_endTime = p.endTime;
_endTime.onChange([this] { _needsFullSweep = true; });
addProperty(_endTime);
_sampleInterval = dictionary.value<double>(SampleIntervalInfo.identifier);
_sampleInterval = p.sampleInterval;
_sampleInterval.onChange([this] { _needsFullSweep = true; });
addProperty(_sampleInterval);
if (dictionary.hasValue<double>(TimeSubSampleInfo.identifier)) {
_timeStampSubsamplingFactor = static_cast<int>(
dictionary.value<double>(TimeSubSampleInfo.identifier)
);
}
_timeStampSubsamplingFactor =
p.timeStampSubsampleFactor.value_or(_timeStampSubsamplingFactor);
_timeStampSubsamplingFactor.onChange([this] { _subsamplingIsDirty = true; });
addProperty(_timeStampSubsamplingFactor);
if (dictionary.hasValue<bool>(RenderFullPathInfo.identifier)) {
_renderFullTrail = dictionary.value<bool>(RenderFullPathInfo.identifier);
}
_renderFullTrail = p.showFullTrail.value_or(_renderFullTrail);
addProperty(_renderFullTrail);
// We store the vertices with ascending temporal order
+1 -1
View File
@@ -185,7 +185,7 @@ namespace {
struct [[codegen::Dictionary(FixedRotation)]] Parameters {
// This value specifies the direction of the new X axis. If this value is not
// specified, it will be computed by completing a right handed coordinate system
// from the Y and Z axis, which must be specified instead. If this value is a
// from the Y and Z axis, which must be specified instead. If this value is a
// string, it is interpreted as the identifier of another scenegraph node. If this
// value is a 3-vector, it is interpreted as a direction vector
std::optional<std::variant<std::string, glm::vec3>> xAxis;
+16 -32
View File
@@ -30,48 +30,32 @@
#include <openspace/util/time.h>
namespace {
constexpr const char* KeyKeyframes = "Keyframes";
struct [[codegen::Dictionary(TimelineRotation)]] Parameters {
// A table of keyframes, with keys formatted as YYYY-MM-DDTHH:MM:SS and values
// that are valid Rotation objects
std::map<std::string, ghoul::Dictionary> keyframes
[[codegen::reference("core_transform_rotation")]];
};
#include "timelinerotation_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation TimelineRotation::Documentation() {
using namespace documentation;
return {
"Timeline Rotation",
"base_transform_rotation_keyframe",
{
{
KeyKeyframes,
new TableVerifier({
{ "*", new TableVerifier(), Optional::No, "Any translation object" }
}),
Optional::No,
"A table of keyframes, with keys formatted as YYYY-MM-DDTHH:MM:SS"
"and values that are valid Rotation objects."
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "base_transform_rotation_keyframe";
return doc;
}
TimelineRotation::TimelineRotation(const ghoul::Dictionary& dictionary) {
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"TimelineTranslation"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
const ghoul::Dictionary& keyframes =
dictionary.value<ghoul::Dictionary>(KeyKeyframes);
for (std::string_view timeString : keyframes.keys()) {
const double t = Time::convertTime(std::string(timeString));
ghoul::mm_unique_ptr<Rotation> rotation =
Rotation::createFromDictionary(
keyframes.value<ghoul::Dictionary>(timeString)
);
for (const std::pair<const std::string, ghoul::Dictionary>& kf : p.keyframes) {
const double t = Time::convertTime(kf.first);
ghoul::mm_unique_ptr<Rotation> rotation = Rotation::createFromDictionary(
kf.second
);
if (rotation) {
_timeline.addKeyframe(t, std::move(rotation));
}
@@ -30,48 +30,31 @@
#include <openspace/util/time.h>
namespace {
constexpr const char* KeyKeyframes = "Keyframes";
struct [[codegen::Dictionary(TimelineTranslation)]] Parameters {
// A table of keyframes, with keys formatted as YYYY-MM-DDTHH:MM:SS and values
// that are valid Translation objects
std::map<std::string, ghoul::Dictionary> keyframes
[[codegen::reference("core_transform_translation")]];
};
#include "timelinetranslation_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation TimelineTranslation::Documentation() {
using namespace documentation;
return {
"Timeline Translation",
"base_transform_translation_keyframe",
{
{
KeyKeyframes,
new TableVerifier({
{ "*", new TableVerifier(), Optional::No, "Any translation object" }
}),
Optional::No,
"A table of keyframes, with keys formatted as YYYY-MM-DDTHH:MM:SS"
"and values that are valid Translation objects."
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "base_transform_translation_keyframe";
return doc;
}
TimelineTranslation::TimelineTranslation(const ghoul::Dictionary& dictionary) {
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"TimelineTranslation"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
const ghoul::Dictionary& keyframes =
dictionary.value<ghoul::Dictionary>(KeyKeyframes);
for (std::string_view timeString : keyframes.keys()) {
const double t = Time::convertTime(std::string(timeString));
for (const std::pair<const std::string, ghoul::Dictionary>& kf : p.keyframes) {
const double t = Time::convertTime(kf.first);
ghoul::mm_unique_ptr<Translation> translation =
Translation::createFromDictionary(
keyframes.value<ghoul::Dictionary>(timeString)
);
Translation::createFromDictionary(kf.second);
if (translation) {
_timeline.addKeyframe(t, std::move(translation));
}
@@ -37,6 +37,7 @@
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <optional>
namespace {
enum Origin {
@@ -72,47 +73,38 @@ namespace {
"Texture Coordinate Origin",
"The origin of the texture coorinate system."
};
struct [[codegen::Dictionary(RenderableDebugPlane)]] Parameters {
// [[codegen::verbatim(TextureInfo.description)]]
std::optional<int> texture;
// [[codegen::verbatim(BillboardInfo.description)]]
std::optional<bool> billboard;
// [[codegen::verbatim(SizeInfo.description)]]
std::optional<float> size;
enum class Origin {
LowerLeft,
LowerRight,
UpperLeft,
UpperRight,
Center
};
// [[codegen::verbatim(OriginInfo.description)]]
std::optional<Origin> origin;
};
#include "renderabledebugplane_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RenderableDebugPlane::Documentation() {
using namespace documentation;
return {
"RenderableDebugPlane",
"debugging_renderable_debugplane",
{
{
TextureInfo.identifier,
new IntVerifier,
Optional::Yes,
TextureInfo.description
},
{
BillboardInfo.identifier,
new BoolVerifier,
Optional::Yes,
BillboardInfo.description
},
{
SizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
SizeInfo.description
},
{
OriginInfo.identifier,
new StringInListVerifier(
{ "LowerLeft", "LowerRight", "UpperLeft", "UpperRight", "Center" }
),
Optional::Yes,
OriginInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "debugging_renderable_debugplane";
return doc;
}
RenderableDebugPlane::RenderableDebugPlane(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _texture(TextureInfo, -1, -1, 512)
@@ -120,17 +112,18 @@ RenderableDebugPlane::RenderableDebugPlane(const ghoul::Dictionary& dictionary)
, _size(SizeInfo, 10.f, 0.f, 1e25f)
, _origin(OriginInfo, properties::OptionProperty::DisplayType::Dropdown)
{
if (dictionary.hasKey(TextureInfo.identifier)) {
_texture = static_cast<int>(dictionary.value<double>(TextureInfo.identifier));
}
const Parameters p = codegen::bake<Parameters>(dictionary);
if (dictionary.hasKey(SizeInfo.identifier)) {
_size = static_cast<float>(dictionary.value<double>(SizeInfo.identifier));
}
if (dictionary.hasKey(BillboardInfo.identifier)) {
_billboard = dictionary.value<bool>(BillboardInfo.identifier);
}
_texture = p.texture.value_or(_texture);
addProperty(_texture);
_size.onChange([this](){ _planeIsDirty = true; });
_size = p.size.value_or(_size);
setBoundingSphere(_size);
addProperty(_size);
_billboard = p.billboard.value_or(_billboard);
addProperty(_billboard);
_origin.addOptions({
{ LowerLeft, "LowerLeft" },
@@ -141,36 +134,30 @@ RenderableDebugPlane::RenderableDebugPlane(const ghoul::Dictionary& dictionary)
});
_origin.setValue(Center);
if (dictionary.hasKey(OriginInfo.identifier)) {
const std::string origin = dictionary.value<std::string>(OriginInfo.identifier);
if (origin == "LowerLeft") {
_origin = LowerLeft;
}
else if (origin == "LowerRight") {
_origin = LowerRight;
}
else if (origin == "UpperLeft") {
_origin = UpperLeft;
}
else if (origin == "UpperRight") {
_origin = UpperRight;
}
else if (origin == "Center") {
_origin = Center;
if (p.origin.has_value()) {
switch (*p.origin) {
case Parameters::Origin::LowerLeft:
_origin = LowerLeft;
break;
case Parameters::Origin::LowerRight:
_origin = LowerRight;
break;
case Parameters::Origin::UpperLeft:
_origin = UpperLeft;
break;
case Parameters::Origin::UpperRight:
_origin = UpperRight;
break;
case Parameters::Origin::Center:
_origin = Center;
break;
default:
throw ghoul::MissingCaseException();
}
}
else {
_origin = Center;
}
addProperty(_texture);
addProperty(_billboard);
addProperty(_size);
_size.onChange([this](){ _planeIsDirty = true; });
setBoundingSphere(_size);
}
bool RenderableDebugPlane::isReady() const {
@@ -68,7 +68,7 @@ private:
properties::FloatProperty _size;
properties::OptionProperty _origin;
bool _planeIsDirty;
bool _planeIsDirty = true;
std::unique_ptr<ghoul::opengl::ProgramObject> _shader;
+2 -1
View File
@@ -56,7 +56,8 @@ namespace openspace::exoplanets::luascriptfunctions {
constexpr const float AU = static_cast<float>(distanceconstants::AstronomicalUnit);
constexpr const float SolarRadius = static_cast<float>(distanceconstants::SolarRadius);
constexpr const float JupiterRadius = static_cast<float>(distanceconstants::JupiterRadius);
constexpr const float JupiterRadius =
static_cast<float>(distanceconstants::JupiterRadius);
ExoplanetSystem findExoplanetSystemInData(std::string_view starName) {
const ExoplanetsModule* module = global::moduleEngine->module<ExoplanetsModule>();
@@ -126,7 +126,7 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary)
else {
_vectorFieldInfo = dictionary.value<ghoul::Dictionary>(KeyVectorField);
}
if (!dictionary.hasValue<ghoul::Dictionary>(KeyFieldlines)) {
LERROR(fmt::format("Renderable does not contain a key for '{}'", KeyFieldlines));
}
+192 -358
View File
@@ -300,199 +300,123 @@ namespace {
"Report GL Errors",
"If set to true, any OpenGL errors will be reported if encountered"
};
struct [[codegen::Dictionary(RenderableGaiaStars)]] Parameters {
// [[codegen::verbatim(FilePathInfo.description)]]
std::string file;
enum class FileReader {
Fits,
Speck,
BinaryRaw,
BinaryOctree,
StreamOctree
};
// [[codegen::verbatim(FileReaderOptionInfo.description)]]
FileReader fileReaderOption;
enum class RenderOption {
Static,
Color,
Motion
};
// [[codegen::verbatim(RenderOptionInfo.description)]]
std::optional<RenderOption> renderOption;
enum class ShaderOption {
PointSSBO [[codegen::key("Point_SSBO")]],
PointVBO [[codegen::key("Point_VBO")]],
BillboardSSBO [[codegen::key("Billboard_SSBO")]],
BillboardVBO [[codegen::key("Billboard_VBO")]],
BillboardSSBONoFBO [[codegen::key("Billboard_SSBO_noFBO")]]
};
// [codegen::verbatim(ShaderOptionInfo.description)]]
std::optional<ShaderOption> shaderOption;
// [codegen::verbatim(PsfTextureInfo.description)]]
std::string texture;
// [codegen::verbatim(ColorTextureInfo.description)]]
std::string colorMap;
// [codegen::verbatim(LuminosityMultiplierInfo.description)]]
std::optional<float> luminosityMultiplier;
// [codegen::verbatim(MagnitudeBoostInfo.description)]]
std::optional<float> magnitudeBoost;
// [codegen::verbatim(CutOffThresholdInfo.description)]]
std::optional<float> cutOffThreshold;
// [codegen::verbatim(SharpnessInfo.description)]]
std::optional<float> sharpness;
// [codegen::verbatim(BillboardSizeInfo.description)]]
std::optional<float> billboardSize;
// [codegen::verbatim(CloseUpBoostDistInfo.description)]]
std::optional<float> closeUpBoostDist;
// [codegen::verbatim(TmPointFilterSizeInfo.description)]]
std::optional<int> filterSize;
// [codegen::verbatim(TmPointSigmaInfo.description)]]
std::optional<float> sigma;
// [codegen::verbatim(AdditionalNodesInfo.description)]]
std::optional<glm::ivec2> additionalNodes;
// [codegen::verbatim(TmPointPxThresholdInfo.description)]]
std::optional<float> pixelWeightThreshold;
// [codegen::verbatim(FirstRowInfo.description)]]
std::optional<int> firstRow;
// [codegen::verbatim(LastRowInfo.description)]]
std::optional<int> lastRow;
// [codegen::verbatim(ColumnNamesInfo.description)]]
std::optional<std::vector<std::string>> columnNames;
// [codegen::verbatim(LodPixelThresholdInfo.description)]]
std::optional<float> lodPixelThreshold;
// [codegen::verbatim(MaxGpuMemoryPercentInfo.description)]]
std::optional<float> maxGpuMemoryPercent;
// [codegen::verbatim(MaxCpuMemoryPercentInfo.description)]]
std::optional<float> maxCpuMemoryPercent;
// [codegen::verbatim(FilterPosXInfo.description)]]
std::optional<glm::vec2> filterPosX;
// [codegen::verbatim(FilterPosYInfo.description)]]
std::optional<glm::vec2> filterPosY;
// [codegen::verbatim(FilterPosZInfo.description)]]
std::optional<glm::vec2> filterPosZ;
// [codegen::verbatim(FilterGMagInfo.description)]]
std::optional<glm::vec2> filterGMag;
// [codegen::verbatim(FilterBpRpInfo.description)]]
std::optional<glm::vec2> filterBpRp;
// [codegen::verbatim(FilterDistInfo.description)]]
std::optional<glm::vec2> filterDist;
// [codegen::verbatim(ReportGlErrorsInfo.description)]]
std::optional<bool> reportGlErrors;
};
#include "renderablegaiastars_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RenderableGaiaStars::Documentation() {
using namespace documentation;
return {
"RenderableGaiaStars",
"gaiamission_renderablegaiastars",
{
{
FilePathInfo.identifier,
new StringVerifier,
Optional::No,
FilePathInfo.description
},
{
FileReaderOptionInfo.identifier,
new StringInListVerifier({
"Fits", "Speck", "BinaryRaw", "BinaryOctree", "StreamOctree"
}),
Optional::No,
FileReaderOptionInfo.description
},
{
RenderOptionInfo.identifier,
new StringInListVerifier({
"Static", "Color", "Motion"
}),
Optional::Yes,
RenderOptionInfo.description
},
{
ShaderOptionInfo.identifier,
new StringInListVerifier({
"Point_SSBO", "Point_VBO", "Billboard_SSBO", "Billboard_VBO",
"Billboard_SSBO_noFBO"
}),
Optional::Yes,
ShaderOptionInfo.description
},
{
PsfTextureInfo.identifier,
new StringVerifier,
Optional::No,
PsfTextureInfo.description
},
{
ColorTextureInfo.identifier,
new StringVerifier,
Optional::No,
ColorTextureInfo.description
},
{
LuminosityMultiplierInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LuminosityMultiplierInfo.description
},
{
MagnitudeBoostInfo.identifier,
new DoubleVerifier,
Optional::Yes,
MagnitudeBoostInfo.description
},
{
CutOffThresholdInfo.identifier,
new DoubleVerifier,
Optional::Yes,
CutOffThresholdInfo.description
},
{
SharpnessInfo.identifier,
new DoubleVerifier,
Optional::Yes,
SharpnessInfo.description
},
{
BillboardSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
BillboardSizeInfo.description
},
{
CloseUpBoostDistInfo.identifier,
new DoubleVerifier,
Optional::Yes,
CloseUpBoostDistInfo.description
},
{
TmPointFilterSizeInfo.identifier,
new IntVerifier,
Optional::Yes,
TmPointFilterSizeInfo.description
},
{
TmPointSigmaInfo.identifier,
new DoubleVerifier,
Optional::Yes,
TmPointSigmaInfo.description
},
{
AdditionalNodesInfo.identifier,
new Vector2Verifier<double>,
Optional::Yes,
AdditionalNodesInfo.description
},
{
TmPointPxThresholdInfo.identifier,
new DoubleVerifier,
Optional::Yes,
TmPointPxThresholdInfo.description
},
{
FirstRowInfo.identifier,
new IntVerifier,
Optional::Yes,
FirstRowInfo.description
},
{
LastRowInfo.identifier,
new IntVerifier,
Optional::Yes,
LastRowInfo.description
},
{
ColumnNamesInfo.identifier,
new StringListVerifier,
Optional::Yes,
ColumnNamesInfo.description
},
{
LodPixelThresholdInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LodPixelThresholdInfo.description
},
{
MaxGpuMemoryPercentInfo.identifier,
new DoubleVerifier,
Optional::Yes,
MaxGpuMemoryPercentInfo.description
},
{
MaxCpuMemoryPercentInfo.identifier,
new DoubleVerifier,
Optional::Yes,
MaxCpuMemoryPercentInfo.description
},
{
FilterPosXInfo.identifier,
new Vector2Verifier<double>,
Optional::Yes,
FilterPosXInfo.description
},
{
FilterPosYInfo.identifier,
new Vector2Verifier<double>,
Optional::Yes,
FilterPosYInfo.description
},
{
FilterPosZInfo.identifier,
new Vector2Verifier<double>,
Optional::Yes,
FilterPosZInfo.description
},
{
FilterGMagInfo.identifier,
new Vector2Verifier<double>,
Optional::Yes,
FilterGMagInfo.description
},
{
FilterBpRpInfo.identifier,
new Vector2Verifier<double>,
Optional::Yes,
FilterBpRpInfo.description
},
{
FilterDistInfo.identifier,
new Vector2Verifier<double>,
Optional::Yes,
FilterDistInfo.description
},
{
ReportGlErrorsInfo.identifier,
new BoolVerifier,
Optional::Yes,
ReportGlErrorsInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "gaiamission_renderablegaiastars";
return doc;
}
RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
@@ -536,13 +460,9 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
{
using File = ghoul::filesystem::File;
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableGaiaStars"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
_filePath = absPath(dictionary.value<std::string>(FilePathInfo.identifier));
_filePath = absPath(p.file);
_dataFile = std::make_unique<File>(_filePath);
_dataFile->setCallback([&](const File&) { _dataIsDirty = true; });
@@ -556,25 +476,24 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
{ gaia::FileReaderOption::BinaryOctree, "BinaryOctree" },
{ gaia::FileReaderOption::StreamOctree, "StreamOctree" }
});
if (dictionary.hasKey(FileReaderOptionInfo.identifier)) {
const std::string fileReaderOption = dictionary.value<std::string>(
FileReaderOptionInfo.identifier
);
if (fileReaderOption == "Fits") {
switch (p.fileReaderOption) {
case Parameters::FileReader::Fits:
_fileReaderOption = gaia::FileReaderOption::Fits;
}
else if (fileReaderOption == "Speck") {
break;
case Parameters::FileReader::Speck:
_fileReaderOption = gaia::FileReaderOption::Speck;
}
else if (fileReaderOption == "BinaryRaw") {
break;
case Parameters::FileReader::BinaryRaw:
_fileReaderOption = gaia::FileReaderOption::BinaryRaw;
}
else if (fileReaderOption == "BinaryOctree") {
break;
case Parameters::FileReader::BinaryOctree:
_fileReaderOption = gaia::FileReaderOption::BinaryOctree;
}
else {
break;
case Parameters::FileReader::StreamOctree:
_fileReaderOption = gaia::FileReaderOption::StreamOctree;
}
break;
default:
throw ghoul::MissingCaseException();
}
_renderOption.addOptions({
@@ -582,18 +501,19 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
{ gaia::RenderOption::Color, "Color" },
{ gaia::RenderOption::Motion, "Motion" }
});
if (dictionary.hasKey(RenderOptionInfo.identifier)) {
const std::string renderOption = dictionary.value<std::string>(
RenderOptionInfo.identifier
);
if (renderOption == "Static") {
_renderOption = gaia::RenderOption::Static;
}
else if (renderOption == "Color") {
_renderOption = gaia::RenderOption::Color;
}
else {
_renderOption = gaia::RenderOption::Motion;
if (p.renderOption.has_value()) {
switch (*p.renderOption) {
case Parameters::RenderOption::Static:
_renderOption = gaia::RenderOption::Static;
break;
case Parameters::RenderOption::Color:
_renderOption = gaia::RenderOption::Color;
break;
case Parameters::RenderOption::Motion:
_renderOption = gaia::RenderOption::Motion;
break;
default:
throw ghoul::MissingCaseException();
}
}
_renderOption.onChange([&]() { _buffersAreDirty = true; });
@@ -614,31 +534,31 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
});
#endif // __APPLE__
if (dictionary.hasKey(ShaderOptionInfo.identifier)) {
// Default shader option:
_shaderOption = gaia::ShaderOption::Billboard_VBO;
const std::string shaderOption = dictionary.value<std::string>(
ShaderOptionInfo.identifier
);
#ifndef __APPLE__
if (shaderOption == "Point_SSBO") {
_shaderOption = gaia::ShaderOption::Point_SSBO;
}
else if (shaderOption == "Billboard_SSBO") {
_shaderOption = gaia::ShaderOption::Billboard_SSBO;
}
else if (shaderOption == "Billboard_SSBO_noFBO") {
_shaderOption = gaia::ShaderOption::Billboard_SSBO_noFBO;
}
if (p.shaderOption.has_value()) {
switch (*p.shaderOption) {
case Parameters::ShaderOption::PointSSBO:
_shaderOption = gaia::ShaderOption::Point_SSBO;
break;
case Parameters::ShaderOption::PointVBO:
#ifdef __APPLE__
throw ghoul::RuntimeError("Shader option is not supported on MacOS");
#endif // __APPLE__
if (shaderOption == "Point_VBO") {
_shaderOption = gaia::ShaderOption::Point_VBO;
}
else if (shaderOption == "Billboard_VBO") {
_shaderOption = gaia::ShaderOption::Billboard_VBO;
_shaderOption = gaia::ShaderOption::Point_VBO;
break;
case Parameters::ShaderOption::BillboardSSBO:
_shaderOption = gaia::ShaderOption::Billboard_SSBO;
break;
case Parameters::ShaderOption::BillboardVBO:
#ifdef __APPLE__
throw ghoul::RuntimeError("Shader option is not supported on MacOS");
#endif // __APPLE__
_shaderOption = gaia::ShaderOption::Billboard_VBO;
break;
case Parameters::ShaderOption::BillboardSSBONoFBO:
_shaderOption = gaia::ShaderOption::Billboard_SSBO_noFBO;
break;
default:
throw ghoul::MissingCaseException();
}
}
_shaderOption.onChange([&]() {
@@ -647,95 +567,34 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
});
addProperty(_shaderOption);
_pointSpreadFunctionTexturePath = absPath(dictionary.value<std::string>(
PsfTextureInfo.identifier
));
_pointSpreadFunctionFile = std::make_unique<File>(_pointSpreadFunctionTexturePath);
_pointSpreadFunctionTexturePath = absPath(p.texture);
_pointSpreadFunctionTexturePath.onChange(
[&](){ _pointSpreadFunctionTextureIsDirty = true; }
);
_pointSpreadFunctionFile = std::make_unique<File>(_pointSpreadFunctionTexturePath);
_pointSpreadFunctionFile->setCallback(
[&](const File&) { _pointSpreadFunctionTextureIsDirty = true; }
);
_colorTexturePath = absPath(dictionary.value<std::string>(
ColorTextureInfo.identifier
));
_colorTexturePath = absPath(p.colorMap);
_colorTextureFile = std::make_unique<File>(_colorTexturePath);
_colorTexturePath.onChange([&]() { _colorTextureIsDirty = true; });
_colorTextureFile->setCallback([&](const File&) { _colorTextureIsDirty = true; });
if (dictionary.hasKey(LuminosityMultiplierInfo.identifier)) {
_luminosityMultiplier = static_cast<float>(
dictionary.value<double>(LuminosityMultiplierInfo.identifier)
);
}
_luminosityMultiplier = p.luminosityMultiplier.value_or(_luminosityMultiplier);
_magnitudeBoost = p.magnitudeBoost.value_or(_magnitudeBoost);
_cutOffThreshold = p.cutOffThreshold.value_or(_cutOffThreshold);
_sharpness = p.sharpness.value_or(_sharpness);
_billboardSize = p.billboardSize.value_or(_billboardSize);
_closeUpBoostDist = p.closeUpBoostDist.value_or(_closeUpBoostDist);
_tmPointFilterSize = p.filterSize.value_or(_tmPointFilterSize);
_tmPointSigma = p.sigma.value_or(_tmPointSigma);
_tmPointPixelWeightThreshold =
p.pixelWeightThreshold.value_or(_tmPointPixelWeightThreshold);
_additionalNodes = p.additionalNodes.value_or(_additionalNodes);
_lodPixelThreshold = p.lodPixelThreshold.value_or(_lodPixelThreshold);
if (dictionary.hasKey(MagnitudeBoostInfo.identifier)) {
_magnitudeBoost = static_cast<float>(
dictionary.value<double>(MagnitudeBoostInfo.identifier)
);
}
if (dictionary.hasKey(CutOffThresholdInfo.identifier)) {
_cutOffThreshold = static_cast<float>(
dictionary.value<double>(CutOffThresholdInfo.identifier)
);
}
if (dictionary.hasKey(SharpnessInfo.identifier)) {
_sharpness = static_cast<float>(
dictionary.value<double>(SharpnessInfo.identifier)
);
}
if (dictionary.hasKey(BillboardSizeInfo.identifier)) {
_billboardSize = static_cast<float>(
dictionary.value<double>(BillboardSizeInfo.identifier)
);
}
if (dictionary.hasKey(CloseUpBoostDistInfo.identifier)) {
_closeUpBoostDist = static_cast<float>(
dictionary.value<double>(CloseUpBoostDistInfo.identifier)
);
}
if (dictionary.hasKey(TmPointFilterSizeInfo.identifier)) {
_tmPointFilterSize = static_cast<int>(
dictionary.value<double>(TmPointFilterSizeInfo.identifier)
);
}
if (dictionary.hasKey(TmPointSigmaInfo.identifier)) {
_tmPointSigma = static_cast<float>(
dictionary.value<double>(TmPointSigmaInfo.identifier)
);
}
if (dictionary.hasKey(TmPointPxThresholdInfo.identifier)) {
_tmPointPixelWeightThreshold = static_cast<float>(
dictionary.value<double>(TmPointPxThresholdInfo.identifier)
);
}
if (dictionary.hasKey(AdditionalNodesInfo.identifier)) {
_additionalNodes = static_cast<glm::ivec2>(
dictionary.value<glm::dvec2>(AdditionalNodesInfo.identifier)
);
}
if (dictionary.hasKey(LodPixelThresholdInfo.identifier)) {
_lodPixelThreshold = static_cast<float>(
dictionary.value<double>(LodPixelThresholdInfo.identifier)
);
}
if (dictionary.hasKey(MaxGpuMemoryPercentInfo.identifier)) {
_maxGpuMemoryPercent = static_cast<float>(
dictionary.value<double>(MaxGpuMemoryPercentInfo.identifier)
);
}
_maxGpuMemoryPercent = p.maxGpuMemoryPercent.value_or(_maxGpuMemoryPercent);
_maxGpuMemoryPercent.onChange([&]() {
if (_ssboData != 0) {
glDeleteBuffers(1, &_ssboData);
@@ -761,59 +620,36 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
_maxStreamingBudgetInBytes = 0;
});
if (dictionary.hasKey(MaxCpuMemoryPercentInfo.identifier)) {
_maxCpuMemoryPercent = static_cast<float>(
dictionary.value<double>(MaxCpuMemoryPercentInfo.identifier)
);
}
if (dictionary.hasKey(FilterPosXInfo.identifier)) {
_posXThreshold = dictionary.value<glm::dvec2>(FilterPosXInfo.identifier);
}
_maxCpuMemoryPercent = p.maxCpuMemoryPercent.value_or(_maxCpuMemoryPercent);
_posXThreshold = p.filterPosX.value_or(_posXThreshold);
addProperty(_posXThreshold);
if (dictionary.hasKey(FilterPosYInfo.identifier)) {
_posXThreshold = dictionary.value<glm::dvec2>(FilterPosYInfo.identifier);
}
_posYThreshold = p.filterPosY.value_or(_posYThreshold);
addProperty(_posYThreshold);
if (dictionary.hasKey(FilterPosZInfo.identifier)) {
_posZThreshold = dictionary.value<glm::dvec2>(FilterPosZInfo.identifier);
}
_posZThreshold = p.filterPosZ.value_or(_posZThreshold);
addProperty(_posZThreshold);
if (dictionary.hasKey(FilterGMagInfo.identifier)) {
_gMagThreshold = dictionary.value<glm::dvec2>(FilterGMagInfo.identifier);
}
_gMagThreshold = p.filterGMag.value_or(_gMagThreshold);
addProperty(_gMagThreshold);
if (dictionary.hasKey(FilterBpRpInfo.identifier)) {
_bpRpThreshold = dictionary.value<glm::dvec2>(FilterBpRpInfo.identifier);
}
_bpRpThreshold = p.filterBpRp.value_or(_bpRpThreshold);
addProperty(_bpRpThreshold);
if (dictionary.hasKey(FilterDistInfo.identifier)) {
_distThreshold = dictionary.value<glm::dvec2>(FilterDistInfo.identifier);
}
_distThreshold = p.filterDist.value_or(_distThreshold);
addProperty(_distThreshold);
// Only add properties correlated to fits files if we're reading from a fits file.
if (_fileReaderOption == gaia::FileReaderOption::Fits) {
if (dictionary.hasKey(FirstRowInfo.identifier)) {
_firstRow = static_cast<int>(
dictionary.value<double>(FirstRowInfo.identifier)
);
}
_firstRow = p.firstRow.value_or(_firstRow);
_firstRow.onChange([&]() { _dataIsDirty = true; });
addProperty(_firstRow);
if (dictionary.hasKey(LastRowInfo.identifier)) {
_lastRow = static_cast<int>(dictionary.value<double>(LastRowInfo.identifier));
}
_lastRow = p.lastRow.value_or(_lastRow);
_lastRow.onChange([&]() { _dataIsDirty = true; });
addProperty(_lastRow);
if (dictionary.hasKey(ColumnNamesInfo.identifier)) {
if (p.columnNames.has_value()) {
ghoul::Dictionary tmpDict = dictionary.value<ghoul::Dictionary>(
ColumnNamesInfo.identifier
);
@@ -834,13 +670,11 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
}
if (_firstRow > _lastRow) {
throw ghoul::RuntimeError("User defined FirstRow is bigger than LastRow.");
throw ghoul::RuntimeError("User defined FirstRow is bigger than LastRow");
}
}
if (dictionary.hasKey(ReportGlErrorsInfo.identifier)) {
_reportGlErrors = dictionary.value<bool>(ReportGlErrorsInfo.identifier);
}
_reportGlErrors = p.reportGlErrors.value_or(_reportGlErrors);
addProperty(_reportGlErrors);
// Add a read-only property for the number of rendered stars per frame.
+251 -412
View File
@@ -35,164 +35,263 @@
#include <thread>
namespace {
constexpr const char* KeyInFileOrFolderPath = "InFileOrFolderPath";
constexpr const char* KeyOutFileOrFolderPath = "OutFileOrFolderPath";
constexpr const char* KeyMaxDist = "MaxDist";
constexpr const char* KeyMaxStarsPerNode = "MaxStarsPerNode";
constexpr const char* KeySingleFileInput = "SingleFileInput";
constexpr const char* KeyFilterPosX = "FilterPosX";
constexpr const char* KeyFilterPosY = "FilterPosY";
constexpr const char* KeyFilterPosZ = "FilterPosZ";
constexpr const char* KeyFilterGMag = "FilterGMag";
constexpr const char* KeyFilterBpRp = "FilterBpRp";
constexpr const char* KeyFilterVelX = "FilterVelX";
constexpr const char* KeyFilterVelY = "FilterVelY";
constexpr const char* KeyFilterVelZ = "FilterVelZ";
constexpr const char* KeyFilterBpMag = "FilterBpMag";
constexpr const char* KeyFilterRpMag = "FilterRpMag";
constexpr const char* KeyFilterBpG = "FilterBpG";
constexpr const char* KeyFilterGRp = "FilterGRp";
constexpr const char* KeyFilterRa = "FilterRa";
constexpr const char* KeyFilterRaError = "FilterRaError";
constexpr const char* KeyFilterDec = "FilterDec";
constexpr const char* KeyFilterDecError = "FilterDecError";
constexpr const char* KeyFilterParallax = "FilterParallax";
constexpr const char* KeyFilterParallaxError = "FilterParallaxError";
constexpr const char* KeyFilterPmra = "FilterPmra";
constexpr const char* KeyFilterPmraError = "FilterPmraError";
constexpr const char* KeyFilterPmdec = "FilterPmdec";
constexpr const char* KeyFilterPmdecError = "FilterPmdecError";
constexpr const char* KeyFilterRv = "FilterRv";
constexpr const char* KeyFilterRvError = "FilterRvError";
constexpr const char* _loggerCat = "ConstructOctreeTask";
struct [[codegen::Dictionary(ConstructOctreeTask)]] Parameters {
// If SingleFileInput is set to true then this specifies the path to a single BIN
// file containing a full dataset. Otherwise this specifies the path to a folder
// with multiple BIN files containing subsets of sorted star data
std::string inFileOrFolderPath;
// If SingleFileInput is set to true then this specifies the output file name
// (including full path). Otherwise this specifies the path to the folder which to
// save all files
std::string outFileOrFolderPath;
// If set it determines what MAX_DIST to use when creating Octree
std::optional<int> maxDist;
// If set it determines what MAX_STAR_PER_NODE to use when creating Octree
std::optional<int> maxStarsPerNode;
// If true then task will read from a single file and output a single binary file
// with the full Octree. If false then task will read all files in specified
// folder and output multiple files for the Octree
std::optional<bool> singleFileInput;
// If defined then only stars with Position X values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterPosX;
// If defined then only stars with Position Y values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterPosY;
// If defined then only stars with Position Z values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterPosZ;
// If defined then only stars with G mean magnitude values between [min, max] will
// be inserted into Octree (if min is set to 20.0 it is read as -Inf, if max is
// set to 20.0 it is read as +Inf). If min = max then all values equal min|max
// will be filtered away. Default GMag = 20.0 if no value existed
std::optional<glm::vec2> filterGMag;
// If defined then only stars with Bp-Rp color values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterBpRp;
// If defined then only stars with Velocity X values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterVelX;
// If defined then only stars with Velocity Y values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterVelY;
// If defined then only stars with Velocity Z values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterVelZ;
// If defined then only stars with Bp mean magnitude values between [min, max]
// will be inserted into Octree (if min is set to 20.0 it is read as -Inf, if max
// is set to 20.0 it is read as +Inf). If min = max then all values equal min|max
// will be filtered away. Default BpMag = 20.0 if no value existed
std::optional<glm::vec2> filterBpMag;
// If defined then only stars with Rp mean magnitude values between [min, max]
// will be inserted into Octree (if min is set to 20.0 it is read as -Inf, if max
// is set to 20.0 it is read as +Inf). If min = max then all values equal min|max
// will be filtered away. Default RpMag = 20.0 if no value existed
std::optional<glm::vec2> filterRpMag;
// If defined then only stars with Bp-G color values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterBpG;
// If defined then only stars with G-Rp color values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterGRp;
// If defined then only stars with RA values between [min, max] will be inserted
// into Octree (if min is set to 0.0 it is read as -Inf, if max is set to 0.0 it
// is read as +Inf). If min = max then all values equal min|max will be filtered
// away
std::optional<glm::vec2> filterRa;
// If defined then only stars with RA Error values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterRaError;
// If defined then only stars with DEC values between [min, max] will be inserted
// into Octree (if min is set to 0.0 it is read as -Inf, if max is set to 0.0 it
// is read as +Inf). If min = max then all values equal min|max will be filtered
// away
std::optional<glm::vec2> filterDec;
// If defined then only stars with DEC Error values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterDecError;
// If defined then only stars with Parallax values between [min, max] will be
// inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set to
// 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterParallax;
// If defined then only stars with Parallax Error values between [min, max] will
// be inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set
// to 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterParallaxError;
// If defined then only stars with Proper Motion RA values between [min, max] will
// be inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set
// to 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterPmra;
// If defined then only stars with Proper Motion RA Error values between
// [min, max] will be inserted into Octree (if min is set to 0.0 it is read as
// -Inf, if max is set to 0.0 it is read as +Inf). If min = max then all values
// equal min|max will be filtered away
std::optional<glm::vec2> filterPmraError;
// If defined then only stars with Proper Motion DEC values between [min, max]
// will be inserted into Octree (if min is set to 0.0 it is read as -Inf, if max
// is set to 0.0 it is read as +Inf). If min = max then all values equal min|max
// will be filtered away
std::optional<glm::vec2> filterPmdec;
// If defined then only stars with Proper Motion DEC Error values between
// [min, max] will be inserted into Octree (if min is set to 0.0 it is read as
// -Inf, if max is set to 0.0 it is read as +Inf). If min = max then all values
// equal min|max will be filtered away
std::optional<glm::vec2> filterPmdecError;
// If defined then only stars with Radial Velocity values between [min, max] will
// be inserted into Octree (if min is set to 0.0 it is read as -Inf, if max is set
// to 0.0 it is read as +Inf). If min = max then all values equal min|max will be
// filtered away
std::optional<glm::vec2> filterRv;
// If defined then only stars with Radial Velocity Error values between [min, max]
// will be inserted into Octree (if min is set to 0.0 it is read as -Inf, if max
// is set to 0.0 it is read as +Inf). If min = max then all values equal min|max
// will be filtered away
std::optional<glm::vec2> filterRvError;
};
#include "constructoctreetask_codegen.cpp"
} // namespace
namespace openspace {
ConstructOctreeTask::ConstructOctreeTask(const ghoul::Dictionary& dictionary) {
openspace::documentation::testSpecificationAndThrow(
documentation(),
dictionary,
"ConstructOctreeTask"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
_inFileOrFolderPath = absPath(dictionary.value<std::string>(KeyInFileOrFolderPath));
_outFileOrFolderPath = absPath(dictionary.value<std::string>(KeyOutFileOrFolderPath));
if (dictionary.hasKey(KeyMaxDist)) {
_maxDist = static_cast<int>(dictionary.value<double>(KeyMaxDist));
}
if (dictionary.hasKey(KeyMaxStarsPerNode)) {
_maxStarsPerNode = static_cast<int>(dictionary.value<double>(KeyMaxStarsPerNode));
}
if (dictionary.hasKey(KeySingleFileInput)) {
_singleFileInput = dictionary.value<bool>(KeySingleFileInput);
}
_inFileOrFolderPath = absPath(p.inFileOrFolderPath);
_outFileOrFolderPath = absPath(p.outFileOrFolderPath);
_maxDist = p.maxDist.value_or(_maxDist);
_maxStarsPerNode = p.maxStarsPerNode.value_or(_maxStarsPerNode);
_singleFileInput = p.singleFileInput.value_or(_singleFileInput);
_octreeManager = std::make_shared<OctreeManager>();
_indexOctreeManager = std::make_shared<OctreeManager>();
// Check for filter params.
if (dictionary.hasKey(KeyFilterPosX)) {
_posX = dictionary.value<glm::dvec2>(KeyFilterPosX);
_filterPosX = true;
}
if (dictionary.hasKey(KeyFilterPosY)) {
_posY = dictionary.value<glm::dvec2>(KeyFilterPosY);
_filterPosY = true;
}
if (dictionary.hasKey(KeyFilterPosZ)) {
_posZ = dictionary.value<glm::dvec2>(KeyFilterPosZ);
_filterPosZ = true;
}
if (dictionary.hasKey(KeyFilterGMag)) {
_gMag = dictionary.value<glm::dvec2>(KeyFilterGMag);
_filterGMag = true;
}
if (dictionary.hasKey(KeyFilterBpRp)) {
_bpRp = dictionary.value<glm::dvec2>(KeyFilterBpRp);
_filterBpRp = true;
}
if (dictionary.hasKey(KeyFilterVelX)) {
_velX = dictionary.value<glm::dvec2>(KeyFilterVelX);
_filterVelX = true;
}
if (dictionary.hasKey(KeyFilterVelY)) {
_velY = dictionary.value<glm::dvec2>(KeyFilterVelY);
_filterVelY = true;
}
if (dictionary.hasKey(KeyFilterVelZ)) {
_velZ = dictionary.value<glm::dvec2>(KeyFilterVelZ);
_filterVelZ = true;
}
if (dictionary.hasKey(KeyFilterBpMag)) {
_bpMag = dictionary.value<glm::dvec2>(KeyFilterBpMag);
_filterBpMag = true;
}
if (dictionary.hasKey(KeyFilterRpMag)) {
_rpMag = dictionary.value<glm::dvec2>(KeyFilterRpMag);
_filterRpMag = true;
}
if (dictionary.hasKey(KeyFilterBpG)) {
_bpG = dictionary.value<glm::dvec2>(KeyFilterBpG);
_filterBpG = true;
}
if (dictionary.hasKey(KeyFilterGRp)) {
_gRp = dictionary.value<glm::dvec2>(KeyFilterGRp);
_filterGRp = true;
}
if (dictionary.hasKey(KeyFilterRa)) {
_ra = dictionary.value<glm::dvec2>(KeyFilterRa);
_filterRa = true;
}
if (dictionary.hasKey(KeyFilterRaError)) {
_raError = dictionary.value<glm::dvec2>(KeyFilterRaError);
_filterRaError = true;
}
if (dictionary.hasKey(KeyFilterDec)) {
_dec = dictionary.value<glm::dvec2>(KeyFilterDec);
_filterDec = true;
}
if (dictionary.hasKey(KeyFilterDecError)) {
_decError = dictionary.value<glm::dvec2>(KeyFilterDecError);
_filterDecError = true;
}
if (dictionary.hasKey(KeyFilterParallax)) {
_parallax = dictionary.value<glm::dvec2>(KeyFilterParallax);
_filterParallax = true;
}
if (dictionary.hasKey(KeyFilterParallaxError)) {
_parallaxError = dictionary.value<glm::dvec2>(KeyFilterParallaxError);
_filterParallaxError = true;
}
if (dictionary.hasKey(KeyFilterPmra)) {
_pmra = dictionary.value<glm::dvec2>(KeyFilterPmra);
_filterPmra = true;
}
if (dictionary.hasKey(KeyFilterPmraError)) {
_pmraError = dictionary.value<glm::dvec2>(KeyFilterPmraError);
_filterPmraError = true;
}
if (dictionary.hasKey(KeyFilterPmdec)) {
_pmdec = dictionary.value<glm::dvec2>(KeyFilterPmdec);
_filterPmdec = true;
}
if (dictionary.hasKey(KeyFilterPmdecError)) {
_pmdecError = dictionary.value<glm::dvec2>(KeyFilterPmdecError);
_filterPmdecError = true;
}
if (dictionary.hasKey(KeyFilterRv)) {
_rv = dictionary.value<glm::dvec2>(KeyFilterRv);
_filterRv = true;
}
if (dictionary.hasKey(KeyFilterRvError)) {
_rvError = dictionary.value<glm::dvec2>(KeyFilterRvError);
_filterRvError = true;
}
_posX = p.filterPosX.value_or(_posX);
_filterPosX = p.filterPosX.has_value();
_posY = p.filterPosY.value_or(_posY);
_filterPosY = p.filterPosY.has_value();
_posZ = p.filterPosZ.value_or(_posZ);
_filterPosZ = p.filterPosZ.has_value();
_gMag = p.filterGMag.value_or(_gMag);
_filterGMag = p.filterGMag.has_value();
_bpRp = p.filterBpRp.value_or(_bpRp);
_filterBpRp = p.filterBpRp.has_value();
_velX = p.filterVelX.value_or(_velX);
_filterVelX = p.filterVelX.has_value();
_velY = p.filterVelY.value_or(_velY);
_filterVelY = p.filterVelY.has_value();
_velZ = p.filterVelZ.value_or(_velZ);
_filterVelZ = p.filterVelZ.has_value();
_bpMag = p.filterBpMag.value_or(_bpMag);
_filterBpMag = p.filterBpMag.has_value();
_rpMag = p.filterRpMag.value_or(_rpMag);
_filterRpMag = p.filterRpMag.has_value();
_bpG = p.filterBpG.value_or(_bpG);
_filterBpG = p.filterBpG.has_value();
_gRp = p.filterGRp.value_or(_gRp);
_filterGRp = p.filterGRp.has_value();
_ra = p.filterRa.value_or(_ra);
_filterRa = p.filterRa.has_value();
_raError = p.filterRaError.value_or(_raError);
_filterRaError = p.filterRaError.has_value();
_dec = p.filterDec.value_or(_dec);
_filterDec = p.filterDec.has_value();
_decError = p.filterDecError.value_or(_decError);
_filterDecError = p.filterDecError.has_value();
_parallax = p.filterParallax.value_or(_parallax);
_filterParallax = p.filterParallax.has_value();
_parallaxError = p.filterParallaxError.value_or(_parallaxError);
_filterParallaxError = p.filterParallaxError.has_value();
_pmra = p.filterPmra.value_or(_pmra);
_filterPmra = p.filterPmra.has_value();
_pmraError = p.filterPmraError.value_or(_pmraError);
_filterPmraError = p.filterPmraError.has_value();
_pmdec = p.filterPmdec.value_or(_pmdec);
_filterPmdec = p.filterPmdec.has_value();
_pmdecError = p.filterPmdecError.value_or(_pmdecError);
_filterPmdecError = p.filterPmdecError.has_value();
_rv = p.filterRv.value_or(_rv);
_filterRv = p.filterRv.has_value();
_rvError = p.filterRvError.value_or(_rvError);
_filterRvError = p.filterRvError.has_value();
}
std::string ConstructOctreeTask::description() {
@@ -201,7 +300,7 @@ std::string ConstructOctreeTask::description() {
}
void ConstructOctreeTask::perform(const Task::ProgressCallback& onProgress) {
onProgress(0.0f);
onProgress(0.f);
if (_singleFileInput) {
constructOctreeFromSingleFile(onProgress);
@@ -210,7 +309,7 @@ void ConstructOctreeTask::perform(const Task::ProgressCallback& onProgress) {
constructOctreeFromFolder(onProgress);
}
onProgress(1.0f);
onProgress(1.f);
}
void ConstructOctreeTask::constructOctreeFromSingleFile(
@@ -543,269 +642,9 @@ bool ConstructOctreeTask::filterStar(const glm::vec2& range, float filterValue,
}
documentation::Documentation ConstructOctreeTask::Documentation() {
using namespace documentation;
return {
"ConstructOctreeTask",
"gaiamission_constructoctreefrombin",
{
{
KeyInFileOrFolderPath,
new StringVerifier,
Optional::No,
"If SingleFileInput is set to true then this specifies the path to a "
"single BIN file containing a full dataset. Otherwise this specifies the "
"path to a folder with multiple BIN files containing subsets of sorted "
"star data.",
},
{
KeyOutFileOrFolderPath,
new StringVerifier,
Optional::No,
"If SingleFileInput is set to true then this specifies the output file "
"name (including full path). Otherwise this specifies the path to the "
"folder which to save all files.",
},
{
KeyMaxDist,
new IntVerifier,
Optional::Yes,
"If set it determines what MAX_DIST to use when creating Octree."
},
{
KeyMaxStarsPerNode,
new IntVerifier,
Optional::Yes,
"If set it determines what MAX_STAR_PER_NODE to use when creating Octree."
},
{
KeySingleFileInput,
new BoolVerifier,
Optional::Yes,
"If true then task will read from a single file and output a single "
"binary file with the full Octree. If false then task will read all "
"files in specified folder and output multiple files for the Octree."
},
{
KeyFilterPosX,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Position X values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterPosY,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Position Y values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterPosZ,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Position Z values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterGMag,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with G mean magnitude values between "
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away. Default "
"GMag = 20.0 if no value existed."
},
{
KeyFilterBpRp,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Bp-Rp color values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterVelX,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Velocity X values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterVelY,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Velocity Y values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterVelZ,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Velocity Z values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterBpMag,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Bp mean magnitude values between "
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away. Default "
"BpMag = 20.0 if no value existed."
},
{
KeyFilterRpMag,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Rp mean magnitude values between "
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away. Default RpMag = "
"20.0 if no value existed."
},
{
KeyFilterBpG,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Bp-G color values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterGRp,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with G-Rp color values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterRa,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with RA values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterRaError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with RA Error values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterDec,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with DEC values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterDecError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with DEC Error values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterParallax,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Parallax values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterParallaxError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Parallax Error values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterPmra,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Proper Motion RA values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterPmraError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Proper Motion RA Error values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterPmdec,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Proper Motion DEC values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterPmdecError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Proper Motion DEC Error values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterRv,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Radial Velocity values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterRvError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Radial Velocity Error values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "gaiamission_constructoctreefrombin";
return doc;
}
} // namespace openspace
+46 -97
View File
@@ -36,55 +36,61 @@
#include <fstream>
#include <set>
#include <optional>
namespace {
constexpr const char* KeyInFileOrFolderPath = "InFileOrFolderPath";
constexpr const char* KeyOutFileOrFolderPath = "OutFileOrFolderPath";
constexpr const char* KeySingleFileProcess = "SingleFileProcess";
constexpr const char* KeyThreadsToUse = "ThreadsToUse";
constexpr const char* KeyFirstRow = "FirstRow";
constexpr const char* KeyLastRow = "LastRow";
constexpr const char* KeyFilterColumnNames = "FilterColumnNames";
constexpr const char* _loggerCat = "ReadFitsTask";
struct [[codegen::Dictionary(ReadFitsTask)]] Parameters {
// If SingleFileProcess is set to true then this specifies the path to a single
// FITS file that will be read. Otherwise it specifies the path to a folder with
// multiple FITS files that are to be read
std::string inFileOrFolderPath;
// If SingleFileProcess is set to true then this specifies the name (including
// entire path) to the output file. Otherwise it specifies the path to the output
// folder which to export binary star data to
std::string outFileOrFolderPath;
// If true then task will read from a single FITS file and output a single binary
// file. If false then task will read all files in specified folder and output
// multiple files sorted by location
std::optional<bool> singleFileProcess;
// Defines how many threads to use when reading from multiple files
std::optional<int> threadsToUse [[codegen::greater(1)]];
// Defines the first row that will be read from the specified FITS file(s). If not
// defined then reading will start at first row
std::optional<int> firstRow;
// Defines the last row that will be read from the specified FITS file(s). If not
// defined (or less than FirstRow) then full file(s) will be read
std::optional<int> lastRow;
// A list of strings with the names of all the additional columns that are to be
// read from the specified FITS file(s). These columns can be used for filtering
// while constructing Octree later
std::optional<std::vector<std::string>> filterColumnNames;
};
#include "readfitstask_codegen.cpp"
} // namespace
namespace openspace {
ReadFitsTask::ReadFitsTask(const ghoul::Dictionary& dictionary) {
openspace::documentation::testSpecificationAndThrow(
documentation(),
dictionary,
"ReadFitsTask"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
_inFileOrFolderPath = absPath(dictionary.value<std::string>(KeyInFileOrFolderPath));
_outFileOrFolderPath = absPath(dictionary.value<std::string>(KeyOutFileOrFolderPath));
_inFileOrFolderPath = absPath(p.inFileOrFolderPath);
_outFileOrFolderPath = absPath(p.outFileOrFolderPath);
_singleFileProcess = p.singleFileProcess.value_or(_singleFileProcess);
_threadsToUse = p.threadsToUse.value_or(_threadsToUse);
_firstRow = p.firstRow.value_or(_firstRow);
_lastRow = p.lastRow.value_or(_lastRow);
if (dictionary.hasKey(KeySingleFileProcess)) {
_singleFileProcess = dictionary.value<bool>(KeySingleFileProcess);
}
if (dictionary.hasKey(KeyThreadsToUse)) {
_threadsToUse = static_cast<size_t>(dictionary.value<double>(KeyThreadsToUse));
if (_threadsToUse < 1) {
LINFO(fmt::format(
"User defined ThreadsToUse was: {}. Will be set to 1", _threadsToUse
));
_threadsToUse = 1;
}
}
if (dictionary.hasKey(KeyFirstRow)) {
_firstRow = static_cast<int>(dictionary.value<double>(KeyFirstRow));
}
if (dictionary.hasKey(KeyLastRow)) {
_lastRow = static_cast<int>(dictionary.value<double>(KeyLastRow));
}
if (dictionary.hasKey(KeyFilterColumnNames)) {
if (p.filterColumnNames.has_value()) {
ghoul::Dictionary d = dictionary.value<ghoul::Dictionary>(KeyFilterColumnNames);
// Ugly fix for ASCII sorting when there are more columns read than 10.
@@ -322,66 +328,9 @@ int ReadFitsTask::writeOctantToFile(const std::vector<float>& octantData, int in
}
documentation::Documentation ReadFitsTask::Documentation() {
using namespace documentation;
return {
"ReadFitsFile",
"gaiamission_fitsfiletorawdata",
{
{
KeyInFileOrFolderPath,
new StringVerifier,
Optional::No,
"If SingleFileProcess is set to true then this specifies the path to a "
"single FITS file that will be read. Otherwise it specifies the path to "
"a folder with multiple FITS files that are to be read.",
},
{
KeyOutFileOrFolderPath,
new StringVerifier,
Optional::No,
"If SingleFileProcess is set to true then this specifies the name "
"(including entire path) to the output file. Otherwise it specifies the "
"path to the output folder which to export binary star data to.",
},
{
KeySingleFileProcess,
new BoolVerifier,
Optional::Yes,
"If true then task will read from a single FITS file and output a single "
"binary file. If false then task will read all files in specified folder "
"and output multiple files sorted by location."
},
{
KeyThreadsToUse,
new IntVerifier,
Optional::Yes,
"Defines how many threads to use when reading from multiple files."
},
{
KeyFirstRow,
new IntVerifier,
Optional::Yes,
"Defines the first row that will be read from the specified FITS "
"file(s). If not defined then reading will start at first row.",
},
{
KeyLastRow,
new IntVerifier,
Optional::Yes,
"Defines the last row that will be read from the specified FITS file(s). "
"If not defined (or less than FirstRow) then full file(s) will be read.",
},
{
KeyFilterColumnNames,
new StringListVerifier,
Optional::Yes,
"A list of strings with the names of all the additional columns that are "
"to be read from the specified FITS file(s). These columns can be used "
"for filtering while constructing Octree later.",
},
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "gaiamission_fitsfiletorawdata";
return doc;
}
} // namespace openspace
+18 -33
View File
@@ -34,23 +34,30 @@
#include <fstream>
namespace {
constexpr const char* KeyInFilePath = "InFilePath";
constexpr const char* KeyOutFilePath = "OutFilePath";
constexpr const char* _loggerCat = "ReadSpeckTask";
struct [[codegen::Dictionary(ReadSpeckTask)]] Parameters {
// The path to the SPECK file that are to be read
std::string inFilePath;
// The path to the file to export raw VBO data to
std::string outFilePath;
};
#include "readspecktask_codegen.cpp"
} // namespace
namespace openspace {
ReadSpeckTask::ReadSpeckTask(const ghoul::Dictionary& dictionary) {
openspace::documentation::testSpecificationAndThrow(
documentation(),
dictionary,
"ReadSpeckTask"
);
documentation::Documentation ReadSpeckTask::Documentation() {
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "gaiamission_speckfiletorawdata";
return doc;
}
_inFilePath = absPath(dictionary.value<std::string>(KeyInFilePath));
_outFilePath = absPath(dictionary.value<std::string>(KeyOutFilePath));
ReadSpeckTask::ReadSpeckTask(const ghoul::Dictionary& dictionary) {
const Parameters p = codegen::bake<Parameters>(dictionary);
_inFilePath = absPath(p.inFilePath);
_outFilePath = absPath(p.outFilePath);
}
std::string ReadSpeckTask::description() {
@@ -92,26 +99,4 @@ void ReadSpeckTask::perform(const Task::ProgressCallback& onProgress) {
onProgress(1.f);
}
documentation::Documentation ReadSpeckTask::Documentation() {
using namespace documentation;
return {
"ReadSpeckTask",
"gaiamission_speckfiletorawdata",
{
{
KeyInFilePath,
new StringVerifier,
Optional::No,
"The path to the SPECK file that are to be read.",
},
{
KeyOutFilePath,
new StringVerifier,
Optional::No,
"The path to the file to export raw VBO data to.",
},
}
};
}
} // namespace openspace
@@ -453,7 +453,9 @@ std::vector<documentation::Documentation> GlobeBrowsingModule::documentations()
globebrowsing::Layer::Documentation(),
globebrowsing::LayerAdjustment::Documentation(),
globebrowsing::LayerManager::Documentation(),
GlobeLabelsComponent::Documentation()
GlobeLabelsComponent::Documentation(),
RingsComponent::Documentation(),
ShadowComponent::Documentation()
};
}
@@ -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 {
@@ -949,7 +949,8 @@ TileMetaData RawTileDataReader::tileMetaData(RawTile& rawTile,
bool allIsMissing = true;
for (int y = 0; y < region.numPixels.y; ++y) {
const size_t yi = (static_cast<unsigned long long>(region.numPixels.y) - 1 - y) * bytesPerLine;
const size_t yi =
(static_cast<unsigned long long>(region.numPixels.y) - 1 - y) * bytesPerLine;
size_t i = 0;
for (int x = 0; x < region.numPixels.x; ++x) {
for (size_t raster = 0; raster < _initData.nRasters; ++raster) {
+78 -106
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);
@@ -1487,7 +1459,7 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
program.setUniform("shadowMapTexture", shadowMapUnit);
program.setUniform("zFightingPercentage", _generalProperties.zFightingPercentage);
}
}
else if (_generalProperties.shadowMapping) {
shadowMapUnit.activate();
// JCC: Avoiding a to recompiling the shaders or having more than one
+77 -138
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 {
@@ -476,7 +415,7 @@ void RingsComponent::draw(const RenderData& data,
_shader->setUniform(_uniformCacheAdvancedRings.colorFilterValue, _colorFilter);
_shader->setUniform(_uniformCacheAdvancedRings.nightFactor, _nightFactor);
_shader->setUniform(_uniformCacheAdvancedRings.sunPosition, _sunPosition);
const glm::dmat4 inverseModelTransform = glm::inverse(modelTransform);
glm::vec3 sunPositionObjectSpace = glm::normalize(
@@ -614,7 +553,7 @@ void RingsComponent::draw(const RenderData& data,
else {
_texture->bind();
}
_geometryOnlyShader->setUniform(_geomUniformCache.ringTexture, ringTextureUnit);
}
@@ -673,7 +612,7 @@ void RingsComponent::loadTexture() {
using namespace ghoul::opengl;
if (!_texturePath.value().empty()) {
std::unique_ptr<Texture> texture = TextureReader::ref().loadTexture(
absPath(_texturePath)
);
+1 -1
View File
@@ -98,7 +98,7 @@ private:
) _uniformCache;
UniformCache(modelViewProjectionMatrix, textureOffset, colorFilterValue, nightFactor,
sunPosition, sunPositionObj, camPositionObj, ringTextureFwrd, ringTextureBckwrd,
ringTextureUnlit, ringTextureColor, ringTextureTransparency, shadowMatrix,
ringTextureUnlit, ringTextureColor, ringTextureTransparency, shadowMatrix,
shadowMapTexture, zFightingPercentage
) _uniformCacheAdvancedRings;
UniformCache(modelViewProjectionMatrix, textureOffset, ringTexture
+29 -49
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() {
@@ -323,7 +303,7 @@ RenderData ShadowComponent::begin(const RenderData& data) {
// Saves current state
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_currentFBO);
global::renderEngine->openglStateCache().viewport(_mViewport);
glBindFramebuffer(GL_FRAMEBUFFER, _shadowFBO);
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_NONE, GL_NONE };
glDrawBuffers(3, drawBuffers);
@@ -105,8 +105,6 @@ private:
properties::IntProperty _distanceFraction;
properties::BoolProperty _enabled;
ghoul::Dictionary _shadowMapDictionary;
int _shadowDepthTextureHeight = 4096;
int _shadowDepthTextureWidth = 4096;
bool _dynamicDepthTextureRes = true;
+2 -1
View File
@@ -184,7 +184,8 @@ void IswaCygnet::render(const RenderData& data, RendererTasks&) {
_data.spatialScale.x * _data.offset,
_data.spatialScale.w
);
glm::vec3 position = glm::vec3(pposition) * static_cast<float>(pow(10.f, pposition.w));
glm::vec3 position =
glm::vec3(pposition) * static_cast<float>(pow(10.f, pposition.w));
// Activate shader
_shader->activate();
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_EXOPLANETS___RENDERABLEHABITABLEZONE___H__
#define __OPENSPACE_MODULE_EXOPLANETS___RENDERABLEHABITABLEZONE___H__
#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLEHABITABLEZONE___H__
#define __OPENSPACE_MODULE_SPACE___RENDERABLEHABITABLEZONE___H__
#include <modules/base/rendering/renderabledisc.h>
#include <openspace/properties/scalar/boolproperty.h>
@@ -72,4 +72,4 @@ private:
} // namespace openspace
#endif // __OPENSPACE_MODULE_EXOPLANETS___RENDERABLEHABITABLEZONE___H__
#endif // __OPENSPACE_MODULE_SPACE___RENDERABLEHABITABLEZONE___H__
+4 -3
View File
@@ -307,7 +307,8 @@ namespace {
};
struct [[codegen::Dictionary(RenderableStars)]] Parameters {
// The path to the SPECK file containing information about the stars being rendered
// The path to the SPECK file containing information about the stars being
// rendered
std::filesystem::path speckFile [[codegen::key("File")]];
// [[codegen::verbatim(ColorTextureInfo.description)]]
@@ -336,8 +337,8 @@ namespace {
// loading. This can be used to trim the dataset's automatic value range
std::optional<float> staticFilter;
// This is the value that is used to replace statically filtered values. Setting this
// value only makes sense if 'StaticFilter' is 'true', as well
// This is the value that is used to replace statically filtered values. Setting
// this value only makes sense if 'StaticFilter' is 'true', as well
std::optional<float> staticFilterReplacement;
// [[codegen::verbatim(MagnitudeExponentInfo.description)]]
@@ -34,19 +34,38 @@
#include <ghoul/glm.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/opengl/programobject.h>
#include <optional>
namespace {
constexpr const char* KeySource = "Source";
constexpr const char* KeyTarget = "Target";
constexpr const char* KeyInstrument = "Instrument";
constexpr const char* KeyColor = "Color";
constexpr const char* KeyColorStart = "Start";
constexpr const char* KeyColorEnd = "End";
struct VBOData {
float position[3];
float color[4];
};
struct [[codegen::Dictionary(RenderableCrawlingLine)]] Parameters {
// Denotes the SPICE name of the source of the renderable crawling line, for
// example, the spacecraft
std::string source;
// Denotes the SPICE name of the target of the crawling line
std::string target;
// Denotes the SPICE name of the instrument that is used to render the crawling
// line
std::string instrument;
struct Color {
// The color at the start of the line
glm::vec4 start [[codegen::color()]];
// The color at the end of the line
glm::vec4 end [[codegen::color()]];
};
// Specifies the colors that are used for the crawling line. One value determines
// the starting color of the line, the second value is the color at the end
Color color;
};
#include "renderablecrawlingline_codegen.cpp"
} // namespace
// @TODO: This class is not properly working anymore and needs to be substantially
@@ -56,76 +75,21 @@ namespace {
namespace openspace {
documentation::Documentation RenderableCrawlingLine::Documentation() {
using namespace documentation;
return {
"RenderableCrawlingLine",
"newhorizons_renderable_crawlingline",
{
{
KeySource,
new StringVerifier,
Optional::No,
"Denotes the SPICE name of the source of the renderable crawling line, "
"for example, the space craft"
},
{
KeyTarget,
new StringVerifier,
Optional::Yes,
"Denotes the SPICE name of the target of the crawling line"
},
{
KeyInstrument,
new StringVerifier,
Optional::No,
"Denotes the SPICE name of the instrument that is used to render the "
"crawling line"
},
{
KeyColor,
new TableVerifier({
{
KeyColorStart,
new Color4Verifier,
Optional::No,
"The color at the start of the line",
},
{
KeyColorEnd,
new Color4Verifier,
Optional::No,
"The color at the end of the line"
}
}),
Optional::No,
"Specifies the colors that are used for the crawling line. One value "
"determines the starting color of the line, the second value is the "
"color at the end of the line."
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "newhorizons_renderable_crawlingline";
return doc;
}
RenderableCrawlingLine::RenderableCrawlingLine(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableCrawlingLine"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
_source = dictionary.value<std::string>(KeySource);
_target = dictionary.value<std::string>(KeyTarget);
_instrumentName = dictionary.value<std::string>(KeyInstrument);
_lineColorBegin = dictionary.value<glm::dvec4>(
std::string(KeyColor) + "." + KeyColorStart
);
_lineColorEnd = dictionary.value<glm::dvec4>(
std::string(KeyColor) + "." + KeyColorEnd
);
_source = p.source;
_target = p.target;
_instrumentName = p.instrument;
_lineColorBegin = p.color.start;
_lineColorEnd = p.color.end;
}
bool RenderableCrawlingLine::isReady() const {
@@ -35,17 +35,10 @@
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/projection.hpp>
#include <optional>
namespace {
constexpr const char* ProgramName = "FovProgram";
constexpr const char* KeyBody = "Body";
constexpr const char* KeyFrame = "Frame";
constexpr const char* KeyInstrument = "Instrument";
constexpr const char* KeyInstrumentName = "Name";
constexpr const char* KeyInstrumentAberration = "Aberration";
constexpr const char* KeyPotentialTargets = "PotentialTargets";
constexpr const char* KeyFrameConversions = "FrameConversions";
constexpr const char* KeyBoundsSimplification = "SimplifyBounds";
constexpr const std::array<const char*, 9> UniformNames = {
"modelViewProjectionTransform", "defaultColorStart", "defaultColorEnd",
@@ -153,142 +146,55 @@ namespace {
}
}
// Needs support for std::map first for the frameConversions
// struct [[codegen::Dictionary(RenderableFov)]] Parameters {
// // The SPICE name of the source body for which the field of view should be
// // rendered
// std::string body;
//
// // The SPICE name of the source body's frame in which the field of view should be
// // rendered
// std::string frame;
//
// struct Instrument {
// // The SPICE name of the instrument that is rendered
// std::string name;
//
// // The aberration correction that is used for this field of view. The default
// // is 'NONE'
// std::optional<std::string> aberration [[codegen::inlist("NONE",
// "LT", "LT+S", "CN", "CN+S", "XLT", "XLT+S", "XCN", "XCN+S")]];
// };
// // A table describing the instrument whose field of view should be rendered
// Instrument instrument;
//
// // A list of potential targets (specified as SPICE names) that the field of view
// // should be tested against
// std::vector<std::string> potentialTargets;
//
// // A list of frame conversions that should be registered with the SpiceManager
// std::optional<std::vector<std::string>> frameConversions;
//
// // [[codegen::verbatim(LineWidthInfo.description)]]
// std::optional<double> lineWidth;
//
// // [[codegen::verbatim(StandoffDistanceInfo.description)]]
// std::optional<double> standOffDistance;
//
// // If this value is set to 'true' the field-of-views bounds values will be
// // simplified on load. Bound vectors will be removed if they are the strict linear
// // interpolation between the two neighboring vectors. This value is disabled on
// // default
// std::optional<bool> simplifyBounds;
// };
//#include "renderablefov_codegen.cpp"
struct [[codegen::Dictionary(RenderableFov)]] Parameters {
// The SPICE name of the source body for which the field of view should be
// rendered
std::string body;
// The SPICE name of the source body's frame in which the field of view should be
// rendered
std::string frame;
struct Instrument {
// The SPICE name of the instrument that is rendered
std::string name;
// The aberration correction that is used for this field of view. The default
// is 'NONE'
std::optional<std::string> aberration [[codegen::inlist("NONE",
"LT", "LT+S", "CN", "CN+S", "XLT", "XLT+S", "XCN", "XCN+S")]];
};
// A table describing the instrument whose field of view should be rendered
Instrument instrument;
// A list of potential targets (specified as SPICE names) that the field of view
// should be tested against
std::vector<std::string> potentialTargets;
// A list of frame conversions that should be registered with the SpiceManager
std::optional<std::map<std::string, std::string>> frameConversions;
// [[codegen::verbatim(LineWidthInfo.description)]]
std::optional<float> lineWidth;
// [[codegen::verbatim(StandoffDistanceInfo.description)]]
std::optional<float> standOffDistance;
// If this value is set to 'true' the field-of-views bounds values will be
// simplified on load. Bound vectors will be removed if they are the strict linear
// interpolation between the two neighboring vectors. This value is disabled on
// default
std::optional<bool> simplifyBounds;
};
#include "renderablefov_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RenderableFov::Documentation() {
using namespace documentation;
return {
"RenderableFieldOfView",
"newhorizons_renderable_fieldofview",
{
{
KeyBody,
new StringVerifier,
Optional::No,
"The SPICE name of the source body for which the field of view should be "
"rendered."
},
{
KeyFrame,
new StringVerifier,
Optional::No,
"The SPICE name of the source body's frame in which the field of view "
"should be rendered."
},
{
KeyInstrument,
new TableVerifier({
{
KeyInstrumentName,
new StringVerifier,
Optional::No,
"The SPICE name of the instrument that is rendered"
},
{
KeyInstrumentAberration,
new StringInListVerifier({
// Taken from SpiceManager::AberrationCorrection
"NONE",
"LT", "LT+S",
"CN", "CN+S",
"XLT", "XLT+S",
"XCN", "XCN+S"
}),
Optional::Yes,
"The aberration correction that is used for this field of view. "
"The default is 'NONE'."
}
}),
Optional::No,
"A table describing the instrument whose field of view should be "
"rendered."
},
{
KeyPotentialTargets,
new StringListVerifier,
Optional::No,
"A list of potential targets (specified as SPICE names) that the field "
"of view should be tested against."
},
{
KeyFrameConversions,
new TableVerifier({
{
DocumentationEntry::Wildcard,
new StringVerifier,
Optional::No
}
}),
Optional::Yes,
"A list of frame conversions that should be registered with the "
"SpiceManager."
},
{
LineWidthInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LineWidthInfo.description
},
{
StandoffDistanceInfo.identifier,
new DoubleVerifier,
Optional::Yes,
StandoffDistanceInfo.description
},
{
KeyBoundsSimplification,
new BoolVerifier,
Optional::Yes,
"If this value is set to 'true' the field-of-views bounds values will be "
"simplified on load. Bound vectors will be removed if they are the "
"strict linear interpolation between the two neighboring vectors. This "
"value is disabled on default."
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "newhorizons_renderable_fieldofview";
return doc;
}
@@ -342,61 +248,37 @@ RenderableFov::RenderableFov(const ghoul::Dictionary& dictionary)
}
})
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableFov"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
_instrument.spacecraft = dictionary.value<std::string>(KeyBody);
_instrument.referenceFrame = dictionary.value<std::string>(KeyFrame);
_instrument.name = dictionary.value<std::string>(
std::string(KeyInstrument) + "." + KeyInstrumentName
);
std::string ia = std::string(KeyInstrument) + "." + KeyInstrumentAberration;
if (dictionary.hasValue<std::string>(ia)) {
const std::string& ac = dictionary.value<std::string>(ia);
_instrument.aberrationCorrection = SpiceManager::AberrationCorrection(ac);
_instrument.spacecraft = p.body;
_instrument.referenceFrame = p.frame;
_instrument.name = p.instrument.name;
if (p.instrument.aberration.has_value()) {
_instrument.aberrationCorrection = SpiceManager::AberrationCorrection(
*p.instrument.aberration
);
}
ghoul::Dictionary pt = dictionary.value<ghoul::Dictionary>(KeyPotentialTargets);
_instrument.potentialTargets.reserve(pt.size());
for (size_t i = 1; i <= pt.size(); ++i) {
std::string target = pt.value<std::string>(std::to_string(i));
_instrument.potentialTargets.push_back(std::move(target));
}
_instrument.potentialTargets = p.potentialTargets;
if (dictionary.hasKey(KeyFrameConversions)) {
ghoul::Dictionary fc = dictionary.value<ghoul::Dictionary>(KeyFrameConversions);
for (std::string_view key : fc.keys()) {
if (p.frameConversions.has_value()) {
for (const std::pair<const std::string, std::string>& fc : *p.frameConversions) {
global::moduleEngine->module<SpacecraftInstrumentsModule>()->addFrame(
std::string(key),
fc.value<std::string>(key)
fc.first,
fc.second
);
}
}
if (dictionary.hasKey(LineWidthInfo.identifier)) {
_lineWidth = static_cast<float>(dictionary.value<double>(
LineWidthInfo.identifier
));
}
if (dictionary.hasKey(StandoffDistanceInfo.identifier)) {
_standOffDistance = static_cast<float>(dictionary.value<double>(
StandoffDistanceInfo.identifier
));
}
if (dictionary.hasKey(KeyBoundsSimplification)) {
_simplifyBounds = dictionary.value<bool>(KeyBoundsSimplification);
}
_lineWidth = p.lineWidth.value_or(_lineWidth);
addProperty(_lineWidth);
addProperty(_drawSolid);
_standOffDistance = p.standOffDistance.value_or(_standOffDistance);
addProperty(_standOffDistance);
_simplifyBounds = p.simplifyBounds.value_or(_simplifyBounds);
addProperty(_drawSolid);
addProperty(_colors.defaultStart);
addProperty(_colors.defaultEnd);
@@ -279,7 +279,6 @@ void RenderablePlaneProjection::updatePlane(const Image& img, double currentTime
glm::vec3(projection[1]),
glm::vec3(projection[2]),
glm::vec3(projection[3])
};
const GLfloat vertex_data[] = {
// square of two triangles drawn within fov in target coordinates
@@ -39,6 +39,7 @@
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureconversion.h>
#include <ghoul/opengl/textureunit.h>
#include <optional>
namespace {
constexpr const char* _loggerCat = "RenderablePlanetProjection";
@@ -56,8 +57,6 @@ namespace {
"boresight", "_radius", "_segments"
};
constexpr const char* KeyGeometry = "Geometry";
constexpr const char* KeyProjection = "Projection";
constexpr const char* KeyRadius = "Geometry.Radius";
constexpr const char* _mainFrame = "GALACTIC";
@@ -134,67 +133,42 @@ namespace {
"Clear Projection Buffer",
"Remove all pending projections from the buffer"
};
struct [[codegen::Dictionary(RenderablePlanetProjection)]] Parameters {
// The geometry that is used for rendering this planet
ghoul::Dictionary geometry [[codegen::reference("space_geometry_planet")]];
// Contains information about projecting onto this planet
ghoul::Dictionary projection
[[codegen::reference("newhorizons_projectioncomponent")]];
// [[codegen::verbatim(ColorTexturePathsInfo.description)]]
std::vector<std::string> colorTexturePaths;
// [[codegen::verbatim(HeightTexturePathsInfo.description)]]
std::vector<std::string> heightTexturePaths;
// [[codegen::verbatim(HeightExaggerationInfo.description)]]
std::optional<float> heightExaggeration;
// [[codegen::verbatim(MeridianShiftInfo.description)]]
std::optional<bool> meridianShift;
// [[codegen::verbatim(AmbientBrightnessInfo.description)]]
std::optional<double> ambientBrightness;
// [[codegen::verbatim(MaxProjectionsPerFrameInfo.description)]]
std::optional<int> maxProjectionsPerFrame;
};
#include "renderableplanetprojection_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RenderablePlanetProjection::Documentation() {
using namespace openspace::documentation;
return {
"Renderable Planet Projection",
"newhorizons_renderable_planetprojection",
{
{
KeyGeometry,
new ReferencingVerifier("space_geometry_planet"),
Optional::No,
"The geometry that is used for rendering this planet.",
},
{
KeyProjection,
new ReferencingVerifier("newhorizons_projectioncomponent"),
Optional::No,
"Contains information about projecting onto this planet.",
},
{
ColorTexturePathsInfo.identifier,
new StringListVerifier,
Optional::No,
ColorTexturePathsInfo.description
},
{
HeightTexturePathsInfo.identifier,
new StringListVerifier,
Optional::Yes,
HeightTexturePathsInfo.description
},
{
HeightExaggerationInfo.identifier,
new DoubleVerifier,
Optional::Yes,
HeightExaggerationInfo.description
},
{
MeridianShiftInfo.identifier,
new BoolVerifier,
Optional::Yes,
MeridianShiftInfo.description
},
{
AmbientBrightnessInfo.identifier,
new DoubleVerifier,
Optional::Yes,
AmbientBrightnessInfo.description
},
{
MaxProjectionsPerFrameInfo.identifier,
new DoubleVerifier,
Optional::Yes,
MaxProjectionsPerFrameInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "newhorizons_renderable_planetprojection";
return doc;
}
RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& dict)
@@ -210,43 +184,24 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
, _projectionsInBuffer(ProjectionsInBufferInfo, 0, 1, 32)
, _clearProjectionBuffer(ClearProjectionBufferInfo)
{
documentation::testSpecificationAndThrow(
Documentation(),
dict,
"RenderablePlanetProjection"
);
const Parameters p = codegen::bake<Parameters>(dict);
ghoul::Dictionary geometryDictionary = dict.value<ghoul::Dictionary>(KeyGeometry);
_geometry = planetgeometry::PlanetGeometry::createFromDictionary(geometryDictionary);
_projectionComponent.initialize(
identifier(),
dict.value<ghoul::Dictionary>(KeyProjection)
);
_geometry = planetgeometry::PlanetGeometry::createFromDictionary(p.geometry);
_projectionComponent.initialize(identifier(), p.projection);
_colorTexturePaths.addOption(0, NoImageText);
_colorTexturePaths.onChange([this](){ _colorTextureDirty = true; });
addProperty(_colorTexturePaths);
if (dict.hasValue<ghoul::Dictionary>(ColorTexturePathsInfo.identifier)) {
const ghoul::Dictionary& value = dict.value<ghoul::Dictionary>(
ColorTexturePathsInfo.identifier
for (const std::string& t : p.colorTexturePaths) {
_colorTexturePaths.addOption(
static_cast<int>(_colorTexturePaths.options().size()),
t
);
for (size_t i = 1; i <= value.size(); ++i) {
std::string texture = absPath(value.value<std::string>(std::to_string(i)));
_colorTexturePaths.addOption(
// as we started with 0, this works
static_cast<int>(_colorTexturePaths.options().size()),
texture
);
_colorTexturePaths = static_cast<int>(
_colorTexturePaths.options().size() - 1
);
}
}
_colorTexturePaths = static_cast<int>(
_colorTexturePaths.options().size() - 1
);
_addColorTexturePath.onChange([this]() {
if (!_addColorTexturePath.value().empty()) {
@@ -271,27 +226,15 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
_heightMapTexturePaths.onChange([this]() { _heightMapTextureDirty = true; });
addProperty(_heightMapTexturePaths);
if (dict.hasValue<ghoul::Dictionary>(HeightTexturePathsInfo.identifier)) {
const ghoul::Dictionary& value = dict.value<ghoul::Dictionary>(
HeightTexturePathsInfo.identifier
for (const std::string& t : p.heightTexturePaths) {
_heightMapTexturePaths.addOption(
static_cast<int>(_heightMapTexturePaths.options().size()),
t
);
for (size_t i = 1; i <= value.size(); ++i) {
std::string texture = absPath(value.value<std::string>(std::to_string(i)));
_heightMapTexturePaths.addOption(
// as we started with 0, this works
static_cast<int>(_heightMapTexturePaths.options().size()),
texture
);
_heightMapTexturePaths = static_cast<int>(
_heightMapTexturePaths.options().size() - 1
);
}
}
_heightMapTexturePaths = static_cast<int>(
_heightMapTexturePaths.options().size() - 1
);
_addHeightMapTexturePath.onChange([this]() {
if (!_addHeightMapTexturePath.value().empty()) {
_heightMapTexturePaths.addOption(
@@ -308,11 +251,12 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
});
addProperty(_addHeightMapTexturePath);
_meridianShift = p.meridianShift.value_or(_meridianShift);
addProperty(_meridianShift);
if (dict.hasValue<bool>(MeridianShiftInfo.identifier)) {
_meridianShift = dict.value<bool>(MeridianShiftInfo.identifier);
}
// @TODO (abock, 2021-03-26) Poking into the Geometry dictionary is not really
// optimal as we don't have local control over how the dictionary is checked. We
// should instead ask the geometry whether it has a radius or not
double radius = std::pow(10.0, 9.0);
if (dict.hasValue<double>(KeyRadius)) {
radius = dict.value<double>(KeyRadius);
@@ -322,25 +266,16 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
addPropertySubOwner(_geometry.get());
addPropertySubOwner(_projectionComponent);
if (dict.hasKey(HeightExaggerationInfo.identifier)) {
_heightExaggeration = static_cast<float>(
dict.value<double>(HeightExaggerationInfo.identifier)
);
}
if (dict.hasKey(MaxProjectionsPerFrameInfo.identifier)) {
_maxProjectionsPerFrame = static_cast<int>(
dict.value<double>(MaxProjectionsPerFrameInfo.identifier)
);
}
_heightExaggeration = p.heightExaggeration.value_or(_heightExaggeration);
addProperty(_heightExaggeration);
addProperty(_meridianShift);
addProperty(_ambientBrightness);
_maxProjectionsPerFrame = p.maxProjectionsPerFrame.value_or(_maxProjectionsPerFrame);
addProperty(_maxProjectionsPerFrame);
addProperty(_ambientBrightness);
addProperty(_projectionsInBuffer);
_clearProjectionBuffer.onChange([this]() {
_imageTimes.clear();
_projectionsInBuffer = static_cast<int>(_imageTimes.size());
+15 -29
View File
@@ -38,39 +38,29 @@
namespace {
constexpr const char* _loggerCat = "HttpSynchronization";
constexpr const char* KeyIdentifier = "Identifier";
constexpr const char* KeyVersion = "Version";
constexpr const char* TempSuffix = ".tmp";
constexpr const char* QueryKeyIdentifier = "identifier";
constexpr const char* QueryKeyFileVersion = "file_version";
constexpr const char* QueryKeyApplicationVersion = "application_version";
constexpr const int ApplicationVersion = 1;
struct [[codegen::Dictionary(HttpSynchronization)]] Parameters {
// A unique identifier for this resource
std::string identifier;
// The version of this resource
int version;
};
#include "httpsynchronization_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation HttpSynchronization::Documentation() {
using namespace openspace::documentation;
return {
"HttpSynchronization",
"http_synchronization",
{
{
KeyIdentifier,
new StringVerifier,
Optional::No,
"A unique identifier for this resource"
},
{
KeyVersion,
new IntVerifier,
Optional::No,
"The version of this resource"
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "http_synchronization";
return doc;
}
HttpSynchronization::HttpSynchronization(const ghoul::Dictionary& dict,
@@ -81,14 +71,10 @@ HttpSynchronization::HttpSynchronization(const ghoul::Dictionary& dict,
, _synchronizationRoot(std::move(synchronizationRoot))
, _synchronizationRepositories(std::move(synchronizationRepositories))
{
documentation::testSpecificationAndThrow(
Documentation(),
dict,
"HttpSynchronization"
);
const Parameters p = codegen::bake<Parameters>(dict);
_identifier = dict.value<std::string>(KeyIdentifier);
_version = static_cast<int>(dict.value<double>(KeyVersion));
_identifier = p.identifier;
_version = p.version;
}
HttpSynchronization::~HttpSynchronization() {
+53 -81
View File
@@ -37,6 +37,8 @@
#include <fstream>
#include <numeric>
#include <memory>
#include <optional>
#include <variant>
namespace {
constexpr const char* KeyUrl = "Url";
@@ -46,61 +48,44 @@ namespace {
constexpr const char* KeyFilename = "Filename";
constexpr const char* TempSuffix = ".tmp";
struct [[codegen::Dictionary(UrlSynchronization)]] Parameters {
// The URL or urls from where the files are downloaded. If multiple URLs are
// provided, all files will be downloaded to the same directory
std::variant<std::string, std::vector<std::string>> url;
// This optional identifier will be part of the used folder structure and, if
// provided, can be used to manually find the downloaded folder in the
// synchronization folder. If this value is not specified, 'UseHash' has to be set
// to 'true'
std::optional<std::string> identifier;
// If this value is set to 'true' and it is not overwritten by the global
// settings, the file(s) pointed to by this URLSynchronization will always be
// downloaded, thus overwriting the local files. This is useful for files that are
// updated regularly remotely and should be fetch at every startup
std::optional<bool> forceOverride [[codegen::key("override")]];
// If this value is set to 'true' (the default), the hash of the URL is appended
// to the directory name to produce a unique directory under all circumstances. If
// this is not desired, the URLSynchronization use the bare directory name alone
// if this value is 'false'. If this value is 'false', the identifier has to be
// specified
std::optional<bool> useHash;
// Optional to provide filename to override the one which is otherwise
// automatically created from the url
std::optional<std::string> filename;
};
#include "urlsynchronization_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation UrlSynchronization::Documentation() {
using namespace openspace::documentation;
return {
"Url Synchronization",
"sync_synchronization_url",
{
{
KeyUrl,
new OrVerifier({ new StringVerifier, new StringListVerifier }),
Optional::No,
"The URL or urls from where the files are downloaded. If multiple URLs "
"are provided, all files will be downloaded to the same directory."
},
{
KeyIdentifier,
new StringVerifier,
Optional::Yes,
"This optional identifier will be part of the used folder structure and, "
"if provided, can be used to manually find the downloaded folder in the "
"synchronization folder. If this value is not specified, 'UseHash' has "
"to be set to 'true'."
},
{
KeyOverride,
new BoolVerifier,
Optional::Yes,
"If this value is set to 'true' and it is not overwritten by the global "
"settings, the file(s) pointed to by this URLSynchronization will always "
"be downloaded, thus overwriting the local files. This is useful for "
"files that are updated regularly remotely and should be fetch at every "
"startup."
},
{
KeyUseHash,
new BoolVerifier,
Optional::Yes,
"If this value is set to 'true' (the default), the hash of the URL is "
"appended to the directory name to produce a unique directory under all "
"circumstances. If this is not desired, the URLSynchronization use the "
"bare directory name alone if this value is 'false'. If this value is "
"'false', the identifier has to be specified."
},
{
KeyFilename,
new StringVerifier,
Optional::Yes,
"Optional to provide filename to override the one which is otherwise "
"automatically created from the url. "
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "sync_synchronization_url";
return doc;
}
UrlSynchronization::UrlSynchronization(const ghoul::Dictionary& dict,
@@ -108,43 +93,33 @@ UrlSynchronization::UrlSynchronization(const ghoul::Dictionary& dict,
: ResourceSynchronization(dict)
, _synchronizationRoot(std::move(synchronizationRoot))
{
documentation::testSpecificationAndThrow(
Documentation(),
dict,
"UrlSynchroniztion"
);
const Parameters p = codegen::bake<Parameters>(dict);
if (dict.hasValue<std::string>(KeyUrl)) {
_urls.push_back(dict.value<std::string>(KeyUrl));
if (std::holds_alternative<std::string>(p.url)) {
_urls.push_back(std::get<std::string>(p.url));
}
else if (std::holds_alternative<std::vector<std::string>>(p.url)) {
_urls = std::get<std::vector<std::string>>(p.url);
}
else {
ghoul::Dictionary urls = dict.value<ghoul::Dictionary>(KeyUrl);
for (size_t i = 1; i <= urls.size(); ++i) {
std::string url = urls.value<std::string>(std::to_string(i));
_urls.push_back(std::move(url));
}
throw ghoul::MissingCaseException();
}
if (dict.hasValue<std::string>(KeyFilename)) {
_filename = dict.value<std::string>(KeyFilename);
}
_filename = p.filename.value_or(_filename);
bool useHash = true;
if (dict.hasValue<bool>(KeyUseHash)) {
useHash = dict.value<bool>(KeyUseHash);
}
bool useHash = p.useHash.value_or(true);
// We just merge all of the URLs together to generate a hash, it's not as stable to
// reordering URLs, but every other solution would be more error prone
std::string urlConcat = std::accumulate(_urls.begin(), _urls.end(), std::string());
size_t hash = std::hash<std::string>{}(urlConcat);
if (dict.hasValue<std::string>(KeyIdentifier)) {
std::string ident = dict.value<std::string>(KeyIdentifier);
if (p.identifier.has_value()) {
if (useHash) {
_identifier = std::move(ident) + "(" + std::to_string(hash) + ")";
_identifier = *p.identifier + "(" + std::to_string(hash) + ")";
}
else {
_identifier = std::move(ident);
_identifier = *p.identifier;
}
}
else {
@@ -154,17 +129,15 @@ UrlSynchronization::UrlSynchronization(const ghoul::Dictionary& dict,
else {
documentation::TestResult res;
res.success = false;
res.offenses.push_back({
std::string(KeyIdentifier) + "|" + KeyUseHash,
documentation::TestResult::Offense::Reason::MissingKey
});
documentation::TestResult::Offense o;
o.offender = std::string(KeyIdentifier) + "|" + KeyUseHash;
o.reason = documentation::TestResult::Offense::Reason::MissingKey;
res.offenses.push_back(o);
throw documentation::SpecificationError(std::move(res), "UrlSynchronization");
}
}
if (dict.hasValue<bool>(KeyOverride)) {
_forceOverride = dict.value<bool>(KeyOverride);
}
_forceOverride = p.forceOverride.value_or(_forceOverride);
}
UrlSynchronization::~UrlSynchronization() {
@@ -193,7 +166,6 @@ void UrlSynchronization::start() {
std::vector<std::unique_ptr<AsyncHttpFileDownload>> downloads;
for (const std::string& url : _urls) {
if (_filename.empty()) {
const size_t lastSlash = url.find_last_of('/');
std::string lastPartOfUrl = url.substr(lastSlash + 1);
@@ -31,6 +31,7 @@
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <ghoul/logging/logmanager.h>
#include <optional>
#include <string>
namespace {
@@ -56,36 +57,26 @@ namespace {
"Property to define a custom unit descriptor to use to describe the distance "
"value. Defaults to the units SI descriptor if not specified."
};
}
struct [[codegen::Dictionary(RenderableDistanceLabel)]] Parameters {
// [[codegen::verbatim(NodeLineInfo.description)]]
std::string nodeLine;
// [[codegen::verbatim(DistanceUnitInfo.description)]]
std::optional<int> distanceUnit;
// [[codegen::verbatim(CustomUnitDescriptorInfo.description)]]
std::optional<std::string> customUnitDescriptor;
};
#include "renderabledistancelabel_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RenderableDistanceLabel::Documentation() {
using namespace documentation;
return {
"Renderable Distance Label",
"vislab_renderable_distance_label",
{
{
NodeLineInfo.identifier,
new StringVerifier,
Optional::No,
NodeLineInfo.description
},
{
DistanceUnitInfo.identifier,
new IntVerifier,
Optional::Yes,
DistanceUnitInfo.description
},
{
CustomUnitDescriptorInfo.identifier,
new StringVerifier,
Optional::Yes,
CustomUnitDescriptorInfo.description
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "vislab_renderable_distance_label";
return doc;
}
RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictionary)
@@ -94,27 +85,16 @@ RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictio
, _distanceUnit(DistanceUnitInfo, 1, 0, 11)
, _customUnitDescriptor(CustomUnitDescriptorInfo)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableDistanceLabel"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
if (dictionary.hasKey(NodeLineInfo.identifier)) {
_nodelineId = dictionary.value<std::string>(NodeLineInfo.identifier);
addProperty(_nodelineId);
}
if (dictionary.hasKey(DistanceUnitInfo.identifier)) {
_distanceUnit = static_cast<int>(
dictionary.value<double>(DistanceUnitInfo.identifier)
);
addProperty(_distanceUnit);
}
if (dictionary.hasKey(CustomUnitDescriptorInfo.identifier)) {
_customUnitDescriptor =
dictionary.value<std::string>(CustomUnitDescriptorInfo.identifier);
addProperty(_customUnitDescriptor);
}
_nodelineId = p.nodeLine;
addProperty(_nodelineId);
_distanceUnit = p.distanceUnit.value_or(_distanceUnit);
addProperty(_distanceUnit);
_customUnitDescriptor = p.customUnitDescriptor.value_or(_customUnitDescriptor);
addProperty(_customUnitDescriptor);
}
void RenderableDistanceLabel::update(const UpdateData&) {
+1 -1
View File
@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2020 *
* Copyright (c) 2014-2021 *
* *
* 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 *
+53 -88
View File
@@ -28,20 +28,35 @@
#include <openspace/documentation/documentation.h>
#include <openspace/util/time.h>
#include <ghoul/misc/dictionary.h>
#include <optional>
namespace {
constexpr const char* KeyDimensions = "Dimensions";
constexpr const char* KeyLowerDomainBound = "LowerDomainBound";
constexpr const char* KeyUpperDomainBound = "UpperDomainBound";
struct [[codegen::Dictionary(RawVolumeMetaData)]] Parameters {
// Specifies the number of grid cells in each dimension
glm::ivec3 dimensions;
constexpr const char* KeyMinValue = "MinValue";
constexpr const char* KeyMaxValue = "MaxValue";
// Specifies the unit used to specity the domain
std::optional<std::string> domainUnit;
constexpr const char* KeyTime = "Time";
constexpr const char* KeyDomainUnit = "DomainUnit";
constexpr const char* KeyValueUnit = "ValueUnit";
// Specifies the lower domain bounds in the model coordinate system
std::optional<glm::vec3> lowerDomainBound;
constexpr const char* KeyGridType = "GridType";
// Specifies the upper domain bounds in the model coordinate system
std::optional<glm::vec3> upperDomainBound;
// Specifies the time on the format YYYY-MM-DDTHH:MM:SS.000Z
std::optional<std::string> time;
// Specifies the unit used to specity the value
std::optional<std::string> valueUnit;
// Specifies the minimum value stored in the volume
std::optional<float> minValue;
// Specifies the maximum value stored in the volume
std::optional<float> maxValue;
};
#include "rawvolumemetadata_codegen.cpp"
} // namespace
namespace openspace::volume {
@@ -49,51 +64,53 @@ namespace openspace::volume {
RawVolumeMetadata RawVolumeMetadata::createFromDictionary(
const ghoul::Dictionary& dictionary)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RawVolumeMetadata"
);
const Parameters p = codegen::bake<Parameters>(dictionary);
RawVolumeMetadata metadata;
metadata.dimensions = dictionary.value<glm::dvec3>(KeyDimensions);
metadata.dimensions = p.dimensions;
metadata.hasDomainBounds = dictionary.hasValue<glm::dvec3>(KeyLowerDomainBound) &&
dictionary.hasValue<glm::dvec3>(KeyUpperDomainBound);
metadata.hasDomainBounds =
p.lowerDomainBound.has_value() &&
p.upperDomainBound.has_value();
if (metadata.hasDomainBounds) {
metadata.lowerDomainBound = dictionary.value<glm::dvec3>(KeyLowerDomainBound);
metadata.upperDomainBound = dictionary.value<glm::dvec3>(KeyUpperDomainBound);
metadata.lowerDomainBound = *p.lowerDomainBound;
metadata.upperDomainBound = *p.upperDomainBound;
}
metadata.hasDomainUnit = static_cast<float>(
dictionary.hasValue<double>(KeyDomainUnit)
);
metadata.hasDomainUnit = p.domainUnit.has_value();
if (metadata.hasDomainUnit) {
metadata.domainUnit = dictionary.value<std::string>(KeyDomainUnit);
metadata.domainUnit = *p.domainUnit;
}
metadata.hasValueRange = dictionary.hasValue<double>(KeyMinValue) &&
dictionary.hasValue<double>(KeyMaxValue);
metadata.hasValueRange = p.minValue.has_value() && p.maxValue.has_value();
if (metadata.hasValueRange) {
metadata.minValue = static_cast<float>(dictionary.value<double>(KeyMinValue));
metadata.maxValue = static_cast<float>(dictionary.value<double>(KeyMaxValue));
metadata.minValue = *p.minValue;
metadata.maxValue = *p.maxValue;
}
metadata.hasValueUnit = static_cast<float>(dictionary.hasValue<double>(KeyValueUnit));
metadata.hasValueUnit = p.valueUnit.has_value();
if (metadata.hasValueUnit) {
metadata.valueUnit = dictionary.value<std::string>(KeyValueUnit);
metadata.valueUnit = *p.valueUnit;
}
metadata.hasTime = dictionary.hasValue<std::string>(KeyTime);
metadata.hasTime = p.time.has_value();
if (metadata.hasTime) {
std::string timeString = dictionary.value<std::string>(KeyTime);
metadata.time = Time::convertTime(timeString);
metadata.time = Time::convertTime(*p.time);
}
return metadata;
}
ghoul::Dictionary RawVolumeMetadata::dictionary() {
constexpr const char* KeyDimensions = "Dimensions";
constexpr const char* KeyLowerDomainBound = "LowerDomainBound";
constexpr const char* KeyUpperDomainBound = "UpperDomainBound";
constexpr const char* KeyMinValue = "MinValue";
constexpr const char* KeyMaxValue = "MaxValue";
constexpr const char* KeyTime = "Time";
constexpr const char* KeyDomainUnit = "DomainUnit";
constexpr const char* KeyValueUnit = "ValueUnit";
constexpr const char* KeyGridType = "GridType";
ghoul::Dictionary dict;
dict.setValue(KeyDimensions, glm::dvec3(dimensions));
dict.setValue(KeyGridType, gridTypeToString(gridType));
@@ -126,61 +143,9 @@ ghoul::Dictionary RawVolumeMetadata::dictionary() {
}
documentation::Documentation RawVolumeMetadata::Documentation() {
using namespace documentation;
return {
"RawVolumeMetadata",
"volume_rawvolumemetadata",
{
{
KeyDimensions,
new DoubleVector3Verifier,
Optional::No,
"Specifies the number of grid cells in each dimension",
},
{
KeyDomainUnit,
new StringVerifier,
Optional::Yes,
"Specifies the unit used to specity the domain",
},
{
KeyLowerDomainBound,
new DoubleVector3Verifier,
Optional::Yes,
"Specifies the lower domain bounds in the model coordinate system",
},
{
KeyUpperDomainBound,
new DoubleVector3Verifier,
Optional::Yes,
"Specifies the upper domain bounds in the model coordinate system",
},
{
KeyTime,
new StringVerifier,
Optional::Yes,
"Specifies the time on the format YYYY-MM-DDTHH:MM:SS.000Z",
},
{
KeyValueUnit,
new StringVerifier,
Optional::Yes,
"Specifies the unit used to specity the value",
},
{
KeyMinValue,
new DoubleVerifier,
Optional::Yes,
"Specifies the minimum value stored in the volume"
},
{
KeyMaxValue,
new DoubleVerifier,
Optional::Yes,
"Specifies the maximum value stored in the volume"
}
}
};
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "volume_rawvolumemetadata";
return doc;
}
} // namespace openspace::volume
+52 -75
View File
@@ -30,6 +30,7 @@
#include <openspace/documentation/verifier.h>
#include <openspace/util/time.h>
#include <openspace/util/spicemanager.h>
#include <ghoul/fmt.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/logging/logmanager.h>
@@ -37,7 +38,6 @@
#include <ghoul/lua/lua_helper.h>
#include <ghoul/misc/dictionaryluaformatter.h>
#include <ghoul/misc/defer.h>
#include <fstream>
namespace {
@@ -48,41 +48,65 @@ namespace {
constexpr const char* KeyValueFunction = "ValueFunction";
constexpr const char* KeyLowerDomainBound = "LowerDomainBound";
constexpr const char* KeyUpperDomainBound = "UpperDomainBound";
struct [[codegen::Dictionary(GenerateRawVolumeTask)]] Parameters {
// The Lua function used to compute the cell values
std::string valueFunction [[codegen::annotation("A Lua expression that returns a "
"function taking three numbers as arguments (x, y, z) and returning a "
"number")]];
// The raw volume file to export data to
std::string rawVolumeOutput [[codegen::annotation("A valid filepath")]];
// The lua dictionary file to export metadata to
std::string dictionaryOutput [[codegen::annotation("A valid filepath")]];
// The timestamp that is written to the metadata of this volume
std::string time;
// A vector representing the number of cells in each dimension
glm::ivec3 dimensions;
// A vector representing the lower bound of the domain
glm::dvec3 lowerDomainBound;
// A vector representing the upper bound of the domain
glm::dvec3 upperDomainBound;
};
#include "generaterawvolumetask_codegen.cpp"
} // namespace
namespace openspace::volume {
GenerateRawVolumeTask::GenerateRawVolumeTask(const ghoul::Dictionary& dictionary) {
openspace::documentation::testSpecificationAndThrow(
documentation(),
dictionary,
"GenerateRawVolumeTask"
);
documentation::Documentation GenerateRawVolumeTask::documentation() {
documentation::Documentation doc = codegen::doc<Parameters>();
doc.id = "generate_raw_volume_task";
return doc;
}
_rawVolumeOutputPath = absPath(dictionary.value<std::string>(KeyRawVolumeOutput));
_dictionaryOutputPath = absPath(dictionary.value<std::string>(KeyDictionaryOutput));
_dimensions = glm::uvec3(dictionary.value<glm::dvec3>(KeyDimensions));
_time = dictionary.value<std::string>(KeyTime);
_valueFunctionLua = dictionary.value<std::string>(KeyValueFunction);
_lowerDomainBound = dictionary.value<glm::dvec3>(KeyLowerDomainBound);
_upperDomainBound = dictionary.value<glm::dvec3>(KeyUpperDomainBound);
GenerateRawVolumeTask::GenerateRawVolumeTask(const ghoul::Dictionary& dictionary) {
const Parameters p = codegen::bake<Parameters>(dictionary);
_rawVolumeOutputPath = absPath(p.rawVolumeOutput);
_dictionaryOutputPath = absPath(p.dictionaryOutput);
_dimensions = p.dimensions;
_time = p.time;
_valueFunctionLua = p.valueFunction;
_lowerDomainBound = p.lowerDomainBound;
_upperDomainBound = p.upperDomainBound;
}
std::string GenerateRawVolumeTask::description() {
return "Generate a raw volume with dimenstions: (" +
std::to_string(_dimensions.x) + ", " +
std::to_string(_dimensions.y) + ", " +
std::to_string(_dimensions.z) + "). " +
"For each cell, set the value by evaluating the lua function: " +
"`" + _valueFunctionLua + "`, with three arguments (x, y, z) ranging from " +
"(" + std::to_string(_lowerDomainBound.x) + ", "
+ std::to_string(_lowerDomainBound.y) + ", " +
std::to_string(_lowerDomainBound.z) + ") to (" +
std::to_string(_upperDomainBound.x) + ", " +
std::to_string(_upperDomainBound.y) + ", " +
std::to_string(_upperDomainBound.z) + ")." +
"Write raw volume data into " + _rawVolumeOutputPath +
" and dictionary with metadata to " + _dictionaryOutputPath;
return fmt::format(
"Generate a raw volume with dimenstions: ({}, {}, {}). For each cell, set the "
"value by evaluating the lua function: `{}`, with three arguments (x, y, z) "
"ranging from ({}, {}, {}) to ({}, {}, {}). Write raw volume data into {} and "
"dictionary with metadata to {}",
_dimensions.x, _dimensions.y, _dimensions.z, _valueFunctionLua,
_lowerDomainBound.x, _lowerDomainBound.y, _lowerDomainBound.z,
_upperDomainBound.x, _upperDomainBound.y, _upperDomainBound.z,
_rawVolumeOutputPath, _dictionaryOutputPath
);
}
void GenerateRawVolumeTask::perform(const Task::ProgressCallback& progressCallback) {
@@ -184,51 +208,4 @@ void GenerateRawVolumeTask::perform(const Task::ProgressCallback& progressCallba
progressCallback(1.0f);
}
documentation::Documentation GenerateRawVolumeTask::documentation() {
using namespace documentation;
return {
"GenerateRawVolumeTask",
"generate_raw_volume_task",
{
{
KeyValueFunction,
new StringAnnotationVerifier("A lua expression that returns a function "
"taking three numbers as arguments (x, y, z) and returning a number."),
Optional::No,
"The lua function used to compute the cell values",
},
{
KeyRawVolumeOutput,
new StringAnnotationVerifier("A valid filepath"),
Optional::No,
"The raw volume file to export data to",
},
{
KeyDictionaryOutput,
new StringAnnotationVerifier("A valid filepath"),
Optional::No,
"The lua dictionary file to export metadata to",
},
{
KeyDimensions,
new DoubleVector3Verifier,
Optional::No,
"A vector representing the number of cells in each dimension",
},
{
KeyLowerDomainBound,
new DoubleVector3Verifier,
Optional::No,
"A vector representing the lower bound of the domain"
},
{
KeyUpperDomainBound,
new DoubleVector3Verifier,
Optional::No,
"A vector representing the upper bound of the domain"
}
}
};
}
} // namespace openspace::volume