[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4787: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3922)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4789: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3922)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4790: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3922)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4791: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3922)
InsideQC Forums • View topic - Timing Fixes

Timing Fixes

Discuss programming topics for the various GPL'd game engine sources.

Moderator: InsideQC Admins

Timing Fixes

Postby Baker » Wed Jul 04, 2012 9:25 am

As far as I can tell, the follow are aspects to solving NetQuake single player running at a frames per second greater than 72.

1. Cannot run more client frames than server frames. Could create odd situation where server misses input in single player (the way the NQ protocol works). Not good.
2. So this means it is ok to run more server frames than client frames. DarkPlaces does this.
3. The main thing that seems to get messed up is sv_gravity. A formula to normalize this to 72 frames per second (maybe even do this for sys_ticrate). DarkPlaces does this.
4. For input smoothness, MH seems to query mouse input more often possibly than running client frames? (More up to date mouse polling for better mouse control)
5. I also noticed MH uses integer data type to track milliseconds, instead of floats for filling out the time variables each frame (interesting).
6. And MH seems to limit sent client commands to avoid frames per second flooding non-local servers.
7. Remember to look at: viewtopic.php?f=12&t=4899
8. There is a nearly pointless host_time global in the Quake code. It isn't used for anything of significance (flashing menu cursor or something, but in many engines like FitzQuake as an example, that got replaced with realtime. ProQuake has a single reference to it for storing viewangle svc time.)

Just trying to size this up.

Not entirely related:
1. Something interesting I noticed about DarkPlaces is that it sends redundant history of client movement intentions to protect against packet loss (like a set of up to 15 previous user movement messages) when using DPP7.
2. I noticed in physics that the lack of sliding in Quakeworld (and I believe Quake 3 as well) is not applying gravity when a player is "on ground". DarkPlaces has that as one of the sv_gameplayfix cvars. I had never quite understood why there was no sliding in Quakeworld.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Timing Fixes

Postby taniwha » Wed Jul 04, 2012 11:47 am

1) the server could accumulate inputs (problematic for buttons, though. hello Mr. Nyquist)
2) see the facetious comment in 1 :) (ie, I agree)
3) or just fix the damn code: the correct equations for x' and v' are [x' = x + vt + att/2, v' = v + at] or [v' = v + at, x' = x + v't - att/2]. Quake does [v' = v + at, x' = x + v't]. ie, quake is missing a very important half of the equation! This will actually make it so you have an effective infinite frame rate :) (already implemented in QF, though I think I miss something because I couldn't make wall climbing framerate-independent)
4) hmm
5) I think float might be better for ms, but with the unit as ms, and maybe int for seconds. 100fps is 10ms, and 101fps is 9.9ms, but int will lose that .9. That will make a mess of things.
6) quite resonable
7) looking, comment later
8) unless you plan on never having speed control of demo playback (which QF does have), you absolutely do need separate variables for game effects and interface effects.

Re NER2: oh, so that's where it's hiding. I've hunted for that a few times and never did figure out why nq slides but qw doesn't. Now I can cvar it in both :)

[edit]Ah, that thread. Yeah, implemented in QF :)
[edit2]Smilies attacked my #8 and turned it into 8)
Leave others their otherness.
http://quakeforge.net/
taniwha
 
Posts: 399
Joined: Thu Jan 14, 2010 7:11 am

Re: Timing Fixes

Postby Baker » Wed Jul 04, 2012 12:14 pm

The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Timing Fixes

Postby r00k » Wed Jul 04, 2012 4:18 pm

r00k
 
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: Timing Fixes

Postby mh » Wed Jul 04, 2012 5:49 pm

Check the YA on the first secret in e1m4 (where you shoot the two switches and crush the knight) - if it smoothly rides down with the plat then you're doing it right.

Spike's comment on that thread is correct - just do it with floats. All the same, I still prefer using an absolute time diff since an effect started rather than accumulating deltas.

Integer milliseconds aren't necessary - that's ancient code and they were more intended to fix other inadvertently introduced timing bugs (which have since been fixed properly).

CL_LerpPoint needs to run as if sv.active is false.

Watch out for sv_gravity in the particle system.

host_time should be nuked.

host_frametime is evil. Need to go through every function where it's used and either (a) pass the correct delta time as a param, or (b) calculate the correct delta time yourself (e.g. as cl.time - cl.oldtime).

The old host_framerate cvar is evil and unintuitive - Fitz's host_timescale is much better.

