Skip to content
Snippets Groups Projects
Commit de900528 authored by Alexis Girault's avatar Alexis Girault
Browse files

ENH: Update timer in vtkInteractor to meet target fps

vtkInteractor::CreateRepeatingTimer would call
vtkInteractorStyle::OnTimer then sleep for the period
given in ms after calling OnTimer again. This isn't
adapted for rendering at a regular framerate, because
the time taken withing the OnTimer function is not
taken into account in the sleep time.

By using OneShotTimer, we can manipulate when to
render the next frame: in (period - time spent) ms
if the time spent in OnTimer is smaller than the period
time, or right away (period of 0 ms) if the time spent
is over the target period (late frame).

An interface is added in the VTKInteractorStyle,
wrapped in the VTKViewer, to set the target framerate.

Default value is 0ms to render as fast as possible. See:
: http://gaming.stackexchange.com/questions/221423/is-there-any-reason-to-limit-my-fps
parent ed4ee276
No related branches found
No related tags found
No related merge requests found
......@@ -42,24 +42,42 @@ VTKInteractorStyle::OnTimer()
{
if (m_simManager->getStatus() != SimulationStatus::RUNNING)
{
this->Interactor->CreateOneShotTimer(m_targetMS);
return;
}
// Update Camera
auto scene = m_simManager->getCurrentScene();
m_simManager->getViewer()->getCurrentRenderer()->updateSceneCamera(scene->getCamera());
m_simManager->getViewer()->getCurrentRenderer()->updateSceneCamera(m_simManager->getCurrentScene()->getCamera());
// Update render delegates
m_simManager->getViewer()->getCurrentRenderer()->updateRenderDelegates();
// Reset camera clipping range
if(this->CurrentRenderer != nullptr)
{
this->CurrentRenderer->ResetCameraClippingRange();
}
this->CurrentRenderer->ResetCameraClippingRange();
// Retrieve actual framerate
auto t = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()-m_pre).count();
auto fps = 1000.0/(double)t;
auto fpsStr = std::to_string((int)fps)+ " fps";
// Render
m_pre = std::chrono::high_resolution_clock::now();
this->Interactor->Render();
m_post = std::chrono::high_resolution_clock::now();
// Plan next render
auto dt = std::chrono::duration_cast<std::chrono::milliseconds>(m_post-m_pre).count();
if (dt < m_targetMS)
{
this->Interactor->CreateOneShotTimer(m_targetMS - dt);
}
else
{
this->Interactor->CreateOneShotTimer(0);
}
// Timing info
std::cout << "\rActual framerate: " << fpsStr << " (" << dt << " ms) "<< std::flush;
}
void
......@@ -315,4 +333,33 @@ VTKInteractorStyle::setSimulationManager(SimulationManager *simManager)
m_simManager = simManager;
}
} // imstk
\ No newline at end of file
double
VTKInteractorStyle::getTargetFrameRate() const
{
if(m_targetMS == 0)
{
LOG(WARNING) << "VTKInteractorStyle::getTargetFrameRate warning: render target period is set to 0ms, "
<< "therefore not regulated by a framerate. Returning 0.";
return 0;
}
return 1000.0/m_targetMS;
}
void
VTKInteractorStyle::setTargetFrameRate(const double &fps)
{
if(fps < 0)
{
LOG(WARNING) << "VTKInteractorStyle::setTargetFrameRate error: framerate must be positive, "
<< "or equal to 0 to render as fast as possible.";
return;
}
if(fps == 0)
{
m_targetMS = 0;
return;
}
m_targetMS = 1000.0/fps;
std::cout << "Target framerate: " << fps << " (" << m_targetMS << " ms)"<< std::endl;
}
} // imstk
......@@ -23,6 +23,7 @@
#define imstkVTKInteractorStyle_h
#include <memory>
#include <chrono>
#include "vtkInteractorStyleTrackballCamera.h"
......@@ -105,9 +106,26 @@ public:
///
void setSimulationManager(SimulationManager* simManager);
protected:
friend class VTKViewer;
///
/// \brief
///
double getTargetFrameRate() const;
///
/// \brief
///
void setTargetFrameRate(const double& fps);
private:
SimulationManager* m_simManager; ///>
SimulationManager* m_simManager;
double m_targetMS = 0.0;
std::chrono::high_resolution_clock::time_point m_pre;
std::chrono::high_resolution_clock::time_point m_post;
};
......
......@@ -66,6 +66,9 @@ VTKViewer::setCurrentScene(std::shared_ptr<Scene>scene)
// Set renderer to renderWindow
m_vtkRenderWindow->AddRenderer(this->getCurrentRenderer()->getVtkRenderer());
// Set renderer to interactorStyle
m_interactorStyle->SetCurrentRenderer(this->getCurrentRenderer()->getVtkRenderer());
// Set name to renderWindow
m_vtkRenderWindow->SetWindowName(m_currentScene->getName().data());
}
......@@ -117,7 +120,7 @@ VTKViewer::startRenderingLoop()
{
m_running = true;
m_vtkRenderWindow->GetInteractor()->Initialize();
m_vtkRenderWindow->GetInteractor()->CreateRepeatingTimer(1000.0/60);
m_vtkRenderWindow->GetInteractor()->CreateOneShotTimer(0);
m_vtkRenderWindow->GetInteractor()->Start();
m_vtkRenderWindow->GetInteractor()->DestroyTimer();
m_running = false;
......@@ -141,4 +144,16 @@ VTKViewer::isRendering() const
return m_running;
}
} //
\ No newline at end of file
double
VTKViewer::getTargetFrameRate() const
{
return m_interactorStyle->getTargetFrameRate();
}
void
VTKViewer::setTargetFrameRate(const double& fps)
{
m_interactorStyle->setTargetFrameRate(fps);
}
} // imstk
......@@ -102,6 +102,16 @@ public:
///
const bool& isRendering() const;
///
/// \brief
///
double getTargetFrameRate() const;
///
/// \brief
///
void setTargetFrameRate(const double &fps);
protected:
vtkSmartPointer<vtkRenderWindow> m_vtkRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment