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

Update camera object ray calculation #3

Merged
merged 7 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "third-party/uuid_v4"]
path = third-party/uuid_v4
url = https://github.com/crashoz/uuid_v4.git
32 changes: 28 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,28 @@ add_definitions(
set(CMAKE_BUILD_TYPE Debug)
# set(CMAKE_BUILD_TYPE Release)


find_package(Git QUIET)

if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
# Update submodules as needed
option(GIT_SUBMODULE "Check submodules during build" ON)
if(GIT_SUBMODULE)
message(STATUS "Submodule update")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
endif()
endif()
endif()

if(NOT EXISTS "${PROJECT_SOURCE_DIR}/third-party/uuid_v4/CMakeLists.txt")
message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.")
endif()

# internal libraries
add_subdirectory(app)
add_subdirectory(src/Camera)
add_subdirectory(src/CollisionManager)
Expand All @@ -27,22 +49,24 @@ add_subdirectory(src/Map)
add_subdirectory(src/Math)
add_subdirectory(src/TextureManager)
add_subdirectory(src/TimeManager)
add_subdirectory(src/Utilities)
add_subdirectory(src/Utility)

# external libraries
add_subdirectory(third-party/uuid_v4)

find_package(SDL2 REQUIRED)

include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/third-party
${SDL2_INCLUDE_DIRS}
)

link_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/include
${SDL2_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/third-party
)
set(LIBRARIES
${SDL2_LIBRARIES}
Expand Down
5 changes: 5 additions & 0 deletions src/Camera/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
link_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}
)


Expand All @@ -14,6 +15,7 @@ add_library(
target_include_directories(ray PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}
)

