PDA

View Full Version : FPS or Time based??



LostInTheWoods
09-17-2002, 08:36 AM
I am currently building a small 3D engine. And i was curious about what to base my engines timing on. The 2 ways i have come up with are these.

First way i thought about was to build 2 seperate pieces of my engine. The first would be JUST the visual things, running as fast as they can, to get the most FPS out of it. And everything else (sounds, collisions, state updates, etc) would be done in a seperate piece, that ONLY fired once every time interval. Problem with this is, I think that requires a fair knowledge of different OSs, and a fair knowledge about threading. I have neither. So doing that would require platform dependent code, and alot more work.

The other way, would to simply base EVERYTHING off of frame rate. Basicaly, i would draw my scene, do sounds, collision detection, input, etc; once per frame, then using glut timmer func, only call a glut post redisplay once every 1/60th of a second. Now I understand that this has 2 problems, first if the fps slow, then the animation will to, and second if the fps draw too fast, then the CPU is just waiting idle for a few milliseconds waiting for its next draw. But i think i could make a much more acurate collision detection, and physics engine doing it this way.

Any suggestions??

t0y
09-17-2002, 09:04 AM
Your first suggestion can lead to some loss of precision in sounds, collisions etc.

The second one was used in all Grand Prix games(up to GP3 at least). Maybe it was to get better physics as you suggest, but it seems that it visually the game was a lot slower that it should be (at least in my computer).

From my point of view the most general way is something like (pseudo-pseudo-code)
[CODE]
do{
time=gettime();
animate(time);
draw(time);
} while(!quit)

You take the current time as a basis to generate a new frame. The animate part can take care of input and physics. Of course input information must be "locked" before using it to perform calculations.

LostInTheWoods
09-17-2002, 09:15 AM
Thanks for the info. One more quick question. You said it looked too slow to you. Is 60-65 frames per second fast enough? I always thought that that was the *key* frame rate to shoot for.

I think that a fixed frame rate like that would work quite well, expecialy for the physics like you said. Also I think that the CPUs of today will have NO problem doing a frame in less than 1/60 of a second, so slow downs due to processor lag, should be minimal. But do you personaly think that 60-65 frames per second is fast enough? Or should I attempt to base my animations on a higher FPS? Remembering, that if i go TOO high, the animations will slow with CPU lag...

Korval
09-17-2002, 09:35 AM
The correct way (or, at least, the way that works very well) to do this is to run your gameloop at the monitor's refresh rate (assuming it doesn't slow down), but each frame get an accurate measure of the time. Make all of your physics, animation, etc calculations based on how much time has elapsed since your last cycle. That way, if your game's framerate drops, the speed of the game will be unaffected (just the responsiveness).

