diff --git a/src/fmri/ActivityAnimation.cpp b/src/fmri/ActivityAnimation.cpp index 7325f80..b4a841d 100644 --- a/src/fmri/ActivityAnimation.cpp +++ b/src/fmri/ActivityAnimation.cpp @@ -11,12 +11,12 @@ using namespace std; using namespace fmri; -ActivityAnimation::Color ActivityAnimation::colorBySign(float intensity) +Color ActivityAnimation::colorBySign(float intensity) { if (intensity > 0) { - return {0, 1, 0}; + return {0, 1, 0, 1}; } else { - return {1, 0, 0}; + return {1, 0, 0, 1}; } } @@ -67,7 +67,7 @@ void ActivityAnimation::draw(float timeScale) glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_FLOAT, 0, colorBuf.data()); + glColorPointer(std::tuple_size::value, GL_FLOAT, 0, colorBuf.data()); glVertexPointer(3, GL_FLOAT, 0, vertexBuffer.data()); glDrawArrays(GL_POINTS, 0, bufferLength / 3); glDisableClientState(GL_COLOR_ARRAY); diff --git a/src/fmri/ActivityAnimation.hpp b/src/fmri/ActivityAnimation.hpp index 8d1f534..27ec3b1 100644 --- a/src/fmri/ActivityAnimation.hpp +++ b/src/fmri/ActivityAnimation.hpp @@ -13,7 +13,6 @@ namespace fmri : public Animation { public: - typedef std::array Color; typedef std::function ColoringFunction; ActivityAnimation( @@ -28,7 +27,7 @@ namespace fmri private: std::size_t bufferLength; - std::vector> colorBuf; + std::vector colorBuf; std::vector startingPos; std::vector delta; std::vector lineIndices; diff --git a/src/fmri/FlatLayerVisualisation.cpp b/src/fmri/FlatLayerVisualisation.cpp index 1169dbd..e97750e 100644 --- a/src/fmri/FlatLayerVisualisation.cpp +++ b/src/fmri/FlatLayerVisualisation.cpp @@ -7,7 +7,7 @@ using namespace fmri; -static inline void computeColor(float intensity, float limit, float *destination) +static inline void computeColor(float intensity, float limit, Color& destination) { const float saturation = std::min(-std::log(std::abs(intensity) / limit) / 10.0f, 1.0f); if (intensity > 0) { @@ -19,13 +19,17 @@ static inline void computeColor(float intensity, float limit, float *destination destination[1] = saturation; destination[2] = saturation; } + if constexpr (std::tuple_size::value >= 4) { + // We have an alpha channel, set it to 1. + destination[3] = 1; + } } FlatLayerVisualisation::FlatLayerVisualisation(const LayerData &layer, Ordering ordering) : LayerVisualisation(layer.numEntries()), ordering(ordering), vertexBuffer(layer.numEntries() * NODE_FACES.size()), - colorBuffer(layer.numEntries() * NODE_FACES.size()), + colorBuffer(layer.numEntries() * VERTICES_PER_NODE), indexBuffer(layer.numEntries() * NODE_FACES.size()) { auto &shape = layer.shape(); @@ -41,20 +45,18 @@ FlatLayerVisualisation::FlatLayerVisualisation(const LayerData &layer, Ordering auto scalingMax = std::max(abs(*minElem), abs(*maxElem)); - int v = 0; + auto colorPos = colorBuffer.begin(); + auto indexPos = indexBuffer.begin(); + for (int i : Range(limit)) { setVertexPositions(i, vertexBuffer.data() + NODE_FACES.size() * i); - const auto vertexBase = static_cast(i * NODE_FACES.size() / 3); + Color nodeColor; + computeColor(data[i], scalingMax, nodeColor); + colorPos = std::fill_n(colorPos, NODE_FACES.size() / 3, nodeColor); - // Define the colors for the vertices - for (auto c : Range(NODE_SHAPE.size() / 3)) { - computeColor(data[i], scalingMax, &colorBuffer[NODE_FACES.size() * i + 3 * c]); - } - - // Set the face nodes indices - for (auto faceNode : NODE_FACES) { - indexBuffer[v++] = vertexBase + faceNode; - } + auto newIndexPos = std::copy(std::begin(NODE_FACES), std::end(NODE_FACES), indexPos); + std::transform(indexPos, newIndexPos, indexPos, [i](auto x) { return x + i * VERTICES_PER_NODE;}); + indexPos = newIndexPos; } // Compute which nodes are active, add those to the active indices @@ -63,6 +65,9 @@ FlatLayerVisualisation::FlatLayerVisualisation(const LayerData &layer, Ordering std::copy_n(&indexBuffer[NODE_FACES.size() * i], NODE_FACES.size(), std::back_inserter(activeIndexBuffer)); } } + + assert(indexPos == indexBuffer.end()); + assert(colorPos == colorBuffer.end()); } void FlatLayerVisualisation::render() @@ -73,7 +78,7 @@ void FlatLayerVisualisation::render() const auto& indices = RenderingState::instance().renderActivatedOnly() ? activeIndexBuffer : indexBuffer; glVertexPointer(3, GL_FLOAT, 0, vertexBuffer.data()); - glColorPointer(3, GL_FLOAT, 0, colorBuffer.data()); + glColorPointer(std::tuple_size::value, GL_FLOAT, 0, colorBuffer.data()); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, indices.data()); glDisableClientState(GL_COLOR_ARRAY); diff --git a/src/fmri/FlatLayerVisualisation.hpp b/src/fmri/FlatLayerVisualisation.hpp index 7ebd0cf..de001a7 100644 --- a/src/fmri/FlatLayerVisualisation.hpp +++ b/src/fmri/FlatLayerVisualisation.hpp @@ -17,7 +17,7 @@ namespace fmri private: Ordering ordering; std::vector vertexBuffer; - std::vector colorBuffer; + std::vector colorBuffer; std::vector indexBuffer; std::vector activeIndexBuffer; @@ -33,6 +33,8 @@ namespace fmri 0, 2, 3, 1, 2, 3 }; + constexpr const auto VERTICES_PER_NODE = NODE_SHAPE.size() / 3; + constexpr const auto FACES_PER_NODE = NODE_FACES.size() / 3; void setVertexPositions(int vertexNo, float *destination); diff --git a/src/fmri/visualisations.cpp b/src/fmri/visualisations.cpp index df98b5e..c38a306 100644 --- a/src/fmri/visualisations.cpp +++ b/src/fmri/visualisations.cpp @@ -170,11 +170,11 @@ static Animation *getReLUAnimation(const fmri::LayerData &prevState, const auto maxValue = max_element(results.begin(), results.end())->first; return new ActivityAnimation(results, prevPositions.data(), curPositions.data(), - [=](float i) -> ActivityAnimation::Color { + [=](float i) -> Color { if (maxValue == 0) { - return {1, 1, 1}; + return {1, 1, 1, 1}; } else { - return {1 - i / maxValue, 1 - i / maxValue, 1}; + return {1 - i / maxValue, 1 - i / maxValue, 1, 1}; } }); } else { @@ -202,11 +202,12 @@ static Animation *getNormalizingAnimation(const fmri::LayerData &prevState, cons auto max_val = *max_element(scaling.begin(), scaling.end()); return new ActivityAnimation(entries, prevPositions.data(), curPositions.data(), - [=](float i) -> ActivityAnimation::Color { + [=](float i) -> Color { auto intensity = clamp((i - 1) / (max_val - 1), 0.f, 1.f); return { 1 - intensity, 1, + 1, 1 }; });