Jump to content
  • Advertisement
Sign in to follow this  
Funkymunky

std::chrono incrementing a time_point by a duration?

This topic is 1054 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to implement a fixed timestep update loop.  I tried the following:

.

	typedef std::chrono::high_resolution_clock clock;
	typedef std::chrono::duration<float, std::ratio<1, 30>> updateRate;
	typedef std::chrono::time_point<clock, updateRate> time;

	const auto frameDelta = updateRate{ 1 };
	static time oldTime = clock::now();
	time newTime = clock::now();

	while(newTime - oldTime >= frameDelta)
	{
		// Here I call my updates

		oldTime += frameDelta;
	}

.

Strangely this operates as an infinite loop.  frameDelta is apparently 1.0f, and when I call oldTime += frameDelta, oldTime doesn't seem to change...

Edited by Funkymunky

Share this post


Link to post
Share on other sites
Advertisement

Have you tried debugging it?

 

How sure are you that frameDelta is 1 / oldTime doesn't change? It sounds like only one of these can be true.

Share this post


Link to post
Share on other sites

BloodyEpi: I did debug into it, that's how I know framDelta is 1.0f and oldTime doesn't change.

Mussi: oldTime is static. This code is called each frame; when the difference between oldTime and newTime is big enough, I should get a fixed timestep update and increment oldTime.

 

EDIT:  If I change the 'float' in the duration to 'double' it seems to work correctly.  WTF.

Edited by Funkymunky

Share this post


Link to post
Share on other sites

Aha yeah I missed that. Upon closer inspection I see what's going on here. First of all, frameDelta should be 1, as you are specifying that the duration is measured in terms of a 1/30 ratio, i.e. duration of 1 represents 1/30th of a second. But that's not what's causing trouble, the real culprit is floating point imprecision. By setting the second template argument in timepoint you are saying you want to measure the time since epoch using a float, where every increase by of represents 1/30th of a second. As the time since epoch is quite a large value, you will run into trouble with floating point imprecision pretty much immediately, e.g. 17693092.0f + 1.0f == 17693092.0f. This is why oldTime never changes.

 

The solution is simple, don't use floats to measure time. You can either specify an integer type or use the default by leaving it blank:

typedef std::chrono::high_resolution_clock clock;

typedef std::chrono::duration<clock::rep, std::ratio<1, 2>> updateRate;

typedef std::chrono::time_point<clock> time;

Share this post


Link to post
Share on other sites
struct Timer
{
	typedef std::chrono::time_point<std::chrono::steady_clock> Moment;

	static const Moment application_start_time;

	Timer()
	{
		Initialize();
	}

	void Initialize() 
	{
		lastUpdate = std::chrono::high_resolution_clock::now();
		dtSeconds = 0.f;
		fps = 0.f;
	}

	// Returns the current time since the application start in seconds.
	static float now_seconds()
	{
		return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - application_start_time).count() / 1000.f;
	}
	
	void Tick() 
	{
		Moment now = std::chrono::high_resolution_clock::now();

		// [NOTE] In most cases microseconds resolution is too high.
		const unsigned diff = std::chrono::duration_cast<std::chrono::microseconds>(now - lastUpdate).count();
		lastUpdate = now;
		
		dtSeconds = diff / (1000.f * 1000.f); // micro-seconds -> seconds
		fps = 1.f / dtSeconds;
	}

	float diff_seconds() const { return dtSeconds; }
	float framesPerSecond() const { return fps; }

private :

	Moment lastUpdate;
	float dtSeconds, fps;
};

// and in a cpp 

const Timer::Moment Timer::application_start_time = std::chrono::high_resolution_clock::now();??

 

This is what I wrote and what I use, it's working just fine, maybe it could be better. I'm happy that I'm done

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!