ioquake / ioq3

The ioquake3 community effort to continue supporting/developing id's Quake III Arena
https://ioquake3.org/
GNU General Public License v2.0
2.41k stars 529 forks source link

Wonky/glitchy pmove player physics on rotating platforms #381

Closed kungfooman closed 6 years ago

kungfooman commented 6 years ago

Hi, does anybody got an idea how to start fixing this? I would like to make very dynamic maps, but the current physics would feel way too buggy

Gif for GitHub: rotate

Video (more FPS than 10fps gif and different recording): https://killtube.org/downloads/ioquake3/rotating_platforms.mp4

description: just standing on the far-end a rotating platform, neither moving nor looking around. But the player-position (?) is glitching, movement feels "off" aswell

If anybody wants to attempt it improving this, thats the map, nice for testing: http://killtube.org/downloads/ioquake3/acc-lapinou.pk3

zturtleman commented 6 years ago

I think client side player movement prediction does not consider the platform the player is standing on. See cg_nopredict 1 and cg_thirdperson 1.

zturtleman commented 6 years ago

Actually it does using CG_AdjustPositionForMover. I guess maybe there is some issue related to it.

kungfooman commented 6 years ago

Thanks for the info, thats nice for debugging this. I just figured that Enemy Territory has an advanced CG_AdjustPositionForMover

https://github.com/etlegacy/etlegacy/blob/master/src/cgame/cg_ents.c#L2084

void CG_AdjustPositionForMover(const vec3_t in, int moverNum, int fromTime, int toTime, vec3_t out, vec3_t outDeltaAngles)
{
    centity_t *cent;
    vec3_t    oldOrigin, origin, deltaOrigin;
    vec3_t    oldAngles, deltaAngles;
    vec3_t    transpose[3];
    vec3_t    matrix[3];
    vec3_t    move, org, org2;

    if (outDeltaAngles)
    {
        VectorClear(outDeltaAngles);
    }

    if (moverNum <= 0 || moverNum >= ENTITYNUM_MAX_NORMAL)
    {
        VectorCopy(in, out);
        return;
    }

    cent = &cg_entities[moverNum];

    if (cent->currentState.eType != ET_MOVER)
    {
        VectorCopy(in, out);
        return;
    }

    if (!(cent->currentState.eFlags & EF_PATH_LINK))
    {
        vec3_t angles;

        BG_EvaluateTrajectory(&cent->currentState.pos, fromTime, oldOrigin, qfalse, cent->currentState.effect2Time);
        BG_EvaluateTrajectory(&cent->currentState.apos, fromTime, oldAngles, qtrue, cent->currentState.effect2Time);

        BG_EvaluateTrajectory(&cent->currentState.pos, toTime, origin, qfalse, cent->currentState.effect2Time);
        BG_EvaluateTrajectory(&cent->currentState.apos, toTime, angles, qtrue, cent->currentState.effect2Time);

        VectorSubtract(origin, oldOrigin, deltaOrigin);
        VectorSubtract(angles, oldAngles, deltaAngles);
    }
    else
    {
        CG_AddLinkedEntity(cent, qtrue, fromTime);

        VectorCopy(cent->lerpOrigin, oldOrigin);
        VectorCopy(cent->lerpAngles, oldAngles);

        CG_AddLinkedEntity(cent, qtrue, toTime);

        VectorSubtract(cent->lerpOrigin, oldOrigin, deltaOrigin);
        VectorSubtract(cent->lerpAngles, oldAngles, deltaAngles);

        CG_AddLinkedEntity(cent, qtrue, cg.time);
    }

    CreateRotationMatrix(deltaAngles, transpose);
    TransposeMatrix(transpose, matrix);

    VectorSubtract(cg.snap->ps.origin, cent->lerpOrigin, org);

    VectorCopy(org, org2);
    RotatePoint(org2, matrix);
    VectorSubtract(org2, org, move);
    VectorAdd(deltaOrigin, move, deltaOrigin);

    VectorAdd(in, deltaOrigin, out);
    if (outDeltaAngles)
    {
        VectorCopy(deltaAngles, outDeltaAngles);
    }

    // NOTE: origin changes when on a rotating object
}

Something to play with

kungfooman commented 6 years ago

Ok, that pretty much fixed it

Some proofish visuals: https://www.youtube.com/watch?v=qoFKZ4AGWPs

The only small side issue left is now proper detection if the player is really on a platform when the player stands on the edge, thats the only case where it bugs out now

ensiform commented 6 years ago

@kungfooman note that ET code can't be combined in the ioquake3 tree due to license conflicts.

kungfooman commented 6 years ago

Thats true for e.g. the linux kernel which explicitly forces 2.0, but ioq3 is "gpl2 or later", as clearly readable in every file header and https://github.com/ioquake/ioq3/blob/master/COPYING.txt

gpl2

ensiform commented 6 years ago

ioquake3 doesn't want to go to v3 because that breaks compatibly with those who can't or won't upgrade then.

OpenJK and jk2mv are exclusively v2 only because of how Raven chose the license text for jk2/jka.

zturtleman commented 6 years ago

Fixed in 33a899d6dd02618aca8c4d13c5f4040f3e5c2ee2 without reviewing ET code.