• Advertisement
Sign in to follow this  

Semi Fixed TimeStep Question.

Recommended Posts

For the following semi-fixed timestep code I am having trouble understanding the following one line.  I could really use a great explanation.

float deltaTime = std::min(totalDeltaTime, MAX_DELTA_TIME);

 

const float MAX_DELTA_TIME = 1.0;
const float DESIRED_FPS = 60.0f;
const int MAX_PHYSICS_STEPS = 6; 
  
const float MS_PER_SECOND = 1000;
const float DESIRED_FRAMETIME = MS_PER_SECOND / DESIRED_FPS;


while (...

float newticks = SDL_GetTicks();
float frametime = newticks - previousticks;
previousticks = newticks;
float totalDeltaTime = frameTime / DESIRED_FRAMETIME;

...

while (totalDeltaTime > 0.0 && i < MAX_PHYSICS_STEPS)
{
  float deltaTime = std::min(totalDeltaTime, MAX_DELTA_TIME);
  
  updates(deltaTime);
  i++;
}
       
    

 

Thank you,

Josheir

Share this post


Link to post
Share on other sites
Advertisement

The code is incomplete, and i never managed to read the fix your timestep article til the end, but i assume the purpose is to prevent updating farther than actual realtime, e.g. we get those deltatimes in the inner loop:

0.16

0.16

0.16

0.05  //  <- our fixed timestep would go into the future, so lets take a smaller timestep instead

... which is usually a bad idea and i'm sure the article mentions this. (You could try the integration example from last post to see you can get very different results when using different timesteps, but there are much worse things happening when physics get more advanced.)

 

So you should forget about semi-fixed timestep and just use constant timestep instead. If your current results are future results, you interpolate them with the old results from the previous update for smooth looking rendering. 

So, assuming above code is correct and it would tell you to update by 0.5 while your target constant is 0.16, update with 0.16 and do this simple math:

float t = 0.05 / 0.16; // = 0.3 so 30% is past and 70% is future

renderPosition = oldPhysicsPosition * (1-t) + currentPhysicsPosition * t; 

 

The article should mention the details (probably at the bottom).

However, the render interpolation is only necessary if smooth movement looks chunky but not if your game easily keeps at target framerate. Updating with constant timestep is what primarily matters.

 

Edit: fixed number typo

 

Edited by JoeJ

Share this post


Link to post
Share on other sites

Do you know or did you read the documentation for std::min( a, b )?

http://www.cplusplus.com/reference/algorithm/min/

It returns the smallest of both a and b, or if they're equal, it returns a.

float deltaTime = std::min(totalDeltaTime, MAX_DELTA_TIME);

So in the above line, deltaTime will never be greater than MAX_DELTA_TIME or 1.0f.  It's basically capping deltaTime.

It would be a lot more helpful for you and us if you let us know what research you've done, what you think the code does and what exactly you don't understand in it.  Right now we're shooting in the dark as to what your actual problem with just that one line is.  The more information you give us on your actual problem, the better we can help you.

Share this post


Link to post
Share on other sites

The while-loop slices totalDeltaTime (the total elapsed time since last iteration through the game loop) into equally sized (i.e. MAX_DELTA_TIME) fixed timesteps but only as long as so much (i.e. MAX_DELTA_TIME) duration is still available. Otherwise only the remaining time is used. That std::min ensures exactly that: Make deltaTime being MAX_DELTA_TIME as long as it fits in, but the remaining time if it doesn't fit. To actually work, a line like "totalDeltaTime -= deltaTime;" needs to be within the while-loop. Also the shortcut "totalDeltaTime>0.0" makes no sense without such a decrement.

Share this post


Link to post
Share on other sites
On ‎12‎/‎25‎/‎2017 at 3:06 PM, Mike2343 said:

It would be a lot more helpful for you and us if you let us know what research you've done,

 

Sorry, I was trying a new style.  

 

Sincerely,

Josheir

Edited by Josheir

Share this post


Link to post
Share on other sites
On ‎12‎/‎25‎/‎2017 at 3:06 PM, Mike2343 said:

Do you know or did you read the documentation for std::min( a, b )?

It isn't the min() function.  It's was my confusion about the constant : MAX_DELTA_TIME.  I was perplexed until haegarr explained.

Josheir

 

Edit:  At least I think I understand:

...Otherwise only the remaining time is used.

Edited by Josheir

Share this post


Link to post
Share on other sites

Suppose you minimize the application so everything stops; 30 seconds later the application is restored.

The counter will now read that you're lagging behind 30 seconds and needs to catch up.

Without the std::min, and depending on how your code works, either you end up calling update( 30 seconds ) which will screw your physics completely; or you end up calling for( int i=0; i<30 seconds * 60fps; ++i )update( 1 / 60 ); which will cause your process to become unresponsive for some time while it simulates 30 seconds worth of physics at maximum CPU power in fast forward.

 

Either way, it won't be pretty. The std::min there prevents these problems by limiting the time elapsed to some arbitrary value (MAX_DELTA_TIME) usually smaller than a second. In other words, pretend the last frame didn't take longer than MAX_DELTA_TIME, even if it took more. It's a safety measure.

 

Edit: Just implement the loops talked by gafferongames in a simple sample, and play with whatever you don't understand. Take it out for example, and see what happens. That will be far more educational than what we can tell you.

Edited by Matias Goldberg

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By owenjr
      Hi there.
      I'm pretty new to this and I don't know if it has been asked before, but here I go.
      I'm developing a game using SFML and C++.
      I would like to use the "Tiled" tool to load maps into my game but I don't actually find any tutorial or guide on how to exaclty use it (I know that I have to read an XML file and stuff). I just step into diverse projects that make all a mess. 
      Anyone knows where can I find good information to make my map loader by myself?
      Thanks in advantage!!
    • By MHG OstryTM
      Hello guys,
      I've released my game for the first time. I'm very excited about it and I hope you'll enjoy the game - Beer Ranger. It's a retro-like puzzle-platfromer which makes you think a lot or die trying. You have a squad of skilled dwarfs with special powers and your goal is tasty beer. There is a lot of traps as well as many solutions how to endure them - it is up to your choice how to complete the level! 
      Link to the project: Project site
      Link to the Steam site with video: Beer Ranger
      Have fun and please write feedback if you feel up to.
      Some screens: 




    • By francoisdiy
      So I wrote a programming language called C-Lesh to program games for my game maker Platformisis. It is a scripting language which tiles into the JavaScript game engine via a memory mapper using memory mapped I/O. Currently, I am porting the language as a standalone interpreter to be able to run on the PC and possibly other devices excluding the phone. The interpreter is being written in C++ so for those of you who are C++ fans you can see the different components implemented. Some background of the language and how to program in C-Lesh can be found here:

      http://www.codeloader.net/readme.html
      As I program this thing I will post code from different components and explain.
    • By isu diss
      I'm trying to duplicate vertices using std::map to be used in a vertex buffer. I don't get the correct index buffer(myInds) or vertex buffer(myVerts). I can get the index array from FBX but it differs from what I get in the following std::map code. Any help is much appreciated.
      struct FBXVTX { XMFLOAT3 Position; XMFLOAT2 TextureCoord; XMFLOAT3 Normal; }; std::map< FBXVTX, int > myVertsMap; std::vector<FBXVTX> myVerts; std::vector<int> myInds; HRESULT FBXLoader::Open(HWND hWnd, char* Filename, bool UsePositionOnly) { HRESULT hr = S_OK; if (FBXM) { FBXIOS = FbxIOSettings::Create(FBXM, IOSROOT); FBXM->SetIOSettings(FBXIOS); FBXI = FbxImporter::Create(FBXM, ""); if (!(FBXI->Initialize(Filename, -1, FBXIOS))) { hr = E_FAIL; MessageBox(hWnd, (wchar_t*)FBXI->GetStatus().GetErrorString(), TEXT("ALM"), MB_OK); } FBXS = FbxScene::Create(FBXM, "REALMS"); if (!FBXS) { hr = E_FAIL; MessageBox(hWnd, TEXT("Failed to create the scene"), TEXT("ALM"), MB_OK); } if (!(FBXI->Import(FBXS))) { hr = E_FAIL; MessageBox(hWnd, TEXT("Failed to import fbx file content into the scene"), TEXT("ALM"), MB_OK); } FbxAxisSystem OurAxisSystem = FbxAxisSystem::DirectX; FbxAxisSystem SceneAxisSystem = FBXS->GetGlobalSettings().GetAxisSystem(); if(SceneAxisSystem != OurAxisSystem) { FbxAxisSystem::DirectX.ConvertScene(FBXS); } FbxSystemUnit SceneSystemUnit = FBXS->GetGlobalSettings().GetSystemUnit(); if( SceneSystemUnit.GetScaleFactor() != 1.0 ) { FbxSystemUnit::cm.ConvertScene( FBXS ); } if (FBXI) FBXI->Destroy(); FbxNode* MainNode = FBXS->GetRootNode(); int NumKids = MainNode->GetChildCount(); FbxNode* ChildNode = NULL; for (int i=0; i<NumKids; i++) { ChildNode = MainNode->GetChild(i); FbxNodeAttribute* NodeAttribute = ChildNode->GetNodeAttribute(); if (NodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh* Mesh = ChildNode->GetMesh(); if (UsePositionOnly) { NumVertices = Mesh->GetControlPointsCount();//number of vertices MyV = new XMFLOAT3[NumVertices]; for (DWORD j = 0; j < NumVertices; j++) { FbxVector4 Vertex = Mesh->GetControlPointAt(j);//Gets the control point at the specified index. MyV[j] = XMFLOAT3((float)Vertex.mData[0], (float)Vertex.mData[1], (float)Vertex.mData[2]); } NumIndices = Mesh->GetPolygonVertexCount();//number of indices MyI = (DWORD*)Mesh->GetPolygonVertices();//index array } else { FbxLayerElementArrayTemplate<FbxVector2>* uvVertices = NULL; Mesh->GetTextureUV(&uvVertices); int idx = 0; for (int i = 0; i < Mesh->GetPolygonCount(); i++)//polygon(=mostly triangle) count { for (int j = 0; j < Mesh->GetPolygonSize(i); j++)//retrieves number of vertices in a polygon { FBXVTX myVert; int p_index = 3*i+j; int t_index = Mesh->GetTextureUVIndex(i, j); FbxVector4 Vertex = Mesh->GetControlPointAt(p_index);//Gets the control point at the specified index. myVert.Position = XMFLOAT3((float)Vertex.mData[0], (float)Vertex.mData[1], (float)Vertex.mData[2]); FbxVector4 Normal; Mesh->GetPolygonVertexNormal(i, j, Normal); myVert.Normal = XMFLOAT3((float)Normal.mData[0], (float)Normal.mData[1], (float)Normal.mData[2]); FbxVector2 uv = uvVertices->GetAt(t_index); myVert.TextureCoord = XMFLOAT2((float)uv.mData[0], (float)uv.mData[1]); if ( myVertsMap.find( myVert ) != myVertsMap.end() ) myInds.push_back( myVertsMap[ myVert ]); else { myVertsMap.insert( std::pair<FBXVTX, int> (myVert, idx ) ); myVerts.push_back(myVert); myInds.push_back(idx); idx++; } } } } } } } else { hr = E_FAIL; MessageBox(hWnd, TEXT("Failed to create the FBX Manager"), TEXT("ALM"), MB_OK); } return hr; } bool operator < ( const FBXVTX &lValue, const FBXVTX &rValue) { if (lValue.Position.x != rValue.Position.x) return(lValue.Position.x < rValue.Position.x); if (lValue.Position.y != rValue.Position.y) return(lValue.Position.y < rValue.Position.y); if (lValue.Position.z != rValue.Position.z) return(lValue.Position.z < rValue.Position.z); if (lValue.TextureCoord.x != rValue.TextureCoord.x) return(lValue.TextureCoord.x < rValue.TextureCoord.x); if (lValue.TextureCoord.y != rValue.TextureCoord.y) return(lValue.TextureCoord.y < rValue.TextureCoord.y); if (lValue.Normal.x != rValue.Normal.x) return(lValue.Normal.x < rValue.Normal.x); if (lValue.Normal.y != rValue.Normal.y) return(lValue.Normal.y < rValue.Normal.y); return(lValue.Normal.z < rValue.Normal.z); }  
    • By Karol Plewa
      Hi, 
       
      I am working on a project where I'm trying to use Forward Plus Rendering on point lights. I have a simple reflective scene with many point lights moving around it. I am using effects file (.fx) to keep my shaders in one place. I am having a problem with Compute Shader code. I cannot get it to work properly and calculate the tiles and lighting properly. 
       
      Is there anyone that is wishing to help me set up my compute shader?
      Thank you in advance for any replies and interest!
  • Advertisement