Implement a simple loading animation.

Loading currently doesn't happen, because loading tries to do some GL
actions which cannot happen in a background thread (in GLUT anyway).

TODO: move all GL options to the main thread, and leave the rest of the
loading to the background.
This commit is contained in:
2018-04-12 14:25:01 +02:00
parent 2bd84abe94
commit 30aa25a09e
3 changed files with 92 additions and 26 deletions

View File

@@ -24,6 +24,7 @@ find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED) find_package(GLUT REQUIRED)
find_package(Boost REQUIRED COMPONENTS filesystem program_options) find_package(Boost REQUIRED COMPONENTS filesystem program_options)
find_package(OpenCV 3 REQUIRED COMPONENTS core imgproc imgcodecs) find_package(OpenCV 3 REQUIRED COMPONENTS core imgproc imgcodecs)
find_package(Threads REQUIRED)
target_link_libraries(fmri PUBLIC target_link_libraries(fmri PUBLIC
Caffe::Caffe Caffe::Caffe
@@ -33,6 +34,7 @@ target_link_libraries(fmri PUBLIC
opencv_core opencv_core
opencv_imgproc opencv_imgproc
opencv_imgcodecs opencv_imgcodecs
Threads::Threads
) )
target_include_directories(fmri PUBLIC target_include_directories(fmri PUBLIC

View File

@@ -217,7 +217,17 @@ void RenderingState::loadSimulationData(const std::map<string, LayerInfo> &info,
layerData = std::move(data); layerData = std::move(data);
currentData = layerData.begin(); currentData = layerData.begin();
updateVisualisers(); queueUpdate();
}
void RenderingState::queueUpdate()
{
loadingFuture = std::async(std::launch::async, []() {
// Currently causes a segfault, due to threaded OpenGL.
// Possible solution: don't do GL things while loading.
//RenderingState::instance().updateVisualisers();
});
isLoading = true;
} }
void RenderingState::updateVisualisers() void RenderingState::updateVisualisers()
@@ -249,34 +259,60 @@ void RenderingState::render(float time) const
// Clear Color and Depth Buffers // Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
configureRenderingContext(); if (!isLoading) {
renderVisualisation(time);
} else {
renderLoadingScreen();
}
glutSwapBuffers();
}
void RenderingState::renderVisualisation(float time) const
{
configureRenderingContext();
glPushMatrix(); glPushMatrix();
// Ensure we render back-to-front for transparency // Ensure we render back-to-front for transparency
if (angle[0] <= 0) { if (angle[0] <= 0) {
// Render from the first to the last layer. // Render from the first to the last layer.
glTranslatef(-LAYER_X_OFFSET / 2 * currentData->size(), 0, 0); glTranslatef(-LAYER_X_OFFSET / 2 * currentData->size(), 0, 0);
for (auto i : Range(currentData->size())) { for (auto i : Range(currentData->size())) {
drawLayer(time, i); drawLayer(time, i);
glTranslatef(LAYER_X_OFFSET, 0, 0); glTranslatef(LAYER_X_OFFSET, 0, 0);
} }
} else { } else {
// Render from the last layer to the first layer. // Render from the last layer to the first layer.
glTranslatef(LAYER_X_OFFSET / 2 * (currentData->size() - 2), 0, 0); glTranslatef(LAYER_X_OFFSET / 2 * (currentData->size() - 2), 0, 0);
for (auto i = currentData->size(); i--;) { for (auto i = currentData->size(); i--;) {
drawLayer(time, i); drawLayer(time, i);
glTranslatef(-LAYER_X_OFFSET, 0, 0); glTranslatef(-LAYER_X_OFFSET, 0, 0);
}
} }
}
glPopMatrix(); glPopMatrix();
renderOverlayText(); renderOverlayText();
}
glutSwapBuffers(); void RenderingState::renderLoadingScreen() const
{
glLoadIdentity();
glTranslatef(0, 0, -4);
glRotatef(360 * getAnimationStep(std::chrono::seconds(4)), 0, 1, 0);
glColor3f(1, 1, 1);
glutWireTeapot(1);
auto pulse = std::cos(2 * M_PI * getAnimationStep(std::chrono::seconds(3)));
pulse *= pulse;
glColor3d(pulse, pulse, 0);
glLoadIdentity();
setOrthographicProjection();
renderText("Loading...", 5, 15);
restorePerspectiveProjection();
} }
void RenderingState::drawLayer(float time, unsigned long i) const void RenderingState::drawLayer(float time, unsigned long i) const
@@ -341,7 +377,7 @@ void RenderingState::handleSpecialKey(int key)
currentData = layerData.end(); currentData = layerData.end();
} }
--currentData; --currentData;
updateVisualisers(); queueUpdate();
break; break;
case GLUT_KEY_RIGHT: case GLUT_KEY_RIGHT:
@@ -349,7 +385,7 @@ void RenderingState::handleSpecialKey(int key)
if (currentData == layerData.end()) { if (currentData == layerData.end()) {
currentData = layerData.begin(); currentData = layerData.begin();
} }
updateVisualisers(); queueUpdate();
break; break;
case GLUT_KEY_F1: case GLUT_KEY_F1:
@@ -419,14 +455,32 @@ float RenderingState::layerAlpha() const
void RenderingState::idleFunc() void RenderingState::idleFunc()
{ {
if (options.mouse_1_pressed) { if (isLoading && loadingFuture.valid()) {
move('w', false); auto result = loadingFuture.wait_for(std::chrono::milliseconds(40));
} switch (result) {
if (options.mouse_2_pressed) { case std::future_status::deferred:
move('s', false); LOG(ERROR) << "loading status was deferred, invalid state!";
} abort();
checkGLErrors(); case std::future_status::timeout:
throttleIdleFunc(); // Still loading
break;
case std::future_status::ready:
loadingFuture.get();
//isLoading = false;
break;
}
} else {
if (options.mouse_1_pressed) {
move('w', false);
}
if (options.mouse_2_pressed) {
move('s', false);
}
checkGLErrors();
throttleIdleFunc();
}
glutPostRedisplay(); glutPostRedisplay();
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <future>
#include "LayerInfo.hpp" #include "LayerInfo.hpp"
#include "LayerData.hpp" #include "LayerData.hpp"
#include "LayerVisualisation.hpp" #include "LayerVisualisation.hpp"
@@ -78,6 +79,9 @@ namespace fmri
std::vector<std::vector<LayerData>>::iterator currentData; std::vector<std::vector<LayerData>>::iterator currentData;
std::vector<std::unique_ptr<LayerVisualisation>> layerVisualisations; std::vector<std::unique_ptr<LayerVisualisation>> layerVisualisations;
std::vector<std::unique_ptr<Animation>> interactionAnimations; std::vector<std::unique_ptr<Animation>> interactionAnimations;
bool isLoading = false;
std::future<void> loadingFuture;
RenderingState() noexcept; RenderingState() noexcept;
@@ -92,5 +96,11 @@ namespace fmri
void renderLayerName(const std::string& name) const; void renderLayerName(const std::string& name) const;
void drawLayer(float time, unsigned long i) const; void drawLayer(float time, unsigned long i) const;
void queueUpdate();
void renderLoadingScreen() const;
void renderVisualisation(float time) const;
}; };
} }