Handling an update cycle using C ++ Chrono?

I definitely got a little lost with the new chrono library in C ++.

Here I have an update loop. It performs two operations:

engine.Update() engine.Render() 

These are long operations, and it is difficult to say how long they are.

Thus, we measure how much time they take, then perform some calculations and determine the best way to gradually invoke the update before we call rendering.

For this I use C ++ 11 Chrono. I chose it because it sounded like a good deal: more accurate, more platform dependent. I find that I have more problems than now.

Below is my code as well as my main problem. Any help on any problem or the correct way to perform my operations is very necessary!

I marked my questions in the comments right next to the corresponding lines, which I will repeat further.

Header file:

 class MyClass { private: typedef std::chrono::high_resolution_clock Clock; Clock::time_point mLastEndTime; milliseconds mDeltaTime; } 

Simplified update cycle

 // time it took last loop milliseconds frameTime; // The highest we'll let that time go. 60 fps = 1/60, and in milliseconds, * 1000 const milliseconds kMaxDeltatime((int)((1.0f / 60.0f) * 1000.0f)); // It hard to tell, but this seems to come out to some tiny number, not what I expected! while (true) { // How long did the last update take? frameTime = duration_cast<milliseconds>(Clock::now() - mLastEndTime); // Is this the best way to get the delta time, with a duration cast? // Mark the last update time mLastEndTime = Clock::now(); // Don't update everything with the frameTime, keep it below our maximum fps. while (frameTime.count() > 0) // Is this the best way to measure greater than 0 milliseconds? { // Determine the minimum time. Our frametime, or the max delta time? mDeltaTime = min(frameTime, kMaxDeltatime); // Update our engine. engine->Update((long)mDeltaTime.count()); // From here, it so much easier to deal with code in longs. Is this the best way to shove a long through my code? // Subtract the delta time out of the total update time frameTime -= mDeltaTime; } engine->Render(); } 

Main question: My mDeltaTime always looks tiny. It is basically stuck in an almost infinite loop. This is due to the fact that kMaxDeltatime is very small, but if I am aiming at 60 frames per second, do I not calculate the correct milliseconds?

Here are all the questions listed above:

 const milliseconds kMaxDeltatime((int)((1.0f / 60.0f) * 1000.0f)); // It hard to tell, but this seems to come out to some tiny number, not what I expected! frameTime = duration_cast<milliseconds>(Clock::now() - mLastEndTime); // Is this the best way to get the delta time, with a duration cast? while (frameTime.count() > 0) // Is this the best way to measure greater than 0 milliseconds? engine->Update((long)mDeltaTime.count()); // From here, it so much easier to deal with code in longs. Is this the best way to shove a long through my code? 

I apologize for the confusion. I feel like an idiot with this chrono library. Most help sites, help materials, or even the most direct code are very confusing to read and understand what I'm applying it to. Pointers to how I should look for solutions or code are very welcome!

EDIT: Joachim noted that std :: min / max only works for milliseconds! Updated code to reflect changes.

+7
source share
1 answer

When using std::chrono you should avoid, as far as possible, casting durations or converting durations to raw integral values. Instead, you should adhere to natural duration and take advantage of the type safety that types of duration provide.

The following are some specific recommendations. For each recommendation, I will give the lines of your source code, and then show how I will rewrite these lines.


 const milliseconds kMaxDeltatime((int)((1.0f / 60.0f) * 1000.0f)); // It hard to tell, but this seems to come out to some tiny number, not what I expected! 

There is no reason for this kind of computation with manual conversion constants. Instead, you can:

 typedef duration<long,std::ratio<1,60>> sixtieths_of_a_sec; constexpr auto kMaxDeltatime = sixtieths_of_a_sec{1}; 

 frameTime = duration_cast<milliseconds>(Clock::now() - mLastEndTime); // Is this the best way to get the delta time, with a duration cast? 

You can simply store the value in your native type:

 auto newEndTime = Clock::now(); auto frameTime = newEndTime - mLastEndTime; mLastEndTime = newEndTime; 

 while (frameTime.count() > 0) // Is this the best way to measure greater than 0 milliseconds? 

Use instead:

 while (frameTime > milliseconds(0)) 

 engine->Update((long)mDeltaTime.count()); // From here, it so much easier to deal with code in longs. Is this the best way to shove a long through my code? 

It’s best to write code that uses chrono::duration types everywhere, rather than using common integral types in general, but if you really need to get a common integral type (for example, if you have to pass long to a third-party API), then you can do something- something like:

 auto mDeltaTime = ... // some duration type long milliseconds = std::chrono::duration_cast<std::duration<long,std::milli>>(mDeltaTime).count(); third_party_api(milliseconds); 

And to get the delta, you have to do something like:

 typedef std::common_type<decltype(frameTime),decltype(kMaxDeltatime)>::type common_duration; auto mDeltaTime = std::min<common_duration>(frameTime, kMaxDeltatime); 
+18
source

All Articles