Host_Frame can keep two separate timers - one for server time and one for client time. Each pass through let each one tick, when they exceed a certain threshold fire off the correct frame events. Apply host_timescale to the frame delta for each for e.g. demo control speed.

Still haven't resolved why gameplay is jerky as hell at host_maxfps 72 but smooth as butter when vsyncing at 72hz with uncapped host_maxfps - indicates that the "higher framerates give smoother gameplay" thing is actually caused by something else, not higher framerates, and that repeatedly querying mouse input is probably not necessary.

Lots of subtle interactions with MDL interpolation at uncapped framerates - things can go utterly nuts. Don't like this bit. I think I have the rules worked out though, so here's my currentl understanding:

- as always, only put MDL lerping on MOVETYPE_STEP entities.

For CL_LerpPoint interpolation:
- movement in the x and y directions doesn't lerp.
- movement in the z direction does lerp if x and y haven't moved, otherwise it doesn't.
- angles never lerp.

For MDL interpolation:
- movement in the x and y directions always lerps.
- movement in the z direction lerps if x and y have moved; if they haven't moved then it doesn't.
- angles always lerp.

In other words, the Fitz setup is correct for x and y, but z needs special handling. Lerp z via CL_LerpPoint if x and y haven't moved, otherwise lerp it via MDL interpoolation.

Cross-checking with a monster standing on a plat (a DK in e4m6 is good for this) it works correct. This makes sense as for MOVETYPE_STEP entities the movement is considered to be part of the step animation (hinted at in Q1, explicit in Q2) and the step animation happens in the x and y directions.
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: Timing Fixes

Postby Baker » Wed Jul 04, 2012 7:45 pm

The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Timing Fixes

Postby taniwha » Thu Jul 05, 2012 12:01 am

QF never does "mdl lerping" (pose lerping is separate). All position/orientation lerping is done in the client code (IMO, the renderer has no business doing such lerping). I recently (in the last week or so) got nq's lerping working nicely, and it ignores U_STEP. But then, QF's renderer has been separate from the client code for quite some time, so it was really just a matter of finishing some 10 year old work.
Leave others their otherness.
http://quakeforge.net/
taniwha
 
Posts: 399
Joined: Thu Jan 14, 2010 7:11 am

Re: Timing Fixes

Postby Spike » Thu Jul 05, 2012 1:25 am

I hate the idea of position interpolation in the renderer too.
doing the blend is fine, but code to calculate which frame numbers/fraction to use is just nasty if its in the renderer.

for example
the csqc api is built around the csqc specifying the exact frame numbers+factors+frametimes.
this means we have 5 fields:
.float frame;
.float frame2;
.float lerpfrac;
.float frame1time;
.float frame2time;
this means that you can directly control the speed of a framegroup animation by explicitly setting the time into the animation via frameXtime. Running animations can be synced with the ground simply by setting it to some specific fraction of the distance traveled, and the feet will sync perfectly. This is also handy when you have haste powerups that change fire speeds and animation speeds to match, as you're no longer tied to 10fps frames.
The lerpfrac field basically says how much of frame2 to use (0 says use only frame1). so set it to 1 when you change the frame and drop it down to 0 over time. the speed at which you drop the lerpfrac value gives you your framerate with a classic quake model. This allows you to animate models at whatever speed you want. There is no expectation that things will animate at 10fps. And the engine will not have to delay animations just to calculate how long that animation will be valid for.
Everything is explicit, and there are no nasty surprises.

The renderer making it up as it goes along is just messy, especially if the ent is drawn multiple times that frame, say in mirrors or rtlighting shadows.
position and angles are already based upon time since last update, might as well just put the lerpfrac assignment in there anyway.
.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: Timing Fixes

Postby mh » Thu Jul 05, 2012 1:40 am

