Page 1 of 2

NO_LERP in QuakeC

Posted: Sat Feb 18, 2012 9:59 pm
by Baker
Do either DarkPlaces or FTEQW (or maybe even the RMQ Engine) have a server-side "this entity has been relocated and it was not through movement" type of flag.

i.e. If an entity was teleported or some sort of relocation of the entity that did not involve its speed as the reason for movement

That way a client knows from the QuakeC via some protocol flag that entity should not have the movement interpolated. I know Fitz 666 protocol has a no_lerp flag server-side that it provides to the client, but as far as I recall this flag isn't controlled by QuakeC.

I'm guessing both engines probably do and maybe I'll self answer this. And probably the Fitz 666 flag can be set by QuakeC.

/ I'm kind of thinking of enhanced client-side chase_active, but to I would really need to know if an entity was teleported. I suppose the Fitz 666 client-side guessing of movement lerping could work.

Re: NO_LERP in QuakeC

Posted: Sun Feb 19, 2012 12:15 am
by Spike
MOVETYPE_STEP says the entity steps periodically - specifically that horizontal movements should be smoothed based upon the time that it moves rather than pure linear interpolation.

Re: NO_LERP in QuakeC

Posted: Mon Feb 20, 2012 4:28 am
by Supa
dpextensions.qc says:

Code: Select all

//DP_EF_TELEPORT_BIT
//idea: id software
//darkplaces implementation: divVerent
//effects bit:
float   EF_TELEPORT_BIT = 2097152;
//description:
//when toggled, interpolation of the entity is skipped for one frame. Useful for teleporting.
//to toggle this bit in QC, you can do:
//  self.effects += (EF_TELEPORT_BIT - 2 * (self.effects & EF_TELEPORT_BIT));

Re: NO_LERP in QuakeC

Posted: Mon Feb 20, 2012 5:13 pm
by mh
The nolerp flag in Fitz 666 is just U_STEP in different clothes.

Generally there are two basic cases for interpolation:

Entities with MOVETYPE_STEP don't get the old Quake interpolation (based on CL_LerpPoint) but should get position/rotation interpolation.
Entities without MOVETYPE_STEP are the other way around.

A number of other conditions can modify these (was the entity present on the last frame, etc) but these are the basic two that are relevant here.

A fatal flaw in the old QSG position/rotation interpolation is that it doesn't take this into account - it just applies it's interpolation to all MDLs irrespective. This is broken for a number of reasons - first because not all MDLs get MOVETYPE_STEP, and second because it's entirely possible for a brush or sprite model to be given MOVETYPE_STEP. That's why it had a lot of gnarly special case code for stuff like rockets and the view model.

DP105 has server-side interpolation which also takes account of entities needing to be on the ground, flying or swimming before they can be interpolated. It's worth looking over that code as I believe it to be infinitely superior to the old QSG tutorials. I'm not certain to what extent it's survived in current versions, but my instincts tell me that the necessary flags have been added to DP7 and it's now done client-side (likely in a substantially changed form).

So fix all of that and I believe one of the core problems will go away. There is a second problem with position/rotation interpolation and that is when an entity is standing on a plat, the plat moves but the entity doesn't. In that case the entity will be moved along with the plat, and if it has MOVETYPE_STEP set, it will be incorrectly interpolated, resulting in movement that is oh-so slightly out of sync with the plat it's on, so it will appear to judder or jiggle. I don't believe a QC-side fix is appropriate for this - it should be possible to pick up this case in the world/physics code and handle it seamlessly, but I haven't investigated much.

Re: NO_LERP in QuakeC

Posted: Mon Feb 20, 2012 5:25 pm
by Baker
Supa's EF_TELEPORT is what I was looking for (although that other knowledge is useful).

But it occurs to me that EF_TELEPORT is probably the wrong thing to do. I didn't realize this until now. (At least in the sense that QuakeC shouldn't be allowed to set it. The client still needs to know so the idea of the server sending that flag is fine.)

The server engine has to know if the entity's position was changed by physics or manually set by QuakeC (even if by spawning or entity creation. Or of course teleport.)

In that case, it should tell the client the first frame.

However, there are weird cases other than move type step. Like brush model movement where the QuakeC just simply relocates a brush if the distance it needs to move is too small (RMQ Demo 2 blocks)

I'm kind of wondering the "right" way to fix that doors case.

Re: NO_LERP in QuakeC

Posted: Mon Feb 20, 2012 5:51 pm
by Baker
Example using Fitz 666 since that is what I am most familiar with:

Have the server set LERP_RESETMOVE when setorigin is called.

In that situation, the origin is being manually set. In all other situations, the origin is being determined by physics.

This is probably not quite 100% right. But the concept is that manual sets of the origin in QuakeC represent spawning, teleportation or some type of non-movement positioning not subject to move lerping. I think Fitz 666 only sets LERP_RESETMOVE for "new entities" operating on the idea that if it is new, it has no previous.

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 1:47 am
by mh
The Fitz lerp code is one of the saner ones, yes. There are a few other conditions where it really should reset the lerp but fails to, however: if an entity is frustum culled is one that immediately springs to mind.

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 2:07 am
by Baker
mh wrote: if an entity is frustum culled is one that immediately springs to mind.
If entity is just slightly out of the current view, it shouldn't interpolate the movement for the next frame?

