Skip to content
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

Dolly camera #1649

Merged
merged 34 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6c9dc1e
spring dampened camera
loveridge Jul 9, 2024
852ae12
skip some calculations
loveridge Jul 9, 2024
80a8aed
space indentation to tabs
loveridge Jul 9, 2024
9461d5d
Move dampers into their own file
loveridge Jul 9, 2024
715ac0d
add ClampRads
loveridge Jul 10, 2024
7891e8b
add timed damper to rotations
loveridge Jul 10, 2024
267c835
smooth old transition code as well
loveridge Jul 10, 2024
27f6a5d
had a flipped sign
loveridge Jul 10, 2024
aa0ccbc
revert my changes to the original transition mode
loveridge Jul 10, 2024
2b2b65a
add lerp smoothed transitions
loveridge Jul 10, 2024
c5f4887
PR comments
loveridge Jul 10, 2024
7a2cc83
vastly improved rotation handling
loveridge Jul 11, 2024
407f954
modify rotoverhead to use an incrementing rot value
loveridge Jul 11, 2024
eebb0e3
needs a default
loveridge Jul 11, 2024
54033ce
keep rot state for fps camera
loveridge Jul 11, 2024
c2cf464
move edge move config into the camera handler. now can be changed wit…
loveridge Jul 11, 2024
63ddc34
clean up camera switches
loveridge Jul 13, 2024
fc19428
allow negative transition times to do nothing
loveridge Jul 13, 2024
710d9a2
Merge remote-tracking branch 'origin/BAR105' into spring-dampened-camera
loveridge Jul 14, 2024
e71c682
update include paths
loveridge Jul 14, 2024
4b5fce1
add timeFactor for timed spring dampened camera
loveridge Jul 17, 2024
1ccba77
add assert
loveridge Jul 31, 2024
fe5d7f8
dollycam initial
loveridge Aug 5, 2024
89a3139
look curves
loveridge Aug 7, 2024
6e5407e
add more dollycam options
loveridge Aug 12, 2024
276a55c
camera should remain in same state when changing between camera handlers
loveridge Aug 13, 2024
27095a8
Merge branch 'camera-handler-transitions' into dollycam
loveridge Aug 13, 2024
a42fe5e
relative modes
loveridge Aug 16, 2024
208fda6
extra addition of position
loveridge Aug 16, 2024
6db8b84
pause and resume
loveridge Aug 17, 2024
8b5481f
Merge remote-tracking branch 'origin/master' into dollycam
loveridge Sep 14, 2024
effc7c1
add include
loveridge Oct 6, 2024
878b98c
reserve vector space
loveridge Oct 6, 2024
790b143
Merge remote-tracking branch 'origin/master' into dollycam
loveridge Nov 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rts/Game/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ make_global_var(sources_engine_Game
"${CMAKE_CURRENT_SOURCE_DIR}/Camera/OverviewController.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Camera/RotOverheadController.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Camera/SpringController.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Camera/DollyController.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/CameraHandler.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ChatMessage.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ClientData.cpp"
Expand Down
13 changes: 13 additions & 0 deletions rts/Game/Camera/CameraController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "CameraController.h"
#include "Game/Camera.h"
#include "Map/Ground.h"
#include "Map/ReadMap.h"
#include "Sim/Misc/GlobalConstants.h"
#include "System/Config/ConfigHandler.h"
Expand Down Expand Up @@ -31,6 +32,7 @@ CCameraController::CCameraController()
}

float3 CCameraController::GetRot() const { return CCamera::GetRotFromDir(GetDir()); }
void CCameraController::SetRot(const float3& newRot) { dir = CCamera::GetFwdFromRot(newRot); }


bool CCameraController::SetStateBool(const StateMap& sm, const std::string& name, bool& var)
Expand Down Expand Up @@ -106,3 +108,14 @@ void CCameraController::GetState(StateMap& sm) const
sm["dz"] = dir.z;
}

float CCameraController::DistanceToGround(float3 from, float3 dir, float fallbackPlaneHeight) {
RECOIL_DETAILED_TRACY_ZONE;
float newGroundDist = CGround::LineGroundCol(from, from + dir * 150000.0f, false);

// if the direction is not pointing towards the map we use provided xz plane as heuristic
if (newGroundDist <= 0.0f) {
newGroundDist = CGround::LinePlaneCol(from, dir, 150000.0f, fallbackPlaneHeight);
}

return newGroundDist;
}
5 changes: 4 additions & 1 deletion rts/Game/Camera/CameraController.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,20 @@ class CCameraController
virtual float3 GetRot() const;

virtual void SetPos(const float3& newPos) { pos = newPos; }
virtual void SetRot(const float3& newRot);
virtual void SetDir(const float3& newDir) { dir = newDir; }
virtual bool DisableTrackingByKey() { return true; }

