Skip to content

Commit

Permalink
Update camera object ray calculation, use only right and left edge an…
Browse files Browse the repository at this point in the history
…gles
  • Loading branch information
bilalkah committed Aug 15, 2024
1 parent c1796aa commit 6f4a040
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 93 deletions.
4 changes: 4 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 @@ -46,4 +49,5 @@ target_link_libraries(
vector
map
scene
texture_manager
)
11 changes: 9 additions & 2 deletions src/Camera/include/Camera/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#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 @@ -30,6 +33,8 @@ struct Camera2DConfig
double depth;
};

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

class Camera2D
{
public:
Expand All @@ -39,19 +44,21 @@ class Camera2D
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
126 changes: 91 additions & 35 deletions src/Camera/src/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,21 @@
*/

#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,
Expand All @@ -27,12 +37,25 @@ void Camera2D::Update(const std::shared_ptr<Scene>& scene) {
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 @@ -52,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
1 change: 0 additions & 1 deletion src/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ target_link_libraries(
game_object
map
vector
utilities
renderer
SDL2
)
4 changes: 2 additions & 2 deletions src/Core/src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void Game::Init() {
config_.view_distance};
camera_ = std::make_shared<Camera2D>(camera_config);

CharacterConfig player_config = {Position2D({3, 1.5}, 1.50), 2.0, 5.5};
CharacterConfig player_config = {Position2D({3, 1.5}, 1.50), 2.0, 0.4};
player_ = std::make_shared<Player>(player_config);

auto camera_position_updator = [this](Position2D position) {
Expand All @@ -48,7 +48,7 @@ void Game::Init() {
const auto candlebra =
std::make_shared<StaticObject>(vector2d(3.5, 1.5), 6, 0.2, 0.2);
const auto candlebra1 =
std::make_shared<StaticObject>(vector2d(12.5, 9.5), 8, 0.2, 0.2);
std::make_shared<StaticObject>(vector2d(12.5, 9.5), 8, 0.4, 0.8);
const auto candlebra2 =
std::make_shared<StaticObject>(vector2d(3.5, 7.5), 6, 0.2, 0.2);

Expand Down
2 changes: 1 addition & 1 deletion src/Graphics/include/Graphics/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class Renderer
void RenderObjects(const std::vector<std::shared_ptr<IGameObject>>& objects,
const std::shared_ptr<Camera2D>& camera_ptr,
RenderQueue& render_queue);
int CalculateHorizontalSlice(const Ray& ray,
int CalculateHorizontalSlice(const double& angle,
const std::shared_ptr<Camera2D> camera_ptr);
std::tuple<int, int, int> CalculateVerticalSlice(const double& distance);
void RenderTextures(RenderQueue& render_queue);
Expand Down
Loading

0 comments on commit 6f4a040

Please sign in to comment.