zed
09-17-2002, 09:47 AM
neither method, the first is closer
basically u want to run all your physics etc at a fixed time eg 30Hz, rendering is done as fast as possible (dont use another thread or timer 'shudders' http://www.opengl.org/discussion_boards/ubb/smile.gif).
method2 is also ok but not as good as the above method

LostInTheWoods
09-17-2002, 10:11 AM
Ok, I think i am going to stick with my current method. ONLY because of my collision physics set up right now.

Currently I actualy physicaly move each object that is moving, instead of using the gltranslate, and glrotate, which only moves the image of the item. I do this because, i want the actual verts of the object to test against the walls and such.

Basicaly my setup now is this.
(psydo code)

void render(void)
{
Move Players bounding sphere;

Check player for collisions, move player accordingly to collisions;

Move players eyes, (gl translate, gl rotate);

Move any moving objects;

Check objects for collisions;

Render visable objects;

Waite untill 1/60 of a second has passes since last frame;

Swap buffers;
}

t0y
09-17-2002, 10:18 AM
LostInTheWoods:
The game was slow. It allows to choose a fixed frame rate up to near 30 (IIRC) but it was probably slow because of a lack of graphics optimization. At the max value it was very playable (in terms of speed). A good framerate depends on the game.

Zed: I can agree that this is a very good optimization for input/sound, but isn't it a little limited for collision and animation? Complex physics can also benefict from this, but simple collision/acceleration/velocity should (i think http://www.opengl.org/discussion_boards/ubb/smile.gif) be animated per-frame for better precision.

LostInTheWoods
09-17-2002, 10:31 AM
That was exactly my thought on this. I mean, isnt it ALOT easier, to do things in sequence, simple is better right? So if the animations are based on frames, and the collisions are based on the animations, which are based on frames, and the sound for a collision, is based on the collision, and so on, dosnt it make logical sence to simply set a constant frame rate, and use that as your engine time keeper?

EDIT:

I mean, I have NO idea how an engine like Q3 does collision detecion, being that the frame rate can be up near 150 fps. Seems to me, you could make alot more cool stuff happen with the physics, and such, if you knew the EXACT location of verts in a given frame. Then again, I was NEVER impressed with the Q3 engines implementation of anything exept the visuals.

Take Q3, Alice, Castle Wolfenstien, ALL based on the Q3 engine. And NON of them had basicaly any items you could kick around, any dynamic objects, simply a set of walls, and a set of enimies, (pretty boring, if you ask me, although it was very pretty)

[This message has been edited by LostInTheWoods (edited 09-17-2002).]

t0y
09-17-2002, 10:41 AM
Lost:
I've never realy done nothing as complex as that so these are just suggestions http://www.opengl.org/discussion_boards/ubb/biggrin.gif.

You should find a way to change your collision detection code, so that you can use gl* calls to move objects around. You're losing on the TnL capabilities. Remember you can always put whatever objects in whatever object's space using matrices (couldn't find better words http://www.opengl.org/discussion_boards/ubb/smile.gif).

On the 60hz part. It is convinient in equations and formulas to have a fixed per-frame time (it's the only advantage I can think of). But if a computer can't keep up, the game time streches (1/60 of a second takes longer) and "low spikes" in performance will affect animations. Consider taking a time-based based approach to rendering.

[This message has been edited by t0y (edited 09-17-2002).]

t0y
09-17-2002, 10:47 AM
Originally posted by LostInTheWoods:
I mean, I have NO idea how an engine like Q3 does collision detecion, being that the frame rate can be up near 150 fps. Seems to me, you could make alot more cool stuff happen with the physics, and such, if you knew the EXACT location of verts in a given frame.


Now we're posting at the same time http://www.opengl.org/discussion_boards/ubb/smile.gif.

If you use a "time tag" as a base for animation instead of a "frame tag" you can find that easily. It works basically the same.

ioquan
09-17-2002, 12:14 PM
The proper way to do this is like this:

On every frame, you get a time scalar. Normally, you want this value to be somewhere in the 0.0 to 1.0 range, but it doesnt really have to be.

Then, you simply scale (multiply) everything's movement by that time scalar. This includes velocities of your objects and animation speeds. Thats all...very simple.

zed
09-17-2002, 07:04 PM
Originally posted by t0y:
LostInTheWoods:

Zed: I can agree that this is a very good optimization for input/sound, but isn't it a little limited for collision and animation? Complex physics can also benefict from this, but simple collision/acceleration/velocity should (i think http://www.opengl.org/discussion_boards/ubb/smile.gif) be animated per-frame for better precision.


this isnt an optimization for speed but for quality! eg accuracy determinabilty + tons more ...icies.
animations of course run at full rate only the physics etc are at a fixed rate. IIRC there was quite a long discussion in flipcode in COTD of why this is a better way than eg what ioquan propses

Ozzy
09-17-2002, 09:38 PM
Originally posted by ioquan:
The proper way to do this is like this:

On every frame, you get a time scalar. Normally, you want this value to be somewhere in the 0.0 to 1.0 range, but it doesnt really have to be.

Then, you simply scale (multiply) everything's movement by that time scalar. This includes velocities of your objects and animation speeds. Thats all...very simple.

simple but that doesn't work! ;)

t0y
09-17-2002, 10:46 PM
Originally posted by zed:
IIRC there was quite a long discussion in flipcode in COTD of why this is a better way than eg what ioquan propses


Do you recall what was the COTD title (general idea)? It isn't searchable (is that a word?) and I couldn't find any title that had something to do with physics and a search on the forums gives an unusable amount of hits.

Thanks

harsman
09-18-2002, 12:31 AM
It was a tip of the day and it's available here (http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-MainLoopTimeSteps&forum=totd&id=-1) . You need a fixed timestep for physics and game logic if you want to have identical results on different systems. This is critical for multiplayer games and games that save replays, e.g racing games.

LostInTheWoods
09-18-2002, 03:55 AM
Ok, I think im still going to stay with a fixed frame rate of 60-65, using a waite to draw method. (basicaly, everything is called by the render loop). Currently I start with the render loop once every 1/60 of a second. It calls the culling loop, which then calls the collision detecion loops, and so on. This will also work for things like sounds, because I can simply either START a sound each frame, check if it is playing, or kill the sound. I dont think any one will notice if there is a 1/60 of a second gap, if a sound is killed to late.

I am pretty confedent that even todays Mediocre hardware will be able to do all of this in 1/60th of a second, or faster. And if it does do it faster, it will simply waite till the end of that time, then call the loop again. I mean a one gig proccessor does what, about 1 billion operations a second. So even if i am using half of the processing power for my Loop, it can handle over 8 million preccesses per 1/60th of a second. And with the culling algorithm i am working on, it should take a HUGE chunk of the rendering out of the GPUs hands. So I think i will stick with this. I will let you know if i come into problems. Thanks

jwatte
09-18-2002, 10:04 AM
Windows 98 and Windows ME has scheduling jitter of up to 100 milliseconds if you use Sleep/SleepEx or wait for a WM_TIMER message.

All typical game loops I've seen look something like:




then = time();
forever {
accumulateInput();
now = time();
if( now >= then+kTimeStep ) {
oldState = curState;
processAccumulatedInput();
clearAccumulatedInput();
runAPhysicsStep( curState );
then += kTimeStep;
}
else {
renderInterpolatedFrame( oldState, curState, (now-then)/kTimeStep );
}
}

Korval
09-18-2002, 10:23 AM
All typical game loops I've seen look something like:

All of those "typical game loops" are broken. Truly accurate physics is not possible with this game loop. Take that "render interpolated frame" section, for example. How do you know that you aren't about to render a frame that violates physics (two objects overlapping, for example)? What about the animations? The animation loop is probably in that "render interpolated frame" section, so it can cause physics irregularities as well. And where does game-logic/AI lie?

Here's a better render loop (in pseudo-code):




For(until user quits)
{
currTime = GetAccurateTime();
timeDiff = currTime - prevTime;
RunGameLoopAndAI(currTime, timeDiff);
RunAnimationSystem(currTime, timeDiff);
RunPhysicsSystem(currTime, timeDiff);
RunPostPhysicsLogic(currTime, timeDiff);
RenderFrame(currTime, timeDiff);
OptionallyVSync();
}


That guarentees accurate physics, as well as allowing the framerate to vary. That way, you cannot possibly get physically imperfect rendering.

t0y
09-18-2002, 11:13 AM
Thanks for the link! It's on my favorites for later reading... http://www.opengl.org/discussion_boards/ubb/smile.gif

Overmind
09-18-2002, 11:32 AM
Yes, you get accurate physics with this game loop, but if you want your game to be 100% deterministic you have to calculate the physics based on fixed timesteps, and you need the game to be deterministic if you use replays or if you make a multiplayer game.

When you calculate your physics, you don't calculate it exactly because that would be too slow. Somtimes calculating it exactly wouldn't be possible either. Just imagine symbolically integrating a complex partigle system http://www.opengl.org/discussion_boards/ubb/eek.gif.

This is best shown with an example: an object is falling down with g=4/s^2.




Case A: 2 fps

Frame 1 2 3 4
------------------------
Speed 2 4 6 8
Position 1 3 6 10

Case B: 4 fps

Frame 1 2 3 4 5 6 7 8
------------------------------------------
Speed 1 2 3 4 5 6 7 8
Position .25 .75 1.5 2.5 3.75 5.25 7 9


The real result using symbolic integration should be s=g*t^2/2=8. The errors are so great because of the low framerate, at higher framerate they are not so noticable, but they are there. The point is that you get different results with different framerates, so at least for the calculations you have to fix it.

[This message has been edited by Overmind (edited 09-18-2002).]

LostInTheWoods
09-18-2002, 11:57 AM
I dont think my physics will be too slow to run at a fixed frame rate of 60fps. Let me know what you think, this is the current physics setup.

Player is 4 bounding spheres, one big one for rough checks, and 3 smaller, head body legs.

Each map is made of rooms, each room has its own collision planes. Each frame i test the large bounding spheres distance to each plane. NO SQRT invovled. just about 5 multiplies and 4 adds.

Then if i am colliding with that plane, i do a smaller sphere test against the same plane. If im colliding with one of the smaller spheres i do a Shere triangle test, 3 sqrts and a hand full of multiplies per poly, max polys on a plane are about 6, 2 is more of the average. Being that im using seperate triangles to render, vs, ones im testing for collisions.

THEN if i have hit, i push the player back, WITH EXACT physics, well, close.

Then I move on to the items collision. Pretty much the same thing as the wall collision code, exept i do a sphere to sphere test first to see if i need to test, then i move onto the sphere plane collisions.

After that I move the object according to the hit.

Thats about it, it requires very little extensive math, simply because I do it each frame, AND because I cut out alot of steps, by testing larger steps, then smaller ones.

I will have to show you my Bullistics collision code, it is realy sweet, acurate rotations on object hit, and such. Me and DaBeav, have been working on this collision theory for a while, hope it works out.

vshader
09-18-2002, 10:42 PM
if anyone's interested i read somewhere that it is because Quake3 does not use fixed timesteps that people with machines running at certain framerates (eg 85fps) can jump higher. it's to do with the way round-off errors accumulate, i think.