[Add] 3D orbit camera and refactor renderer.
This commit is contained in:
parent
a6646820c5
commit
9bf8b277ff
@ -6,4 +6,8 @@ struct Vec3 {
|
|||||||
float x, y , z;
|
float x, y , z;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Vec3 operator+(const Vec3& a, const Vec3& b) {
|
||||||
|
return {a.x + b.x, a.y + b.y, a.z + b.z};
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace BettolaMath. */
|
} /* namespace BettolaMath. */
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
#include <SDL3/SDL_error.h>
|
#include <SDL3/SDL_error.h>
|
||||||
/* FINE LSP!! I'll play your games!!!! */
|
/* FINE LSP!! I'll play your games!!!! */
|
||||||
#include <SDL3/SDL_events.h> /* ~HJAPPY?!?!?! */
|
#include <SDL3/SDL_events.h> /* ~HJAPPY?!?!?! */
|
||||||
|
#include <SDL3/SDL_mouse.h>
|
||||||
|
#include <SDL3/SDL_oldnames.h>
|
||||||
#include <SDL3/SDL_stdinc.h>
|
#include <SDL3/SDL_stdinc.h>
|
||||||
#include <SDL3/SDL_timer.h>
|
#include <SDL3/SDL_timer.h>
|
||||||
#include <SDL3/SDL_video.h>
|
#include <SDL3/SDL_video.h>
|
||||||
@ -10,6 +12,7 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include "game/player.h"
|
||||||
|
|
||||||
#include "bettola.h"
|
#include "bettola.h"
|
||||||
|
|
||||||
@ -78,6 +81,11 @@ void Bettola::process_events(void) {
|
|||||||
while(SDL_PollEvent(&event)) {
|
while(SDL_PollEvent(&event)) {
|
||||||
if(event.type == SDL_EVENT_QUIT) {
|
if(event.type == SDL_EVENT_QUIT) {
|
||||||
_is_running = false;
|
_is_running = false;
|
||||||
|
} else if(event.type == SDL_EVENT_MOUSE_MOTION) {
|
||||||
|
/* Y is inverted. */
|
||||||
|
_camera.process_mouse_movement((float)event.motion.xrel, (float)-event.motion.yrel);
|
||||||
|
} else if(event.type == SDL_EVENT_MOUSE_WHEEL) {
|
||||||
|
_camera.process_mouse_scroll((float)event.wheel.y);
|
||||||
} else if(event.type == SDL_EVENT_KEY_DOWN) {
|
} else if(event.type == SDL_EVENT_KEY_DOWN) {
|
||||||
switch(event.key.key) {
|
switch(event.key.key) {
|
||||||
case SDLK_W: _input.up = true; break;
|
case SDLK_W: _input.up = true; break;
|
||||||
@ -102,6 +110,11 @@ void Bettola::update(double dt) {
|
|||||||
float dir_y = (_input.down ? 1.0f : 0.0f) - (_input.up ? 1.0f : 0.0f);
|
float dir_y = (_input.down ? 1.0f : 0.0f) - (_input.up ? 1.0f : 0.0f);
|
||||||
_game_client.get_player_for_write().set_velocity_direction(dir_x, dir_y);
|
_game_client.get_player_for_write().set_velocity_direction(dir_x, dir_y);
|
||||||
|
|
||||||
|
/* Update camera to follow the player. */
|
||||||
|
const auto& player = _game_client.get_player();
|
||||||
|
BettolaMath::Vec3 player_pos = { player.get_x(), 0.0f, player.get_y() };
|
||||||
|
_camera.update(player_pos);
|
||||||
|
|
||||||
/* Process network messages and send input to the server. */
|
/* Process network messages and send input to the server. */
|
||||||
_game_client.process_network_messages();
|
_game_client.process_network_messages();
|
||||||
_game_client.send_input(_input, dt);
|
_game_client.send_input(_input, dt);
|
||||||
@ -111,13 +124,15 @@ void Bettola::update(double dt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Bettola::render(void) {
|
void Bettola::render(void) {
|
||||||
_renderer.render(_game_client.get_player(), _game_client.get_remote_players());
|
_renderer.render(_camera.get_view_matrix(), _game_client.get_player(),
|
||||||
|
_game_client.get_remote_players());
|
||||||
SDL_GL_SwapWindow(_window);
|
SDL_GL_SwapWindow(_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bettola::create_window(void) {
|
bool Bettola::create_window(void) {
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
|
||||||
/* Don't you dare f.ckin fail to open!!!!! */
|
/* Don't you dare f.ckin fail to open!!!!! */
|
||||||
@ -129,6 +144,9 @@ bool Bettola::create_window(void) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Capture mouse cursor. */
|
||||||
|
SDL_SetWindowRelativeMouseMode(_window, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include "graphics/renderer.h"
|
#include "graphics/renderer.h"
|
||||||
|
#include "graphics/camera.h"
|
||||||
#include "game_client.h"
|
#include "game_client.h"
|
||||||
|
|
||||||
class Bettola {
|
class Bettola {
|
||||||
@ -29,5 +30,6 @@ private:
|
|||||||
|
|
||||||
Renderer _renderer;
|
Renderer _renderer;
|
||||||
GameClient _game_client;
|
GameClient _game_client;
|
||||||
|
Camera _camera;
|
||||||
Player::InputState _input;
|
Player::InputState _input;
|
||||||
};
|
};
|
||||||
|
|||||||
76
src/graphics/camera.cpp
Normal file
76
src/graphics/camera.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include <cmath>
|
||||||
|
#include "math/mat4.h"
|
||||||
|
#include "math/vec3.h"
|
||||||
|
#include "camera.h"
|
||||||
|
|
||||||
|
|
||||||
|
Camera::Camera(void) :
|
||||||
|
_position({0.0f, 0.0f, 0.0f}),
|
||||||
|
_front({0.0f, 0.0f, -1.0f}),
|
||||||
|
_up({0.0f, 1.0f, 0.0f}),
|
||||||
|
_right({0.0f, 0.0f, 0.0f}),
|
||||||
|
_world_up({0.0f, 1.0f, -1.0f}),
|
||||||
|
_yaw(-90.0f),
|
||||||
|
_pitch(0.0f),
|
||||||
|
_distance(10.0f),
|
||||||
|
_mouse_sensitivity(0.1f),
|
||||||
|
_zoom_sensitivity(0.5f) {
|
||||||
|
|
||||||
|
_update_camera_vectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::update(const BettolaMath::Vec3& target_pos) {
|
||||||
|
_position.x = target_pos.x - _front.x * _distance;
|
||||||
|
_position.y = target_pos.y - _front.y * _distance;
|
||||||
|
_position.z = target_pos.z - _front.z * _distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::process_mouse_movement(float x_offset, float y_offset) {
|
||||||
|
_yaw += x_offset * _mouse_sensitivity;
|
||||||
|
_pitch += y_offset * _mouse_sensitivity;
|
||||||
|
|
||||||
|
/* Constrain pitch. */
|
||||||
|
if(_pitch > 89.0f) _pitch = 89.0f;
|
||||||
|
if(_pitch < -89.0f) _pitch = -89.0f;
|
||||||
|
|
||||||
|
_update_camera_vectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::process_mouse_scroll(float y_offset) {
|
||||||
|
_distance -= y_offset * _zoom_sensitivity;
|
||||||
|
if(_distance < 2.0f) _distance = 2.0f;
|
||||||
|
if(_distance > 20.0f) _distance = 20.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
BettolaMath::Mat4 Camera::get_view_matrix(void) const {
|
||||||
|
return BettolaMath::Mat4::look_at(_position, _position + _front, _up);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::_update_camera_vectors(void) {
|
||||||
|
BettolaMath::Vec3 front;
|
||||||
|
float yaw_rad = _yaw*M_PI/180.0f;
|
||||||
|
float pitch_rad = _pitch*M_PI/180.0f;
|
||||||
|
|
||||||
|
front.x = cos(yaw_rad) * cos(pitch_rad);
|
||||||
|
front.y = sin(pitch_rad);
|
||||||
|
front.z = sin(yaw_rad) * cos(pitch_rad);
|
||||||
|
|
||||||
|
/* Normalise the front vector. */
|
||||||
|
float f_mag = sqrt(front.x*front.x + front.y*front.y + front.z*front.z);
|
||||||
|
_front.x = front.x / f_mag;
|
||||||
|
_front.y = front.y / f_mag;
|
||||||
|
_front.z = front.z / f_mag;
|
||||||
|
|
||||||
|
_right.x = _front.y * _world_up.z - _front.z * _world_up.y;
|
||||||
|
_right.y = _front.z * _world_up.x - _front.x * _world_up.z;
|
||||||
|
_right.z = _front.x * _world_up.y - _front.y * _world_up.x;
|
||||||
|
float r_mag = sqrt(_right.x*_right.x + _right.y*_right.y + _right.z*_right.z);
|
||||||
|
_right.x /= r_mag; _right.y /= r_mag; _right.z /= r_mag;
|
||||||
|
|
||||||
|
/* Up vector. */
|
||||||
|
_up.x = _right.y * _front.z - _right.z * _front.y;
|
||||||
|
_up.y = _right.z * _front.x - _right.x * _front.z;
|
||||||
|
_up.z = _right.x * _front.y - _right.y * _front.x;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
32
src/graphics/camera.h
Normal file
32
src/graphics/camera.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "math/mat4.h"
|
||||||
|
#include "math/vec3.h"
|
||||||
|
|
||||||
|
class Camera {
|
||||||
|
public:
|
||||||
|
Camera(void);
|
||||||
|
|
||||||
|
void update(const BettolaMath::Vec3& target_pos);
|
||||||
|
|
||||||
|
void process_mouse_movement(float x_offset, float y_offset);
|
||||||
|
void process_mouse_scroll(float y_offset);
|
||||||
|
|
||||||
|
BettolaMath::Mat4 get_view_matrix(void) const;
|
||||||
|
private:
|
||||||
|
void _update_camera_vectors(void);
|
||||||
|
|
||||||
|
float _yaw;
|
||||||
|
float _pitch;
|
||||||
|
float _distance;
|
||||||
|
|
||||||
|
BettolaMath::Vec3 _position;
|
||||||
|
BettolaMath::Vec3 _front;
|
||||||
|
BettolaMath::Vec3 _up;
|
||||||
|
BettolaMath::Vec3 _right;
|
||||||
|
BettolaMath::Vec3 _world_up;
|
||||||
|
|
||||||
|
|
||||||
|
float _mouse_sensitivity;
|
||||||
|
float _zoom_sensitivity;
|
||||||
|
};
|
||||||
@ -1,6 +1,7 @@
|
|||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include "game/player.h"
|
||||||
#include <SDL3/SDL_timer.h>
|
#include <SDL3/SDL_timer.h>
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
@ -134,7 +135,8 @@ bool Renderer::init(int screen_width, int screen_height) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render(const Player& player, const std::vector<RemotePlayer>& remote_players) {
|
void Renderer::render(const BettolaMath::Mat4& view_matrix, const Player& player,
|
||||||
|
const std::vector<RemotePlayer>& remote_players) {
|
||||||
glClearColor(0.1f, 0.1f, 0.3f, 1.0f);
|
glClearColor(0.1f, 0.1f, 0.3f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Need to clear depth buffer too. */
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Need to clear depth buffer too. */
|
||||||
GL_CHECK_ERROR();
|
GL_CHECK_ERROR();
|
||||||
@ -142,11 +144,6 @@ void Renderer::render(const Player& player, const std::vector<RemotePlayer>& rem
|
|||||||
_shader.use();
|
_shader.use();
|
||||||
GL_CHECK_ERROR();
|
GL_CHECK_ERROR();
|
||||||
|
|
||||||
/* Make the camera stalk the player. */
|
|
||||||
BettolaMath::Vec3 camera_pos = { player.get_x(), 5.0f, player.get_y() + 8.0f };
|
|
||||||
BettolaMath::Vec3 player_pos = { player.get_x(), 0.0f, player.get_y() };
|
|
||||||
BettolaMath::Mat4 view = BettolaMath::Mat4::look_at(camera_pos, player_pos, {0.0f,1.0f,0.0f});
|
|
||||||
|
|
||||||
BettolaMath::Mat4 projection = BettolaMath::Mat4::perspective((45.0f * M_PI) / 180.0f, 800.0f/600.0f, 0.1f, 100.0f);
|
BettolaMath::Mat4 projection = BettolaMath::Mat4::perspective((45.0f * M_PI) / 180.0f, 800.0f/600.0f, 0.1f, 100.0f);
|
||||||
|
|
||||||
GLint view_loc = glGetUniformLocation(_shader.get_id(), "view");
|
GLint view_loc = glGetUniformLocation(_shader.get_id(), "view");
|
||||||
@ -154,7 +151,7 @@ void Renderer::render(const Player& player, const std::vector<RemotePlayer>& rem
|
|||||||
GLint model_loc = glGetUniformLocation(_shader.get_id(), "model");
|
GLint model_loc = glGetUniformLocation(_shader.get_id(), "model");
|
||||||
GLint color_loc = glGetUniformLocation(_shader.get_id(), "overrideColor");
|
GLint color_loc = glGetUniformLocation(_shader.get_id(), "overrideColor");
|
||||||
|
|
||||||
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view.get_ptr());
|
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view_matrix.get_ptr());
|
||||||
GL_CHECK_ERROR();
|
GL_CHECK_ERROR();
|
||||||
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection.get_ptr());
|
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection.get_ptr());
|
||||||
GL_CHECK_ERROR();
|
GL_CHECK_ERROR();
|
||||||
|
|||||||
@ -12,7 +12,8 @@ public:
|
|||||||
~Renderer(void);
|
~Renderer(void);
|
||||||
|
|
||||||
bool init(int screen_width, int screen_height);
|
bool init(int screen_width, int screen_height);
|
||||||
void render(const Player& player, const std::vector<RemotePlayer>& remote_players);
|
void render(const BettolaMath::Mat4& view_matrix, const Player& player,
|
||||||
|
const std::vector<RemotePlayer>& remote_players);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _init_shaders();
|
bool _init_shaders();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user