-
Notifications
You must be signed in to change notification settings - Fork 227
bugfix(physics): Fix diagonal movement speed discrepancy #3003
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -963,15 +963,22 @@ Real PhysicsBehavior::getForwardSpeed2D() const | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Real dot = vx + vy; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Real speedSquared = vx*vx + vy*vy; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // DEBUG_ASSERTCRASH( speedSquared != 0, ("zero speedSquared will overflow sqrtf()!") );// lorenzen... sanity check | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Real speed = (Real)sqrtf( speedSquared ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_PHYSICS_FORWARD_SPEED | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Real speed = (Real)sqrtf( vx*vx + vy*vy ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (dot >= 0.0f) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return speed; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return -speed; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Inverse scale len by (1 + sqrt(2)) / 2 to adjust to the average of the former min/max movement speed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The inverse looks intuitively wrong, but it is correct, because the value returned by this function is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // used to determine the additional velocity needed to reach the target speed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constexpr const Real DiagonalCompensation = 1.0f / 1.20710678f; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dot *= DiagonalCompensation; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is wrong, the speed is not the dot product, the dot product tells you the difference in direction between the two vectors. If it goes negative then it means your vectors are going in opposite directions. The speed of a vector is the magnitude of the vector. The speed for 2D is: The speed for 3D is: you still need to check the dot product and negate the speed if the dot product is negative.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dot is correct. Chat GippyHere's a side-by-side comparison using a true velocity magnitude of 100 in each case.
This reveals that the original function is effectively applying a heading-dependent scale factor:
So if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The dot product is not correct for calculating the speed. The only relation the dot product has with the speed is the direction of the movement in relation to the orientation of the model/hull. So whether it is forwards or backwards etc. in the code, the dot product is used to tell the difference in angle between You have to workout the magnitude of The flaw in the original code is that they used Since these intermediate products are not unit scaled they give the faster motion in the diagonal direction, but they also don't give the true speed either.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Problem is I tested it in game and it looked right, but I did not do a lab test. Maybe it needs a lab test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The This function is just returning speed which is only a scalar value, it has no direction information within it apart from forwards and backwards. Both calculations need to be done, Beyond this, to make the speeds, on average, closer to the original flawed speeds you can then scale the calculated speed just by multiplying it with a constant. This will scale in all directions due to so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So similar to what i put in the original issue This should be the actual fix for this. Real PhysicsBehavior::getForwardSpeed2D() const
{
//Determine the direction of the velocity relative to the direction the unit is facing using the dot product
const Coord3D *dir = getObject()->getUnitDirectionVector2D();
Real vx = m_vel.x * dir->x;
Real vy = m_vel.y * dir->y;
Real dot = vx + vy;
//Return the speed of the unit - Magnitude of the velocity is the speed
if (dot >= 0.0f)
return (Real)sqrtf( sqr(m_vel.x) + sqr(m_vel.y) ) * scalingValue;
//Negative dot product means the unit is moving in reverse
return -(Real)sqrtf( sqr(m_vel.x) + sqr(m_vel.y) ) * scalingValue;
}And for 3D it is the same Real PhysicsBehavior::getForwardSpeed3D() const
{
//Determine the direction of the velocity relative to the direction the unit is facing using the dot product
Vector3 dir = getObject()->getTransformMatrix()->Get_X_Vector();
Real vx = m_vel.x * dir.X;
Real vy = m_vel.y * dir.Y;
Real vz = m_vel.z * dir.Z;
Real dot = vx + vy + vz;
//Return the speed of the unit - Magnitude of the velocity is the speed
if (dot >= 0.0f)
return (Real)sqrtf( sqr(m_vel.x) + sqr(m_vel.y) + sqr(m_vel.z) ) * scalingValue;
//Negative dot product means the unit is moving in reverse
return -(Real)sqrtf( sqr(m_vel.x) + sqr(m_vel.y) + sqr(m_vel.z) ) * scalingValue;
}There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with @Mauller here, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its a bit of a weird situation and don't know if it actually can occur (maybe helicopters?). But this basically says the unit is moving slightly sideways, like it is drifting. The speed with which it moves however is determined by the velocity vector only, hence why the dot product of direction and velocity cannot be used to calculate the speed. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return dot; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //------------------------------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -989,12 +996,22 @@ Real PhysicsBehavior::getForwardSpeed3D() const | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Real dot = vx + vy + vz; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_PHYSICS_FORWARD_SPEED | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Real speed = (Real)sqrtf( vx*vx + vy*vy + vz*vz ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (dot >= 0.0f) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return speed; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return -speed; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Inverse scale len by (1 + sqrt(3)) / 2 to adjust to the average of the former min/max movement speed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The inverse looks intuitively wrong, but it is correct, because the value returned by this function is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // used to determine the additional velocity needed to reach the target speed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constexpr const Real DiagonalCompensation = 1.0f / 1.36602540f; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dot *= DiagonalCompensation; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return dot; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //------------------------------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.