implement smooth camera

This commit is contained in:
2026-02-23 14:27:56 +01:00
parent 861fb34d39
commit 6698ace0c6
4 changed files with 44 additions and 19 deletions

View File

@ -11,19 +11,25 @@ class OrbitCamera3D {
private: private:
Camera camera; Camera camera;
Vector3 position;
Vector3 target; Vector3 target;
Vector3 target_target;
float distance; float distance;
float angle_x; float angle_x;
float angle_y; float angle_y;
// Input
Vector2 last_mouse; Vector2 last_mouse;
bool dragging; bool rotating;
bool panning; bool panning;
bool target_lock; bool target_lock;
public: public:
OrbitCamera3D() OrbitCamera3D()
: camera({0}), target(Vector3Zero()), distance(CAMERA_DISTANCE), : camera({0}), position(Vector3Zero()), target(Vector3Zero()),
angle_x(0.0), angle_y(0.0), last_mouse(Vector2Zero()), dragging(false), target_target(Vector3Zero()), distance(CAMERA_DISTANCE), angle_x(0.0),
angle_y(0.0), last_mouse(Vector2Zero()), rotating(false),
panning(false), target_lock(true) { panning(false), target_lock(true) {
camera.position = Vector3(0, 0, -1.0 * distance); camera.position = Vector3(0, 0, -1.0 * distance);
camera.target = target; camera.target = target;
@ -35,6 +41,8 @@ public:
~OrbitCamera3D() {} ~OrbitCamera3D() {}
public: public:
auto HandleCameraInput() -> Vector2;
auto Update(const Vector3 &current_target) -> void; auto Update(const Vector3 &current_target) -> void;
}; };

View File

@ -28,6 +28,7 @@ constexpr float ZOOM_MULTIPLIER = 4.0;
constexpr float PAN_SPEED = 2.0; constexpr float PAN_SPEED = 2.0;
constexpr float PAN_MULTIPLIER = 10.0; constexpr float PAN_MULTIPLIER = 10.0;
constexpr float ROT_SPEED = 1.0; constexpr float ROT_SPEED = 1.0;
constexpr float CAMERA_SMOOTH_SPEED = 15.0;
// Physics Engine // Physics Engine
constexpr float SIM_SPEED = 4.0; // How large each update should be constexpr float SIM_SPEED = 4.0; // How large each update should be
@ -38,7 +39,7 @@ constexpr float DAMPENING_CONSTANT = 1.0; // Mass spring system
constexpr float REST_LENGTH = 2.0; // Mass spring system constexpr float REST_LENGTH = 2.0; // Mass spring system
constexpr float VERLET_DAMPENING = 0.05; // [0, 1] constexpr float VERLET_DAMPENING = 0.05; // [0, 1]
constexpr float BH_FORCE = 2.0; // BH: [1.0, 3.0] constexpr float BH_FORCE = 2.0; // BH: [1.0, 3.0]
constexpr float THETA = 1.0; // Barnes-Hut [0.5, ~] constexpr float THETA = 1.0; // Barnes-Hut [0.5, 1.0]
constexpr float SOFTENING = 0.01; // Barnes-Hut [0.01, 1.0] constexpr float SOFTENING = 0.01; // Barnes-Hut [0.01, 1.0]
constexpr float GRID_FORCE = 0.02; // Grid: [0.0, ~0.05] constexpr float GRID_FORCE = 0.02; // Grid: [0.0, ~0.05]
constexpr float REPULSION_RANGE = 5.0 * REST_LENGTH; // Grid constexpr float REPULSION_RANGE = 5.0 * REST_LENGTH; // Grid

View File

@ -1,20 +1,34 @@
#include "camera.hpp" #include "camera.hpp"
#include "config.hpp"
#include "util.hpp"
auto OrbitCamera3D::Update(const Vector3 &current_target) -> void { #include <iostream>
#include <raylib.h>
#include <raymath.h>
auto OrbitCamera3D::HandleCameraInput() -> Vector2 {
Vector2 mouse = GetMousePosition(); Vector2 mouse = GetMousePosition();
if (mouse.x >= GetScreenWidth() / 2.0 && mouse.y >= MENU_HEIGHT) { if (mouse.x >= GetScreenWidth() / 2.0 && mouse.y >= MENU_HEIGHT) {
if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) { if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) {
dragging = true; rotating = true;
last_mouse = mouse; last_mouse = mouse;
} else if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { } else if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
panning = true; panning = true;
target_lock = false; target_lock = false;
last_mouse = mouse; last_mouse = mouse;
} }
// Zoom
float wheel = GetMouseWheelMove();
if (IsKeyDown(KEY_LEFT_SHIFT)) {
distance -= wheel * ZOOM_SPEED * ZOOM_MULTIPLIER;
} else {
distance -= wheel * ZOOM_SPEED;
}
} }
if (IsMouseButtonReleased(MOUSE_RIGHT_BUTTON)) { if (IsMouseButtonReleased(MOUSE_RIGHT_BUTTON)) {
dragging = false; rotating = false;
} }
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) { if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
panning = false; panning = false;
@ -23,8 +37,13 @@ auto OrbitCamera3D::Update(const Vector3 &current_target) -> void {
if (IsKeyPressed(KEY_L)) { if (IsKeyPressed(KEY_L)) {
target_lock = !target_lock; target_lock = !target_lock;
} }
return mouse;
}
if (dragging) { auto OrbitCamera3D::Update(const Vector3 &current_target) -> void {
Vector2 mouse = HandleCameraInput();
if (rotating) {
Vector2 dx = Vector2Subtract(mouse, last_mouse); Vector2 dx = Vector2Subtract(mouse, last_mouse);
last_mouse = mouse; last_mouse = mouse;
@ -38,13 +57,15 @@ auto OrbitCamera3D::Update(const Vector3 &current_target) -> void {
Vector2 dx = Vector2Subtract(mouse, last_mouse); Vector2 dx = Vector2Subtract(mouse, last_mouse);
last_mouse = mouse; last_mouse = mouse;
// float speed = PAN_SPEED;
float speed; float speed;
if (IsKeyDown(KEY_LEFT_SHIFT)) { if (IsKeyDown(KEY_LEFT_SHIFT)) {
speed = distance * PAN_SPEED / 1000.0 * PAN_MULTIPLIER; speed = distance * PAN_SPEED / 1000.0 * PAN_MULTIPLIER;
} else { } else {
speed = distance * PAN_SPEED / 1000.0; speed = distance * PAN_SPEED / 1000.0;
} }
// The panning needs to happen in camera coordinates, otherwise rotating the
// camera breaks it
Vector3 forward = Vector3 forward =
Vector3Normalize(Vector3Subtract(camera.target, camera.position)); Vector3Normalize(Vector3Subtract(camera.target, camera.position));
Vector3 right = Vector3Normalize(Vector3CrossProduct(forward, camera.up)); Vector3 right = Vector3Normalize(Vector3CrossProduct(forward, camera.up));
@ -57,17 +78,13 @@ auto OrbitCamera3D::Update(const Vector3 &current_target) -> void {
} }
if (target_lock) { if (target_lock) {
target = current_target; target_target = current_target;
target = Vector3MoveTowards(
target, target_target,
CAMERA_SMOOTH_SPEED * GetFrameTime() *
Vector3Length(Vector3Subtract(target, target_target)));
} }
if (mouse.x >= GetScreenWidth() / 2.0 && mouse.y >= MENU_HEIGHT) {
float wheel = GetMouseWheelMove();
if (IsKeyDown(KEY_LEFT_SHIFT)) {
distance -= wheel * ZOOM_SPEED * ZOOM_MULTIPLIER;
} else {
distance -= wheel * ZOOM_SPEED;
}
}
distance = Clamp(distance, MIN_CAMERA_DISTANCE, MAX_CAMERA_DISTANCE); distance = Clamp(distance, MIN_CAMERA_DISTANCE, MAX_CAMERA_DISTANCE);
// Spherical coordinates // Spherical coordinates

View File

@ -23,7 +23,6 @@
// - Click states to display them in the board // - Click states to display them in the board
// - Find shortest path to any winning state and mark it in the graph // - Find shortest path to any winning state and mark it in the graph
// - Also mark the next move along the path on the board // - Also mark the next move along the path on the board
// TODO: Smooth camera (on target change)
// TODO: Mark the starting state // TODO: Mark the starting state
// TODO: Mark the visited states // TODO: Mark the visited states