target_link_libraries(
Expand All @@ -34,6 +36,7 @@ add_library(
target_include_directories(camera PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}
)


Expand All @@ -45,4 +48,6 @@ target_link_libraries(
character
vector
map
scene
texture_manager
)
14 changes: 11 additions & 3 deletions src/Camera/include/Camera/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@
#define CAMERA_CAMERA_H

#include "Camera/raycaster.h"
#include "Graphics/scene.h"
#include <Camera/ray.h>
#include <Characters/character.h>
#include <GameObjects/game_object.h>
#include <GameObjects/static_object.h>
#include <Map/map.h>
#include <memory>
#include <optional>
#include <third-party/uuid_v4/uuid_v4.h>
#include <unordered_map>

namespace wolfenstein {

Expand All @@ -29,28 +33,32 @@ struct Camera2DConfig
double depth;
};

typedef std::pair<Ray, Ray> RayPair;

class Camera2D
{
public:
explicit Camera2D(const Camera2DConfig& config);
~Camera2D() = default;

void Update(const std::shared_ptr<Map>& map);
void Update(const std::shared_ptr<Scene>& scene);

std::shared_ptr<RayVector> GetRays() const;
std::optional<RayPair> GetObjectRay(std::string id);
std::shared_ptr<Ray> GetCrosshairRay() const;
Position2D GetPosition() const;
double GetFov() const;
double GetDeltaAngle() const;

void SetPosition(const Position2D& position);

Ray CalculateObjectRay(const std::shared_ptr<IGameObject>& object) const;

private:
void InitRays();
void Calculate(const std::shared_ptr<IGameObject>& object);
double WorldAngleToCameraAngle(double angle) const;
Camera2DConfig config_;
std::shared_ptr<RayVector> rays_;
std::unordered_map<std::string, RayPair> objects_;
std::shared_ptr<RayCaster> ray_cast_;
std::shared_ptr<Ray> crosshair_ray_;
Position2D position_;
Expand Down
132 changes: 95 additions & 37 deletions src/Camera/src/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,52 @@
*/

#include "Camera/camera.h"
#include "Camera/ray.h"
#include "Math/vector.h"
#include <TextureManager/texture_manager.h>
#include <cmath>
#include <string>

namespace wolfenstein {

void Camera2D::InitRays() {
rays_ = std::make_shared<RayVector>();
for (int i = 0; i < config_.width / 2; i++) {
rays_->emplace_back(Ray());
}
}

Camera2D::Camera2D(const Camera2DConfig& config)
: config_(config),
ray_cast_(std::make_shared<RayCaster>(config.width / 2, config.fov,
config.depth)) {
InitRays();
}

void Camera2D::Update(const std::shared_ptr<Map>& map_ptr) {
ray_cast_->Update(map_ptr, position_, rays_);
void Camera2D::Update(const std::shared_ptr<Scene>& scene) {
ray_cast_->Update(scene->GetMap(), position_, rays_);
crosshair_ray_ = std::make_shared<Ray>(rays_->at(config_.width / 4));

// Update object rays
objects_.clear();
for (const auto& object : scene->GetObjects()) {
if (object->GetObjectType() == ObjectType::STATIC_OBJECT) {
Calculate(object);
}
}
}

std::shared_ptr<RayVector> Camera2D::GetRays() const {
return rays_;
}

std::optional<RayPair> Camera2D::GetObjectRay(std::string id) {
if (objects_.find(id) != objects_.end()) {
return objects_[id];
}
return std::nullopt;
}

std::shared_ptr<Ray> Camera2D::GetCrosshairRay() const {
return crosshair_ray_;
}
Expand All @@ -50,44 +75,77 @@ void Camera2D::SetPosition(const Position2D& position) {
position_ = position;
}

Ray Camera2D::CalculateObjectRay(
const std::shared_ptr<IGameObject>& object) const {
Ray object_ray{};
auto static_object = std::dynamic_pointer_cast<StaticObject>(object);
const auto object_pose = static_object->GetPose();
const auto w = static_object->GetWidth();

// check if object is in the camera view
auto object_distance = Distance(object_pose, position_.pose);
if (object_distance > config_.depth) {
return object_ray;
void Camera2D::Calculate(const std::shared_ptr<IGameObject>& object) {
if (object->GetObjectType() == ObjectType::STATIC_OBJECT) {

auto static_object = std::dynamic_pointer_cast<StaticObject>(object);
const auto object_pose = static_object->GetPose();
const auto width = static_object->GetWidth();

// check if object is in the camera view
auto object_distance = object_pose.Distance(position_.pose);
if (object_distance > config_.depth) {
return;
}

// Object center angle
const auto object_center_angle = std::atan2(
object_pose.y - position_.pose.y, object_pose.x - position_.pose.x);

// Object left edge point and angle
auto object_left_edge_angle =
SubRadian(object_center_angle, ToRadians(90.0));
const auto left_edge_point =
object_pose +
vector2d{width / 2 * std::cos(object_left_edge_angle),
width / 2 * std::sin(object_left_edge_angle)};
const auto left_edge_angle =
std::atan2(left_edge_point.y - position_.pose.y,
left_edge_point.x - position_.pose.x);
const auto camera_angle_left = WorldAngleToCameraAngle(left_edge_angle);

// Object right edge point and angle
auto object_right_edge_angle =
SumRadian(object_center_angle, ToRadians(90.0));
const auto right_edge_point =
object_pose +
vector2d{width / 2 * std::cos(object_right_edge_angle),
width / 2 * std::sin(object_right_edge_angle)};
const auto right_edge_angle =
std::atan2(right_edge_point.y - position_.pose.y,
right_edge_point.x - position_.pose.x);
const auto camera_angle_right =
WorldAngleToCameraAngle(right_edge_angle);

// Check if object is in the camera view
if (camera_angle_right < -config_.fov / 2 ||
camera_angle_left > config_.fov / 2) {
return;
}
const auto texture_id = static_object->GetTextureId();

// Calculate object raypair
RayPair object_ray_pair;
object_ray_pair.first.Reset(position_.pose, camera_angle_left);
object_ray_pair.first.is_hit = true;
object_ray_pair.first.perpendicular_distance = object_distance;
object_ray_pair.first.wall_id = texture_id;

object_ray_pair.second.Reset(position_.pose, camera_angle_right);
object_ray_pair.second.is_hit = true;
object_ray_pair.second.perpendicular_distance = object_distance;
object_ray_pair.second.wall_id = texture_id;

objects_[object->GetId()] = object_ray_pair;
}

const auto object_center_angle = std::atan2(
object_pose.y - position_.pose.y, object_pose.x - position_.pose.x);

auto object_left_edge_angle =
SubRadian(object_center_angle, ToRadians(90.0));
const auto left_edge_point =
object_pose + vector2d{w * std::cos(object_left_edge_angle),
w * std::sin(object_left_edge_angle)};
const auto left_edge_angle =
std::atan2(left_edge_point.y - position_.pose.y,
left_edge_point.x - position_.pose.x);
object_ray.theta =
left_edge_angle > 0 ? left_edge_angle : 2 * M_PI + left_edge_angle;
object_ray.is_hit = true;
object_ray.perpendicular_distance = object_distance;
object_ray.wall_id = static_object->GetTextureId();

return object_ray;
}

void Camera2D::InitRays() {
rays_ = std::make_shared<RayVector>();
for (int i = 0; i < config_.width / 2; i++) {
rays_->emplace_back(Ray());
}
double Camera2D::WorldAngleToCameraAngle(double angle) const {
const auto vector_of_crosshair = crosshair_ray_->direction;
const auto vector_of_ray = vector2d{std::cos(angle), std::sin(angle)};
const auto angle_between = CalculateAngleBetweenTwoVectorsSigned(
vector_of_ray, vector_of_crosshair);
return angle_between;
}

} // namespace wolfenstein
4 changes: 4 additions & 0 deletions src/Characters/include/Characters/enemy.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
#define CHARACTERS_ENEMY_H_

#include "character.h"
#include <Utility/uuid_generator.h>

namespace wolfenstein {

class Enemy : public ICharacter, public IGameObject
{
public:
explicit Enemy();
~Enemy() = default;

void Update(double delta_time) override;
Expand All @@ -28,11 +30,13 @@ class Enemy : public ICharacter, public IGameObject
vector2d GetPose() const override;
void SetPosition(Position2D position) override;
Position2D GetPosition() const override;
std::string GetId() const override;

private:
void Move(double delta_time);

Position2D position_;
std::string id_;
};

} // namespace wolfenstein
Expand Down
3 changes: 3 additions & 0 deletions src/Characters/include/Characters/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define CHARACTERS_PLAYER_H

#include "character.h"
#include <Utility/uuid_generator.h>
#include <functional>

namespace wolfenstein {
Expand All @@ -31,6 +32,7 @@ class Player : public ICharacter, public IGameObject
vector2d GetPose() const override;
void SetPosition(Position2D position) override;
Position2D GetPosition() const override;
std::string GetId() const override;

void SetCameraPositionUpdator(std::function<void(Position2D)> updator);

Expand All @@ -41,6 +43,7 @@ class Player : public ICharacter, public IGameObject
Position2D position_;
double rotation_speed_;
double translation_speed_;
std::string id_;
std::function<void(Position2D)> camera_position_updator_;
};

Expand Down
8 changes: 8 additions & 0 deletions src/Characters/src/enemy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace wolfenstein {

Enemy::Enemy() {
id_ = UuidGenerator::GetInstance().GenerateUuid().bytes();
}

void Enemy::Update(double delta_time) {
Move(delta_time);
}
Expand All @@ -26,6 +30,10 @@ Position2D Enemy::GetPosition() const {
return position_;
}

std::string Enemy::GetId() const {
return id_;
}

void Enemy::Move(double delta_time) {
(void)delta_time;
// Move enemy
Expand Down
Loading