mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-01 01:01:37 -06:00
Fix stitched trail rendering for RenderableTrailTrajectory Adapt Lua scheduler helper scripts to new Dictionary layout Make Spice throw exceptions on default again Enable caching on default for CTX and MOLA data Add NOAA rt data (commented out in LodEarth)
382 lines
14 KiB
C++
382 lines
14 KiB
C++
/*****************************************************************************************
|
|
* *
|
|
* OpenSpace *
|
|
* *
|
|
* Copyright (c) 2014-2016 *
|
|
* *
|
|
* 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/base/rendering/renderabletrail.h>
|
|
|
|
#include <openspace/documentation/verifier.h>
|
|
#include <openspace/engine/openspaceengine.h>
|
|
#include <openspace/rendering/renderengine.h>
|
|
#include <openspace/scene/translation.h>
|
|
|
|
namespace {
|
|
const char* KeyTranslation = "Translation";
|
|
const char* KeyColor = "Color";
|
|
const char* KeyEnableFade = "EnableFade";
|
|
const char* KeyFade = "Fade";
|
|
const char* KeyLineWidth = "LineWidth";
|
|
const char* KeyPointSize = "PointSize";
|
|
const char* KeyRendering = "Rendering";
|
|
|
|
// The possible values for the _renderingModes property
|
|
enum RenderingMode {
|
|
RenderingModeLines = 0,
|
|
RenderingModePoints,
|
|
RenderingModeLinesPoints
|
|
};
|
|
|
|
// Fragile! Keep in sync with documentation
|
|
static const std::map<std::string, RenderingMode> RenderingModeConversion = {
|
|
{ "Lines", RenderingModeLines },
|
|
{ "Points", RenderingModePoints },
|
|
{ "Lines+Points", RenderingModeLinesPoints },
|
|
{ "Points+Lines", RenderingModeLinesPoints }
|
|
};
|
|
}
|
|
|
|
namespace openspace {
|
|
|
|
Documentation RenderableTrail::Documentation() {
|
|
using namespace documentation;
|
|
return {
|
|
"RenderableTrail",
|
|
"base_renderable_renderabletrail",
|
|
{
|
|
{
|
|
KeyTranslation,
|
|
new ReferencingVerifier("core_transform_translation"),
|
|
"This object is used to compute locations along the path. Any "
|
|
"Translation object can be used here.",
|
|
Optional::No
|
|
},
|
|
{
|
|
KeyColor,
|
|
new DoubleVector3Verifier,
|
|
"The main color the for lines and points on this trail. The value is "
|
|
"interpreted as an RGB value.",
|
|
Optional::No
|
|
},
|
|
{
|
|
KeyEnableFade,
|
|
new BoolVerifier,
|
|
"Toggles whether the trail should fade older points out. If this value "
|
|
"is 'true', the 'Fade' parameter determines the speed of fading. If this "
|
|
"value is 'false', the entire trail is rendered at full opacity and "
|
|
"color. The default value is 'true'.",
|
|
Optional::Yes
|
|
},
|
|
{
|
|
KeyFade,
|
|
new DoubleVerifier,
|
|
"The fading factor that is applied to the trail if the 'EnableFade' "
|
|
"value is 'true'. If it is 'false', this setting has no effect. The "
|
|
"higher the number, the less fading is applied. This value defaults to "
|
|
"1.0.",
|
|
Optional::Yes
|
|
},
|
|
{
|
|
KeyLineWidth,
|
|
new DoubleVerifier,
|
|
"This value specifies the line width of the trail if this rendering "
|
|
"method is selected. It defaults to 2.0.",
|
|
Optional::Yes
|
|
},
|
|
{
|
|
KeyPointSize,
|
|
new DoubleVerifier,
|
|
"This value specifies the base size of the points along the line if this "
|
|
"rendering method is selected. If a subsampling of the values is "
|
|
"performed, the subsampled values are half this size. The default value "
|
|
"is 1.0.",
|
|
Optional::Yes
|
|
},
|
|
{
|
|
KeyRendering,
|
|
new StringInListVerifier(
|
|
// Taken from the RenderingModeConversion map above
|
|
{ "Lines", "Points", "Lines+Points", "Points + Lines" }
|
|
),
|
|
"Determines how the trail should be rendered to the screen. If 'Lines' "
|
|
"is selected, only the line part is visible, if 'Points' is selected, "
|
|
"only the corresponding points (and subpoints) are shown. "
|
|
"Lines+Points' shows both parts. On default, only the lines are rendered",
|
|
Optional::Yes
|
|
}
|
|
},
|
|
Exhaustive::No
|
|
};
|
|
}
|
|
|
|
RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary)
|
|
: Renderable(dictionary)
|
|
, _lineColor("lineColor", "Color", glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
|
, _useLineFade("useLineFade", "Use Line Fade", true)
|
|
, _lineFade("lineFade", "Line Fade", 1.f, 0.f, 20.f)
|
|
, _lineWidth("lineWidth", "Line Width", 2.f, 1.f, 20.f)
|
|
, _pointSize("pointSize", "Point Size", 1, 1, 64)
|
|
, _renderingModes(
|
|
"renderingMode",
|
|
"Rendering Mode",
|
|
properties::OptionProperty::DisplayType::Dropdown
|
|
)
|
|
{
|
|
_translation = std::unique_ptr<Translation>(Translation::createFromDictionary(
|
|
dictionary.value<ghoul::Dictionary>(KeyTranslation)
|
|
));
|
|
addPropertySubOwner(_translation.get());
|
|
|
|
_lineColor = dictionary.value<glm::vec3>(KeyColor);
|
|
addProperty(_lineColor);
|
|
|
|
if (dictionary.hasKeyAndValue<bool>(KeyEnableFade)) {
|
|
_useLineFade = dictionary.value<bool>(KeyEnableFade);
|
|
}
|
|
addProperty(_useLineFade);
|
|
|
|
if (dictionary.hasKeyAndValue<double>(KeyFade)) {
|
|
_lineFade = dictionary.value<double>(KeyFade);
|
|
}
|
|
addProperty(_lineFade);
|
|
|
|
if (dictionary.hasKeyAndValue<double>(KeyLineWidth)) {
|
|
_lineWidth = dictionary.value<double>(KeyLineWidth);
|
|
}
|
|
addProperty(_lineWidth);
|
|
|
|
if (dictionary.hasKeyAndValue<double>(KeyPointSize)) {
|
|
_pointSize = dictionary.value<double>(KeyPointSize);
|
|
}
|
|
addProperty(_pointSize);
|
|
|
|
_renderingModes.addOptions({
|
|
{ RenderingModeLines, "Lines" },
|
|
{ RenderingModePoints, "Points" },
|
|
{ RenderingModeLinesPoints, "Lines+Points" }
|
|
});
|
|
|
|
// This map is not accessed out of order as long as the Documentation is adapted
|
|
// whenever the map changes. The documentation will check for valid values
|
|
if (dictionary.hasKeyAndValue<std::string>(KeyRendering)) {
|
|
_renderingModes = RenderingModeConversion.at(
|
|
dictionary.value<std::string>(KeyRendering)
|
|
);
|
|
}
|
|
else {
|
|
_renderingModes = RenderingModeLines;
|
|
}
|
|
addProperty(_renderingModes);
|
|
}
|
|
|
|
bool RenderableTrail::initialize() {
|
|
RenderEngine& renderEngine = OsEng.renderEngine();
|
|
_programObject = renderEngine.buildRenderProgram(
|
|
"EphemerisProgram",
|
|
"${MODULE_BASE}/shaders/renderabletrail_vs.glsl",
|
|
"${MODULE_BASE}/shaders/renderabletrail_fs.glsl"
|
|
);
|
|
|
|
setRenderBin(Renderable::RenderBin::Overlay);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RenderableTrail::deinitialize() {
|
|
RenderEngine& renderEngine = OsEng.renderEngine();
|
|
if (_programObject) {
|
|
renderEngine.removeRenderProgram(_programObject);
|
|
_programObject = nullptr;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool RenderableTrail::isReady() const {
|
|
return _programObject != nullptr;
|
|
}
|
|
|
|
void RenderableTrail::render(const RenderData & data) {
|
|
_programObject->activate();
|
|
|
|
glm::dmat4 modelTransform =
|
|
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
|
|
glm::dmat4(data.modelTransform.rotation) *
|
|
glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)));
|
|
|
|
_programObject->setUniform("projectionTransform", data.camera.projectionMatrix());
|
|
|
|
_programObject->setUniform("color", _lineColor);
|
|
_programObject->setUniform("useLineFade", _useLineFade);
|
|
if (_useLineFade) {
|
|
_programObject->setUniform("lineFade", _lineFade);
|
|
}
|
|
|
|
static std::map<RenderInformation::VertexSorting, int> SortingMapping = {
|
|
// Fragile! Keep in sync with shader
|
|
{ RenderInformation::VertexSorting::NewestFirst, 0 },
|
|
{ RenderInformation::VertexSorting::OldestFirst, 1 },
|
|
{ RenderInformation::VertexSorting::NoSorting, 2}
|
|
};
|
|
|
|
bool usingFramebufferRenderer =
|
|
OsEng.renderEngine().rendererImplementation() ==
|
|
RenderEngine::RendererImplementation::Framebuffer;
|
|
|
|
if (usingFramebufferRenderer) {
|
|
glDepthMask(false);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
}
|
|
|
|
bool renderLines =
|
|
_renderingModes == RenderingModeLines |
|
|
_renderingModes == RenderingModeLinesPoints;
|
|
|
|
bool renderPoints =
|
|
_renderingModes == RenderingModePoints |
|
|
_renderingModes == RenderingModeLinesPoints;
|
|
|
|
if (renderLines) {
|
|
glLineWidth(_lineWidth);
|
|
}
|
|
if (renderPoints) {
|
|
glEnable(GL_PROGRAM_POINT_SIZE);
|
|
}
|
|
|
|
auto render = [renderLines, renderPoints, p = _programObject.get(), &data,
|
|
&modelTransform, pointSize = _pointSize.value()]
|
|
(RenderInformation& info, int nVertices, int offset)
|
|
{
|
|
// We pass in the model view transformation matrix as double in order to maintain
|
|
// high precision for vertices; especially for the trails, a high vertex precision
|
|
// is necessary as they are usually far away from their reference
|
|
p->setUniform(
|
|
"modelViewTransform",
|
|
data.camera.combinedViewMatrix() * modelTransform * info._localTransform
|
|
);
|
|
|
|
// The vertex sorting method is used to tweak the fading along the trajectory
|
|
p->setUniform(
|
|
"vertexSortingMethod",
|
|
SortingMapping[info.sorting]
|
|
);
|
|
|
|
// This value is subtracted from the vertex id in the case of a potential ring
|
|
// buffer (as used in RenderableTrailOrbit) to keep the first vertex at its
|
|
// brightest
|
|
p->setUniform(
|
|
"idOffset",
|
|
offset
|
|
);
|
|
|
|
p->setUniform("nVertices", nVertices);
|
|
|
|
if (renderPoints) {
|
|
// The stride parameter determines the distance between larger points and
|
|
// smaller ones
|
|
p->setUniform("stride", info.stride);
|
|
p->setUniform("pointSize", pointSize);
|
|
}
|
|
|
|
// Fragile! Keep in sync with fragment shader
|
|
enum RenderPhase {
|
|
RenderPhaseLines = 0,
|
|
RenderPhasePoints
|
|
};
|
|
|
|
glBindVertexArray(info._vaoID);
|
|
if (renderLines) {
|
|
p->setUniform("renderPhase", RenderPhaseLines);
|
|
// Subclasses of this renderer might be using the index array or might now be
|
|
// so we check if there is data available and if there isn't, we use the
|
|
// glDrawArrays draw call; otherwise the glDrawElements
|
|
if (info._iBufferID == 0) {
|
|
glDrawArrays(
|
|
GL_LINE_STRIP,
|
|
info.first,
|
|
info.count
|
|
);
|
|
}
|
|
else {
|
|
glDrawElements(
|
|
GL_LINE_STRIP,
|
|
info.count,
|
|
GL_UNSIGNED_INT,
|
|
reinterpret_cast<void*>(info.first * sizeof(unsigned int))
|
|
);
|
|
}
|
|
}
|
|
if (renderPoints) {
|
|
// Subclasses of this renderer might be using the index array or might now be
|
|
// so we check if there is data available and if there isn't, we use the
|
|
// glDrawArrays draw call; otherwise the glDrawElements
|
|
p->setUniform("renderPhase", RenderPhasePoints);
|
|
if (info._iBufferID == 0) {
|
|
glDrawArrays(GL_POINTS, info.first, info.count);
|
|
}
|
|
else {
|
|
glDrawElements(
|
|
GL_POINTS,
|
|
info.count,
|
|
GL_UNSIGNED_INT,
|
|
reinterpret_cast<void*>(info.first * sizeof(unsigned int))
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
// The combined size of vertices; -1 because we duplicate the penultimate point
|
|
int totalNumber =
|
|
_primaryRenderInformation.count + _floatingRenderInformation.count - 1;
|
|
|
|
// The primary information might use an index buffer, so we might need to start at an
|
|
// offset
|
|
int primaryOffset =
|
|
_primaryRenderInformation._iBufferID == 0 ? 0 : _primaryRenderInformation.first;
|
|
|
|
// Render the primary batch of vertices
|
|
render(_primaryRenderInformation, totalNumber, primaryOffset);
|
|
|
|
// The secondary batch is optional, so we need to check whether we have any data here
|
|
if (_floatingRenderInformation._vaoID != 0 && _floatingRenderInformation.count != 0) {
|
|
render(
|
|
_floatingRenderInformation,
|
|
totalNumber,
|
|
// -1 because we duplicate the penultimate point between the vertices
|
|
-(primaryOffset + _primaryRenderInformation.count - 1)
|
|
);
|
|
}
|
|
|
|
if (renderPoints) {
|
|
glDisable(GL_PROGRAM_POINT_SIZE);
|
|
}
|
|
|
|
glBindVertexArray(0);
|
|
|
|
if (usingFramebufferRenderer) {
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glDepthMask(true);
|
|
}
|
|
|
|
_programObject->deactivate();
|
|
}
|
|
|
|
} // namespace openspace
|