From 4f370a4bbde260fb26c4f9f083c55cdf616099ae Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Mon, 30 Apr 2018 13:05:23 +0200 Subject: [PATCH] Implement visualisation of the labels, if available. --- src/fmri/Drawable.cpp | 2 +- src/fmri/FlatLayerVisualisation.cpp | 2 +- src/fmri/LabelVisualisation.cpp | 46 +++++++++++++++++++++++++++++ src/fmri/LabelVisualisation.hpp | 20 +++++++++++++ src/fmri/LayerData.cpp | 5 ++++ src/fmri/LayerData.hpp | 4 ++- src/fmri/RenderingState.cpp | 7 +++++ src/fmri/utils.hpp | 7 +++++ 8 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/fmri/LabelVisualisation.cpp create mode 100644 src/fmri/LabelVisualisation.hpp diff --git a/src/fmri/Drawable.cpp b/src/fmri/Drawable.cpp index 41c8f32..d9dab6a 100644 --- a/src/fmri/Drawable.cpp +++ b/src/fmri/Drawable.cpp @@ -2,7 +2,7 @@ void fmri::Drawable::patchTransparancy() { - if constexpr (std::tuple_size::value < 4) { + if constexpr (!alphaEnabled()) { // Not compiling with alpha support return; } diff --git a/src/fmri/FlatLayerVisualisation.cpp b/src/fmri/FlatLayerVisualisation.cpp index 0a69314..646ccce 100644 --- a/src/fmri/FlatLayerVisualisation.cpp +++ b/src/fmri/FlatLayerVisualisation.cpp @@ -19,7 +19,7 @@ static inline void computeColor(float intensity, float limit, Color& destination destination[1] = saturation; destination[2] = saturation; } - if constexpr (std::tuple_size::value >= 4) { + if constexpr (alphaEnabled()) { // We have an alpha channel, set it to 1. destination[3] = 1; } diff --git a/src/fmri/LabelVisualisation.cpp b/src/fmri/LabelVisualisation.cpp new file mode 100644 index 0000000..d73ba37 --- /dev/null +++ b/src/fmri/LabelVisualisation.cpp @@ -0,0 +1,46 @@ +#include +#include "LabelVisualisation.hpp" +#include "glutils.hpp" + +using namespace fmri; + +void LabelVisualisation::draw(float) +{ + glPushMatrix(); + glTranslatef(LAYER_X_OFFSET, 0, 0); + + for (auto i = 0u; i < nodeLabels.size(); ++i) { + glPushMatrix(); + glTranslatef(nodePositions_[3 * i], nodePositions_[3 * i + 1], nodePositions_[3 * i + 2]); + if constexpr (alphaEnabled()) { + glColor4fv(colorBuffer[i].data()); + } else { + glColor3fv(colorBuffer[i].data()); + } + renderText(nodeLabels[i]); + glPopMatrix(); + } + + glPopMatrix(); +} + +LabelVisualisation::LabelVisualisation(const std::vector &positions, const LayerData &prevData, + const std::vector &labels) +{ + const auto limit = std::min(prevData.numEntries(), labels.size()); + const auto maxVal = *std::max_element(prevData.data(), prevData.data() + prevData.numEntries()); + + auto nodeInserter = std::back_inserter(nodePositions_); + + for (auto i = 0u; i < limit; ++i) { + if (prevData[i] < DISPLAY_LIMIT) { + continue; + } + + colorBuffer.emplace_back(Color{1 - prevData[i] / maxVal, 1 - prevData[i] / maxVal, 1}); + std::copy_n(positions.begin() + 3 * i, 3, nodeInserter); + nodeLabels.emplace_back(labels[i]); + } + + patchTransparancy(); +} diff --git a/src/fmri/LabelVisualisation.hpp b/src/fmri/LabelVisualisation.hpp new file mode 100644 index 0000000..a429322 --- /dev/null +++ b/src/fmri/LabelVisualisation.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "LayerData.hpp" +#include "Animation.hpp" + +namespace fmri +{ + class LabelVisualisation : public Animation + { + public: + LabelVisualisation(const std::vector& positions, const LayerData& prevData, const std::vector& labels); + void draw(float time) override; + + private: + static constexpr float DISPLAY_LIMIT = 0.01; + + std::vector nodeLabels; + std::vector nodePositions_; + }; +} diff --git a/src/fmri/LayerData.cpp b/src/fmri/LayerData.cpp index 3b12418..0fd2766 100644 --- a/src/fmri/LayerData.cpp +++ b/src/fmri/LayerData.cpp @@ -42,6 +42,11 @@ DType const * LayerData::data() const return data_.get(); } +const DType &LayerData::operator[](std::size_t i) const +{ + return data_[i]; +} + ostream& operator<< (ostream& o, const LayerData& layer) { o << layer.name() << '('; diff --git a/src/fmri/LayerData.hpp b/src/fmri/LayerData.hpp index c4630d9..039929a 100644 --- a/src/fmri/LayerData.hpp +++ b/src/fmri/LayerData.hpp @@ -30,7 +30,9 @@ namespace fmri const string &name() const; const vector &shape() const; DType const *data() const; - size_t numEntries() const; + std::size_t numEntries() const; + + const DType& operator[] (std::size_t i) const; private: string name_; vector shape_; diff --git a/src/fmri/RenderingState.cpp b/src/fmri/RenderingState.cpp index ca42ba1..e0e6f40 100644 --- a/src/fmri/RenderingState.cpp +++ b/src/fmri/RenderingState.cpp @@ -7,6 +7,7 @@ #include "Range.hpp" #include "glutils.hpp" #include "Simulator.hpp" +#include "LabelVisualisation.hpp" using namespace fmri; @@ -68,6 +69,8 @@ static VisualisationList loadVisualisations(const Options& options) auto [layerInfo, layerData] = Simulator::loadSimulationData(options); + auto labels = options.labels(); + VisualisationList result; for (auto &&item : layerData) { @@ -89,6 +92,10 @@ static VisualisationList loadVisualisations(const Options& options) VisualisationList::value_type dataSet; + if (labels) { + animations.emplace_back(new LabelVisualisation(layers.rbegin()->get()->nodePositions(), *prevData, labels.value())); + } + for (auto i = 0u; i < layers.size(); ++i) { auto interaction = i < animations.size() ? move(animations[i]) : nullptr; dataSet.emplace_back(move(layers[i]), move(interaction)); diff --git a/src/fmri/utils.hpp b/src/fmri/utils.hpp index 985527f..f58afa6 100644 --- a/src/fmri/utils.hpp +++ b/src/fmri/utils.hpp @@ -246,4 +246,11 @@ namespace fmri * @return Resulting list of floats. */ const std::vector & animate(const std::vector &start, const std::vector &delta, float time); + + /** + * @return Whether alpha support is enabled, compile time. + */ + constexpr bool alphaEnabled() { + return std::tuple_size::value >= 4; + } }