extract orbital camera into separate file
This commit is contained in:
@ -11,6 +11,7 @@ include_directories(include)
|
||||
|
||||
add_executable(masssprings
|
||||
src/main.cpp
|
||||
src/camera.cpp
|
||||
src/renderer.cpp
|
||||
src/physics.cpp
|
||||
src/puzzle.cpp
|
||||
|
||||
41
include/camera.hpp
Normal file
41
include/camera.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef __CAMERA_HPP_
|
||||
#define __CAMERA_HPP_
|
||||
|
||||
#include <raylib.h>
|
||||
#include <raymath.h>
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
class OrbitCamera3D {
|
||||
friend class Renderer;
|
||||
|
||||
private:
|
||||
Camera camera;
|
||||
Vector3 target;
|
||||
float distance;
|
||||
float angle_x;
|
||||
float angle_y;
|
||||
Vector2 last_mouse;
|
||||
bool dragging;
|
||||
bool panning;
|
||||
bool target_lock;
|
||||
|
||||
public:
|
||||
OrbitCamera3D()
|
||||
: camera({0}), target(Vector3Zero()), distance(CAMERA_DISTANCE),
|
||||
angle_x(0.0), angle_y(0.0), last_mouse(Vector2Zero()), dragging(false),
|
||||
panning(false), target_lock(true) {
|
||||
camera.position = Vector3(0, 0, -1.0 * distance);
|
||||
camera.target = target;
|
||||
camera.up = Vector3(0, 1.0, 0);
|
||||
camera.fovy = CAMERA_FOV;
|
||||
camera.projection = CAMERA_PERSPECTIVE;
|
||||
}
|
||||
|
||||
~OrbitCamera3D() {}
|
||||
|
||||
public:
|
||||
auto Update(const Vector3 ¤t_target) -> void;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -86,7 +86,6 @@ public:
|
||||
|
||||
class MassSpringSystem {
|
||||
private:
|
||||
// TODO: Use references
|
||||
std::vector<Mass *> mass_vec;
|
||||
std::vector<int> indices;
|
||||
std::vector<int64_t> cell_ids;
|
||||
|
||||
@ -282,6 +282,8 @@ public:
|
||||
std::vector<std::pair<State, State>>>;
|
||||
};
|
||||
|
||||
// Provide hash functions so we can use State and <State, State> as hash-set
|
||||
// keys for masses and springs.
|
||||
template <> struct std::hash<State> {
|
||||
std::size_t operator()(const State &s) const noexcept { return s.Hash(); }
|
||||
};
|
||||
|
||||
@ -1,57 +1,24 @@
|
||||
#ifndef __RENDERER_HPP_
|
||||
#define __RENDERER_HPP_
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <raylib.h>
|
||||
#include <raymath.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "camera.hpp"
|
||||
#include "config.hpp"
|
||||
#include "puzzle.hpp"
|
||||
#include "physics.hpp"
|
||||
|
||||
class OrbitCamera3D {
|
||||
friend class Renderer;
|
||||
|
||||
private:
|
||||
Camera camera;
|
||||
Vector3 target;
|
||||
float distance;
|
||||
float angle_x;
|
||||
float angle_y;
|
||||
Vector2 last_mouse;
|
||||
bool dragging;
|
||||
bool panning;
|
||||
bool target_lock;
|
||||
|
||||
public:
|
||||
OrbitCamera3D(Vector3 target, float distance)
|
||||
: camera({0}), target(target), distance(distance), angle_x(0.0),
|
||||
angle_y(0.0), last_mouse(Vector2Zero()), dragging(false),
|
||||
panning(false), target_lock(true) {
|
||||
camera.position = Vector3(0, 0, -1.0 * distance);
|
||||
camera.target = target;
|
||||
camera.up = Vector3(0, 1.0, 0);
|
||||
camera.fovy = CAMERA_FOV;
|
||||
camera.projection = CAMERA_PERSPECTIVE;
|
||||
}
|
||||
|
||||
~OrbitCamera3D() {}
|
||||
|
||||
public:
|
||||
auto Update(const Mass ¤t_mass) -> void;
|
||||
};
|
||||
#include "puzzle.hpp"
|
||||
|
||||
class Renderer {
|
||||
private:
|
||||
OrbitCamera3D camera;
|
||||
const OrbitCamera3D &camera;
|
||||
RenderTexture render_target;
|
||||
RenderTexture klotski_target;
|
||||
RenderTexture menu_target;
|
||||
|
||||
Material vertex_mat;
|
||||
|
||||
// Instancing
|
||||
Material vertex_mat;
|
||||
int transforms_size;
|
||||
Matrix *transforms;
|
||||
Mesh cube_instance;
|
||||
@ -62,18 +29,14 @@ public:
|
||||
bool connect_solutions;
|
||||
|
||||
public:
|
||||
Renderer()
|
||||
: camera(OrbitCamera3D(Vector3(0, 0, 0), CAMERA_DISTANCE)),
|
||||
mark_solutions(false), connect_solutions(false), transforms_size(0),
|
||||
transforms(nullptr) {
|
||||
Renderer(const OrbitCamera3D &camera)
|
||||
: camera(camera), mark_solutions(false), connect_solutions(false),
|
||||
transforms_size(0), transforms(nullptr) {
|
||||
render_target = LoadRenderTexture(GetScreenWidth() / 2.0,
|
||||
GetScreenHeight() - MENU_HEIGHT);
|
||||
klotski_target = LoadRenderTexture(GetScreenWidth() / 2.0,
|
||||
GetScreenHeight() - MENU_HEIGHT);
|
||||
menu_target = LoadRenderTexture(GetScreenWidth(), MENU_HEIGHT);
|
||||
|
||||
vertex_mat = LoadMaterialDefault();
|
||||
vertex_mat.maps[MATERIAL_MAP_DIFFUSE].color = VERTEX_COLOR;
|
||||
}
|
||||
|
||||
Renderer(const Renderer ©) = delete;
|
||||
@ -86,10 +49,9 @@ public:
|
||||
UnloadRenderTexture(klotski_target);
|
||||
UnloadRenderTexture(menu_target);
|
||||
|
||||
UnloadMaterial(vertex_mat);
|
||||
|
||||
// Instancing
|
||||
if (transforms != nullptr) {
|
||||
UnloadMaterial(vertex_mat);
|
||||
MemFree(transforms);
|
||||
UnloadMesh(cube_instance);
|
||||
|
||||
@ -106,9 +68,6 @@ private:
|
||||
-> void;
|
||||
|
||||
public:
|
||||
auto UpdateCamera(const MassSpringSystem &mass_springs,
|
||||
const State ¤t_state) -> void;
|
||||
|
||||
auto UpdateTextureSizes() -> void;
|
||||
|
||||
auto DrawMassSprings(const MassSpringSystem &mass_springs,
|
||||
|
||||
80
src/camera.cpp
Normal file
80
src/camera.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "camera.hpp"
|
||||
|
||||
auto OrbitCamera3D::Update(const Vector3 ¤t_target) -> void {
|
||||
Vector2 mouse = GetMousePosition();
|
||||
if (mouse.x >= GetScreenWidth() / 2.0 && mouse.y >= MENU_HEIGHT) {
|
||||
if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) {
|
||||
dragging = true;
|
||||
last_mouse = mouse;
|
||||
} else if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
|
||||
panning = true;
|
||||
target_lock = false;
|
||||
last_mouse = mouse;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsMouseButtonReleased(MOUSE_RIGHT_BUTTON)) {
|
||||
dragging = false;
|
||||
}
|
||||
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
|
||||
panning = false;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_L)) {
|
||||
target_lock = !target_lock;
|
||||
}
|
||||
|
||||
if (dragging) {
|
||||
Vector2 dx = Vector2Subtract(mouse, last_mouse);
|
||||
last_mouse = mouse;
|
||||
|
||||
angle_x -= dx.x * ROT_SPEED / 200.0;
|
||||
angle_y += dx.y * ROT_SPEED / 200.0;
|
||||
|
||||
angle_y = Clamp(angle_y, -1.5, 1.5); // Prevent flipping
|
||||
}
|
||||
|
||||
if (panning) {
|
||||
Vector2 dx = Vector2Subtract(mouse, last_mouse);
|
||||
last_mouse = mouse;
|
||||
|
||||
// float speed = PAN_SPEED;
|
||||
float speed;
|
||||
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||
speed = distance * PAN_SPEED / 1000.0 * PAN_MULTIPLIER;
|
||||
} else {
|
||||
speed = distance * PAN_SPEED / 1000.0;
|
||||
}
|
||||
Vector3 forward =
|
||||
Vector3Normalize(Vector3Subtract(camera.target, camera.position));
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(forward, camera.up));
|
||||
Vector3 up = Vector3Normalize(Vector3CrossProduct(right, forward));
|
||||
|
||||
Vector3 offset = Vector3Add(Vector3Scale(right, -dx.x * speed),
|
||||
Vector3Scale(up, dx.y * speed));
|
||||
|
||||
target = Vector3Add(target, offset);
|
||||
}
|
||||
|
||||
if (target_lock) {
|
||||
target = current_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);
|
||||
|
||||
// Spherical coordinates
|
||||
float x = cos(angle_y) * sin(angle_x) * distance;
|
||||
float y = sin(angle_y) * distance;
|
||||
float z = cos(angle_y) * cos(angle_x) * distance;
|
||||
|
||||
camera.position = Vector3Add(target, Vector3(x, y, z));
|
||||
camera.target = target;
|
||||
}
|
||||
11
src/main.cpp
11
src/main.cpp
@ -46,10 +46,11 @@ auto main(int argc, char *argv[]) -> int {
|
||||
InitWindow(INITIAL_WIDTH * 2, INITIAL_HEIGHT + MENU_HEIGHT, "MassSprings");
|
||||
|
||||
// Game setup
|
||||
Renderer renderer;
|
||||
OrbitCamera3D camera;
|
||||
Renderer renderer(camera);
|
||||
MassSpringSystem mass_springs;
|
||||
StateManager state = StateManager(mass_springs);
|
||||
InputHandler input = InputHandler(state, renderer);
|
||||
StateManager state(mass_springs);
|
||||
InputHandler input(state, renderer);
|
||||
|
||||
// Game loop
|
||||
#ifdef PRINT_TIMINGS
|
||||
@ -68,7 +69,8 @@ auto main(int argc, char *argv[]) -> int {
|
||||
// Input update
|
||||
state.previous_state = state.current_state;
|
||||
input.HandleInput();
|
||||
state.UpdateGraph();
|
||||
state.UpdateGraph(); // Add state added after user input
|
||||
camera.Update(mass_springs.GetMass(state.current_state).position);
|
||||
|
||||
// Physics update
|
||||
#ifdef PRINT_TIMINGS
|
||||
@ -98,7 +100,6 @@ auto main(int argc, char *argv[]) -> int {
|
||||
std::chrono::high_resolution_clock::now();
|
||||
#endif
|
||||
|
||||
renderer.UpdateCamera(mass_springs, state.current_state);
|
||||
renderer.UpdateTextureSizes();
|
||||
renderer.DrawMassSprings(mass_springs, state.current_state,
|
||||
state.winning_states);
|
||||
|
||||
@ -15,91 +15,6 @@
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
auto OrbitCamera3D::Update(const Mass ¤t_mass) -> void {
|
||||
Vector2 mouse = GetMousePosition();
|
||||
if (mouse.x >= GetScreenWidth() / 2.0 && mouse.y >= MENU_HEIGHT) {
|
||||
if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) {
|
||||
dragging = true;
|
||||
last_mouse = mouse;
|
||||
} else if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
|
||||
panning = true;
|
||||
target_lock = false;
|
||||
last_mouse = mouse;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsMouseButtonReleased(MOUSE_RIGHT_BUTTON)) {
|
||||
dragging = false;
|
||||
}
|
||||
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
|
||||
panning = false;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_L)) {
|
||||
target_lock = !target_lock;
|
||||
}
|
||||
|
||||
if (dragging) {
|
||||
Vector2 dx = Vector2Subtract(mouse, last_mouse);
|
||||
last_mouse = mouse;
|
||||
|
||||
angle_x -= dx.x * ROT_SPEED / 200.0;
|
||||
angle_y += dx.y * ROT_SPEED / 200.0;
|
||||
|
||||
angle_y = Clamp(angle_y, -1.5, 1.5); // Prevent flipping
|
||||
}
|
||||
|
||||
if (panning) {
|
||||
Vector2 dx = Vector2Subtract(mouse, last_mouse);
|
||||
last_mouse = mouse;
|
||||
|
||||
// float speed = PAN_SPEED;
|
||||
float speed;
|
||||
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||
speed = distance * PAN_SPEED / 1000.0 * PAN_MULTIPLIER;
|
||||
} else {
|
||||
speed = distance * PAN_SPEED / 1000.0;
|
||||
}
|
||||
Vector3 forward =
|
||||
Vector3Normalize(Vector3Subtract(camera.target, camera.position));
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(forward, camera.up));
|
||||
Vector3 up = Vector3Normalize(Vector3CrossProduct(right, forward));
|
||||
|
||||
Vector3 offset = Vector3Add(Vector3Scale(right, -dx.x * speed),
|
||||
Vector3Scale(up, dx.y * speed));
|
||||
|
||||
target = Vector3Add(target, offset);
|
||||
}
|
||||
|
||||
if (target_lock) {
|
||||
target = current_mass.position;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Spherical coordinates
|
||||
float x = cos(angle_y) * sin(angle_x) * distance;
|
||||
float y = sin(angle_y) * distance;
|
||||
float z = cos(angle_y) * cos(angle_x) * distance;
|
||||
|
||||
camera.position = Vector3Add(target, Vector3(x, y, z));
|
||||
camera.target = target;
|
||||
}
|
||||
|
||||
auto Renderer::UpdateCamera(const MassSpringSystem &mass_springs,
|
||||
const State ¤t) -> void {
|
||||
const Mass &c = mass_springs.masses.at(current);
|
||||
camera.Update(c);
|
||||
}
|
||||
|
||||
auto Renderer::UpdateTextureSizes() -> void {
|
||||
if (!IsWindowResized()) {
|
||||
return;
|
||||
@ -128,6 +43,8 @@ auto Renderer::AllocateGraphInstancing(const MassSpringSystem &mass_springs)
|
||||
instancing_shader.locs[SHADER_LOC_VECTOR_VIEW] =
|
||||
GetShaderLocation(instancing_shader, "viewPos");
|
||||
|
||||
vertex_mat = LoadMaterialDefault();
|
||||
vertex_mat.maps[MATERIAL_MAP_DIFFUSE].color = VERTEX_COLOR;
|
||||
vertex_mat.shader = instancing_shader;
|
||||
|
||||
transforms = (Matrix *)MemAlloc(mass_springs.masses.size() * sizeof(Matrix));
|
||||
|
||||
Reference in New Issue
Block a user