View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0004493 | The Dark Mod | Physics | public | 11.03.2017 16:19 | 05.12.2023 01:37 |
Reporter | grayman | Assigned To | duzenko | ||
Priority | normal | Severity | normal | Reproducibility | have not tried |
Status | resolved | Resolution | fixed | ||
Product Version | TDM 2.05 | ||||
Target Version | TDM 2.06 | Fixed in Version | TDM 2.06 | ||
Summary | 0004493: Some physics events have changed in 2.05 due to faster fps | ||||
Description | See if there are physics events that are tied specifically to fps, and see if they can be switched to being time-based, which should be a constant across fps differences. | ||||
Tags | No tags attached. | ||||
Attached Files | proofofconcept-pushentityfix.txt (4,043 bytes)
Index: game/physics/Physics_Player.cpp =================================================================== --- game/physics/Physics_Player.cpp (Revision 6945) +++ game/physics/Physics_Player.cpp (Arbeitskopie) @@ -283,6 +283,63 @@ planes[numplanes].Normalize(); numplanes++; + // BluePill : Push test tweaked for low frametimes (Proof of Concept, relies on hardcoded values) + // needs further testing for various framerates (including < 60fps) and whether it can negatively affect mission gameplay + if ( push && current.velocity.LengthSqr() > 0.0F ) + { + // calculate the "real time" velocity as if the framerate was constantly 60fps + // idPhysics_RigidBody::Evaluate (-> idODE_*::Evaluate) already takes account of the frametime + // just applying current.velocity would cause the actual movement to be velocity*frametime� per frame, while it should be velocity*frametime. + idVec3 realtimeVelocity = current.velocity; + // prevent potential division by zero (minimum frametime should be 1ms) + if (frametime > 0.0001F) + realtimeVelocity *= (0.0166667f / frametime); + + // BluePill : Hardcoded trace range of 15, need to test for different crouch/walk speeds + // calculate the end of the reachable range to push entities + end = current.origin + current.velocity * ( 15.0F / current.velocity.LengthFast() ); + + // see if we can make it there + gameLocal.clip.Translation( trace, current.origin, end, clipModel, clipModel->GetAxis(), clipMask, self ); + + // if we are not blocked by the world + if ( trace.c.entityNum != ENTITYNUM_WORLD ) { + + clipModel->SetPosition( current.origin, clipModel->GetAxis() ); + + // clip movement, only push idMoveables, don't push entities the player is standing on + // apply impact to pushed objects + pushFlags = PUSHFL_CLIP | PUSHFL_ONLYMOVEABLE | PUSHFL_NOGROUNDENTITIES | PUSHFL_APPLYIMPULSE; + + // clip & push + + // greebo: Don't use the idPusher + //totalMass = gameLocal.push.ClipTranslationalPush( trace, self, pushFlags, end, end - current.origin, cv_pm_pushmod.GetFloat() ); + + // Set the trace result to zero, we're pushing into things here + // trace.fraction = 0.0f; + trace.endpos = current.origin; + + // greebo: Check the entity in front of us + idEntity* pushedEnt = gameLocal.entities[trace.c.entityNum]; + if (pushedEnt != NULL) + { + // Register the blocking physics object with our push force + m_PushForce->SetPushEntity(pushedEnt, 0); + m_PushForce->SetContactInfo(trace, realtimeVelocity); + + totalMass = pushedEnt->GetPhysics()->GetMass(); + } + + if (totalMass > 0.0f) { + // decrease velocity based on the total mass of the objects being pushed ? + current.velocity *= 1.0f - idMath::ClampFloat(0.0f, 1000.0f, totalMass - 20.0f) * (1.0f / 950.0f); + + pushed = true; + } + } + } + for ( bumpcount = 0; bumpcount < numbumps; bumpcount++ ) { // calculate position we are trying to move to @@ -391,7 +448,8 @@ } } - // if we can push other entities and not blocked by the world + // original push test code; the new push test is located above this loop + /*// if we can push other entities and not blocked by the world if ( push && trace.c.entityNum != ENTITYNUM_WORLD ) { clipModel->SetPosition( current.origin, clipModel->GetAxis() ); @@ -401,7 +459,7 @@ pushFlags = PUSHFL_CLIP | PUSHFL_ONLYMOVEABLE | PUSHFL_NOGROUNDENTITIES | PUSHFL_APPLYIMPULSE; // clip & push - + // greebo: Don't use the idPusher //totalMass = gameLocal.push.ClipTranslationalPush( trace, self, pushFlags, end, end - current.origin, cv_pm_pushmod.GetFloat() ); @@ -425,7 +483,7 @@ current.velocity *= 1.0f - idMath::ClampFloat( 0.0f, 1000.0f, totalMass - 20.0f ) * ( 1.0f / 950.0f ); pushed = true; } - + current.origin = trace.endpos; time_left -= time_left * trace.fraction; @@ -433,7 +491,7 @@ if ( trace.fraction >= 1.0f ) { break; } - } + }*/ if ( !stepped ) { // let the entity know about the collision crouchsmoothfix.txt (957 bytes)
Index: game/Player.cpp =================================================================== --- game/Player.cpp (Revision 6945) +++ game/Player.cpp (Arbeitskopie) @@ -7027,7 +7027,14 @@ SetEyeHeight( newEyeOffset ); } else { // smooth out duck height changes - SetEyeHeight( EyeHeight() * pm_crouchrate.GetFloat() + newEyeOffset * ( 1.0f - pm_crouchrate.GetFloat() ) ); + + // smoothing takes a constant amount of frames (and a constant minimum time if com_fixedTic == 0) + // SetEyeHeight( EyeHeight() * pm_crouchrate.GetFloat() + newEyeOffset * ( 1.0f - pm_crouchrate.GetFloat() ) ); + + // smoothing in a constant duration + // multiply the crouchrate by a frametime factor (frametime 1/30 => 2, 1/60 => 1, 1/120 => 0.5, ...) + float crouchrate = (1.0f - pm_crouchrate.GetFloat()) * ((1.0f * gameLocal.getMsec()) / gameLocal.GetMSec()); + SetEyeHeight(EyeHeight() * (1 - crouchrate) + newEyeOffset * crouchrate); } } movespeed_cratepush_grabentity_betafixes.txt (12,884 bytes)
Index: game/physics/Physics_Player.cpp =================================================================== --- game/physics/Physics_Player.cpp (Revision 6950) +++ game/physics/Physics_Player.cpp (Arbeitskopie) @@ -199,18 +199,19 @@ void idPhysics_Player::Accelerate( const idVec3 &wishdir, const float wishspeed, const float accel ) { #if 1 // q2 style - float addspeed, accelspeed, currentspeed; + //float addspeed; + float accelspeed, currentspeed; currentspeed = current.velocity * wishdir; - addspeed = wishspeed - currentspeed; + /*addspeed = wishspeed - currentspeed; if (addspeed <= 0) { return; - } - accelspeed = accel * frametime * wishspeed; - if (accelspeed > addspeed) { + }*/ + // this acceleration has friction-like effects if currentspeed is bigger than wishspeed. + accelspeed = accel * frametime * (wishspeed - currentspeed); // accel * frametime * wishspeed; + /*if (accelspeed > addspeed) { accelspeed = addspeed; - } - + }*/ current.velocity += accelspeed * wishdir; #else // proper way (avoids strafe jump maxspeed bug), but feels bad @@ -283,6 +284,63 @@ planes[numplanes].Normalize(); numplanes++; + // BluePill : Push test tweaked for low frametimes (relies on hardcoded values) + // needs further testing whether it can negatively affect mission gameplay + if ( push && current.velocity.LengthSqr() > 0.0F ) + { + // calculate the "real time" velocity as if the framerate was constantly 60fps + // idPhysics_RigidBody::Evaluate (-> idODE_*::Evaluate) already takes account of the frametime + // just applying current.velocity would cause the actual movement to be velocity*frametime� per frame, while it should be velocity*frametime. + idVec3 realtimeVelocity = current.velocity; + // prevent potential division by zero (minimum frametime should be 1ms) + if (frametime > 0.0001F) + realtimeVelocity *= (MS2SEC(USERCMD_MSEC) / frametime); + + // BluePill : Hardcoded trace range of 5.0, looked good for different crouch/walk speeds + // calculate the end of the reachable range to push entities + end = current.origin + current.velocity * ( 5.0F / current.velocity.LengthFast() ); + + // see if we can make it there + gameLocal.clip.Translation( trace, current.origin, end, clipModel, clipModel->GetAxis(), clipMask, self ); + + // if we are not blocked by the world + if ( trace.c.entityNum != ENTITYNUM_WORLD ) { + + clipModel->SetPosition( current.origin, clipModel->GetAxis() ); + + // clip movement, only push idMoveables, don't push entities the player is standing on + // apply impact to pushed objects + pushFlags = PUSHFL_CLIP | PUSHFL_ONLYMOVEABLE | PUSHFL_NOGROUNDENTITIES | PUSHFL_APPLYIMPULSE; + + // clip & push + + // greebo: Don't use the idPusher + //totalMass = gameLocal.push.ClipTranslationalPush( trace, self, pushFlags, end, end - current.origin, cv_pm_pushmod.GetFloat() ); + + // Set the trace result to zero, we're pushing into things here + // trace.fraction = 0.0f; + trace.endpos = current.origin; + + // greebo: Check the entity in front of us + idEntity* pushedEnt = gameLocal.entities[trace.c.entityNum]; + if (pushedEnt != NULL) + { + // Register the blocking physics object with our push force + m_PushForce->SetPushEntity(pushedEnt, 0); + m_PushForce->SetContactInfo(trace, realtimeVelocity); + + totalMass = pushedEnt->GetPhysics()->GetMass(); + } + + if (totalMass > 0.0f) { + // decrease velocity based on the total mass of the objects being pushed ? + current.velocity *= 1.0f - idMath::ClampFloat(0.0f, 1000.0f, totalMass - 20.0f) * (1.0f / 950.0f); + + pushed = true; + } + } + } + for ( bumpcount = 0; bumpcount < numbumps; bumpcount++ ) { // calculate position we are trying to move to @@ -391,7 +449,8 @@ } } - // if we can push other entities and not blocked by the world + // original push test code; the new push test is located above this loop + /*// if we can push other entities and not blocked by the world if ( push && trace.c.entityNum != ENTITYNUM_WORLD ) { clipModel->SetPosition( current.origin, clipModel->GetAxis() ); @@ -401,7 +460,7 @@ pushFlags = PUSHFL_CLIP | PUSHFL_ONLYMOVEABLE | PUSHFL_NOGROUNDENTITIES | PUSHFL_APPLYIMPULSE; // clip & push - + // greebo: Don't use the idPusher //totalMass = gameLocal.push.ClipTranslationalPush( trace, self, pushFlags, end, end - current.origin, cv_pm_pushmod.GetFloat() ); @@ -425,7 +484,7 @@ current.velocity *= 1.0f - idMath::ClampFloat( 0.0f, 1000.0f, totalMass - 20.0f ) * ( 1.0f / 950.0f ); pushed = true; } - + current.origin = trace.endpos; time_left -= time_left * trace.fraction; @@ -433,7 +492,7 @@ if ( trace.fraction >= 1.0f ) { break; } - } + }*/ if ( !stepped ) { // let the entity know about the collision @@ -571,7 +630,7 @@ Handles both ground friction and water friction ================== */ -void idPhysics_Player::Friction( void ) +void idPhysics_Player::Friction( const idVec3 &wishdir, const float forceFriction ) { idVec3 vel = current.velocity; @@ -595,11 +654,14 @@ return; } - float drop = 0; + // float drop = 0; + float friction = 0.0f; // spectator friction if ( current.movementType == PM_SPECTATOR ) { - drop += speed * PM_FLYFRICTION * frametime; + // TODO if anyone is crazy enough to add multiplayer and spectator mode to TDM : Check whether this works as intented! + friction = PM_FLYFRICTION; + //drop += speed * PM_FLYFRICTION * frametime; } // apply ground friction else if ( walking && waterLevel <= WATERLEVEL_FEET ) @@ -608,30 +670,43 @@ { // grayman - #2409 - less friction on slick surfaces - float friction = PM_FRICTION; // default + friction = PM_FRICTION; // default if (groundMaterial && (groundMaterial->IsSlick())) { friction *= PM_SLICK; // reduce friction } - float control = (speed < PM_STOPSPEED) ? PM_STOPSPEED : speed; - drop += control * friction * frametime; + + /*float control = (speed < PM_STOPSPEED) ? PM_STOPSPEED : speed; + drop += control * friction * frametime;*/ } } // apply water friction even if just wading - else if ( waterLevel ) { - drop += speed * PM_WATERFRICTION * waterLevel * frametime; + else if (waterLevel) { + friction = PM_WATERFRICTION * waterLevel; + //drop += speed * PM_WATERFRICTION * waterLevel * frametime; } // apply air friction else { - drop += speed * PM_AIRFRICTION * frametime; + friction = PM_AIRFRICTION; + //drop += speed * PM_AIRFRICTION * frametime; } + if (forceFriction > 0.0f) + friction = forceFriction; + // bluepill: don't apply friction to the current acceleration direction as the acceleration calculation does that already. + // don't set drop as this friction calculation doesn't treat all velocity components equally + idVec3 frictionComponent = vel - ((vel * wishdir) * wishdir); + if (frictionComponent.LengthSqr() <= 1.5625f) // Length() <= 1.25f; value seems good enough + current.velocity -= frictionComponent; + else + current.velocity += frictionComponent * (friction * frametime * (0.0f - 1.0f)); // -1.0 for 100% frictionComponent + // scale the velocity - float newspeed = speed - drop; + /*float newspeed = speed - drop; if (newspeed < 0) { newspeed = 0; } - current.velocity *= ( newspeed / speed ); + current.velocity *= ( newspeed / speed );*/ } /* @@ -665,7 +740,7 @@ // Lower ranged weapons while swimming static_cast<idPlayer*>(self)->SetImmobilization( "WaterMove", EIM_ATTACK_RANGED ); - Friction(); + //Friction(); float scale = CmdScale( command ); @@ -711,6 +786,9 @@ idPhysics_Player::Accelerate( wishdir, wishspeed, PM_WATERACCELERATE ); + // don't apply friction on the wishdir direction + idPhysics_Player::Friction( wishdir ); + // make sure we can go up slopes easily under water if ( groundPlane && ( current.velocity * groundTrace.c.normal ) < 0.0f ) { float vel = current.velocity.Length(); @@ -736,7 +814,7 @@ float scale; // normal slowdown - idPhysics_Player::Friction(); + //idPhysics_Player::Friction(); scale = idPhysics_Player::CmdScale( command ); @@ -752,6 +830,9 @@ idPhysics_Player::Accelerate( wishdir, wishspeed, PM_FLYACCELERATE ); + // don't apply friction on the wishdir direction + idPhysics_Player::Friction( wishdir ); + idPhysics_Player::SlideMove( false, false, false, false ); } @@ -766,7 +847,7 @@ float wishspeed; float scale; - idPhysics_Player::Friction(); + //idPhysics_Player::Friction(); scale = idPhysics_Player::CmdScale( command ); @@ -784,6 +865,9 @@ // not on ground, so little effect on velocity idPhysics_Player::Accelerate( wishdir, wishspeed, PM_AIRACCELERATE ); + + // don't apply friction on the wishdir direction + idPhysics_Player::Friction( wishdir ); // we may have a ground plane that is very steep, even // though we don't have a groundentity @@ -820,7 +904,8 @@ return; } - Friction(); + // BluePill : Move friction calculation after acceleration. + //Friction(); float scale = CmdScale( command ); @@ -868,6 +953,7 @@ } } + Accelerate( wishdir, wishspeed, accelerate ); if ( /*( groundMaterial && groundMaterial->IsSlick() ) || grayman #2409 */ current.movementFlags & PMF_TIME_KNOCKBACK ) @@ -875,6 +961,9 @@ current.velocity += gravityVector * frametime; } + // BluePill : don't apply friction on the wishdir direction, Accelerate does that already. + Friction( wishdir ); + idVec3 oldVelocity = current.velocity; // slide along the ground plane @@ -942,12 +1031,12 @@ =============== */ void idPhysics_Player::NoclipMove( void ) { - float speed, drop, friction, newspeed, stopspeed; + //float speed, drop, friction, newspeed, stopspeed; float scale, wishspeed; idVec3 wishdir; // friction - speed = current.velocity.Length(); + /*speed = current.velocity.Length(); if ( speed < 20.0f ) { current.velocity = vec3_origin; } @@ -966,7 +1055,7 @@ } current.velocity *= newspeed / speed; - } + }*/ // accelerate scale = idPhysics_Player::CmdScale( command ); @@ -978,6 +1067,9 @@ idPhysics_Player::Accelerate( wishdir, wishspeed, PM_ACCELERATE ); + // don't apply friction on the wishdir direction + idPhysics_Player::Friction( wishdir, PM_NOCLIPFRICTION ); + // move current.origin += frametime * current.velocity; } @@ -997,7 +1089,7 @@ // fly movement - idPhysics_Player::Friction(); + // idPhysics_Player::Friction(); scale = idPhysics_Player::CmdScale( command ); @@ -1011,6 +1103,9 @@ wishspeed = wishdir.Normalize(); idPhysics_Player::Accelerate( wishdir, wishspeed, PM_FLYACCELERATE ); + + // don't apply friction on the wishdir direction + idPhysics_Player::Friction( wishdir ); idPhysics_Player::SlideMove( false, false, false, false ); } @@ -1620,12 +1715,15 @@ // ========================== End Surface Extent Test ================== // do strafe friction - idPhysics_Player::Friction(); + // idPhysics_Player::Friction(); // accelerate wishspeed = wishvel.Normalize(); idPhysics_Player::Accelerate( wishvel, wishspeed, accel ); + // don't apply friction on the wishdir direction + idPhysics_Player::Friction( wishdir ); + // cap the vertical travel velocity upscale = current.velocity * -gravityNormal; if ( upscale < -m_ClimbMaxVelVert * playerSpeed ) Index: game/physics/Physics_Player.h =================================================================== --- game/physics/Physics_Player.h (Revision 6950) +++ game/physics/Physics_Player.h (Arbeitskopie) @@ -399,7 +399,7 @@ float CmdScale( const usercmd_t &cmd ) const; void Accelerate( const idVec3 &wishdir, const float wishspeed, const float accel ); bool SlideMove( bool gravity, bool stepUp, bool stepDown, bool push ); - void Friction( void ); + void Friction( const idVec3 &wishdir = idVec3(), const float forceFriction = -1 ); void WaterMove( void ); void FlyMove( void ); void AirMove( void ); Index: game/Force_Grab.cpp =================================================================== --- game/Force_Grab.cpp (Revision 6950) +++ game/Force_Grab.cpp (Arbeitskopie) @@ -215,8 +215,9 @@ dir1 = m_dragPosition - dragOrigin; l1 = dir1.Normalize(); - //dT = MS2SEC( USERCMD_MSEC ); // time elapsed is time between user mouse commands - dT = MS2SEC(gameLocal.getMsec()); // duzenko 4409: fixed tick + USERCMD_MSEC -> flickering + // BluePill : reverted to USERCMD_MSEC because the frametime is already considered by idPhysics_*::Evaluate of the grabbed entity. + dT = MS2SEC( USERCMD_MSEC ); // time elapsed is time between user mouse commands + //dT = MS2SEC(gameLocal.getMsec()); // duzenko 4409: fixed tick + USERCMD_MSEC -> flickering if( !m_bApplyDamping ) m_damping = 0.0f; grabentity_dropbody_betafixes.txt (2,842 bytes)
Index: game/Force_Grab.cpp =================================================================== --- game/Force_Grab.cpp (Revision 6950) +++ game/Force_Grab.cpp (Arbeitskopie) @@ -215,8 +215,9 @@ dir1 = m_dragPosition - dragOrigin; l1 = dir1.Normalize(); - //dT = MS2SEC( USERCMD_MSEC ); // time elapsed is time between user mouse commands dT = MS2SEC(gameLocal.getMsec()); // duzenko 4409: fixed tick + USERCMD_MSEC -> flickering + if (dT < MS2SEC( USERCMD_MSEC )) // BluePill : Fix grab speed for higher framerates + dT = MS2SEC( USERCMD_MSEC ); // time elapsed is time between user mouse commands if( !m_bApplyDamping ) m_damping = 0.0f; Index: game/physics/Physics_AF.cpp =================================================================== --- game/physics/Physics_AF.cpp (Revision 6950) +++ game/physics/Physics_AF.cpp (Arbeitskopie) @@ -5491,6 +5491,7 @@ idVec6 force; idRotation rotation; float vSqr, maxLinearVelocity, maxAngularVelocity; + float frictionTickMul; maxLinearVelocity = af_maxLinearVelocity.GetFloat() / timeStep; maxAngularVelocity = af_maxAngularVelocity.GetFloat() / timeStep; @@ -5522,6 +5523,9 @@ // make absolutely sure all contact constraints are satisfied VerifyContactConstraints(); + // make friction independent of the frametime (i.e. the time between two calls of this function) + frictionTickMul = timeStep / MS2SEC(gameLocal.GetMSec()); + // calculate the position of the bodies for the next physics state for ( i = 0; i < bodies.Num(); i++ ) { body = bodies[i]; @@ -5544,15 +5548,15 @@ // apply a higher friction value if the AF is underwater waterLevel = body->GetWaterLevel(); if( waterLevel == 0.0f || this->water == NULL ) { - body->next->spatialVelocity.SubVec3(0) -= body->linearFriction * body->next->spatialVelocity.SubVec3(0); + body->next->spatialVelocity.SubVec3(0) -= frictionTickMul * body->linearFriction * body->next->spatialVelocity.SubVec3(0); } else { - body->next->spatialVelocity.SubVec3(0) -= (body->linearFriction * (this->water->GetViscosity()+WATER_FRICTION) * waterLevel) * body->next->spatialVelocity.SubVec3(0); + body->next->spatialVelocity.SubVec3(0) -= frictionTickMul * (body->linearFriction * (this->water->GetViscosity() + WATER_FRICTION) * waterLevel) * body->next->spatialVelocity.SubVec3(0); } #else - body->next->spatialVelocity.SubVec3(0) -= body->linearFriction * body->next->spatialVelocity.SubVec3(0); + body->next->spatialVelocity.SubVec3(0) -= frictionTickMul * body->linearFriction * body->next->spatialVelocity.SubVec3(0); #endif - body->next->spatialVelocity.SubVec3(1) -= body->angularFriction * body->next->spatialVelocity.SubVec3(1); + body->next->spatialVelocity.SubVec3(1) -= frictionTickMul * body->angularFriction * body->next->spatialVelocity.SubVec3(1); } } | ||||
related to | 0003706 | resolved | grayman | Vine arrow bounces around |
parent of | 0004552 | resolved | nbohr1more | Slide when coming to a stop |
parent of | 0004924 | resolved | stgatilov | Rope physics mad when FPS is low and uncapped |
parent of | 0004983 | closed | AIs randomly dying with uncapped and low FPS | |
parent of | 0004426 | resolved | duzenko | Grabber items vibrating |
parent of | 0004696 | resolved | stgatilov | At high FPS player footsteps don't always play |
parent of | 0004741 | resolved | grayman | Possible stutter in player movement |
parent of | 0005666 | confirmed | Shooting a noise arrow then picking it up, sound keeps playing - at HIGH FPS | |
related to | 0004865 | resolved | cabalistic | Improve the way how FPS cap works (uncapped FPS) |
related to | 0005464 | resolved | nbohr1more | TDM 2.08-2.09 beta 1: uncapped FPS causing weird player physics |
related to | 0006333 | resolved | stgatilov | Jumping player sometimes pauses at top on very high FPS |
child of | 0004409 | resolved | duzenko | Add an option to lift the 60 fps lock |
Not all the children of this issue are yet resolved or closed. |
Okay the crate test is confirmed and it's significant. With fps at 60 fps max, the smallest crate moves quickly and easily. At 300 fps, it's slooooooooooooooooooow. Find test map attached Steps: Open TDM map falltest.map move smallest crate around. Set com_fixedTic 1 vid_restart (not sure if this is necessary) Try moving small crate again. |
|
Another issue is the player crouching and standing, those animations can play a lot faster. | |
Dragging/carrying as well as throwing entities is affected, too. Crouching slowly is much slower with high fps (at least 400+), everything else (crouching normally, crouching fast, walking slow, etc.) seems to work fine. I've attached a PoC fix for the push crate issue. It still needs to be tested in actual missions as well as with different walk speeds and light items that can be kicked away. At least it seemed to fix that issue in the falltest map. The player velocity value is not per second but per frame (at least that's my observation) and is used as the push velocity. idPhysics_RigidBody::Evaluate also applies frametime as a velocity factor, causing the distance per frame to be in the order of velocity*frametime². The fix removes the first frametime factor in the push velocity using a constant frametime of 1/60. Another issue was that the entity was only pushed every ~6th frame because the trace distance used to check for entities to push was too small (lower frametime -> lower velocity -> lower trace distance). The fix uses a constant distance of 15 units. |
|
Added a fix for crouch smoothing. The grab speed basically has the same issue as pushing entities. It can be fixed by uncommenting "dT = MS2SEC( USERCMD_MSEC );" (Force_Grab.cpp line 218 in rev. 6946) and commenting the following line but according to duzenko's comment, it'd cause flickering. I haven't seen such flickering but I'm not sure about low framerates. The throwing range seems to be a non-issue since it only halves from 60 to 500 fps. |
|
Ideally all this should be moved to time based instead of gametic, so even at 1 fps throwing an object would go as far as at 3000fps. | |
The actual problem for the player velocity while crouching slowly seems to be friction. While idPhysics_Player::Accelerate accelerates less per frame with a lower frametime to keep the same acceleration over real time, idPhysics_Player::Friction always resets the velocity in the next frame because of the small creep acceleration. At normal framerates, the same thing also occurs but the "temporary" velocity in that frame caused by acceleration is higher (though at 60fps that's still below 1/2 of the maximum slow creep speed). The friction calculation likely needs a more physically correct approach, at least to determine whether static friction is overcome, in which case it should not "eat away" all the velocity. It needs to take acceleration (or accelerating force) into account for that, currently it only uses the current velocity. It might also be necessary (and better?) to move the friction calculation directly after the acceleration. |
|
Very nice! A few testing notes: KO'd or Killed (Ragdoll) AI still float down in slow motion when FPS is very high. "noclip" mode still has slow movement or freezing at high FPS. |
|
Attached movespeed_cratepush_grabentity_betafixes.txt, which overrides proofofconcept-pushentityfix.txt. Replaced acceleration as well as friction in idPhysics_Player with a smoothing calculation that takes the frametime into account. I've first tried to fix the old algorithms but wasn't able to find a way to make slow movement equal for different framerates. [Edit : The new Friction function doesn't touch the velocity in acceleration direction since the Acceleration calculation automatically "accelerates backwards" when the player is too fast. It only applies friction to all directions when the player doesn't accelerate (no move buttons pressed).] I've refined the crate push distance a bit and used USERCMD_MSEC instead of a hardcoded 1/60 reference frametime. The grab entity fix that reverts someone else's change is also included, I included further "investigation" of that in the ToDo-list below. It looks good so far (tested LadderMove, NoclipMove, WalkMove and WaterMove; not sure how to test AirMove and FlyMove), using the original friction constants with the new function. One map that definitely needs further testing with this is Swing. At least the start where one has to jump on small swings seemed different to me than with TDM 2.05. Other than that, I couldn't find any issues with the changes. I couldn't find differences in 20/30/40/50/60fps and above, except that pushing crates feels less smooth on lower framerates due to the crates moving away from the player by a higher distance per frame (didn't look like a real issue though). Current ToDo-list : - Compare different movement speeds before and after the fixes since the previous movement modifiers are still used in a different calculation. - Take a look at AI ragdolls (fall, grab and throw). - Take a look at the entity throwing range. - Test whether steep slopes still work as intended. - Test the effects of all changes in actual missions. - Find out more about duzenko's comment in Force_Grab.cpp ("fixed tick + USERCMD_MSEC -> flickering"); grabbing seems fine even with that change reverted. |
|
The Force_Grab change is almost certainly: http://bugs.thedarkmod.com/view.php?id=4426 |
|
Hmm, movespeed_cratepush_grabentity_betafixes.txt doesn't require proofofconcept-pushentityfix.txt does it? I applied the crouch fix and your latest betafix and all seemed to be working well but then I shot an arrow at an AI in noclip mode and the game crashed to Desktop. |
|
Attached grabentity_dropbody_betafixes.txt. For all fixes, apply movespeed_cratepush_grabentity_betafixes.txt without the Force_Grab.cpp changes and then this patch. The frame time used for the grab speed now is limited to the default 16ms tick but the actual frame time is used for anything above that. That should prevent flickering at low frame rates and the slowdown at high frame rates. I've also added a frame time dependant factor to the body friction calculation in Physics_AF.cpp that should fix the slow motion ragdoll issue. |
|
Applied to trunk, didn't test. However I think limiting grab speed on low fps could lead to slow movement? (Mortal Kombat Kompete behaves like that) |
|
Thanks! If this works out, I guess the last remaining issue with uncapped FPS is audio timing issues. I think they are limited to triggered events but I haven't even begun untangling that side of things. |
|
One other area I'm concerned about: interleaved thinking. The amount of frames between each time an AI thinks is governed by the AI spawnarg "max_interleave_think_frames". Each AI uses "idAI::GetThinkInterleave()" to determine the next frame where it should think. Increasing the frames between thinking events improves performance. See http://wiki.thedarkmod.com/index.php?title=Interleaved_Thinking_optimization With increased frame rates, this might now need to be a time-based measure, rather than a frame-based measure. --------------------------------------------- In general, how does increased frame rate affect cycles like general entity thinking, frame-based events, etc.? Perhaps researching anywhere gameLocal.framenum is used might show other areas that need to become time-based rather than frame-based. |
|
When I run TheDarkMod.exe, I noticed that when running then trying to stop, there's now a small slide at the end. If I use TheDarkModTools.exe, there's no sliding, which is how it works in TDM 2.05. I tried with fixedTic off and on, and at 60 and 144 fps. Behaviour is the same, but the sliding might be more pronounced at 144 fps. Video: https://www.youtube.com/watch?v=bvL6f7F_Xsc First part is TheDarkMod.exe, second part is TheDarkModTools.exe |
|
2.05 works correctly: when walking and stopping, there's a short slide at the end, and when running and stopping, there's a longer slide at the end. Testing with the latest SVN (@60fps), the behavior is the same. My sense is that the sliding might take slightly longer to stop, but it's still reasonable behavior. There have been no changes to the sliding code to make it behave differently since I corrected it in 1.03, 6.5 years ago. It's possible that any changes for different fps settings might have affected the way friction works, which might account for differences you're seeing. If a different FPS setting makes sliding behave WAY differently than the 2.05 behavior, then adjustments are needed to bring it back in line with 2.05. |
|
I don't see major changes with stopping either. And I think it makes sense to stop in a fraction of second rather than immediately when running? | |
In 2.05 ... A walking slide stops in about a second. A running slide stops in about 2.5 seconds. 2.06 should do the same. |
|
Just wanted to clarify; the sliding on stop is on other surfaces such as wood or stone. In 2.04 and 2.05 you stop almost immediately. In SVN TheDarkMod.exe, there's a slide before coming to a stop. No other EXE is affected (TheDarkModTools.exe, TheDarkModx64.exe, TheDarkModx64Tools.exe) |
|
I've added a patch in the child issue 4552 that should solve the sliding issue. While the new sliding duration is higher (except for running) the difference should be minimal since the sliding speed goes toward zero during that time frame. Another difference from 2.05 is that slow crouch / creep speed is higher because the new friction doesn't longer prevent reaching the wishspeed of around 16.6 instead of 8, meaning that it might be necessary to add another movement multiplier for that case. Other movement types aren't affected. |
|
"Underwater air time". This is accelerated with uncapped FPS. | |
In SVN, even though the FPS is uncapped at either setting com_fixedTic 0 fixes the "underwater air time" issue. | |
Don't know if it's related to this or not, but my mouse sensitivity slider has changed completely compared to 2.05. There are 8 levels, and anything above two is so fast now that it's hard to select anything. | |
What is the value of the sensitivity cvar in console when you move the slider to the middle position? It was recently changed from int to float to allow for modern high-dpi mice. |
|
"What is the value of the sensitivity cvar in console" How would I find that? |
|
UsercmdGen.cpp idCVar idUsercmdGenLocal::sensitivity( "sensitivity", "5", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse view sensitivity" ); sensitivity = 5 (default) |
|
Another bug specific to com_fixedTic 1 Mission: Swing 1) Climb onto the first ledge from the ladder 2) When fully upright, jump 3) Note that you will hover as if your head is stuck in the ceiling This does not happen in other modes. |
|
And another: Mission: The Alchemist With com_fixedTic 1, simply crouch-walking from the street to the side-walk fails. You must jump or mantle onto the sidewalk even though the curb is very shallow. com_fixedTic 0 solves this even with uncapped FPS via com_smp 1. |
|
Fixed the underwater air time (svn rev 7131) - needs testing. I think the mouse slider is 1 to 30 with step of 0.5? Any way it makes sense to create a separate bug. |
|
Sidewalk climb. I think the problem here is that when moving in small steps there's a chance player kinda puts his foot on the curb side which causes him to slide down and back. Please not that the curb side is not exactly vertical but very steep slope. Unless someone can make out how to adopt the existing code to such situations I'm going to go ahead and just skip frames here which is a bummer... Might also fix the Swing issues though I was never able to repeat that. |
|
Swing no longer exhibits the stuck-head problem but now has a new issue... Landing on the moving platform causes you to wildly jump positions and it's nearly impossible to get a proper landing. com_fixedTic 0 solves that. Edit: Climbing stairs while crouched causes lots of hopping motion too. |
|
Try rev 7137 Do we have more slope surfaces to test? Like http://www.valdisole.net/upload/cms/Piste_a_Folgarida_Marilleva.jpg |
|
"The Rift" is full of slopes as I recall... Rev 7137 fixes the platform jumping issue in "Swing" and cures the hopping motion while climbing stairs in "Briarwood Manor". Unfortunately, the head-getting-stuck issue has returned to "Swing" but it is pretty brief and is not infuriating like the curb issue in "The Alchemist". It doesn't break the mission, eg. low priority IMHO. |
|
I tested a recent build and the none of the issues were seen in Swing. I'll retest tonight. |
|
I think it worth noting here that a major change was committed for uncapped FPS mode in svn rev 8435. See related issue 0004924, or more specifically: https://bugs.thedarkmod.com/view.php?id=4924#c11885 And the forums: http://forums.thedarkmod.com/index.php?/topic/20173-limit-timestep/ |
|
I fixed some bug in zeroing vertical velocity when walking (svn rev 10498). More importantly, I commented out a piece of code (removing difference between current velocity and desired velocity) in svn rev 10499 (0006333). It would great if someone could explain why it was necessary, or "let's hope I didn't break anything" =) |
|
Date Modified | Username | Field | Change |
---|---|---|---|
11.03.2017 16:19 | grayman | New Issue | |
11.03.2017 16:38 | AluminumHaste | File Added: falltest.zip | |
11.03.2017 16:38 | AluminumHaste | Note Added: 0008763 | |
13.03.2017 01:01 | AluminumHaste | Note Added: 0008764 | |
19.06.2017 14:08 | BluePill | File Added: proofofconcept-pushentityfix.txt | |
19.06.2017 14:09 | BluePill | Note Added: 0008916 | |
19.06.2017 14:09 | BluePill | Note Edited: 0008916 | |
19.06.2017 19:57 | BluePill | File Added: crouchsmoothfix.txt | |
19.06.2017 20:12 | BluePill | Note Added: 0008917 | |
19.06.2017 20:25 | AluminumHaste | Note Added: 0008918 | |
19.06.2017 23:58 | BluePill | Note Added: 0008919 | |
20.06.2017 05:20 | nbohr1more | Note Added: 0008920 | |
20.06.2017 23:49 | BluePill | File Added: movespeed_cratepush_grabentity_betafixes.txt | |
20.06.2017 23:52 | BluePill | Note Added: 0008921 | |
20.06.2017 23:54 | BluePill | Note Edited: 0008921 | |
21.06.2017 00:02 | BluePill | Note Edited: 0008921 | |
21.06.2017 00:02 | BluePill | Note Edited: 0008921 | |
21.06.2017 01:32 | nbohr1more | Note Added: 0008922 | |
21.06.2017 01:33 | nbohr1more | Relationship added | related to 0004409 |
21.06.2017 01:34 | nbohr1more | Note Edited: 0008922 | |
21.06.2017 02:39 | nbohr1more | Note Added: 0008923 | |
27.06.2017 19:26 | BluePill | File Added: grabentity_dropbody_betafixes.txt | |
27.06.2017 19:34 | BluePill | Note Added: 0008933 | |
27.06.2017 19:35 | BluePill | Note Edited: 0008933 | |
27.06.2017 20:07 | duzenko | Note Added: 0008934 | |
27.06.2017 20:39 | nbohr1more | Note Added: 0008935 | |
28.06.2017 12:28 | grayman | Note Added: 0008937 | |
28.06.2017 12:29 | grayman | Note Edited: 0008937 | |
02.07.2017 02:40 | AluminumHaste | Note Added: 0008940 | |
02.07.2017 03:17 | grayman | Note Added: 0008941 | |
02.07.2017 07:33 | duzenko | Note Added: 0008945 | |
02.07.2017 12:17 | grayman | Note Added: 0008947 | |
02.07.2017 17:04 | nbohr1more | Relationship added | parent of 0004552 |
02.07.2017 17:27 | AluminumHaste | Note Added: 0008950 | |
03.07.2017 02:33 | BluePill | Note Added: 0008957 | |
03.07.2017 02:33 | BluePill | Note Edited: 0008957 | |
08.08.2017 01:34 | nbohr1more | Relationship added | child of 0004060 |
08.08.2017 01:34 | nbohr1more | Relationship deleted | child of 0004060 |
09.08.2017 15:02 | Springheel | Note Added: 0009069 | |
27.08.2017 05:00 | nbohr1more | Note Added: 0009117 | |
10.09.2017 15:05 | Springheel | Note Added: 0009206 | |
11.09.2017 07:29 | duzenko | Note Added: 0009207 | |
11.09.2017 07:43 | duzenko | Note Edited: 0009207 | |
11.09.2017 21:35 | Springheel | Note Added: 0009208 | |
11.09.2017 22:01 | nbohr1more | Note Added: 0009209 | |
12.09.2017 00:32 | nbohr1more | Note Added: 0009210 | |
12.09.2017 03:17 | nbohr1more | Note Added: 0009211 | |
12.09.2017 10:41 | duzenko | Note Added: 0009212 | |
13.09.2017 15:52 | duzenko | Note Added: 0009213 | |
14.09.2017 01:31 | nbohr1more | Note Added: 0009218 | |
14.09.2017 02:40 | nbohr1more | Note Edited: 0009218 | |
14.09.2017 04:16 | nbohr1more | Relationship added | related to 0003706 |
14.09.2017 09:30 | duzenko | Note Added: 0009230 | |
14.09.2017 09:32 | duzenko | Note Edited: 0009230 | |
15.09.2017 01:10 | nbohr1more | Note Added: 0009242 | |
05.10.2017 12:52 | nbohr1more | Note Added: 0009393 | |
12.12.2017 08:26 | duzenko | Assigned To | => duzenko |
12.12.2017 08:26 | duzenko | Status | new => assigned |
12.12.2017 08:26 | duzenko | Status | assigned => resolved |
12.12.2017 08:26 | duzenko | Fixed in Version | => TDM 2.06 |
12.12.2017 08:26 | duzenko | Resolution | open => fixed |
15.07.2018 05:44 | duzenko | Relationship added | related to 0004865 |
23.12.2018 12:53 | stgatilov | Relationship added | related to 0004924 |
01.02.2019 05:37 | nbohr1more | Relationship added | related to 0004983 |
01.02.2019 05:40 | nbohr1more | Relationship deleted | related to 0004409 |
01.02.2019 05:40 | nbohr1more | Relationship added | child of 0004409 |
01.02.2019 05:40 | nbohr1more | Relationship deleted | related to 0004924 |
01.02.2019 05:41 | nbohr1more | Relationship added | parent of 0004924 |
01.02.2019 05:41 | nbohr1more | Relationship deleted | related to 0004983 |
01.02.2019 05:41 | nbohr1more | Relationship added | parent of 0004983 |
01.02.2019 05:43 | nbohr1more | Relationship added | parent of 0004426 |
01.02.2019 05:46 | nbohr1more | Relationship added | parent of 0004696 |
01.02.2019 05:50 | nbohr1more | Relationship added | parent of 0004741 |
05.12.2019 08:48 | stgatilov | Note Added: 0011890 | |
12.01.2021 04:23 | nbohr1more | Relationship added | related to 0005464 |
11.11.2023 09:34 | stgatilov | Relationship added | related to 0006333 |
11.11.2023 10:58 | stgatilov | Note Added: 0016171 | |
05.12.2023 01:37 | nbohr1more | Relationship added | parent of 0005666 |