At first, I was going to ask why but I think I'll try to explain why I think you are saying this.

If entity went out of the view, should not interpolate between out of view position and in-view position since combination may be out-of-view? No. That can't be right so ... it must be ...

Or more likely, since it was out-of-view before it didn't receive a recalc of the interpolation positioning (which only occur if the entity gets prepared for rendering), therefore the interpolation helper variables are stale (could be several seconds old); hence they should not be used for the next frame.

(Or re-write code to refresh movement interpolation helper variables before frustum culling takes place ...)

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 2:32 am
by Baker
Strike this. False alarm.

Add: This may very well explain a really weird thing I saw that made me very mad once.

I pressed paused super quick during weapon transition of a side-mounted weapon and I saw a super garbled weapon once. This was my own engine.

But I had implemented FitzQuake interpolation fully.

If a view weapon goes off-screen, the animation should reset. I'm maybe 50%-60% sure this was the cause. Fixing that was on my to-do list, but frankly I had no idea how or why it happened. My thoughts on this are not fresh, but if I switched during frame X and it went off-screen and then later I switch back to that weapon and it suddenly is on frame Y, the old stale interpolation stuff might be used.

I was quite mad because I hate movement and animation interpolation flaws as they are often super-hard to figure out why they are occurring.
However, this doesn't sound right. If I switch weapons, the model changes. Fitz 666 detects this and resets the lerp. Never mind. (Still validate that side mounted weapons or custom positioned weapons reset correctly if weapon change occurs, this is rare instance where model change should probably trigger move lerp reset if it doesn't do this already and I do not believe it does.)

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 1:13 pm
by mh
Your "more likely" guess is correct - the previous frame and move data is stale and may give invalid results if it's used later. Note that this condition (being frustum culled) won't be caught by the 0.2 second check in Fitz's CL_ParseUpdate.

Model change should just reset frames - it's actually a potential crasher if it doesn't reset frames because the previous frame may refer to one that is outside of array bounds for the new model. Fitz does this correctly.

It's also necessary to detect if static entities were present on the previous frame and reset their frame lerps if not - they won't be caught by the standard CL_ParseUpdate check.

I'm not sure if it's necessary to reset move in the first case (definitely not in the second as static entities don't move) - I can't see why it would be.

For weapon models, I believe you can track a change in STAT_ACTIVEWEAPON and reset the lerp there. I haven't done this myself though. The weird morphing you see is probably a previous frame number giving out of bounds positions but still within a valid memory area (otherwise it would have crashed with unreadable memory).

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 3:55 pm
by metlslime
Hi.... some interesting comments in here.

I just checked the code to see if that frustum culling issue was real; and it seems that Fitzquake already handles it correctly -- lerp state is updated on entities before they are culled, so it can't get stale from frustum culling.

Regarding the entities riding lifts bug -- this is a known issue that I somehow failed to noticed before releasing 0.85. I should really figure that one out at some point.

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 6:32 pm
by mh
Crossposting from func just to keep all the info together:
I've been doing some more investigation of this one and have traced the cause - it's hinted at by the header comment of SV_Physics_Step: "Monsters freefall when they don't have a ground entity, otherwise all movement is done with discrete steps."

Some tests confirm it (basically just not sending an entity that meets the freefall conditions in SV_Physics_Step) - a monster on a lift isn't MOVETYPE_STEPping, it's in freefall.

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 7:04 pm
by Baker
Nice!

/I've always hated that.

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 7:11 pm
by Baker
Monsters are free to walk on a lift if it is moving up (for sure?) and maybe if the lift is moving down. Isn't it more that monsters ...

1) X Y position should follow MOVETYPE_STEP. No movement smoothing.
2) Z position should be interpolated (always?). With movement smoothing.

Re: NO_LERP in QuakeC

Posted: Wed Feb 22, 2012 8:51 pm
by Spike
there's a few cases here.
1: monster stepping around the map
2: monster motionless on a moving func_plat
3: monster stepping around moving func_plat
4: monster getting pushed from the side by a func_train or some such
5: monster plumetting to its death after being pushed off a cliff by a func_train or some such
6: fiend/dog jumping at you (or getting blown around by knockback in some mods).

fitzquake's protocol has a 'time until next step'. if that value doesn't drop past 0 then you know it was gravity etc and you lerp the movement in the packet based upon the inter-packet timing. if that value is reset after dropping to 0 then its stepped that frame, and the difference between this and the previous should be gradually added such that it exactly matches the new position when that timer reaches 0 again. calculate the change/time and add it until the next time. should work.

fte's protocol doesn't contain that extra info, and monsters walking around on a moving platform interpolate as if they were grenades or whatever, because it detects a change every single frame, with some really big changes every 10th of a second or so... jerky indeed.