totem
4th April 2011, 11:10
I have to read a file that describes animations frames at constant interval. i know this interval so I used QTimer to regularly trigger an update.
The problem is, when i approximately measure the time it takes (with a stopwatch), i see an important difference between theoretical and actual times.
So i wrote an example code showing my problem : It's a shape that go around in a scene. every round it makes I decrease the framerate and display few things :
- the time it took to make a round
- the time it should have taken, regarding current frame rate
- the relative difference between these 2 times
#include <QApplication>
#include <QtGui>
qreal interval = 1.0 ;
const qreal nbFrames = 100.0 ;
class View : public QGraphicsView
{
Q_OBJECT
QGraphicsScene *scene ;
QGraphicsRectItem *item ;
int timerid ;
qreal angle, step, radius ;
QTime t0, t1 ;
public :
View(void)
: scene(new QGraphicsScene),
angle(0), // start angle=0°
step(360.0/nbFrames), // 1 round == 852 frames
radius(150.0) // circle radius
{
scene->setBackgroundBrush(Qt::darkBlue) ;
setScene(scene) ;
// draw circle path
new QGraphicsEllipseItem(QRectF(-radius,-radius,2*radius,2*radius),0,scene) ;
// draw shape
item = new QGraphicsRectItem(QRectF(-25,-15,50,30),0,scene) ;
item->setBrush(Qt::darkYellow) ;
item->setPen(QPen(Qt::black)) ;
// draw start point
QGraphicsEllipseItem *start = new QGraphicsEllipseItem(QRectF(radius-2,-2,4,4),0,scene) ;
start->setBrush(Qt::red) ;
start->setPen(QPen(Qt::black)) ;
// start animation
t0 = QTime::currentTime() ;
qDebug() << "start at" << t0.toString("hh:mm:ss.zzz") << ", interval =" << interval ;
timerid = startTimer(interval) ;
}
protected :
void timerEvent(QTimerEvent *e)
{
if(angle>=360)
{
// compute time and restart
t1 = QTime::currentTime() ;
qreal theoric = 0.001*interval*nbFrames ;
qreal measured = 0.001*t0.msecsTo(t1) ;
qreal diff = (measured-theoric) ;
qreal delta = 100*diff/measured ;
qDebug() << "round time :" << measured << "s, should be" << theoric << "s (diff ="<<diff<<"("<<delta<<"%) for"<<interval<<")" ;
killTimer(timerid) ;
interval++ ; // decrease framerate
angle = 0 ;
t0 = QTime::currentTime() ;
timerid = startTimer(interval) ;
}
else
{
// compute new position
qreal radians = M_PI*angle/180.0 ;
qreal x = radius*cos(radians) ;
qreal y = radius*sin(radians) ;
item->setPos(x,y) ;
// step ahead
angle += step ;
}
}
} ;
int main(int argc, char** argv)
{
QApplication app(argc,argv) ;
View view ;
view.setGeometry(QRect(100,100,600,500)) ;
view.show() ;
return app.exec() ;
}
#include "main.moc"
And here is what I obtain on my comps (one desktop and one laptop, both on XP SP3 i guess) : After an interval of 20ms, whatever interval i give, the total time of an animation is the same for a range of a dozen framerate :
round time : 1.418 s, should be 1.4 s (diff = 0.018 ( 1.26939 %) for 14 )
round time : 1.512 s, should be 1.5 s (diff = 0.012 ( 0.793651 %) for 15
round time : 1.606 s, should be 1.6 s (diff = 0.006 ( 0.373599 %) for 16
round time : 1.715 s, should be 1.7 s (diff = 0.015 ( 0.874636 %) for 17
round time : 1.808 s, should be 1.8 s (diff = 0.008 ( 0.442478 %) for 18
round time : 1.917 s, should be 1.9 s (diff = 0.017 ( 0.886802 %) for 19
round time : 2.011 s, should be 2 s (diff = 0.011 ( 0.546992 %) for 20 )
round time : 3.149 s, should be 2.1 s (diff = 1.049 ( 33.3122 %) for 21 )
round time : 3.148 s, should be 2.2 s (diff = 0.948 ( 30.1144 %) for 22 )
round time : 3.149 s, should be 2.3 s (diff = 0.849 ( 26.9609 %) for 23 )
round time : 3.149 s, should be 2.4 s (diff = 0.749 ( 23.7853 %) for 24 )
round time : 3.149 s, should be 2.5 s (diff = 0.649 ( 20.6097 %) for 25 )
round time : 3.148 s, should be 2.6 s (diff = 0.548 ( 17.4079 %) for 26 )
round time : 3.149 s, should be 2.7 s (diff = 0.449 ( 14.2585 %) for 27 )
round time : 3.149 s, should be 2.8 s (diff = 0.349 ( 11.0829 %) for 28 )
round time : 3.149 s, should be 2.9 s (diff = 0.249 ( 7.90727 %) for 29 )
round time : 3.149 s, should be 3 s (diff = 0.149 ( 4.73166 %) for 30 )
round time : 3.149 s, should be 3.1 s (diff = 0.049 ( 1.55605 %) for 31 )
round time : 4.193 s, should be 3.2 s (diff = 0.993 ( 23.6823 %) for 32 )
round time : 4.723 s, should be 3.3 s (diff = 1.423 ( 30.1292 %) for 33 )
round time : 4.724 s, should be 3.4 s (diff = 1.324 ( 28.0271 %) for 34 )
round time : 4.723 s, should be 3.5 s (diff = 1.223 ( 25.8946 %) for 35 )
round time : 4.724 s, should be 3.6 s (diff = 1.124 ( 23.7934 %) for 36 )
round time : 4.723 s, should be 3.7 s (diff = 1.023 ( 21.66 %) for 37 )
round time : 4.723 s, should be 3.8 s (diff = 0.923 ( 19.5427 %) for 38 )
round time : 4.724 s, should be 3.9 s (diff = 0.824 ( 17.4428 %) for 39 )
round time : 4.723 s, should be 4 s (diff = 0.723 ( 15.3081 %) for 40 )
round time : 4.723 s, should be 4.1 s (diff = 0.623 ( 13.1908 %) for 41 )
round time : 4.724 s, should be 4.2 s (diff = 0.524 ( 11.0923 %) for 42 )
round time : 4.723 s, should be 4.3 s (diff = 0.423 ( 8.95617 %) for 43 )
round time : 4.724 s, should be 4.4 s (diff = 0.324 ( 6.85859 %) for 44 )
round time : 4.723 s, should be 4.5 s (diff = 0.223 ( 4.72158 %) for 45 )
round time : 4.723 s, should be 4.6 s (diff = 0.123 ( 2.60428 %) for 46 )
round time : 5.082 s, should be 4.7 s (diff = 0.382 ( 7.51673 %) for 47 )
round time : 6.298 s, should be 4.8 s (diff = 1.498 ( 23.7853 %) for 48 )
round time : 6.298 s, should be 4.9 s (diff = 1.398 ( 22.1975 %) for 49 )
round time : 6.298 s, should be 5 s (diff = 1.298 ( 20.6097 %) for 50 )
round time : 6.298 s, should be 5.1 s (diff = 1.198 ( 19.0219 %) for 51 )
round time : 6.297 s, should be 5.2 s (diff = 1.097 ( 17.421 %) for 52 )
round time : 6.298 s, should be 5.3 s (diff = 0.998 ( 15.8463 %) for 53 )
round time : 6.298 s, should be 5.4 s (diff = 0.898 ( 14.2585 %) for 54 )
round time : 6.298 s, should be 5.5 s (diff = 0.798 ( 12.6707 %) for 55 )
round time : 6.298 s, should be 5.6 s (diff = 0.698 ( 11.0829 %) for 56 )
round time : 6.298 s, should be 5.7 s (diff = 0.598 ( 9.49508 %) for 57 )
round time : 6.297 s, should be 5.8 s (diff = 0.497 ( 7.89265 %) for 58 )
round time : 6.298 s, should be 5.9 s (diff = 0.398 ( 6.31947 %) for 59 )
round time : 6.298 s, should be 6 s (diff = 0.298 ( 4.73166 %) for 60 )
round time : 6.298 s, should be 6.1 s (diff = 0.198 ( 3.14386 %) for 61 )
round time : 6.298 s, should be 6.2 s (diff = 0.098 ( 1.55605 %) for 62 )
round time : 7.545 s, should be 6.3 s (diff = 1.245 ( 16.501 %) for 63 )
round time : 7.872 s, should be 6.4 s (diff = 1.472 ( 18.6992 %) for 64 )
Unfortunately for my app i need an interval of 33ms, which is obviously one of the worse result : 30% of difference. It means that for an animation of 10s, my app will display an animation which lasts 13s.
Is it a known issue, and what are the possible alternatives ?
The problem is, when i approximately measure the time it takes (with a stopwatch), i see an important difference between theoretical and actual times.
So i wrote an example code showing my problem : It's a shape that go around in a scene. every round it makes I decrease the framerate and display few things :
- the time it took to make a round
- the time it should have taken, regarding current frame rate
- the relative difference between these 2 times
#include <QApplication>
#include <QtGui>
qreal interval = 1.0 ;
const qreal nbFrames = 100.0 ;
class View : public QGraphicsView
{
Q_OBJECT
QGraphicsScene *scene ;
QGraphicsRectItem *item ;
int timerid ;
qreal angle, step, radius ;
QTime t0, t1 ;
public :
View(void)
: scene(new QGraphicsScene),
angle(0), // start angle=0°
step(360.0/nbFrames), // 1 round == 852 frames
radius(150.0) // circle radius
{
scene->setBackgroundBrush(Qt::darkBlue) ;
setScene(scene) ;
// draw circle path
new QGraphicsEllipseItem(QRectF(-radius,-radius,2*radius,2*radius),0,scene) ;
// draw shape
item = new QGraphicsRectItem(QRectF(-25,-15,50,30),0,scene) ;
item->setBrush(Qt::darkYellow) ;
item->setPen(QPen(Qt::black)) ;
// draw start point
QGraphicsEllipseItem *start = new QGraphicsEllipseItem(QRectF(radius-2,-2,4,4),0,scene) ;
start->setBrush(Qt::red) ;
start->setPen(QPen(Qt::black)) ;
// start animation
t0 = QTime::currentTime() ;
qDebug() << "start at" << t0.toString("hh:mm:ss.zzz") << ", interval =" << interval ;
timerid = startTimer(interval) ;
}
protected :
void timerEvent(QTimerEvent *e)
{
if(angle>=360)
{
// compute time and restart
t1 = QTime::currentTime() ;
qreal theoric = 0.001*interval*nbFrames ;
qreal measured = 0.001*t0.msecsTo(t1) ;
qreal diff = (measured-theoric) ;
qreal delta = 100*diff/measured ;
qDebug() << "round time :" << measured << "s, should be" << theoric << "s (diff ="<<diff<<"("<<delta<<"%) for"<<interval<<")" ;
killTimer(timerid) ;
interval++ ; // decrease framerate
angle = 0 ;
t0 = QTime::currentTime() ;
timerid = startTimer(interval) ;
}
else
{
// compute new position
qreal radians = M_PI*angle/180.0 ;
qreal x = radius*cos(radians) ;
qreal y = radius*sin(radians) ;
item->setPos(x,y) ;
// step ahead
angle += step ;
}
}
} ;
int main(int argc, char** argv)
{
QApplication app(argc,argv) ;
View view ;
view.setGeometry(QRect(100,100,600,500)) ;
view.show() ;
return app.exec() ;
}
#include "main.moc"
And here is what I obtain on my comps (one desktop and one laptop, both on XP SP3 i guess) : After an interval of 20ms, whatever interval i give, the total time of an animation is the same for a range of a dozen framerate :
round time : 1.418 s, should be 1.4 s (diff = 0.018 ( 1.26939 %) for 14 )
round time : 1.512 s, should be 1.5 s (diff = 0.012 ( 0.793651 %) for 15
round time : 1.606 s, should be 1.6 s (diff = 0.006 ( 0.373599 %) for 16
round time : 1.715 s, should be 1.7 s (diff = 0.015 ( 0.874636 %) for 17
round time : 1.808 s, should be 1.8 s (diff = 0.008 ( 0.442478 %) for 18
round time : 1.917 s, should be 1.9 s (diff = 0.017 ( 0.886802 %) for 19
round time : 2.011 s, should be 2 s (diff = 0.011 ( 0.546992 %) for 20 )
round time : 3.149 s, should be 2.1 s (diff = 1.049 ( 33.3122 %) for 21 )
round time : 3.148 s, should be 2.2 s (diff = 0.948 ( 30.1144 %) for 22 )
round time : 3.149 s, should be 2.3 s (diff = 0.849 ( 26.9609 %) for 23 )
round time : 3.149 s, should be 2.4 s (diff = 0.749 ( 23.7853 %) for 24 )
round time : 3.149 s, should be 2.5 s (diff = 0.649 ( 20.6097 %) for 25 )
round time : 3.148 s, should be 2.6 s (diff = 0.548 ( 17.4079 %) for 26 )
round time : 3.149 s, should be 2.7 s (diff = 0.449 ( 14.2585 %) for 27 )
round time : 3.149 s, should be 2.8 s (diff = 0.349 ( 11.0829 %) for 28 )
round time : 3.149 s, should be 2.9 s (diff = 0.249 ( 7.90727 %) for 29 )
round time : 3.149 s, should be 3 s (diff = 0.149 ( 4.73166 %) for 30 )
round time : 3.149 s, should be 3.1 s (diff = 0.049 ( 1.55605 %) for 31 )
round time : 4.193 s, should be 3.2 s (diff = 0.993 ( 23.6823 %) for 32 )
round time : 4.723 s, should be 3.3 s (diff = 1.423 ( 30.1292 %) for 33 )
round time : 4.724 s, should be 3.4 s (diff = 1.324 ( 28.0271 %) for 34 )
round time : 4.723 s, should be 3.5 s (diff = 1.223 ( 25.8946 %) for 35 )
round time : 4.724 s, should be 3.6 s (diff = 1.124 ( 23.7934 %) for 36 )
round time : 4.723 s, should be 3.7 s (diff = 1.023 ( 21.66 %) for 37 )
round time : 4.723 s, should be 3.8 s (diff = 0.923 ( 19.5427 %) for 38 )
round time : 4.724 s, should be 3.9 s (diff = 0.824 ( 17.4428 %) for 39 )
round time : 4.723 s, should be 4 s (diff = 0.723 ( 15.3081 %) for 40 )
round time : 4.723 s, should be 4.1 s (diff = 0.623 ( 13.1908 %) for 41 )
round time : 4.724 s, should be 4.2 s (diff = 0.524 ( 11.0923 %) for 42 )
round time : 4.723 s, should be 4.3 s (diff = 0.423 ( 8.95617 %) for 43 )
round time : 4.724 s, should be 4.4 s (diff = 0.324 ( 6.85859 %) for 44 )
round time : 4.723 s, should be 4.5 s (diff = 0.223 ( 4.72158 %) for 45 )
round time : 4.723 s, should be 4.6 s (diff = 0.123 ( 2.60428 %) for 46 )
round time : 5.082 s, should be 4.7 s (diff = 0.382 ( 7.51673 %) for 47 )
round time : 6.298 s, should be 4.8 s (diff = 1.498 ( 23.7853 %) for 48 )
round time : 6.298 s, should be 4.9 s (diff = 1.398 ( 22.1975 %) for 49 )
round time : 6.298 s, should be 5 s (diff = 1.298 ( 20.6097 %) for 50 )
round time : 6.298 s, should be 5.1 s (diff = 1.198 ( 19.0219 %) for 51 )
round time : 6.297 s, should be 5.2 s (diff = 1.097 ( 17.421 %) for 52 )
round time : 6.298 s, should be 5.3 s (diff = 0.998 ( 15.8463 %) for 53 )
round time : 6.298 s, should be 5.4 s (diff = 0.898 ( 14.2585 %) for 54 )
round time : 6.298 s, should be 5.5 s (diff = 0.798 ( 12.6707 %) for 55 )
round time : 6.298 s, should be 5.6 s (diff = 0.698 ( 11.0829 %) for 56 )
round time : 6.298 s, should be 5.7 s (diff = 0.598 ( 9.49508 %) for 57 )
round time : 6.297 s, should be 5.8 s (diff = 0.497 ( 7.89265 %) for 58 )
round time : 6.298 s, should be 5.9 s (diff = 0.398 ( 6.31947 %) for 59 )
round time : 6.298 s, should be 6 s (diff = 0.298 ( 4.73166 %) for 60 )
round time : 6.298 s, should be 6.1 s (diff = 0.198 ( 3.14386 %) for 61 )
round time : 6.298 s, should be 6.2 s (diff = 0.098 ( 1.55605 %) for 62 )
round time : 7.545 s, should be 6.3 s (diff = 1.245 ( 16.501 %) for 63 )
round time : 7.872 s, should be 6.4 s (diff = 1.472 ( 18.6992 %) for 64 )
Unfortunately for my app i need an interval of 33ms, which is obviously one of the worse result : 30% of difference. It means that for an animation of 10s, my app will display an animation which lasts 13s.
Is it a known issue, and what are the possible alternatives ?