PDA

View Full Version : Standardizing performance on different systems



Operational
09-09-2006, 10:19 PM
I’ve looked around and can’t even find a mention of this problem let alone a solution.

The Situation
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.

The Problem
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?

k_szczech
09-10-2006, 01:39 AM
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.

Rodrix
09-10-2006, 08:40 PM
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? :)

k_szczech
09-11-2006, 01:32 AM
before calling your Render() routine and just afterwardsWhat 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
acceleration m/(s^2)
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.

tang.T
09-11-2006, 03:30 AM
my way : prepare your scence in idle, render it in 30Hz. but not for fps game

Rodrix
09-11-2006, 09:45 PM
Dear k_szczech,


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?

Cheers! :)
Rod

k_szczech
09-11-2006, 11:12 PM
Hi!

if the value exceeds =>360 or <=-360 then make it equal to 0Actually it would be better to add/subtract 360 degrees, so 362 degrees will give 2 degrees.

But if I use radians I would be stuck with the ugly 2*PI. What do you do?Well, I like to keep all angles in radians since it's easier to use them in equations. I'm converting these to degrees every time I use them in glRotatef or when I want to display it to user.
No matter if you use radians or degrees you will have to convert one to another, since for physics you need radians but you need degrees for glRotatef (unless you construct matrix yourself).
And I see no reason why 2*PI is uglier than 360 - they're both constants and for CPU it makes no difference. :)

Komat
09-12-2006, 12:25 AM
Originally posted by k_szczech:
Well, I like to keep all angles in radians since it's easier to use them in equations. I'm converting these to degrees every time I use them in glRotatef or when I want to display it to user.
Additional way of representing angles might be number of rotations (e.g. 0.5 rotations = PI radians = 180 degrees).



And I see no reason why 2*PI is uglier than 360 - they're both constants and for CPU it makes no difference.One reason might be that the PI has infinite decimal expansion.

Operational
09-17-2006, 07:07 PM
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.