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:
@@ -24,6 +24,7 @@ find_package(OpenGL REQUIRED)
|
||||
find_package(GLUT REQUIRED)
|
||||
find_package(Boost REQUIRED COMPONENTS filesystem program_options)
|
||||
find_package(OpenCV 3 REQUIRED COMPONENTS core imgproc imgcodecs)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
target_link_libraries(fmri PUBLIC
|
||||
Caffe::Caffe
|
||||
@@ -33,6 +34,7 @@ target_link_libraries(fmri PUBLIC
|
||||
opencv_core
|
||||
opencv_imgproc
|
||||
opencv_imgcodecs
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
target_include_directories(fmri PUBLIC
|
||||
|
||||
@@ -217,7 +217,17 @@ void RenderingState::loadSimulationData(const std::map<string, LayerInfo> &info,
|
||||
layerData = std::move(data);
|
||||
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()
|
||||
@@ -249,34 +259,60 @@ void RenderingState::render(float time) const
|
||||
// Clear Color and Depth Buffers
|
||||
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();
|
||||
|
||||
// Ensure we render back-to-front for transparency
|
||||
if (angle[0] <= 0) {
|
||||
// Render from the first to the last layer.
|
||||
glTranslatef(-LAYER_X_OFFSET / 2 * currentData->size(), 0, 0);
|
||||
for (auto i : Range(currentData->size())) {
|
||||
drawLayer(time, i);
|
||||
glTranslatef(LAYER_X_OFFSET, 0, 0);
|
||||
}
|
||||
} else {
|
||||
// Render from the last layer to the first layer.
|
||||
glTranslatef(LAYER_X_OFFSET / 2 * (currentData->size() - 2), 0, 0);
|
||||
for (auto i = currentData->size(); i--;) {
|
||||
drawLayer(time, i);
|
||||
// Render from the first to the last layer.
|
||||
glTranslatef(-LAYER_X_OFFSET / 2 * currentData->size(), 0, 0);
|
||||
for (auto i : Range(currentData->size())) {
|
||||
drawLayer(time, i);
|
||||
glTranslatef(LAYER_X_OFFSET, 0, 0);
|
||||
}
|
||||
} else {
|
||||
// Render from the last layer to the first layer.
|
||||
glTranslatef(LAYER_X_OFFSET / 2 * (currentData->size() - 2), 0, 0);
|
||||
for (auto i = currentData->size(); i--;) {
|
||||
drawLayer(time, i);
|
||||
|
||||
glTranslatef(-LAYER_X_OFFSET, 0, 0);
|
||||
glTranslatef(-LAYER_X_OFFSET, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
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
|
||||
@@ -341,7 +377,7 @@ void RenderingState::handleSpecialKey(int key)
|
||||
currentData = layerData.end();
|
||||
}
|
||||
--currentData;
|
||||
updateVisualisers();
|
||||
queueUpdate();
|
||||
break;
|
||||
|
||||
case GLUT_KEY_RIGHT:
|
||||
@@ -349,7 +385,7 @@ void RenderingState::handleSpecialKey(int key)
|
||||
if (currentData == layerData.end()) {
|
||||
currentData = layerData.begin();
|
||||
}
|
||||
updateVisualisers();
|
||||
queueUpdate();
|
||||
break;
|
||||
|
||||
case GLUT_KEY_F1:
|
||||
@@ -419,14 +455,32 @@ float RenderingState::layerAlpha() const
|
||||
|
||||
void RenderingState::idleFunc()
|
||||
{
|
||||
if (options.mouse_1_pressed) {
|
||||
move('w', false);
|
||||
}
|
||||
if (options.mouse_2_pressed) {
|
||||
move('s', false);
|
||||
}
|
||||
if (isLoading && loadingFuture.valid()) {
|
||||
auto result = loadingFuture.wait_for(std::chrono::milliseconds(40));
|
||||
switch (result) {
|
||||
case std::future_status::deferred:
|
||||
LOG(ERROR) << "loading status was deferred, invalid state!";
|
||||
abort();
|
||||
|
||||
checkGLErrors();
|
||||
throttleIdleFunc();
|
||||
case std::future_status::timeout:
|
||||
// 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();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <future>
|
||||
#include "LayerInfo.hpp"
|
||||
#include "LayerData.hpp"
|
||||
#include "LayerVisualisation.hpp"
|
||||
@@ -78,6 +79,9 @@ namespace fmri
|
||||
std::vector<std::vector<LayerData>>::iterator currentData;
|
||||
std::vector<std::unique_ptr<LayerVisualisation>> layerVisualisations;
|
||||
std::vector<std::unique_ptr<Animation>> interactionAnimations;
|
||||
bool isLoading = false;
|
||||
std::future<void> loadingFuture;
|
||||
|
||||
|
||||
RenderingState() noexcept;
|
||||
|
||||
@@ -92,5 +96,11 @@ namespace fmri
|
||||
void renderLayerName(const std::string& name) const;
|
||||
|
||||
void drawLayer(float time, unsigned long i) const;
|
||||
|
||||
void queueUpdate();
|
||||
|
||||
void renderLoadingScreen() const;
|
||||
|
||||
void renderVisualisation(float time) const;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user