Iâ€™ve looked around and canâ€™t even find a mention of this problem let alone a solution.
Iâ€™ve got a program that has various objects, each with positions and velocities. Each call of my glutIdleFunc function updates the world in the following manner
positionVector = positionVector + velocityVector * timestep
where timestep is a constant.
is that different computers, or more importantly the same computer if you resize the window, the number of glutIdleFunctions executed per second changes. This means that the positionVector is updated at different speeds making the objects move at different speeds.
So an object that moved 1000 pixels in 10 seconds might move 1000 pizels in 1 second if you resize the window to be smaller.
Is there a way to force OpenGL to only execute a certain number of glutIdleFunctions per second, or is there some other way to fix this?
You almost answered your own question
Each frame measure time that passed since last frame - this will give you timestep. So timestep will not be constant - it will be calculated every frame.
For very slow systems you should add some limitation (for example: timestamp must not be greater than 0.5s).
Also, on fast systems you can run into problem where timestamp is 0 (if you use integer), so you should make your program ready for that.
Another way would be to leave timestep as constant and use timer to force repaint of the window - this, however will require that system can keep up with the framerate you applicatoin is trying to achieve. It can cause this application to have serious problem on slower systems and on fast systems it will be a waste of their possibilities.
This my solution I implemented:
You measure time before calling your Render() routine and just afterwards. You calculate the difference between both times in every call. Lets call this difference /\TIME.
/\TIME * Sync = Fixed time step
for example my time step is 16ms
/\TIME * Sync = 16
Sync = (/\TIME) / 16
So now you multiply:
positionVector = positionVector + velocityVector * Sync
Hope its useful!
Do you guys concurr?
before calling your Render() routine and just afterwards
What about time that passes when your program is outside the Render() routine?
I just measure the time when I enter this routine and subtract previous value.
By the way - many people measure and store time in miliseconds, but I think it’s good to keep all values in standard units:
time - s
distance - m
velocity - m/s
I would also suggest:
angle - radians
angular velocity - radians/s
If you keep time in miliseconds then you will have a lot of *1000 and /1000 and your code will turn into mess.
I personally measure time that passed since last frame in at least miroseconds and store it in float, but I also store that measured alue as integer (or whatever I used) to have precise value when calculating time difference in next frame.
my way : prepare your scence in idle, render it in 30Hz. but not for fps game
I measure the time for the whole Loop routine.
For example my loop routine contains the Render() and also Sound(). In this way, I know how much time elapses between each Render call, having into account all external factors too.
And Yes! I calculate /\Time with a single GetTickTime() call at the beggining of the loop too, instead of calling one at the beggining and another at the end. I use that too. I didn’t state it that way because I thought that the explanation was more clear that other way to understand the concept (and later optimization follows).
About multiplying *1000 I haven’t needed yet since I use very small steps for gltranslate, etc, to make a smooth transition. However I may probably need it when I use key-frame time-based animations.
What var type do you use for rotations (radians)?
I use float and if I got an object rotating, the value can go up to infinity (or overflow) if it rotates many times. One way to optimize this would be to add then condition that that if the value exceeds =>360 or <=-360 then make it equal to 0, if I use degrees.
But if I use radians I would be stuck with the ugly 2*PI. What do you do?
Thanks for the replies, I’ve been busy lately, I’ll implement the solution when I get time and let you know how it goes.
I’ve been using radians, not really sure why since there is no difference between degrees and radians and I do have to convert to degrees for the glRotate calls.