mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-22 11:18:22 -05:00
Merge branch 'master' into feature/model-animation
* Resolve conflicts
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Submodule modules/kameleon/ext/kameleon updated: 8a5e966659...606edb945b
@@ -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__
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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&) {
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user