I've actually been heading in the other direction and seriously considering putting CL_LerpPoint lerping into the renderer. The main reason why is that ent->origin and ent->angles don't actually serve any other purpose on the client - last time I searched I could find nothing else that used them (aside from sound - that's another typical Quake yuck). So these become properties for the renderer and the client just has msg_origins and msg_angles.

I'd really like to split entity_t in two - have two more lightweight structs, one containing just the stuff that the client needs, the other just the stuff that the renderer needs. With C++ these would inherit from a much smaller struct just containing anything that's common (model, for instance). That would help a lot with reducing unnecessary crosstalk between subsystems.

I have split out the calculation of the lerp data from the actual rendering functions though; it's calced once at the start of a frame during an initial pass that also sets up bboxes (properly rotated and per-frame for MDLs) and some other things - that way it can be safely reused as many times per entity as required (such as a shadow pass).
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: Timing Fixes

Postby taniwha » Thu Jul 05, 2012 2:20 am

Leave others their otherness.
http://quakeforge.net/
taniwha
 
Posts: 399
Joined: Thu Jan 14, 2010 7:11 am

Re: Timing Fixes

Postby mh » Thu Jul 05, 2012 10:07 am

Frame lerping for static entities - I knew there was a reason to keep that away from the client.
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: Timing Fixes

Postby taniwha » Thu Jul 05, 2012 10:18 am

Ah, yes. Good argument, I'd forgotten about static entities. However, that section that's between the renderer and client in my plan could handle static ents nicely.
Leave others their otherness.
http://quakeforge.net/
taniwha
 
Posts: 399
Joined: Thu Jan 14, 2010 7:11 am

Re: Timing Fixes

Postby Spike » Thu Jul 05, 2012 11:00 am

Static ents are by definition static. If you're editing the pose numbers then its hardly static.
Skingroups work on static ents without editing the ent after all...

Use timestamps to calculate the framegroup's pose in the renderer, but have the client explicitly state which framegroups to use.

CL_LerpPoint is used for position interpolation.
Sticking that in the renderer means that you're never quite sure what fraction is used within the client (at least without spagetti). This is a problem when you're positioning entities in mirrors, viewmodels, etc.
This is especially problematic for attachments which do not move themselves, but are stuck to their attached entity. Putting CL_LerpPoint in the renderer would thus require that attachments were done in the renderer too.
As well as particle trails.
On the other hand, if its in the client then you can directly store your model matrix in the (static?) entity itself.
.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: Timing Fixes

Postby taniwha » Thu Jul 05, 2012 12:20 pm

To me, static means they are never updated by the server; the client handles any canned animations (which it does, otherwise those poor zombies in start.bsp would be statues). The question is, where in the client does the animation code belong? In the network side? I think we all agree not. In the renderer? I believe not: why complicate the renderer with animation stuff? That leaves the interface layer between the network code and the renderer. The interface layer takes entity state from the network (including once-only state: ie, static entities) does any necessary animations (translation lerping, pose selection, model selection, etc) and passes that to the renderer. The only part the renderer would have in animation would be lerping between two poses (lerp point selected by the interface layer).

This would allow for some sophisticated client-side animations. Eg, I've played around with the torches in blender, and it looks like they might look fairly good lerped between frames 0-N (I don't remember the exact number now), snapped (ie, no lerp) back to 0 and rotated 90 degrees along their local Z axis. Unless the texture disagrees, I think this should make a nice, continuous smooth animation of the torch's flame. There's no way I'd want to put something like that in the renderer, and certainly not in the network code (they are static, after all). But in the interface layer with a nice little csqc hook, it should go quite nicely. Can even do "silly" things like telling the renderer to render only tris 0 ... N with one orientation and tris N+1 ... M with another orientation (or any other render options) (eg, if the torch base texture makes the above mentioned rotation obvious, or unarmed player characters, or knights).

QF does store the translation matrix in the entity, for all entities, in the client code.
Leave others their otherness.
http://quakeforge.net/
taniwha
 
Posts: 399
Joined: Thu Jan 14, 2010 7:11 am

Re: Timing Fixes

Postby mh » Thu Jul 05, 2012 12:54 pm

I've been storing matrixes in entities for ages.

To me it seems unclean.

You've got one bunch of code running on the client that does frame interpolation for non-static entities.
You've got another bunch of code running in the renderer that does frame interpolation for static entities.

Putting both in the one place seems a cleaner and more robust way of doing things.

Plus, like I said, doing all these calculations one-time-only per frame and at the start of the frame makes the whole complication of shadows and mirrors go away - because it's only done once the entity can be drawn as many times as I like and it doesn't cause problems.

So the real question comes down to being: what should that "one place" be? Client or renderer?

(As an aside: it seems when I say "the renderer" people think I mean "in the draw functions" - the answer to that one is "no!" - they've no place in the draw functions; they go into a "PrepForRendering" function which can be called at any time from anywhere).

For both types of origin/angles interpolation I've probably got one more evolution to come, as there are two types of interpolation here and it's clear that any given entity gets one or other (or neither) but never both. That one can go to the client, but I've a hard time seeing how frame interpolation belongs on the client.
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Next

Return to Engine Programming

Who is online

Users browsing this forum: No registered users and 2 guests