From 561c07c602a841e61e72226dd6966e28d1103bd1 Mon Sep 17 00:00:00 2001 From: MitchellHansen Date: Sat, 29 Oct 2016 00:42:49 -0700 Subject: [PATCH] Turned off experimental phong lighting in the kernel fixed all compiler errors thrown by MSVC Switched experimental octree map back to the old map Refactored old map system, prettied it up --- include/Camera.h | 4 +- include/Old_map.h | 42 +++ include/Renderer.h | 2 +- include/util.hpp | 6 +- kernels/ray_caster_kernel.cl | 20 +- notes/notes.cpp | 32 ++ src/Camera.cpp | 12 +- src/Map.cpp | 34 +- src/Old_map.cpp | 225 +++++++++++++ src/Ray.cpp | 12 +- src/main.cpp | 592 +++++++++++++++++------------------ 11 files changed, 642 insertions(+), 339 deletions(-) create mode 100644 include/Old_map.h create mode 100644 notes/notes.cpp create mode 100644 src/Old_map.cpp diff --git a/include/Camera.h b/include/Camera.h index e9d6f92..56548a2 100644 --- a/include/Camera.h +++ b/include/Camera.h @@ -31,8 +31,8 @@ public: private: - float friction_coefficient = 0.1; - float default_impulse = 1.0; + float friction_coefficient = 0.1f; + float default_impulse = 1.0f; // 3D vector sf::Vector3f movement; diff --git a/include/Old_map.h b/include/Old_map.h new file mode 100644 index 0000000..bbb9069 --- /dev/null +++ b/include/Old_map.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +#include + +class Old_Map { +public: + + Old_Map(sf::Vector3i dim); + ~Old_Map(); + + void generate_terrain(); + + sf::Vector3i getDimensions(); + char* get_voxel_data(); + +protected: + +private: + + double* height_map; + char *voxel_data; + sf::Vector3i dimensions; + + void set_voxel(sf::Vector3i position, int val); + double sample(int x, int y); + void set_sample(int x, int y, double value); + void sample_square(int x, int y, int size, double value); + void sample_diamond(int x, int y, int size, double value); + void diamond_square(int stepsize, double scale); + + +}; diff --git a/include/Renderer.h b/include/Renderer.h index a81cedb..cda2007 100644 --- a/include/Renderer.h +++ b/include/Renderer.h @@ -36,7 +36,7 @@ public: private: CL_Wrapper *cl; - bool sharing_supported = False; + bool sharing_supported = false; sf::Uint8 *drawing_surface; sf::RenderWindow* window; diff --git a/include/util.hpp b/include/util.hpp index 532ff14..10ff55d 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -64,7 +64,7 @@ public: else { t.setFont(f); t.setCharacterSize(20); - t.setPosition(20, slot * pixel_spacing); + t.setPosition(static_cast(20), static_cast(slot * pixel_spacing)); } } @@ -140,11 +140,11 @@ inline float AngleBetweenVectors(sf::Vector3f a, sf::Vector3f b){ } inline float DegreesToRadians(float in) { - return in * PI / 180.0f; + return static_cast(in * PI / 180.0f); } inline float RadiansToDegrees(float in) { - return in * 180.0f / PI; + return static_cast(in * 180.0f / PI); } inline std::string read_file(std::string file_name){ diff --git a/kernels/ray_caster_kernel.cl b/kernels/ray_caster_kernel.cl index a8f7a91..1309fb5 100644 --- a/kernels/ray_caster_kernel.cl +++ b/kernels/ray_caster_kernel.cl @@ -16,7 +16,13 @@ float4 white_light(float4 input, float3 light, int3 mask) { // 0 1 2 3 4 5 6 7 8 9 // {r, g, b, i, x, y, z, x', y', z'} -float4 cast_light_rays(float3 eye_direction, float3 ray_origin, float4 voxel_color, float3 voxel_normal, global float* lights, global int* light_count) { +float4 cast_light_rays( + float3 eye_direction, + float3 ray_origin, + float4 voxel_color, + float3 voxel_normal, + global float* lights, + global int* light_count) { // set the ray origin to be where the initial ray intersected the voxel // which side z, and the x and y position @@ -183,10 +189,10 @@ __kernel void min_kern( write_imagef(image, pixel, (float4)(.25, .00, .25, 1.00)); return; case 5: - { + //write_imagef(image, pixel, (float4)(.00, .00, + 0.5, 1.00)); - //write_imagef(image, pixel, white_light((float4)(.35, .00, ((1.0 - 0) / (128 - 0) * (voxel.z - 128)) + 1, 0.2), (float3)(lights[7], lights[8], lights[9]), mask)); - + write_imagef(image, pixel, white_light((float4)(.35, .00, ((1.0 - 0) / (128 - 0) * (voxel.z - 128)) + 1, 0.2), (float3)(lights[7], lights[8], lights[9]), mask)); + return; float3 vox = convert_float3(voxel); float3 norm = normalize(convert_float3(mask) * convert_float3(voxel_step)); @@ -204,13 +210,13 @@ __kernel void min_kern( )); return; - } + case 6: write_imagef(image, pixel, (float4)(.30, .80, .10, 1.00)); return; default: - write_imagef(image, pixel, (float4)(.30, .80, .10, 1.00)); - return; + //write_imagef(image, pixel, (float4)(.30, .10, .10, 1.00)); + continue; } } diff --git a/notes/notes.cpp b/notes/notes.cpp new file mode 100644 index 0000000..66c224d --- /dev/null +++ b/notes/notes.cpp @@ -0,0 +1,32 @@ +// TODO + +/* + +OpenCL: + - Add phong lighting / fix the current implementation + - Switch to switch lighting models + - Separate out into a part of the rendering module + +Map: + - Reimplement the old map, put it into an old_map structure + - Implement the new octree structure + - storing the pre-octree volumetric data + - determining when to load volumetric data into the in-memory structure + - building the octree from that raw volumetric data + - combining with other octree nodes to allow streaming of leafs + - passing that data into the renderer + - renderer needs to then traverse the octree + - Terrain generation for real this time + - Loader of 3rd party voxel data + +Renderer: + - Determine when to switch between the cpu and gpu rendering + - call to the map to make sure that the gpu/cpu has an up to date copy + of the volumetric data + + + + + +*/ + diff --git a/src/Camera.cpp b/src/Camera.cpp index f95dc32..55a7379 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -34,22 +34,22 @@ int Camera::add_relative_impulse(DIRECTION impulse_direction, float speed) { switch (impulse_direction) { case DIRECTION::UP: - dir = sf::Vector2f(direction.y, direction.x + PI); + dir = sf::Vector2f(direction.y, direction.x + PI_F); break; case DIRECTION::DOWN: dir = sf::Vector2f(direction.y, direction.x); break; case DIRECTION::LEFT: - dir = sf::Vector2f(direction.y + PI + PI / 2, PI / 2); + dir = sf::Vector2f(direction.y + PI_F + PI_F / 2, PI_F / 2); break; case DIRECTION::RIGHT: - dir = sf::Vector2f(direction.y + PI / 2, PI / 2); + dir = sf::Vector2f(direction.y + PI_F / 2, PI_F / 2); break; case DIRECTION::FORWARD: - dir = sf::Vector2f(direction.y, direction.x + PI / 2); + dir = sf::Vector2f(direction.y, direction.x + PI_F / 2); break; case DIRECTION::REARWARD: - dir = sf::Vector2f(direction.y + PI, (direction.x * -1) + PI / 2 ); + dir = sf::Vector2f(direction.y + PI_F, (direction.x * -1) + PI_F / 2 ); break; } @@ -58,7 +58,7 @@ int Camera::add_relative_impulse(DIRECTION impulse_direction, float speed) { movement *= speed; return 1; -} +} int Camera::slew_camera(sf::Vector2f input) { direction -= input; diff --git a/src/Map.cpp b/src/Map.cpp index 5ab2be8..eb3e8a7 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -27,30 +27,30 @@ struct block { void Map::generate_octree() { - char* arr[8192]; - for (int i = 0; i < 8192; i++) { - arr[i] = 0; - } + char* arr[8192]; + for (int i = 0; i < 8192; i++) { + arr[i] = 0; + } int* dataset = new int[32 * 32 * 32]; for (int i = 0; i < 32 * 32 * 32; i++) { dataset[0] = i; } - int level = log2(32); + int level = static_cast(log2(32)); - leaf top_node; - top_node.level = level; + leaf top_node; + top_node.level = level; - for (int i = 0; i < 16 * 16 * 16; i++){ - for (int i = 0; i < 8 * 8 * 8; i++){ - for (int i = 0; i < 4 * 4 * 4; i++){ - for (int i = 0; i < 2 * 2 * 2; i++){ + for (int i = 0; i < 16 * 16 * 16; i++) { + for (int i = 0; i < 8 * 8 * 8; i++) { + for (int i = 0; i < 4 * 4 * 4; i++) { + for (int i = 0; i < 2 * 2 * 2; i++) { - } - } - } - } + } + } + } + } @@ -67,13 +67,13 @@ void Map::generate_octree() { unsigned int leafmask = 255; unsigned int validmask = leafmask << 8; - + parent &= validmask; parent &= leafmask; std::cout << BitCount(parent & leafmask); - unsigned int children[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + unsigned int children[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; } diff --git a/src/Old_map.cpp b/src/Old_map.cpp new file mode 100644 index 0000000..11898ea --- /dev/null +++ b/src/Old_map.cpp @@ -0,0 +1,225 @@ +#pragma once +#include +#include +#include +#include "util.hpp" +#include + +Old_Map::Old_Map(sf::Vector3i dim) { + dimensions = dim; +} + + +Old_Map::~Old_Map() { +} + +void Old_Map::generate_terrain() { + std::mt19937 gen; + std::uniform_real_distribution dis(-1.0, 1.0); + auto f_rand = std::bind(dis, gen); + + voxel_data = new char[dimensions.x * dimensions.y * dimensions.z]; + height_map = new double[dimensions.x * dimensions.y]; + + for (int i = 0; i < dimensions.x * dimensions.y * dimensions.z; i++) { + voxel_data[i] = 0; + } + + for (int i = 0; i < dimensions.x * dimensions.y; i++) { + height_map[i] = 0; + } + + //size of grid to generate, note this must be a + //value 2^n+1 + int DATA_SIZE = dimensions.x + 1; + //an initial seed value for the corners of the data + double SEED = rand() % 25 + 25; + + //seed the data + set_sample(0, 0, SEED); + set_sample(0, dimensions.y, SEED); + set_sample(dimensions.x, 0, SEED); + set_sample(dimensions.x, dimensions.y, SEED); + + double h = 30.0;//the range (-h -> +h) for the average offset + //for the new value in range of h + //side length is distance of a single square side + //or distance of diagonal in diamond + for (int sideLength = DATA_SIZE - 1; + //side length must be >= 2 so we always have + //a new value (if its 1 we overwrite existing values + //on the last iteration) + sideLength >= 2; + //each iteration we are looking at smaller squares + //diamonds, and we decrease the variation of the offset + sideLength /= 2, h /= 2.0) { + //half the length of the side of a square + //or distance from diamond center to one corner + //(just to make calcs below a little clearer) + int halfSide = sideLength / 2; + + //generate the new square values + for (int x = 0; x < DATA_SIZE - 1; x += sideLength) { + for (int y = 0; y < DATA_SIZE - 1; y += sideLength) { + //x, y is upper left corner of square + //calculate average of existing corners + double avg = sample(x, y) + //top left + sample(x + sideLength, y) +//top right + sample(x, y + sideLength) + //lower left + sample(x + sideLength, y + sideLength);//lower right + avg /= 4.0; + + //center is average plus random offset + set_sample(x + halfSide, y + halfSide, + //We calculate random value in range of 2h + //and then subtract h so the end value is + //in the range (-h, +h) + avg + (f_rand() * 2 * h) - h); + } + } + + //generate the diamond values + //since the diamonds are staggered we only move x + //by half side + //NOTE: if the data shouldn't wrap then x < DATA_SIZE + //to generate the far edge values + for (int x = 0; x < DATA_SIZE - 1; x += halfSide) { + //and y is x offset by half a side, but moved by + //the full side length + //NOTE: if the data shouldn't wrap then y < DATA_SIZE + //to generate the far edge values + for (int y = (x + halfSide) % sideLength; y < DATA_SIZE - 1; y += sideLength) { + //x, y is center of diamond + //note we must use mod and add DATA_SIZE for subtraction + //so that we can wrap around the array to find the corners + double avg = + sample((x - halfSide + DATA_SIZE) % DATA_SIZE, y) + //left of center + sample((x + halfSide) % DATA_SIZE, y) + //right of center + sample(x, (y + halfSide) % DATA_SIZE) + //below center + sample(x, (y - halfSide + DATA_SIZE) % DATA_SIZE); //above center + avg /= 4.0; + + //new value = average plus random offset + //We calculate random value in range of 2h + //and then subtract h so the end value is + //in the range (-h, +h) + avg = avg + (f_rand() * 2 * h) - h; + //update value for center of diamond + set_sample(x, y, avg); + + //wrap values on the edges, remove + //this and adjust loop condition above + //for non-wrapping values. + if (x == 0) set_sample(DATA_SIZE - 1, y, avg); + if (y == 0) set_sample(x, DATA_SIZE - 1, avg); + } + } + } + + + for (int x = 0; x < dimensions.x; x++) { + for (int y = 0; y < dimensions.y; y++) { + + if (height_map[x + y * dimensions.x] > 0) { + + int z = static_cast(height_map[x + y * dimensions.x]); + + while (z > 0) { + voxel_data[x + dimensions.x * (y + dimensions.z * z)] = 5; + z--; + } + } + + } + } + + + for (int x = 0; x < dimensions.x / 10; x++) { + for (int y = 0; y < dimensions.y / 10; y++) { + for (int z = 0; z < dimensions.z; z++) { + if (rand() % 1000 < 1) + voxel_data[x + dimensions.x * (y + dimensions.z * z)] = rand() % 6; + } + } + } + +} + + +void Old_Map::set_voxel(sf::Vector3i position, int val) { + voxel_data[position.x + dimensions.x * (position.y + dimensions.z * position.z)] = val; +} + +sf::Vector3i Old_Map::getDimensions() { + return dimensions; +} + +char* Old_Map::get_voxel_data() { + return voxel_data; +} + +double Old_Map::sample(int x, int y) { + return height_map[(x & (dimensions.x - 1)) + (y & (dimensions.y - 1)) * dimensions.x]; +} + +void Old_Map::set_sample(int x, int y, double value) { + height_map[(x & (dimensions.x - 1)) + (y & (dimensions.y - 1)) * dimensions.x] = value; +} + +void Old_Map::sample_square(int x, int y, int size, double value) { + int hs = size / 2; + + // a b + // + // x + // + // c d + + double a = sample(x - hs, y - hs); + double b = sample(x + hs, y - hs); + double c = sample(x - hs, y + hs); + double d = sample(x + hs, y + hs); + + set_sample(x, y, ((a + b + c + d) / 4.0) + value); + +} + +void Old_Map::sample_diamond(int x, int y, int size, double value) { + int hs = size / 2; + + // c + // + //a x b + // + // d + + double a = sample(x - hs, y); + double b = sample(x + hs, y); + double c = sample(x, y - hs); + double d = sample(x, y + hs); + + set_sample(x, y, ((a + b + c + d) / 4.0) + value); +} + +void Old_Map::diamond_square(int stepsize, double scale) { + + std::mt19937 generator; + std::uniform_real_distribution uniform_distribution(-1.0, 1.0); + auto f_rand = std::bind(uniform_distribution, std::ref(generator)); + + int halfstep = stepsize / 2; + + for (int y = halfstep; y < dimensions.y + halfstep; y += stepsize) { + for (int x = halfstep; x < dimensions.x + halfstep; x += stepsize) { + sample_square(x, y, stepsize, f_rand() * scale); + } + } + + for (int y = 0; y < dimensions.y; y += stepsize) { + for (int x = 0; x < dimensions.x; x += stepsize) { + sample_diamond(x + halfstep, y, stepsize, f_rand() * scale); + sample_diamond(x, y + halfstep, stepsize, f_rand() * scale); + } + } + +} \ No newline at end of file diff --git a/src/Ray.cpp b/src/Ray.cpp index e0894e8..70d62b4 100644 --- a/src/Ray.cpp +++ b/src/Ray.cpp @@ -30,9 +30,9 @@ sf::Color Ray::Cast() { // Setup the voxel coords from the camera origin voxel = sf::Vector3( - floorf(origin.x), - floorf(origin.y), - floorf(origin.z) + static_cast(floorf(origin.x)), + static_cast(floorf(origin.y)), + static_cast(floorf(origin.z)) ); // Delta T is the units a ray must travel along an axis in order to @@ -113,18 +113,18 @@ sf::Color Ray::Cast() { if (face == 0) { alpha = AngleBetweenVectors(sf::Vector3f(1, 0, 0), map->global_light); - alpha = fmod(alpha, 0.785) * 2; + alpha = static_cast(fmod(alpha, 0.785) * 2); } else if (face == 1) { alpha = AngleBetweenVectors(sf::Vector3f(0, 1, 0), map->global_light); - alpha = fmod(alpha, 0.785) * 2; + alpha = static_cast(fmod(alpha, 0.785) * 2); } else if (face == 2){ //alpha = 1.57 / 2; alpha = AngleBetweenVectors(sf::Vector3f(0, 0, 1), map->global_light); - alpha = fmod(alpha, 0.785) * 2; + alpha = static_cast(fmod(alpha, 0.785) * 2); } alpha *= 162; diff --git a/src/main.cpp b/src/main.cpp index 6e3f52c..d1050ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,9 +1,3 @@ -#include -#include -#include -#include -#include - #ifdef linux #include #include @@ -25,7 +19,14 @@ #include #endif -#include "Map.h" + +#include +#include +#include +#include +#include + +#include "Old_Map.h" #include "Curses.h" #include "util.hpp" #include "RayCaster.h" @@ -52,7 +53,7 @@ float elap_time(){ std::chrono::time_point now = std::chrono::system_clock::now(); std::chrono::duration elapsed_time = now - start; - return elapsed_time.count(); + return static_cast(elapsed_time.count()); } sf::Sprite window_sprite; @@ -64,299 +65,296 @@ sf::Texture window_texture; int main() { + sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "SFML"); + CL_Wrapper c; - //Map m(sf::Vector3i (50, 50, 50)); - //m.generate_octree(); - return 1; - - //sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "SFML"); - - //if (c.compile_kernel("../kernels/ray_caster_kernel.cl", true, "min_kern") < 0) { - // std::cin.get(); - // return -1; - //} - // - //std::cout << "map..."; - // sf::Vector3i map_dim(MAP_X, MAP_Y, MAP_Z); - // Map* map = new Map(map_dim); - // - //c.create_buffer("map_buffer", sizeof(char) * map_dim.x * map_dim.y * map_dim.z, map->list); - //c.create_buffer("dim_buffer", sizeof(int) * 3, &map_dim); - - //sf::Vector2i view_res(WINDOW_X, WINDOW_Y); - //c.create_buffer("res_buffer", sizeof(int) * 2, &view_res); - // - - // double y_increment_radians = DegreesToRadians(50.0 / view_res.y); - // double x_increment_radians = DegreesToRadians(80.0 / view_res.x); - - //std::cout << "view matrix..."; - // - //sf::Vector4f* view_matrix = new sf::Vector4f[WINDOW_X * WINDOW_Y * 4]; - - // for (int y = -view_res.y / 2; y < view_res.y / 2; y++) { - // for (int x = -view_res.x / 2; x < view_res.x / 2; x++) { - - // // 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 + view_res.x / 2) + view_res.x * (y + view_res.y / 2); - // ray = Normalize(ray); - - // view_matrix[index] = sf::Vector4f( - // ray.x, - // ray.y, - // ray.z, - // 0 - // ); - // } - // } - - //c.create_buffer("view_matrix_buffer", sizeof(float) * 4 * view_res.x * view_res.y, view_matrix); - - //Camera camera( - // sf::Vector3f(70, 60, 50), - // sf::Vector2f(0.0f, 1.00f) - //); - // - //c.create_buffer("cam_dir_buffer", sizeof(float) * 4, (void*)camera.get_direction_pointer(), CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR); - //c.create_buffer("cam_pos_buffer", sizeof(float) * 4, (void*)camera.get_position_pointer(), CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR); - // - //int light_count = 2; - //c.create_buffer("light_count_buffer", sizeof(int), &light_count); - - //// {r, g, b, i, x, y, z, x', y', z'} - //sf::Vector3f v = Normalize(sf::Vector3f(1.0, 0.0, 0.0)); - //sf::Vector3f v2 = Normalize(sf::Vector3f(1.1, 0.4, 0.7)); - //float light[] = { 0.4, 0.8, 0.1, 1, 50, 50, 50, v.x, v.y, v.z, - // 0.4, 0.8, 0.1, 1, 50, 50, 50, v2.x, v2.y, v2.z}; - //c.create_buffer("light_buffer", sizeof(float) * 10 * light_count, light, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR); - - //// The drawing canvas - // unsigned char* pixel_array = new sf::Uint8[WINDOW_X * WINDOW_Y * 4]; - - // for (int i = 0; i < WINDOW_X * WINDOW_Y * 4; i += 4) { - - // pixel_array[i] = 255; // R? - // pixel_array[i + 1] = 255; // G? - // pixel_array[i + 2] = 255; // B? - // pixel_array[i + 3] = 100; // A? - // } - - //sf::Texture t; - // t.create(WINDOW_X, WINDOW_Y); - // t.update(pixel_array); - - // int error; - // cl_mem image_buff = clCreateFromGLTexture( - // c.getContext(), CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, - // 0, t.getNativeHandle(), &error); - - // if (c.assert(error, "clCreateFromGLTexture")) - // return -1; - - // c.store_buffer(image_buff, "image_buffer"); - - // c.set_kernel_arg("min_kern", 0, "map_buffer"); - // c.set_kernel_arg("min_kern", 1, "dim_buffer"); - // c.set_kernel_arg("min_kern", 2, "res_buffer"); - // c.set_kernel_arg("min_kern", 3, "view_matrix_buffer"); - // c.set_kernel_arg("min_kern", 4, "cam_dir_buffer"); - // c.set_kernel_arg("min_kern", 5, "cam_pos_buffer"); - //c.set_kernel_arg("min_kern", 6, "light_buffer"); - //c.set_kernel_arg("min_kern", 7, "light_count_buffer"); - //c.set_kernel_arg("min_kern", 8, "image_buffer"); - - //sf::Sprite s; - //s.setTexture(t); - //s.setPosition(0, 0); - - // // The step size in milliseconds between calls to Update() - // // Lets set it to 16.6 milliseonds (60FPS) - // float step_size = 0.0166f; - - // // Timekeeping values for the loop - // double frame_time = 0.0, - // elapsed_time = 0.0, - // delta_time = 0.0, - // accumulator_time = 0.0, - // current_time = 0.0; - - // fps_counter fps; - - //// ============================= RAYCASTER SETUP ================================== - - //// Setup the sprite and texture - //window_texture.create(WINDOW_X, WINDOW_Y); - //window_sprite.setPosition(0, 0); - - //// State values - - //sf::Vector3f cam_vec(0, 0, 0); + if (c.compile_kernel("../kernels/ray_caster_kernel.cl", true, "min_kern") < 0) { + std::cin.get(); + return -1; + } + + std::cout << "map..."; + sf::Vector3i map_dim(MAP_X, MAP_Y, MAP_Z); + Old_Map* map = new Old_Map(map_dim); + map->generate_terrain(); + + c.create_buffer("map_buffer", sizeof(char) * map_dim.x * map_dim.y * map_dim.z, map->get_voxel_data()); + c.create_buffer("dim_buffer", sizeof(int) * 3, &map_dim); + + sf::Vector2i view_res(WINDOW_X, WINDOW_Y); + c.create_buffer("res_buffer", sizeof(int) * 2, &view_res); + + + double y_increment_radians = DegreesToRadians(50.0f / view_res.y); + double x_increment_radians = DegreesToRadians(80.0f / view_res.x); + + std::cout << "view matrix..."; + + sf::Vector4f* view_matrix = new sf::Vector4f[WINDOW_X * WINDOW_Y * 4]; + + for (int y = -view_res.y / 2; y < view_res.y / 2; y++) { + for (int x = -view_res.x / 2; x < view_res.x / 2; x++) { + + // The base ray direction to slew from + sf::Vector3f ray(1, 0, 0); + + // Y axis, pitch + ray = sf::Vector3f( + static_cast(ray.z * sin(y_increment_radians * y) + ray.x * cos(y_increment_radians * y)), + static_cast(ray.y), + static_cast(ray.z * cos(y_increment_radians * y) - ray.x * sin(y_increment_radians * y)) + ); + + + // Z axis, yaw + ray = sf::Vector3f( + static_cast(ray.x * cos(x_increment_radians * x) - ray.y * sin(x_increment_radians * x)), + static_cast(ray.x * sin(x_increment_radians * x) + ray.y * cos(x_increment_radians * x)), + static_cast(ray.z) + ); + + int index = (x + view_res.x / 2) + view_res.x * (y + view_res.y / 2); + ray = Normalize(ray); + + view_matrix[index] = sf::Vector4f( + ray.x, + ray.y, + ray.z, + 0 + ); + } + } + + c.create_buffer("view_matrix_buffer", sizeof(float) * 4 * view_res.x * view_res.y, view_matrix); + + Camera camera( + sf::Vector3f(70, 60, 50), + sf::Vector2f(0.0f, 1.00f) + ); + + c.create_buffer("cam_dir_buffer", sizeof(float) * 4, (void*)camera.get_direction_pointer(), CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR); + c.create_buffer("cam_pos_buffer", sizeof(float) * 4, (void*)camera.get_position_pointer(), CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR); + + int light_count = 2; + c.create_buffer("light_count_buffer", sizeof(int), &light_count); + + // {r, g, b, i, x, y, z, x', y', z'} + sf::Vector3f v = Normalize(sf::Vector3f(1.0f, 0.0f, 0.0f)); + sf::Vector3f v2 = Normalize(sf::Vector3f(1.1f, 0.4f, 0.7f)); + float light[] = { 0.4f, 0.8f, 0.1f, 1.0f, 50.0f, 50.0f, 50.0f, v.x, v.y, v.z, + 0.4f, 0.8f, 0.1f, 1.0f, 50.0f, 50.0f, 50.0f, v2.x, v2.y, v2.z}; + c.create_buffer("light_buffer", sizeof(float) * 10 * light_count, light, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR); + + // The drawing canvas + unsigned char* pixel_array = new sf::Uint8[WINDOW_X * WINDOW_Y * 4]; + + for (int i = 0; i < WINDOW_X * WINDOW_Y * 4; i += 4) { + + pixel_array[i] = 255; // R? + pixel_array[i + 1] = 255; // G? + pixel_array[i + 2] = 255; // B? + pixel_array[i + 3] = 100; // A? + } + + sf::Texture t; + t.create(WINDOW_X, WINDOW_Y); + t.update(pixel_array); + + int error; + cl_mem image_buff = clCreateFromGLTexture( + c.getContext(), CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, + 0, t.getNativeHandle(), &error); + + if (c.assert(error, "clCreateFromGLTexture")) + return -1; + + c.store_buffer(image_buff, "image_buffer"); + + c.set_kernel_arg("min_kern", 0, "map_buffer"); + c.set_kernel_arg("min_kern", 1, "dim_buffer"); + c.set_kernel_arg("min_kern", 2, "res_buffer"); + c.set_kernel_arg("min_kern", 3, "view_matrix_buffer"); + c.set_kernel_arg("min_kern", 4, "cam_dir_buffer"); + c.set_kernel_arg("min_kern", 5, "cam_pos_buffer"); + c.set_kernel_arg("min_kern", 6, "light_buffer"); + c.set_kernel_arg("min_kern", 7, "light_count_buffer"); + c.set_kernel_arg("min_kern", 8, "image_buffer"); + + sf::Sprite s; + s.setTexture(t); + s.setPosition(0, 0); + + // The step size in milliseconds between calls to Update() + // Lets set it to 16.6 milliseonds (60FPS) + float step_size = 0.0166f; + + // Timekeeping values for the loop + double frame_time = 0.0, + elapsed_time = 0.0, + delta_time = 0.0, + accumulator_time = 0.0, + current_time = 0.0; + + fps_counter fps; + + // ============================= RAYCASTER SETUP ================================== + + // Setup the sprite and texture + window_texture.create(WINDOW_X, WINDOW_Y); + window_sprite.setPosition(0, 0); + + // State values + + sf::Vector3f cam_vec(0, 0, 0); //RayCaster ray_caster(map, map_dim, view_res); - //sf::Vector2f *dp = camera.get_direction_pointer(); - //debug_text cam_text_x(1, 30, &dp->x, "X: "); - //debug_text cam_text_y(2, 30, &dp->y, "Y: "); - - //sf::Vector3f *mp = camera.get_movement_pointer(); - //debug_text cam_text_mov_x(4, 30, &mp->x, "X: "); - //debug_text cam_text_mov_y(5, 30, &mp->y, "Y: "); - //debug_text cam_text_mov_z(6, 30, &mp->y, "Z: "); - ////debug_text cam_text_z(3, 30, &p->z); - - //debug_text light_x(7, 30, &light[7], "X: "); - //debug_text light_y(8, 30, &light[8], "Y: "); - //debug_text light_z(9, 30, &light[9], "Z: "); - //// =============================================================================== - - //// Mouse capture - //sf::Vector2i deltas; - //sf::Vector2i fixed(window.getSize()); - //bool mouse_enabled = true; - - //sf::Vector3f cam_mov_vec; - - //while (window.isOpen()) { - - // // Poll for events from the user - // sf::Event event; - // while (window.pollEvent(event)) { - - // // If the user tries to exit the application via the GUI - // if (event.type == sf::Event::Closed) - // window.close(); - // if (event.type == sf::Event::KeyPressed) { - // if (event.key.code == sf::Keyboard::Space) { - // if (mouse_enabled) - // mouse_enabled = false; - // else - // mouse_enabled = true; - // } - // } - // } - - // cam_vec.x = 0; - // cam_vec.y = 0; - // cam_vec.z = 0; - - // float speed = 1.0f; - - // if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)) { - // speed = 0.2f; - // } - // if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) { - // camera.add_relative_impulse(Camera::DIRECTION::DOWN, speed); - // } - // if (sf::Keyboard::isKeyPressed(sf::Keyboard::E)) { - // camera.add_relative_impulse(Camera::DIRECTION::UP, speed); - // } - // if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) { - // camera.add_relative_impulse(Camera::DIRECTION::FORWARD, speed); - // } - // if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { - // camera.add_relative_impulse(Camera::DIRECTION::REARWARD, speed); - // } - // if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) { - // camera.add_relative_impulse(Camera::DIRECTION::LEFT, speed); - // } - // if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { - // camera.add_relative_impulse(Camera::DIRECTION::RIGHT, speed); - // } - // if (sf::Keyboard::isKeyPressed(sf::Keyboard::T)) { - // camera.set_position(sf::Vector3f(50, 50, 50)); - // } - - // camera.add_static_impulse(cam_vec); - - // if (mouse_enabled) { - // deltas = fixed - sf::Mouse::getPosition(); - // if (deltas != sf::Vector2i(0, 0) && mouse_enabled == true) { - - // // Mouse movement - // sf::Mouse::setPosition(fixed); - // camera.slew_camera(sf::Vector2f( - // deltas.y / 300.0f, - // deltas.x / 300.0f - // )); - // } - // } - - // // Time keeping - // elapsed_time = elap_time(); - // delta_time = elapsed_time - current_time; - // current_time = elapsed_time; - // if (delta_time > 0.2f) - // delta_time = 0.2f; - // accumulator_time += delta_time; - // while ((accumulator_time - step_size) >= step_size) { - // accumulator_time -= step_size; - - // // ==== DELTA TIME LOCKED ==== - // } - - // float l[] = { - // light[9] * sin(delta_time / 1) + light[7] * cos(delta_time / 1), - // light[8], - // light[9] * cos(delta_time / 1) - light[7] * sin(delta_time / 1) - // }; - - // float l2[] = { - // l[0] * cos(delta_time) - l[2] * sin(delta_time), - // l[0] * sin(delta_time) + l[2] * cos(delta_time), - // l[2] - // }; - - // light[7] = l[0]; - // light[8] = l[1]; - // light[9] = l[2]; - - // // ==== FPS LOCKED ==== - // camera.update(delta_time); - - // // Run the raycast - // c.run_kernel("min_kern", WORK_SIZE); - // - // // ==== RENDER ==== - - // window.clear(sf::Color::Black); - - // window.draw(s); - - // // Give the frame counter the frame time and draw the average frame time - // fps.frame(delta_time); - // fps.draw(&window); - - // cam_text_x.draw(&window); - // cam_text_y.draw(&window); - - // cam_text_mov_x.draw(&window); - // cam_text_mov_y.draw(&window); - // cam_text_mov_z.draw(&window); - - // light_x.draw(&window); - // light_y.draw(&window); - // light_z.draw(&window); - // - // window.display(); - - //} + sf::Vector2f *dp = camera.get_direction_pointer(); + debug_text cam_text_x(1, 30, &dp->x, "X: "); + debug_text cam_text_y(2, 30, &dp->y, "Y: "); + + sf::Vector3f *mp = camera.get_movement_pointer(); + debug_text cam_text_mov_x(4, 30, &mp->x, "X: "); + debug_text cam_text_mov_y(5, 30, &mp->y, "Y: "); + debug_text cam_text_mov_z(6, 30, &mp->y, "Z: "); + //debug_text cam_text_z(3, 30, &p->z); + + debug_text light_x(7, 30, &light[7], "X: "); + debug_text light_y(8, 30, &light[8], "Y: "); + debug_text light_z(9, 30, &light[9], "Z: "); + // =============================================================================== + + // Mouse capture + sf::Vector2i deltas; + sf::Vector2i fixed(window.getSize()); + bool mouse_enabled = true; + + sf::Vector3f cam_mov_vec; + + while (window.isOpen()) { + + // Poll for events from the user + sf::Event event; + while (window.pollEvent(event)) { + + // If the user tries to exit the application via the GUI + if (event.type == sf::Event::Closed) + window.close(); + if (event.type == sf::Event::KeyPressed) { + if (event.key.code == sf::Keyboard::Space) { + if (mouse_enabled) + mouse_enabled = false; + else + mouse_enabled = true; + } + } + } + + cam_vec.x = 0; + cam_vec.y = 0; + cam_vec.z = 0; + + float speed = 1.0f; + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)) { + speed = 0.2f; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) { + camera.add_relative_impulse(Camera::DIRECTION::DOWN, speed); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::E)) { + camera.add_relative_impulse(Camera::DIRECTION::UP, speed); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) { + camera.add_relative_impulse(Camera::DIRECTION::FORWARD, speed); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { + camera.add_relative_impulse(Camera::DIRECTION::REARWARD, speed); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) { + camera.add_relative_impulse(Camera::DIRECTION::LEFT, speed); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { + camera.add_relative_impulse(Camera::DIRECTION::RIGHT, speed); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::T)) { + camera.set_position(sf::Vector3f(50, 50, 50)); + } + + camera.add_static_impulse(cam_vec); + + if (mouse_enabled) { + deltas = fixed - sf::Mouse::getPosition(); + if (deltas != sf::Vector2i(0, 0) && mouse_enabled == true) { + + // Mouse movement + sf::Mouse::setPosition(fixed); + camera.slew_camera(sf::Vector2f( + deltas.y / 300.0f, + deltas.x / 300.0f + )); + } + } + + // Time keeping + elapsed_time = elap_time(); + delta_time = elapsed_time - current_time; + current_time = elapsed_time; + if (delta_time > 0.2f) + delta_time = 0.2f; + accumulator_time += delta_time; + while ((accumulator_time - step_size) >= step_size) { + accumulator_time -= step_size; + + // ==== DELTA TIME LOCKED ==== + } + + float l[] = { + static_cast(light[9] * sin(delta_time / 1) + light[7] * cos(delta_time / 1)), + static_cast(light[8]), + static_cast(light[9] * cos(delta_time / 1) - light[7] * sin(delta_time / 1)) + }; + + float l2[] = { + static_cast(l[0] * cos(delta_time) - l[2] * sin(delta_time)), + static_cast(l[0] * sin(delta_time) + l[2] * cos(delta_time)), + static_cast(l[2]) + }; + + light[7] = l[0]; + light[8] = l[1]; + light[9] = l[2]; + + // ==== FPS LOCKED ==== + camera.update(delta_time); + + // Run the raycast + c.run_kernel("min_kern", WORK_SIZE); + + // ==== RENDER ==== + + window.clear(sf::Color::Black); + + window.draw(s); + + // Give the frame counter the frame time and draw the average frame time + fps.frame(delta_time); + fps.draw(&window); + + cam_text_x.draw(&window); + cam_text_y.draw(&window); + + cam_text_mov_x.draw(&window); + cam_text_mov_y.draw(&window); + cam_text_mov_z.draw(&window); + + light_x.draw(&window); + light_y.draw(&window); + light_z.draw(&window); + + window.display(); + + } return 0; }