From 14987e3ba778e77030e48edd15c5fcf984f7a8c7 Mon Sep 17 00:00:00 2001 From: mitchellhansen Date: Wed, 3 Aug 2016 22:29:31 -0700 Subject: [PATCH] There we go! The raycaster now has a camera that renders without distortion and can be pitched, yawed, and moved on the XYZ axis. I'm not sure now if I want to: Add lighting, improve performance, or start working on porting it to OpenCL --- include/Map.h | 2 +- include/RayCaster.h | 2 +- src/Ray.cpp | 21 +++++++++++---------- src/RayCaster.cpp | 36 ++++++++++++++++++++++++++++++------ src/main.cpp | 6 +++--- 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/include/Map.h b/include/Map.h index 3f78a52..6034a50 100644 --- a/include/Map.h +++ b/include/Map.h @@ -10,7 +10,7 @@ public: list[i] = 0; } - for (int i = 50; i < 52; i++) { + for (int i = 51; i < 52; i++) { list[55 + dim.x * (55 + dim.z * i)] = 1; } diff --git a/include/RayCaster.h b/include/RayCaster.h index a938ab0..9d022a7 100644 --- a/include/RayCaster.h +++ b/include/RayCaster.h @@ -37,7 +37,7 @@ private: sf::Vector3 camera_position; // The distance in units the view plane is from the iris point - int view_plane_distance = 300; + int view_plane_distance = 200; // Precalculated values for the view plane rays sf::Vector3f *view_plane_vectors; diff --git a/src/Ray.cpp b/src/Ray.cpp index d6c1231..69a0384 100644 --- a/src/Ray.cpp +++ b/src/Ray.cpp @@ -38,17 +38,17 @@ sf::Color Ray::Cast() { // Delta T is the units a ray must travel along an axis in order to // traverse an integer split delta_t = sf::Vector3( - fabsf(1.0f / direction.x), - fabsf(1.0f / direction.y), - fabsf(1.0f / direction.z) + fabsf(1.0f / direction.x), + fabsf(1.0f / direction.y), + fabsf(1.0f / direction.z) ); // Intersection T is the collection of the next intersection points // for all 3 axis XYZ. intersection_t = sf::Vector3( - delta_t.x + origin.x, - delta_t.y + origin.y, - delta_t.z + origin.z + delta_t.x, + delta_t.y, + delta_t.z ); int dist = 0; @@ -99,7 +99,8 @@ sf::Color Ray::Cast() { } // If we hit a voxel - switch (map->list[voxel.x + dimensions.x * (voxel.y + dimensions.z * voxel.z)]) { + int index = voxel.x + dimensions.x * (voxel.y + dimensions.z * voxel.z); + switch (map->list[index]) { case 1: return sf::Color::Red; case 2: @@ -107,11 +108,11 @@ sf::Color Ray::Cast() { case 3: return sf::Color::Yellow; case 4: - return sf::Color(40, 230, 96, 200); + return sf::Color(80, 0, 150, 255); case 5: - return sf::Color(80, 120, 96, 100); + return sf::Color(255, 120, 255, 255); case 6: - return sf::Color(150, 80, 220, 200); + return sf::Color(150, 80, 220, 255); } dist++; diff --git a/src/RayCaster.cpp b/src/RayCaster.cpp index fed5948..ec3b40a 100644 --- a/src/RayCaster.cpp +++ b/src/RayCaster.cpp @@ -20,23 +20,48 @@ RayCaster::RayCaster( resolution = viewport_resolution; image = new sf::Color[resolution.x * resolution.y]; + // Calculate the view plane vectors + // Because casting to individual pixels causes barrel distortion, + // Get the radian increments + // Set the camera origin + // Rotate the ray by the specified pixel * increment + + double y_increment_radians = DegreesToRadians(50.0 / resolution.y); + double x_increment_radians = DegreesToRadians(80.0 / resolution.x); + view_plane_vectors = new sf::Vector3f[resolution.x * resolution.y]; for (int y = -resolution.y / 2 ; y < resolution.y / 2; y++) { for (int x = -resolution.x / 2; x < resolution.x / 2; x++) { - view_plane_vectors[(x + resolution.x / 2) + resolution.x * (y + resolution.y / 2)] = Normalize(sf::Vector3f(view_plane_distance, x, y)); + + // The base ray direction to slew from + sf::Vector3f ray(1, 0, 0); + + // Y axis, pitch + ray = sf::Vector3f( + ray.z * sin(y_increment_radians * y) + ray.x * cos(y_increment_radians * y), + ray.y, + ray.z * cos(y_increment_radians * y) - ray.x * sin(y_increment_radians * y) + ); + + // Z axis, yaw + ray = sf::Vector3f( + ray.x * cos(x_increment_radians * x) - ray.y * sin(x_increment_radians * x), + ray.x * sin(x_increment_radians * x) + ray.y * cos(x_increment_radians * x), + ray.z + ); + + int index = (x + resolution.x / 2) + resolution.x * (y + resolution.y / 2); + view_plane_vectors[index] = Normalize(ray); } } } - RayCaster::~RayCaster() { delete image; delete view_plane_vectors; } - - sf::Color* RayCaster::CastRays(sf::Vector3 camera_direction, sf::Vector3 camera_position) { // Setup the camera for this cast @@ -44,7 +69,6 @@ sf::Color* RayCaster::CastRays(sf::Vector3 camera_direction, sf::Vector3< camera_direction_cartesian = Normalize(SphereToCart(camera_direction)); this->camera_position = camera_position; - // Start the loop at the top left, scan right and work down for (int y = 0; y < resolution.y; y++) { for (int x = 0; x < resolution.x; x++) { @@ -73,7 +97,7 @@ sf::Color* RayCaster::CastRays(sf::Vector3 camera_direction, sf::Vector3< Ray r(map, resolution, sf::Vector2i(x, y), camera_position, ray); // Cast it and assign its return value - image[x + resolution.x*y] = r.Cast(); + image[x + resolution.x * y] = r.Cast(); } } diff --git a/src/main.cpp b/src/main.cpp index 7199334..cb63a86 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,8 +6,8 @@ #include "RayCaster.h" #include -const int WINDOW_X = 400; -const int WINDOW_Y = 400; +const int WINDOW_X = 600; +const int WINDOW_Y = 600; float elap_time(){ @@ -52,7 +52,7 @@ int main() { window_sprite.setPosition(0, 0); // State values - sf::Vector3i map_dim(100, 100, 100); + sf::Vector3i map_dim(200, 200, 200); sf::Vector2i view_res(WINDOW_X, WINDOW_Y); sf::Vector3f cam_dir(1.0f, 0.0f, 1.57f); sf::Vector3f cam_pos(50, 50, 50);