From 40e56bf005aa9ff4c9f229ed8fb23a0328ba5c24 Mon Sep 17 00:00:00 2001 From: Lovisa Hassler Date: Mon, 17 Dec 2018 17:18:36 -0500 Subject: [PATCH] improved our label class, handles precision errors and rescales depending on distance --- .../solarsystem/dsn/spacecraftslabels.asset | 12 +- modules/dsn/rendering/renderablelabel.cpp | 186 ++++++++++++------ modules/dsn/rendering/renderablelabel.h | 34 ++-- 3 files changed, 155 insertions(+), 77 deletions(-) diff --git a/data/assets/scene/solarsystem/dsn/spacecraftslabels.asset b/data/assets/scene/solarsystem/dsn/spacecraftslabels.asset index c1cf5f25de..1a98b728da 100644 --- a/data/assets/scene/solarsystem/dsn/spacecraftslabels.asset +++ b/data/assets/scene/solarsystem/dsn/spacecraftslabels.asset @@ -6,12 +6,12 @@ local OuterSpaceLabels = { Renderable = { Type = "RenderableLabel", Enabled = true, + --ScaleFactor = 1.0, LabelIdentifierMap = spacecrafts.labelMapVoyagers, TextColor = { 1.0, 0.6, 0.2, 1.0 }, DrawLabels = true, - TextSize = 10.0, - TextMinSize = 1.0, - TextMaxSize = 80.0, + --LabelSize = 6.5, + LabelSizeRange = {5.8, 6.3}, }, GUI = { Name = "Outer Space Labels", @@ -24,12 +24,12 @@ local MarsLabels = { Renderable = { Type = "RenderableLabel", Enabled = true, + --ScaleFactor = 1.0, LabelIdentifierMap = spacecrafts.labelMapMars, TextColor = { 0.4, 0.4, 0.4, 1.0 }, DrawLabels = true, - TextSize = 5.0, - TextMinSize = 1.0, - TextMaxSize = 80.0, + --LabelSize = 6.5, + LabelSizeRange = {5.8, 6.3}, }, GUI = { Name = "Mars Labels", diff --git a/modules/dsn/rendering/renderablelabel.cpp b/modules/dsn/rendering/renderablelabel.cpp index 535a5405bf..381a02993e 100644 --- a/modules/dsn/rendering/renderablelabel.cpp +++ b/modules/dsn/rendering/renderablelabel.cpp @@ -60,20 +60,40 @@ namespace { "The text color for the astronomical object." }; - constexpr openspace::properties::Property::PropertyInfo TextSizeInfo = { - "TextSize", - "Text Size", - "The text size for the astronomical object labels." + constexpr openspace::properties::Property::PropertyInfo LabelSizeInfo = { + "LabelSize", + "Label Size", + "The static label size if no LabelSizeRange interval are set " }; - constexpr openspace::properties::Property::PropertyInfo LabelMinSizeInfo = { + //constexpr openspace::properties::Property::PropertyInfo TextMinSizeInfo = { + // "TextMinSize", + // "Text Min Size", + // "The minimal size (in pixels) of the text for the labels for the astronomical " + // "objects being rendered." + //}; + + //constexpr openspace::properties::Property::PropertyInfo TextMaxSizeInfo = { + // "TextMaxSize", + // "Text Max Size", + // "The maximum size (in pixels) of the text for the labels for the astronomical " + // "objects being rendered." + //}; + constexpr openspace::properties::Property::PropertyInfo LabelSizeRangeInfo = { + "LabelSizeRange", + "Label Size Range", + "These values determine the min and max size of this label when it is " + "scaled depending on distance" + }; + + constexpr openspace::properties::Property::PropertyInfo TextMinSizeInfo = { "TextMinSize", "Text Min Size", "The minimal size (in pixels) of the text for the labels for the astronomical " "objects being rendered." }; - constexpr openspace::properties::Property::PropertyInfo LabelMaxSizeInfo = { + constexpr openspace::properties::Property::PropertyInfo TextMaxSizeInfo = { "TextMaxSize", "Text Max Size", "The maximum size (in pixels) of the text for the labels for the astronomical " @@ -152,22 +172,22 @@ namespace openspace { TextColorInfo.description }, { - TextSizeInfo.identifier, + LabelSizeInfo.identifier, new DoubleVerifier, Optional::Yes, - TextSizeInfo.description + LabelSizeInfo.description }, { - LabelMinSizeInfo.identifier, + TextMinSizeInfo.identifier, new DoubleVerifier, Optional::Yes, - LabelMinSizeInfo.description + TextMinSizeInfo.description }, { - LabelMaxSizeInfo.identifier, + TextMaxSizeInfo.identifier, new DoubleVerifier, Optional::Yes, - LabelMaxSizeInfo.description + TextMaxSizeInfo.description }, { FadeInDistancesInfo.identifier, @@ -193,16 +213,22 @@ namespace openspace { RenderableLabel::RenderableLabel(const ghoul::Dictionary& dictionary) : Renderable(dictionary) - , _scaleFactor(ScaleFactorInfo, 10.f, 0.f, 600.f) + , _scaleFactor(ScaleFactorInfo, 5.0f, 1.f, 100.f) , _textColor( TextColorInfo, glm::vec4(1.0f, 1.0, 1.0f, 1.f), glm::vec4(0.f), glm::vec4(1.f) ) - , _textSize(TextSizeInfo, 8.0, 0.5, 24.0) - , _textMinSize(LabelMinSizeInfo, 8.f, 0.5f, 24.f) - , _textMaxSize(LabelMaxSizeInfo, 20.f, 0.5f, 100.f) + , _labelSize(LabelSizeInfo, 20.0, 0.0, 100.0) + , _labelSizeRange( + LabelSizeRangeInfo, + glm::vec2(0.0f), + glm::vec2(0.0), + glm::vec2(100.0) + ) + // , _textMinSize(TextMinSizeInfo, 5.f, 0.0f, 100.f) + // , _textMaxSize(TextMaxSizeInfo, 50.f, 0.0f, 100.f) , _drawLabels(DrawLabelInfo, false) , _fadeInDistance( FadeInDistancesInfo, @@ -257,20 +283,29 @@ namespace openspace { addProperty(_textColor); _textColor.onChange([&]() { _textColorIsDirty = true; }); - if (dictionary.hasKey(TextSizeInfo.identifier)) { - _textSize = dictionary.value(TextSizeInfo.identifier); - } - addProperty(_textSize); + // Can have either a static size or a scaled interval + if (dictionary.hasKey(LabelSizeInfo.identifier)) { + _labelSize = dictionary.value(LabelSizeInfo.identifier); + addProperty(_labelSize); + _hasStaticLabelSize = true; - if (dictionary.hasKey(LabelMinSizeInfo.identifier)) { - _textMinSize = dictionary.value(LabelMinSizeInfo.identifier); + }else if(dictionary.hasKey(LabelSizeRangeInfo.identifier)) + { + glm::vec2 labelsizeRange = dictionary.value(LabelSizeRangeInfo.identifier); + _labelSizeRange.set(labelsizeRange); + addProperty(_labelSizeRange); } - addProperty(_textMinSize); - if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) { - _textMaxSize = dictionary.value(LabelMaxSizeInfo.identifier); - } - addProperty(_textMaxSize); + //if (dictionary.hasKey(TextMinSizeInfo.identifier)) { + // _textMinSize = dictionary.value(TextMinSizeInfo.identifier); + //} + //addProperty(_textMinSize); + + //if (dictionary.hasKey(TextMaxSizeInfo.identifier)) { + // _textMaxSize = dictionary.value(TextMaxSizeInfo.identifier); + //} + //addProperty(_textMaxSize); + } else { LERROR(fmt::format("Needs a valid {}", LabelIdentifierMapInfo.identifier)); @@ -301,7 +336,7 @@ namespace openspace { void RenderableLabel::initialize() { bool success = loadData(); if (!success) { - throw ghoul::RuntimeError("Error loading data"); + throw ghoul::RuntimeError("Error with identifiers for labels"); } } @@ -320,31 +355,68 @@ namespace openspace { } } + /* To combat precision errors when we approach a node very far out in space + * we place the label on a set distance from the camera instead of at the node's + * actual world position */ void RenderableLabel::renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix, const glm::dvec3& orthoRight, - const glm::dvec3& orthoUp, - float fadeInVariable) + const glm::dvec3& orthoUp) { - float scale = 1.f; if (_hasLabelIdMap) { _labelData.clear(); loadLabelDataFromId(); } glm::vec4 textColor = _textColor; - textColor.a *= fadeInVariable; + + //float fadeInVariable = 1.f; + //if (!_disableFadeInDistance) { + // float distCamera = static_cast(glm::length(data.camera.positionVec3())); + // const glm::vec2 fadeRange = _fadeInDistance; + // const float a = 1.f / (fadeRange.y - fadeRange.x); + // const float b = -(fadeRange.x / (fadeRange.y - fadeRange.x)); + // const float funcValue = a * distCamera + b; + // fadeInVariable *= funcValue > 1.f ? 1.f : funcValue; + + // if (funcValue < 0.01f) { + // return; + // } + //} for (const std::pair& pair : _labelData) { - //glm::vec3 scaledPos(_transformationMatrix * glm::dvec4(pair.first, 1.0)); - glm::vec3 scaledPos(pair.first); - scaledPos *= scale; + + // The world position of the SceneGraphNode + glm::dvec3 nodePos = pair.first; + std::string labelText = pair.second; + + double distCamera = glm::distance(data.camera.positionVec3(), nodePos); + + double textSize = 0.0; + if (!_hasStaticLabelSize) { + const glm::vec2 labelSizeRange = _labelSizeRange; + // Pass in the labelSizeRanges in opposite order (max,min) since we want the largest value + // when the distance is the smallest + textSize = maxMinNormalize(distCamera, glm::dvec2(labelSizeRange.y, labelSizeRange.x), glm::dvec2(20000.0, _maxDistanceUnit)); + } + else { + textSize = _labelSize; + } + double labelPosLength = (1.0 / _scaleFactor) * _maxDistanceUnit; + // The direction vector from the camera to the SceneGraphNode + glm::dvec3 nodeDir = normalize(data.camera.positionVec3() - nodePos); + // The new label position vector, calculated from the camera + glm::dvec3 labelPos = data.camera.positionVec3() - (nodeDir * labelPosLength); + + //textColor.a *= fadeInVariable; + double textScale = pow(10, textSize); + ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render( *_font, - scaledPos, - pair.second, + labelPos, + labelText, textColor, - pow(_scaleFactor, _textSize.value()), + textScale, static_cast(_textMinSize), static_cast(_textMaxSize), modelViewProjectionMatrix, @@ -357,24 +429,27 @@ namespace openspace { } } + double RenderableLabel::maxMinNormalize(double value, glm::dvec2 newRange, glm::dvec2 oldRange) + { + double newMax = newRange.y; + double newMin = newRange.x; + + double oldMax = oldRange.y; + double oldMin = oldRange.x; + + if (value >= oldMax) + return newMax; + + double nominator = (newMax - newMin) * (value - oldMax); + double denominator = oldMax - oldMin; + + double newValue = nominator / denominator + newMax; + + return newValue; + } + void RenderableLabel::render(const RenderData& data, RendererTasks&) { - float scale = 1.f; - - float fadeInVariable = 1.f; - if (!_disableFadeInDistance) { - float distCamera = static_cast(glm::length(data.camera.positionVec3())); - const glm::vec2 fadeRange = _fadeInDistance; - const float a = 1.f / ((fadeRange.y - fadeRange.x) * scale); - const float b = -(fadeRange.x / (fadeRange.y - fadeRange.x)); - const float funcValue = a * distCamera + b; - fadeInVariable *= funcValue > 1.f ? 1.f : funcValue; - - if (funcValue < 0.01f) { - return; - } - } - glm::dmat4 modelMatrix = glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation glm::dmat4(data.modelTransform.rotation) * // Spice rotation @@ -407,8 +482,7 @@ namespace openspace { data, modelViewProjectionMatrix, orthoRight, - orthoUp, - fadeInVariable + orthoUp ); } } diff --git a/modules/dsn/rendering/renderablelabel.h b/modules/dsn/rendering/renderablelabel.h index 5c0b809410..5c6e28287a 100644 --- a/modules/dsn/rendering/renderablelabel.h +++ b/modules/dsn/rendering/renderablelabel.h @@ -52,37 +52,32 @@ namespace openspace { bool isReady() const override; void render(const RenderData& data, RendererTasks& rendererTask) override; - // void update(const UpdateData& data) override; static documentation::Documentation Documentation(); private: - //enum Unit { - // Meter = 0, - // Kilometer = 1, - // Parsec = 2, - // Kiloparsec = 3, - // Megaparsec = 4, - // Gigaparsec = 5, - // GigalightYears = 6 - //}; + + const double _maxDistanceUnit = 1E10; void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix, - const glm::dvec3& orthoRight, const glm::dvec3& orthoUp, float fadeInVariable); + const glm::dvec3& orthoRight, const glm::dvec3& orthoUp); bool loadData(); bool loadLabelDataFromId(); + bool _hasStaticLabelSize = false; bool _dataIsDirty = true; bool _textColorIsDirty = true; bool _hasLabel = false; bool _hasLabelIdMap = false; + double maxMinNormalize(double value, glm::dvec2 newRange, glm::dvec2 oldRange); properties::FloatProperty _scaleFactor; properties::Vec4Property _textColor; - properties::FloatProperty _textSize; - properties::FloatProperty _textMinSize; - properties::FloatProperty _textMaxSize; + properties::FloatProperty _labelSize; + properties::Vec2Property _labelSizeRange; + //properties::FloatProperty _textMinSize; + //properties::FloatProperty _textMaxSize; properties::BoolProperty _drawLabels; properties::Vec2Property _fadeInDistance; properties::BoolProperty _disableFadeInDistance; @@ -92,8 +87,17 @@ namespace openspace { std::shared_ptr _font; ghoul::Dictionary _labelIdMap; - std::vector> _labelData; + std::vector> _labelData; glm::dmat4 _transformationMatrix = glm::dmat4(1.0); + + /*The minimal size(in pixels) of the text for the labels + for the astronomical objects being rendered.*/ + double _textMinSize = 1.0; + /*The maximal size(in pixels) of the text for the labels + for the astronomical objects being rendered.*/ + double _textMaxSize = 100.0; + + }; } // namespace openspace