mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-01 09:10:18 -06:00
297 lines
11 KiB
C++
297 lines
11 KiB
C++
/*****************************************************************************************
|
|
* *
|
|
* OpenSpace *
|
|
* *
|
|
* Copyright (c) 2014-2023 *
|
|
* *
|
|
* 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 *
|
|
* without restriction, including without limitation the rights to use, copy, modify, *
|
|
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
|
* permit persons to whom the Software is furnished to do so, subject to the following *
|
|
* conditions: *
|
|
* *
|
|
* The above copyright notice and this permission notice shall be included in all copies *
|
|
* or substantial portions of the Software. *
|
|
* *
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
|
****************************************************************************************/
|
|
|
|
#include <modules/space/labelscomponent.h>
|
|
|
|
#include <openspace/engine/globals.h>
|
|
#include <openspace/engine/windowdelegate.h>
|
|
#include <openspace/documentation/documentation.h>
|
|
#include <openspace/util/updatestructures.h>
|
|
#include <ghoul/filesystem/filesystem.h>
|
|
#include <ghoul/font/fontmanager.h>
|
|
#include <ghoul/font/fontrenderer.h>
|
|
#include <optional>
|
|
|
|
namespace {
|
|
constexpr std::string_view _loggerCat = "LabelsComponent";
|
|
|
|
constexpr int RenderOptionFaceCamera = 0;
|
|
constexpr int RenderOptionPositionNormal = 1;
|
|
|
|
constexpr openspace::properties::Property::PropertyInfo EnabledInfo = {
|
|
"Enabled",
|
|
"Enabled",
|
|
"This setting determines whether the labels will be visible or not. They are "
|
|
"disabled per default",
|
|
// @VISIBILITY(?)
|
|
openspace::properties::Property::Visibility::AdvancedUser
|
|
};
|
|
|
|
constexpr openspace::properties::Property::PropertyInfo FileInfo = {
|
|
"File",
|
|
"File",
|
|
"The speck label file with the data for the labels",
|
|
openspace::properties::Property::Visibility::AdvancedUser
|
|
};
|
|
|
|
constexpr openspace::properties::Property::PropertyInfo ColorInfo = {
|
|
"Color",
|
|
"Color",
|
|
"The color of the labels",
|
|
openspace::properties::Property::Visibility::NoviceUser
|
|
};
|
|
|
|
constexpr openspace::properties::Property::PropertyInfo SizeInfo = {
|
|
"Size",
|
|
"Size",
|
|
"The size of the labels in pixels",
|
|
// @VISIBILITY(2.5)
|
|
openspace::properties::Property::Visibility::User
|
|
};
|
|
|
|
constexpr openspace::properties::Property::PropertyInfo FontSizeInfo = {
|
|
"FontSize",
|
|
"Font Size",
|
|
"Font size for the labels. This is different from the text size",
|
|
openspace::properties::Property::Visibility::User
|
|
};
|
|
|
|
constexpr openspace::properties::Property::PropertyInfo MinMaxInfo = {
|
|
"MinMaxSize",
|
|
"Min/Max Size",
|
|
"The minimum and maximum size (in pixels) of the labels",
|
|
openspace::properties::Property::Visibility::AdvancedUser
|
|
};
|
|
|
|
constexpr openspace::properties::Property::PropertyInfo FaceCameraInfo = {
|
|
"FaceCamera",
|
|
"Face Camera",
|
|
"If enabled, the labels will be rotated to face the camera. For non-linear "
|
|
"display rendering (for example fisheye) this should be set to false.",
|
|
openspace::properties::Property::Visibility::AdvancedUser
|
|
};
|
|
|
|
constexpr openspace::properties::Property::PropertyInfo TransformationMatrixInfo = {
|
|
"TransformationMatrix",
|
|
"Transformation Matrix",
|
|
"Transformation matrix to be applied to the labels",
|
|
// @VISIBILITY(?)
|
|
openspace::properties::Property::Visibility::Developer
|
|
};
|
|
|
|
struct [[codegen::Dictionary(LabelsComponent)]] Parameters {
|
|
// [[codegen::verbatim(EnabledInfo.description)]]
|
|
std::optional<bool> enabled;
|
|
|
|
// [[codegen::verbatim(FileInfo.description)]]
|
|
std::filesystem::path file;
|
|
|
|
// The opacity of the labels
|
|
std::optional<float> opacity [[codegen::inrange(0.0, 1.0)]];
|
|
|
|
// [[codegen::verbatim(ColorInfo.description)]]
|
|
std::optional<glm::vec3> color [[codegen::color()]];
|
|
|
|
// [[codegen::verbatim(SizeInfo.description)]]
|
|
std::optional<float> size;
|
|
|
|
// [[codegen::verbatim(FontSizeInfo.description)]]
|
|
std::optional<float> fontSize;
|
|
|
|
// [[codegen::verbatim(MinMaxInfo.description)]]
|
|
std::optional<glm::ivec2> minMaxSize;
|
|
|
|
enum class [[codegen::map(openspace::DistanceUnit)]] Unit {
|
|
Meter [[codegen::key("m")]],
|
|
Kilometer [[codegen::key("Km")]],
|
|
Parsec [[codegen::key("pc")]],
|
|
Kiloparsec [[codegen::key("Kpc")]],
|
|
Megaparsec [[codegen::key("Mpc")]],
|
|
Gigaparsec [[codegen::key("Gpc")]],
|
|
Gigalightyear [[codegen::key("Gly")]]
|
|
};
|
|
std::optional<Unit> unit;
|
|
|
|
// [[codegen::verbatim(FaceCameraInfo.description)]]
|
|
std::optional<bool> faceCamera;
|
|
|
|
// [[codegen::verbatim(TransformationMatrixInfo.description)]]
|
|
std::optional<glm::dmat4x4> transformationMatrix;
|
|
};
|
|
#include "labelscomponent_codegen.cpp"
|
|
} // namespace
|
|
|
|
namespace openspace {
|
|
|
|
documentation::Documentation LabelsComponent::Documentation() {
|
|
return codegen::doc<Parameters>("space_labelscomponent");
|
|
}
|
|
|
|
LabelsComponent::LabelsComponent(const ghoul::Dictionary& dictionary)
|
|
: properties::PropertyOwner({ "Labels" })
|
|
, _enabled(EnabledInfo, false)
|
|
, _color(ColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
|
, _size(SizeInfo, 8.f, 0.5f, 24.f)
|
|
, _fontSize(FontSizeInfo, 50.f, 1.f, 300.f)
|
|
, _minMaxSize(
|
|
MinMaxInfo,
|
|
glm::ivec2(8, 500),
|
|
glm::ivec2(0),
|
|
glm::ivec2(1000)
|
|
)
|
|
, _faceCamera(FaceCameraInfo, true)
|
|
{
|
|
const Parameters p = codegen::bake<Parameters>(dictionary);
|
|
|
|
_labelFile = absPath(p.file);
|
|
|
|
if (p.unit.has_value()) {
|
|
_unit = codegen::map<DistanceUnit>(*p.unit);
|
|
}
|
|
else {
|
|
_unit = DistanceUnit::Meter;
|
|
}
|
|
|
|
_enabled = p.enabled.value_or(_enabled);
|
|
addProperty(_enabled);
|
|
|
|
_opacity = p.opacity.value_or(_opacity);
|
|
addProperty(Fadeable::_opacity);
|
|
|
|
addProperty(Fadeable::_fade);
|
|
|
|
_color = p.color.value_or(_color);
|
|
_color.setViewOption(properties::Property::ViewOptions::Color);
|
|
addProperty(_color);
|
|
|
|
_size = p.size.value_or(_size);
|
|
addProperty(_size);
|
|
|
|
_fontSize = p.fontSize.value_or(_fontSize);
|
|
_fontSize.onChange([this]() { initialize(); });
|
|
addProperty(_fontSize);
|
|
// @TODO (emmbr, 2021-05-31): Temporarily set as read only, to avoid errors from font
|
|
// rendering (avoid filling font atlas)
|
|
_fontSize.setReadOnly(true);
|
|
|
|
_minMaxSize = p.minMaxSize.value_or(_minMaxSize);
|
|
_minMaxSize.setViewOption(properties::Property::ViewOptions::MinMaxRange);
|
|
addProperty(_minMaxSize);
|
|
|
|
if (p.faceCamera.has_value()) {
|
|
_faceCamera = *p.faceCamera;
|
|
}
|
|
else {
|
|
// @TODO (abock. 2021-01-31) In the other DU classes, this is done with an enum,
|
|
// and doing it based on the fisheye rendering seems a bit brittle?
|
|
|
|
// (malej 2022-SEP-14)
|
|
// For non-linear display rendering (for example fisheye) _faceCamera should be
|
|
// false, otherwise true
|
|
_faceCamera = !global::windowDelegate->isFisheyeRendering();
|
|
}
|
|
addProperty(_faceCamera);
|
|
|
|
_transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix);
|
|
}
|
|
|
|
speck::Labelset& LabelsComponent::labelSet() {
|
|
return _labelset;
|
|
}
|
|
|
|
const speck::Labelset& LabelsComponent::labelSet() const {
|
|
return _labelset;
|
|
}
|
|
|
|
void LabelsComponent::initialize() {
|
|
_font = global::fontManager->font(
|
|
"Mono",
|
|
_fontSize,
|
|
ghoul::fontrendering::FontManager::Outline::Yes,
|
|
ghoul::fontrendering::FontManager::LoadGlyphs::No
|
|
);
|
|
}
|
|
|
|
void LabelsComponent::loadLabels() {
|
|
LINFO(fmt::format("Loading label file {}", _labelFile));
|
|
_labelset = speck::label::loadFileWithCache(_labelFile);
|
|
}
|
|
|
|
bool LabelsComponent::isReady() const {
|
|
return !(_labelset.entries.empty());
|
|
}
|
|
|
|
bool LabelsComponent::enabled() const {
|
|
return _enabled;
|
|
}
|
|
|
|
void LabelsComponent::render(const RenderData& data,
|
|
const glm::dmat4& modelViewProjectionMatrix,
|
|
const glm::vec3& orthoRight, const glm::vec3& orthoUp,
|
|
float fadeInVariable)
|
|
{
|
|
if (!_enabled) {
|
|
return;
|
|
}
|
|
float scale = static_cast<float>(toMeter(_unit));
|
|
|
|
int renderOption = _faceCamera ? RenderOptionFaceCamera : RenderOptionPositionNormal;
|
|
|
|
ghoul::fontrendering::FontRenderer::ProjectedLabelsInformation labelInfo;
|
|
labelInfo.orthoRight = orthoRight;
|
|
labelInfo.orthoUp = orthoUp;
|
|
labelInfo.minSize = _minMaxSize.value().x;
|
|
labelInfo.maxSize = _minMaxSize.value().y;
|
|
labelInfo.cameraPos = data.camera.positionVec3();
|
|
labelInfo.cameraLookUp = data.camera.lookUpVectorWorldSpace();
|
|
labelInfo.renderType = renderOption;
|
|
labelInfo.mvpMatrix = modelViewProjectionMatrix;
|
|
labelInfo.scale = pow(10.f, _size);
|
|
labelInfo.enableDepth = true;
|
|
labelInfo.enableFalseDepth = false;
|
|
|
|
glm::vec4 textColor = glm::vec4(glm::vec3(_color), opacity() * fadeInVariable);
|
|
|
|
for (const speck::Labelset::Entry& e : _labelset.entries) {
|
|
if (!e.isEnabled) {
|
|
continue;
|
|
}
|
|
|
|
// Transform and scale the labels
|
|
glm::vec3 transformedPos(_transformationMatrix * glm::dvec4(e.position, 1.0));
|
|
glm::vec3 scaledPos(transformedPos);
|
|
scaledPos *= scale;
|
|
|
|
ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render(
|
|
*_font,
|
|
scaledPos,
|
|
e.text,
|
|
textColor,
|
|
labelInfo
|
|
);
|
|
}
|
|
}
|
|
|
|
} // namespace openspace
|