// return the position to send to new controllers SetPos
virtual float3 SwitchFrom() const = 0;
virtual void SwitchTo(const int oldCam, const bool showText = true) = 0;
virtual void SwitchTo(const CCameraController* oldCam, const bool showText = true) = 0;

virtual void GetState(StateMap& sm) const;
virtual bool SetState(const StateMap& sm);
virtual void SetTrackingInfo(const float3& pos, float radius) { SetPos(pos); }

static float DistanceToGround(float3 from, float3 dir, float fallbackPlaneHeight);

/**
* Whether the camera's distance to the ground or to the units
* should be used to determine whether to show them as icons or normal.
Expand Down
178 changes: 178 additions & 0 deletions rts/Game/Camera/DollyController.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#include <SDL_keycode.h>
#include <tracy/Tracy.hpp>

#include "DollyController.h"
#include "Game/Camera.h"
#include "Game/Camera/CameraController.h"
#include "Game/CameraHandler.h"
#include "Game/UI/MouseHandler.h"
#include "Map/ReadMap.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitHandler.h"
#include "System/Config/ConfigHandler.h"
#include "System/Log/ILog.h"
#include "System/Math/NURBS.h"
#include "System/MathConstants.h"
#include "System/Misc/SpringTime.h"
#include "System/Misc/TracyDefs.h"
#include "System/SpringMath.h"
#include "System/float3.h"

CONFIG(float, CamDollyFOV).defaultValue(45.0f);

CDollyController::CDollyController()
: rot(2.677f, 0.0f, 0.0f)
, lookTarget(0.f, 0.f, 0.f)
, position(400.f, 400.f, 400.f)
{
RECOIL_DETAILED_TRACY_ZONE;
configHandler->NotifyOnChange(this, {"CamDollyFOV"});
ConfigUpdate();
}

CDollyController::~CDollyController()
{
RECOIL_DETAILED_TRACY_ZONE;
configHandler->RemoveObserver(this);
}

void CDollyController::ConfigUpdate()
{
RECOIL_DETAILED_TRACY_ZONE;
fov = configHandler->GetFloat("CamDollyFOV");
}

void CDollyController::ConfigNotify(const std::string& key, const std::string& value)
{
RECOIL_DETAILED_TRACY_ZONE;
ConfigUpdate();
}

void CDollyController::Run(float milliseconds)
{
startTime = spring_gettime().toMilliSecsf();
endTime = startTime + milliseconds;
pauseTime = 0.f;
}

void CDollyController::Pause(float percent)
{
if (percent >= 0.f && percent <= 1.f) {
pauseTime = percent * (endTime - startTime) + startTime;
} else {
pauseTime = spring_gettime().toMilliSecsf();
}
}

void CDollyController::Resume()
{
float current = spring_gettime().toMilliSecsf();
float duration = endTime - startTime;
startTime = current - pauseTime + startTime;
endTime = startTime + duration;
pauseTime = 0.f;
}

void CDollyController::Update()
{
ZoneScoped;
float curTime = spring_gettime().toMilliSecsf();
if (pauseTime > 0.f) {
curTime = pauseTime;
}
float percent = 0;
if (endTime != startTime) {
percent = std::clamp(1 - (endTime - curTime) / (endTime - startTime), 0.f, 1.f);
}
if (mode == DOLLY_MODE_CURVE) {
float minU = NURBS::minU(curveDegree, curveControlPoints, nurbsKnots);
float maxU = NURBS::maxU(curveDegree, curveControlPoints, nurbsKnots);
float u = minU + percent * (maxU - minU);
pos = NURBS::SolveNURBS(curveDegree, curveControlPoints, nurbsKnots, u);
} else if (mode == DOLLY_MODE_POSITION) {
pos = position;
}

// LOG_L(L_INFO, "Dollypos: %s", pos.str().c_str());
float relative = relmode - 1.0;
if (lookMode == DOLLY_LOOKMODE_POSITION) {
pos += lookTarget * relative;
dir = (lookTarget - pos).Normalize();
} else if (lookMode == DOLLY_LOOKMODE_CURVE) {
float minU = NURBS::minU(lookCurveDegree, lookControlPoints, lookKnots);
float maxU = NURBS::maxU(lookCurveDegree, lookControlPoints, lookKnots);
float u = minU + percent * (maxU - minU);
float3 lookT = NURBS::SolveNURBS(lookCurveDegree, lookControlPoints, lookKnots, u);
pos += lookT * relative;
dir = (lookT - pos).Normalize();
} else if (lookMode == DOLLY_LOOKMODE_UNIT) {
CUnit* unit = unitHandler.GetUnit(lookUnit);
if (unit != nullptr) {
pos += unit->drawPos * relative;
dir = (unit->drawPos - pos).Normalize();
}
}

float3 newRot = CCamera::GetRotFromDir(GetDir());
int wraps = std::trunc(rot.y / math::TWOPI);
newRot.y += math::TWOPI * wraps;
float ydiff = rot.y - newRot.y;
if (abs(ydiff) > math::PI) {
newRot.y += math::TWOPI * Sign(ydiff);
}
rot = newRot;
camHandler->CameraTransition(0.01f);
}

void CDollyController::SwitchTo(const CCameraController* oldCam, const bool showText)
{
RECOIL_DETAILED_TRACY_ZONE;
if (showText)
LOG("Switching to Dolly style camera");
startTime = endTime = 0.f;
rot = oldCam->GetRot();
}

void CDollyController::SetNURBS(int degree, const std::vector<float4>& cpoints,
const std::vector<float>& knots)
{
curveDegree = degree;
curveControlPoints = cpoints;
nurbsKnots = knots;
}

void CDollyController::SetLookPosition(const float3& pos)
{
lookTarget = pos;
}

void CDollyController::SetLookUnit(int unitid)
{
lookUnit = unitid;
}

void CDollyController::SetLookCurve(int degree, const std::vector<float4>& cpoints,
const std::vector<float>& knots)
{
lookCurveDegree = degree;
lookControlPoints = cpoints;
lookKnots = knots;
}

void CDollyController::GetState(StateMap& sm) const
{
RECOIL_DETAILED_TRACY_ZONE;
CCameraController::GetState(sm);
}

bool CDollyController::SetState(const StateMap& sm)
{
RECOIL_DETAILED_TRACY_ZONE;
CCameraController::SetState(sm);
SetStateFloat(sm, "rx", rot.x);
SetStateFloat(sm, "ry", rot.y);
SetStateFloat(sm, "rz", rot.z);
return true;
}
99 changes: 99 additions & 0 deletions rts/Game/Camera/DollyController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef _DOLLY_CONTROLLER_H
#define _DOLLY_CONTROLLER_H

#include "CameraController.h"
#include "Game/UI/MouseHandler.h"

class CDollyController : public CCameraController
{
public:
CDollyController();
~CDollyController();
enum {
DOLLY_MODE_POSITION = 1,
DOLLY_MODE_CURVE = 2,
};
enum {
DOLLY_RELATIVE_WORLD = 1,
DOLLY_RELATIVE_TARGET = 2,
};
enum {
DOLLY_LOOKMODE_POSITION = 1,
DOLLY_LOOKMODE_UNIT = 2,
DOLLY_LOOKMODE_CURVE = 3,
};
const std::string GetName() const
{
return "dolly";
}

void KeyMove(float3 move) {};
void MouseMove(float3 move) {};
void ScreenEdgeMove(float3 move) {};
void MouseWheelMove(float move) {};
void MouseWheelMove(float move, const float3& newDir) {};

void Update();
void SetPos(const float3& newPos)
{
pos = newPos;
};
void SetRot(const float3& newRot)
{
rot = newRot;
};
float3 GetRot() const
{
return rot;
};

float3 SwitchFrom() const
{
return pos;
};
void SwitchTo(const CCameraController* oldCam, const bool showText);

void Run(float milliseconds);
void Pause(float percent);
void Resume();
void GetState(StateMap& sm) const;
bool SetState(const StateMap& sm);

void ConfigNotify(const std::string& key, const std::string& value);
void ConfigUpdate();

void SetMode(int newMode) { mode = std::clamp(newMode, 1, 2); }
void SetRelativeMode(int newMode) { relmode = std::clamp(newMode, 1, 2); }
void SetPosition(const float3& newPosition) { position = newPosition; };
void SetNURBS(int degree, const std::vector<float4> &cpoints, const std::vector<float> &knots);

void SetLookMode(int newMode) { lookMode = std::clamp(newMode, 1, 3); };
void SetLookPosition(const float3 &pos);
void SetLookUnit(int unitid);
void SetLookCurve(int degree, const std::vector<float4> &cpoints, const std::vector<float> &knots);

private:
float3 rot;
int mode = 1;
int relmode = 1;
float3 position;

std::vector<float4> curveControlPoints;
std::vector<float> nurbsKnots;

int lookMode = 1;
float3 lookTarget;
int lookUnit;
int lookCurveDegree;
std::vector<float4> lookControlPoints;
std::vector<float> lookKnots;

int curveDegree = 3;
float startTime = 1.;
float endTime = 1.;
float pauseTime = 0.;
};

#endif // _DOLLY_CONTROLLER_H
2 changes: 1 addition & 1 deletion rts/Game/Camera/DummyController.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class CDummyController: public CCameraController {
void MouseWheelMove(float move, const float3& newDir) override {}

float3 SwitchFrom() const override { return ZeroVector; }
void SwitchTo(const int, const bool) override {}
void SwitchTo(const CCameraController*, const bool) override {}
};

#endif
Expand Down
Loading