improved our label class, handles precision errors and rescales depending on distance

This commit is contained in:
Lovisa Hassler
2018-12-17 17:18:36 -05:00
parent 3d4114247f
commit 40e56bf005
3 changed files with 155 additions and 77 deletions

View File

@@ -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",

View File

@@ -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<float>(TextSizeInfo.identifier);
}
addProperty(_textSize);
// Can have either a static size or a scaled interval
if (dictionary.hasKey(LabelSizeInfo.identifier)) {
_labelSize = dictionary.value<float>(LabelSizeInfo.identifier);
addProperty(_labelSize);
_hasStaticLabelSize = true;
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
_textMinSize = dictionary.value<float>(LabelMinSizeInfo.identifier);
}else if(dictionary.hasKey(LabelSizeRangeInfo.identifier))
{
glm::vec2 labelsizeRange = dictionary.value<glm::vec2>(LabelSizeRangeInfo.identifier);
_labelSizeRange.set(labelsizeRange);
addProperty(_labelSizeRange);
}
addProperty(_textMinSize);
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
_textMaxSize = dictionary.value<float>(LabelMaxSizeInfo.identifier);
}
addProperty(_textMaxSize);
//if (dictionary.hasKey(TextMinSizeInfo.identifier)) {
// _textMinSize = dictionary.value<float>(TextMinSizeInfo.identifier);
//}
//addProperty(_textMinSize);
//if (dictionary.hasKey(TextMaxSizeInfo.identifier)) {
// _textMaxSize = dictionary.value<float>(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<float>(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<glm::dvec3, std::string>& 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<int>(_textMinSize),
static_cast<int>(_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<float>(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
);
}
}

View File

@@ -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<ghoul::fontrendering::Font> _font;
ghoul::Dictionary _labelIdMap;
std::vector<std::pair<glm::vec3, std::string>> _labelData;
std::vector<std::pair<glm::dvec3, std::string>> _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