From 3492cfa63dbd406875c792eb7a90002f1e104f53 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Sun, 4 Feb 2024 21:04:07 +0000 Subject: [PATCH 1/2] World: Add projection correction factor Rays are all sent from the center of the camera plane, which makes rays with a greater angle longer than if they were properly sent perpendicularly from the camera plane. Correct this by projecting the ray to the look direction (which is perpendicular to the camera plane). --- World.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/World.cpp b/World.cpp index a7f7bf1..8f37c24 100644 --- a/World.cpp +++ b/World.cpp @@ -267,7 +267,10 @@ void World::render(sf::RenderWindow& window) } else if (rayAngle > 360) { rayAngle -= 360; } - float obstacleScale = worldToCamera / castRay(player.x, player.y, rayAngle); + float obstacleScale = worldToCamera / ( + castRay(player.x, player.y, rayAngle) * + cosf(deltaAngle*deg_to_rad) + ); /* 2 Is wall height in meters. */ fillColumn(window, i, obstacleScale); } From 9678e8c286e9cea11de67cf7ea70391a39af14f9 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Mon, 5 Feb 2024 00:33:01 +0000 Subject: [PATCH 2/2] World: Introduce a struct for raycast results In order to implement more complexe behaviors, more information than the distance is needed from a raycast. Add a new struct to store and return this information, currently hit position and hit type, and update castRay to return that instead. --- World.cpp | 20 +++++++++++++++++--- World.h | 12 ++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/World.cpp b/World.cpp index 8f37c24..d23aa1f 100644 --- a/World.cpp +++ b/World.cpp @@ -99,7 +99,7 @@ std::ostream& operator<<(std::ostream& ostream, World const& world) return(ostream); } -float World::castRay(float originX, float originY, float orientation) const +RaycastResult World::castRay(float originX, float originY, float orientation) const { /* * Reference used for ray intersection computations : @@ -214,7 +214,21 @@ float World::castRay(float originX, float originY, float orientation) const float vDist = sqrtf((originX - vCheckX)*(originX - vCheckX) + (originY - vCheckY)*(originY - vCheckY)); - return hDist > vDist ? vDist : hDist; + + RaycastResult result{}; + if (hDist > vDist) { + result.distance = vDist; + result.hitX = vCheckX; + result.hitY = vCheckY; + } else { + result.distance = hDist; + result.hitX = hCheckX; + result.hitY = hCheckY; + } + result.hitBlock = getBlock(floorf(result.hitX) + vRound, + floorf(result.hitY)); + + return result; } void World::fillColumn(sf::RenderWindow& window, unsigned int column, @@ -268,7 +282,7 @@ void World::render(sf::RenderWindow& window) rayAngle -= 360; } float obstacleScale = worldToCamera / ( - castRay(player.x, player.y, rayAngle) * + castRay(player.x, player.y, rayAngle).distance * cosf(deltaAngle*deg_to_rad) ); /* 2 Is wall height in meters. */ diff --git a/World.h b/World.h index 7b24d70..5e3a7e2 100644 --- a/World.h +++ b/World.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "Color.h" #include "Player.h" @@ -20,6 +21,13 @@ enum class BlockType { WINDOW, }; +struct RaycastResult { + float distance; + float hitX; + float hitY; + BlockType hitBlock; +}; + class World { public: Player player; @@ -61,9 +69,9 @@ private: * @param originX Ray X origin, strictly positive * @param originY Ray Y origin, strictly positive * @param orientation Angle to cast to, in degrees between 0 and 360 - * @return Distance of the hit to the origin. + * @return Result struct containing information on the hit. */ - float castRay(float originX, float originY, float orientation) const; + RaycastResult castRay(float originX, float originY, float orientation) const; };