-
Notifications
You must be signed in to change notification settings - Fork 117
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
spring dampened camera #1589
spring dampened camera #1589
Conversation
rts/System/SpringDampers.cpp
Outdated
|
||
float spring_damper_damping(float halflife) | ||
{ | ||
return halflife_to_damping(halflife) / 2.0f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return halflife_to_damping(halflife) / 2.0f; | |
static constepxr float why_halve? = 0.5f; | |
return halflife_to_damping(halflife) * well_named_constant; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These constants are all related to the derivation of stiffness and damping inputs to a single halflife value. The math is a bit too complicated for me so you'll have to read the guy's blogpost if you want more info. But my take away from it is that we can have a single input value that gives it a more or less "springiness".
rts/Game/CameraHandler.cpp
Outdated
|
||
timed_spring_damper_exact_vector(currentPos, camTransState.posVelocity, camTransState.startPos, | ||
targetPos, camTransState.timeEnd, camTransState.halflife, damping, eydt, dt, 2.0f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
timed_spring_damper_exact_vector(currentPos, camTransState.posVelocity, camTransState.startPos, | |
targetPos, camTransState.timeEnd, camTransState.halflife, damping, eydt, dt, 2.0f); | |
static constexpr float APPREHENSION = 2.0f; // value chosen on the basis of XYZ | |
timed_spring_damper_exact_vector(currentPos, camTransState.posVelocity, camTransState.startPos, | |
targetPos, camTransState.timeEnd, camTransState.halflife, damping, eydt, dt, APPREHENSION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is what the guy writes about apprehension:
apprehension parameter controls how far into the future we try to track the linear interpolation. A value of 2 means two-times the half life, or that we expect the blend-out to be 75% done by the goal time.
The spring damping demo linked as a source shows that it overshoots (0:05s and onwards). Large discrete movements happen often for cameras (move by clicking minimap, selecting important units like ctrl+c that focus the unit, etc.) so this specific behaviour of the spring-damping mode sounds quite undesirable |
These are specifically the spring functions for a critically dampened spring that should approach the goal without additional oscillations: https://theorangeduck.com/page/spring-roll-call#critical |
@@ -20,7 +20,7 @@ CONFIG(float, FPSFOV).defaultValue(45.0f); | |||
CONFIG(bool, FPSClampPos).defaultValue(true); | |||
|
|||
|
|||
CFPSController::CFPSController(): oldHeight(300.0f) | |||
CFPSController::CFPSController(): oldHeight(300.0f), rot(2.677f, 0.0f, 0.0f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's 2.677?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same default as spring camera.
rot.y += mouseScale * move.x; | ||
rot.x = std::clamp(rot.x + mouseScale * move.y * move.z, 0.01f, math::PI * 0.99f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so what's the difference between rot
and dir
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rot
is the rotation vector, encoding pitch, yaw and roll. dir
is the 3d direction vector.
@@ -19,16 +19,19 @@ class CRotOverheadController : public CCameraController | |||
void MouseWheelMove(float move, const float3& newDir) { MouseWheelMove(move); } | |||
|
|||
void SetPos(const float3& newPos); | |||
void SetRot(const float3& newRot) { rot = newRot; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this (and the same for the Spring camera below) mean that passing rot
with a non-zero z
component nets you a rolled (potentially upside-down etc) camera? Since previously GetRotFromDir
always ensured zero z
:
Line 516 in c183d49
r.z = 0.0f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this allows rotatable overhead camera to roll if the newRot has a z
component. Unfortunately there is no mechanism to set this in practice, should I add a config value to enable a modifier to roll the camera? Perhaps MOVE_STATE_TLT. And/or set it with SetCameraState
.
As for switching to other cameras, the more constrained cameras manage their constraints to prevent rolls. Spring camera does it with float3 GetRot() const { return (float3(rot.x, GetAzimuth(), 0.0f)); }
, so the current rot.z
has no effect. The rest of the cameras don't override the CameraController SetRot, so they just set the dir
and therefore cannot roll. Except for overview camera, which throws out the x and z components.
But in general, if a camera is expected to operate under certain constraints, then it should manage those constraints internally. For example, as overview camera does by throwing out or otherwise constraining the values. And we do see this all over, such as spring camera clamping the rot.x
to the 90 degree range of .5pi to pi.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately camera rolling breaks a number of other things, so I won't be adding any way for the rotatable overhead camera to be rolled from gameside.
@@ -379,6 +569,7 @@ void CCameraHandler::SetCameraMode(unsigned int newMode) | |||
CCameraController* newCamCtrl = camControllers[currCamCtrlNum = newMode]; | |||
|
|||
newCamCtrl->SetPos(oldCamCtrl->SwitchFrom()); | |||
newCamCtrl->SetRot(oldCamCtrl->GetRot()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See previous comment, is this a vector to pass a previously-impossible rotation by switching from a less constrained camera to a more constained one?
The PR is now big and scary so I've extracted an uncontroversial part #1598 |
If the |
Does this look merge-able @sprunk @loveridge ? |
It looks fine and I didn't find any obvious code problems, I was just too scared to give a full "Approved" mark. |
I'd be happy to get it in |
Adds a new option for spring dampened camera transitions.
https://discord.com/channels/549281623154229250/724924957074915358/1260277856370561145
About a microsecond faster than the old transition mode:
![image](https://private-user-images.githubusercontent.com/13026303/347092041-051fe85d-de9b-4326-b2e3-fe0b01e735e6.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzMzQ0MzIsIm5iZiI6MTczOTMzNDEzMiwicGF0aCI6Ii8xMzAyNjMwMy8zNDcwOTIwNDEtMDUxZmU4NWQtZGU5Yi00MzI2LWIyZTMtZmUwYjAxZTczNWU2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjEyVDA0MjIxMlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTI2ZDFjNWM4YmZlMWE4NjMzNzM3MmQwMDVmMzcwZDVjNGM1MGVmNTRiOWZmODA0MzE2MGNmODE1NWJlYWUxYmImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.5DZrfemfokdNtUjbrSNmGyhQbeSMsUQcNuZ0Cjq-LVM)
![image](https://private-user-images.githubusercontent.com/13026303/347092352-a0218885-8d3d-4f72-b74e-0ccb77087274.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzMzQ0MzIsIm5iZiI6MTczOTMzNDEzMiwicGF0aCI6Ii8xMzAyNjMwMy8zNDcwOTIzNTItYTAyMTg4ODUtOGQzZC00ZjcyLWI3NGUtMGNjYjc3MDg3Mjc0LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjEyVDA0MjIxMlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTE5YWRiMzBkZTAxNzg3Y2ViNGJlYzk5YzE1Njk0MDgyYWNlZTJkNGZkNzY2NTNiMGU3ODBjN2FkOTg5YzlhODMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.QCNV2EcaUjvLiNKjHZwe10RSodptbvJDYdhggICf9NY)