diff --git a/include/ConfigDB.h b/include/ConfigDB.h index d7ab811..c43729a 100644 --- a/include/ConfigDB.h +++ b/include/ConfigDB.h @@ -11,8 +11,6 @@ public: bool init(std::string root_config_path); - - private: diff --git a/include/Hardware_Caster.h b/include/Hardware_Caster.h index 8fa39d4..25bd71a 100644 --- a/include/Hardware_Caster.h +++ b/include/Hardware_Caster.h @@ -153,7 +153,7 @@ public: // Queries hardware, creates the command queue and context, and compiles kernel - int init(); + bool init(); // Creates a texture to send to the GPU via height and width // Creates a viewport vector array via vertical and horizontal fov @@ -164,12 +164,13 @@ public: bool assign_lights(std::vector *data) ; // We take a ptr to the map and create the map, and map_dimensions buffer for the GPU - bool assign_map(Old_Map *map) ; + bool assign_map(std::shared_ptr map); + bool release_map(); // We take a ptr to the camera and create a camera direction and position buffer - bool assign_camera(Camera *camera) ; + bool assign_camera(std::shared_ptr camera); + bool release_camera(); - // TODO: Hoist this to the base class // Creates 3 buffers relating to the texture atlas: texture_atlas, atlas_dim, and tile_dim // With these on the GPU we can texture any quad with an atlas tile bool create_texture_atlas(sf::Texture *t, sf::Vector2i tile_dim); @@ -183,7 +184,10 @@ public: // Take the viewport sprite and draw it to the screen void draw(sf::RenderWindow* window) ; + // Load the saved device config from a file bool load_config(); + + // Save the chosen device config to a file void save_config(); // ================================== DEBUG ======================================= @@ -196,17 +200,14 @@ public: private: - // Iterate the devices available and choose the best one - // Also checks for the sharing extension - int acquire_platform_and_device(); + // Cycle through the OpenCL devices and store *all* of their data, not super useful + bool query_hardware(); + // Cycle through the OpenCL devices and store only the minimal amount of data that we need bool aquire_hardware(); - bool query_hardware(); - - // With respect to the individual platforms implementation of sharing - // create a shared cl_gl context - int create_shared_context(); + // Create a shared cl_gl context with respect to the individual platforms implementation of sharing + bool create_shared_context(); // Using the context and the device create a command queue for them bool create_command_queue(); @@ -241,18 +242,23 @@ private: // Run a test kernel that prints out the kernel args void print_kernel_arguments(); - // CL error code handler. ImGui overlaps the assert() function annoyingly so I had to rename it + // Cl can return 0 or 1 for success, greater or lower for fail. Return true or false based on that requirement static bool cl_assert(int error_code); + + // Take an integer error code and return the string of the related CL ENUM static std::string cl_err_lookup(int error_code); - //static bool vr_assert(int error_code) + // Setters and getters cl_device_id getDeviceID(); cl_platform_id getPlatformID(); cl_context getContext(); cl_kernel getKernel(std::string kernel_name); cl_command_queue getCommandQueue(); - // Our device data + // List of queried devices + std::vector device_list; + + // Our picked device data cl_platform_id platform_id; cl_device_id device_id; @@ -265,21 +271,22 @@ private: std::map buffer_map; std::unordered_map>> image_map; + // Hardware caster holds and renders its own textures sf::Sprite viewport_sprite; sf::Texture viewport_texture; - Old_Map * map = nullptr; - Camera *camera = nullptr; - // std::vector *lights; - std::vector *lights; - int light_count = 0; sf::Uint8 *viewport_image = nullptr; sf::Vector4f *viewport_matrix = nullptr; sf::Vector2i viewport_resolution; - int error = 0; + std::shared_ptr camera; + std::shared_ptr map; - std::vector device_list; + std::vector *lights; + int light_count = 0; + + + int error = 0; }; diff --git a/include/Input.h b/include/Input.h index e7d4de3..4db76d9 100644 --- a/include/Input.h +++ b/include/Input.h @@ -44,6 +44,14 @@ public: virtual void recieve_event(VrEventPublisher* publisher, std::unique_ptr(event)) override { if (event.get()->type == vr::Event::Closed) { window_ref->close(); + + } else if (event.get()->type == vr::Event::KeyPressed) { + + vr::KeyPressed *key_event = static_cast(event.get()); + + if (key_event->code == sf::Keyboard::Escape) { + window_ref->close(); + } } }; diff --git a/include/LightController.h b/include/LightController.h index f722465..4d1c32f 100644 --- a/include/LightController.h +++ b/include/LightController.h @@ -8,9 +8,9 @@ #include "LightHandle.h" -// Lighting is a bit tricky as we need to - - +// Typical light workflow: +// 1.) Create light prototype with desired values +// 2.) Submit prototype to the LightController struct LightPrototype { @@ -56,6 +56,7 @@ public: LightController(std::shared_ptr raycaster); ~LightController(); + // find a free light 'slot' and create std::shared_ptr create_light(LightPrototype light_prototype); void remove_light(unsigned int light_index); diff --git a/src/Camera.cpp b/src/Camera.cpp index 84f461d..b8114b3 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -2,14 +2,13 @@ #include "Pub_Sub.h" -Camera::Camera() { -} +Camera::Camera() {} Camera::Camera(sf::Vector3f position, sf::Vector2f direction, sf::RenderWindow* window) : - position(position), direction(direction), window(window) - { - fixed = sf::Vector2i(sf::Vector2i(window->getSize().x/2, window->getSize().y/2)); + position(position), direction(direction), window(window) { + + fixed = sf::Vector2i(sf::Vector2i(window->getSize().x/2, window->getSize().y/2)); } Camera::~Camera() { diff --git a/src/Hardware_Caster.cpp b/src/Hardware_Caster.cpp index e758d05..3e6cf94 100644 --- a/src/Hardware_Caster.cpp +++ b/src/Hardware_Caster.cpp @@ -4,7 +4,7 @@ Hardware_Caster::Hardware_Caster() {} Hardware_Caster::~Hardware_Caster() {} -int Hardware_Caster::init() { +bool Hardware_Caster::init() { Logger::log("Initializing the Hardware Caster", Logger::LogLevel::INFO); @@ -68,68 +68,99 @@ int Hardware_Caster::init() { } -bool Hardware_Caster::assign_map(Old_Map *map) { - +bool Hardware_Caster::assign_map(std::shared_ptr map) { + this->map = map; auto dimensions = map->getDimensions(); - + if (!create_buffer("map", sizeof(char) * dimensions.x * dimensions.y * dimensions.z, map->get_voxel_data())) return false; - + if (!create_buffer("map_dimensions", sizeof(int) * 3, &dimensions)) return false; + + return true; +} + +bool Hardware_Caster::release_map() { + this->map = nullptr; + + if (!release_buffer("map")) + return false; + + if (!release_buffer("map_dimensions")) + return false; + return true; } -bool Hardware_Caster::assign_camera(Camera *camera) { +bool Hardware_Caster::assign_camera(std::shared_ptr camera) { + this->camera = camera; if (!create_buffer("camera_direction", sizeof(float) * 4, (void*)camera->get_direction_pointer(), CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR)) return false; - + if (!create_buffer("camera_position", sizeof(float) * 4, (void*)camera->get_position_pointer(), CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR)) return false; return true; } -bool Hardware_Caster::validate() { +bool Hardware_Caster::release_camera() { - Logger::log("Validating OpenCL kernel args", Logger::LogLevel::INFO); + this->camera = nullptr; - // Check to make sure everything has been entered; - if (camera == nullptr || - map == nullptr || - viewport_image == nullptr || - viewport_matrix == nullptr) { + if (!release_buffer("camera_direction")) + return false; - Logger::log("Raycaster.validate() failed, camera, map, or viewport not initialized", Logger::LogLevel::WARN); + if (!release_buffer("camera_position")) return false; - } else { - - // Set all the kernel args - set_kernel_arg("raycaster", 0, "map"); - set_kernel_arg("raycaster", 1, "map_dimensions"); - set_kernel_arg("raycaster", 2, "viewport_resolution"); - set_kernel_arg("raycaster", 3, "viewport_matrix"); - set_kernel_arg("raycaster", 4, "camera_direction"); - set_kernel_arg("raycaster", 5, "camera_position"); - set_kernel_arg("raycaster", 6, "lights"); - set_kernel_arg("raycaster", 7, "light_count"); - set_kernel_arg("raycaster", 8, "image"); - set_kernel_arg("raycaster", 9, "seed"); - set_kernel_arg("raycaster", 10, "texture_atlas"); - set_kernel_arg("raycaster", 11, "atlas_dim"); - set_kernel_arg("raycaster", 12, "tile_dim"); + return true; +} - return true; - //print_kernel_arguments(); - } +bool Hardware_Caster::validate() { + + Logger::log("Validating OpenCL kernel args", Logger::LogLevel::INFO); + // Check to make sure everything has been entered + if (!camera.get()) { + Logger::log("Raycaster.validate() failed, camera not initialized", Logger::LogLevel::WARN); + return false; + } + if (!map.get()) { + Logger::log("Raycaster.validate() failed, map not initialized", Logger::LogLevel::WARN); + return false; + } + if (!viewport_image) { + Logger::log("Raycaster.validate() failed, viewport_image not initialized", Logger::LogLevel::WARN); + return false; + } + if (!viewport_matrix) { + Logger::log("Raycaster.validate() failed, viewport_matrix not initialized", Logger::LogLevel::WARN); + return false; + } + // Set all the kernel args + set_kernel_arg("raycaster", 0, "map"); + set_kernel_arg("raycaster", 1, "map_dimensions"); + set_kernel_arg("raycaster", 2, "viewport_resolution"); + set_kernel_arg("raycaster", 3, "viewport_matrix"); + set_kernel_arg("raycaster", 4, "camera_direction"); + set_kernel_arg("raycaster", 5, "camera_position"); + set_kernel_arg("raycaster", 6, "lights"); + set_kernel_arg("raycaster", 7, "light_count"); + set_kernel_arg("raycaster", 8, "image"); + set_kernel_arg("raycaster", 9, "seed"); + set_kernel_arg("raycaster", 10, "texture_atlas"); + set_kernel_arg("raycaster", 11, "atlas_dim"); + set_kernel_arg("raycaster", 12, "tile_dim"); + + return true; + } bool Hardware_Caster::create_texture_atlas(sf::Texture *t, sf::Vector2i tile_dim) { @@ -500,7 +531,8 @@ bool Hardware_Caster::query_hardware() return true; } -int Hardware_Caster::create_shared_context() { +bool Hardware_Caster::create_shared_context() +{ // Hurray for standards! // Setup the context properties to grab the current GL context diff --git a/src/LightController.cpp b/src/LightController.cpp index 7ad9dc3..a936888 100644 --- a/src/LightController.cpp +++ b/src/LightController.cpp @@ -2,8 +2,10 @@ LightController::LightController(std::shared_ptr raycaster) : packed_data_array(reserved_count), open_list(reserved_count) { + // initialize the open list with numbers 1 -> open_list.size() std::iota(open_list.begin(), open_list.end(), 0); + // raycaster->assign_lights(&packed_data_array); } diff --git a/src/main.cpp b/src/main.cpp index 2749bb4..f047b87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,13 +85,8 @@ int main() { srand(time(nullptr)); - // ============================= Map _map(32); - //_map.test(); - //std::cin.get(); - //return 0; - // ============================= sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "SFML"); window.setMouseCursorVisible(false); @@ -104,24 +99,22 @@ int main() { // Start up the raycaster std::shared_ptr raycaster(new Hardware_Caster()); - - if (raycaster->init() != 1) { + if (!raycaster->init()) abort(); - } - + // Create and generate the old 3d array style map - Old_Map* map = new Old_Map(sf::Vector3i(MAP_X, MAP_Y, MAP_Z)); + std::shared_ptr map(new Old_Map(sf::Vector3i(MAP_X, MAP_Y, MAP_Z))); map->generate_terrain(); // Send the data to the GPU raycaster->assign_map(map); // Create a new camera with (starting position, direction) - Camera *camera = new Camera( + std::shared_ptr camera(new Camera( sf::Vector3f(50, 50, 50), sf::Vector2f(1.5f, 0.0f), &window - ); + )); // *link* the camera to the GPU raycaster->assign_camera(camera); @@ -129,59 +122,65 @@ int main() { // Generate and send the viewport to the GPU. Also creates the viewport texture raycaster->create_viewport(WINDOW_X, WINDOW_Y, 0.625f * 90.0f, 90.0f); - float w = 60.0; - float h = 90.0; - - + // Initialize the light controller and link it to the GPU LightController light_controller(raycaster); + + // Create a light prototype, send it to the controller, and get the handle back LightPrototype prototype( sf::Vector3f(100.0f, 100.0f, 75.0f), sf::Vector3f(-1.0f, -1.0f, -1.5f), sf::Vector4f(0.4f, 0.4f, 0.4f, 1.0f) ); - - std::shared_ptr handle(light_controller.create_light(prototype)); + std::shared_ptr light_handle(light_controller.create_light(prototype)); // Load in the spritesheet texture sf::Texture spritesheet; - spritesheet.loadFromFile("../assets/textures/minecraft_tiles.png"); + if (!spritesheet.loadFromFile("../assets/textures/minecraft_tiles.png")) + Logger::log("Failed to load spritesheet from file", Logger::LogLevel::WARN); raycaster->create_texture_atlas(&spritesheet, sf::Vector2i(16, 16)); // Checks to see if proper data was uploaded, then sets the kernel args // ALL DATA LOADING MUST BE FINISHED - raycaster->validate(); + if (!raycaster->validate()) { + abort(); + }; + // Start up the input handler and link the camera to some of the events Input input_handler; camera->subscribe_to_publisher(&input_handler, vr::Event::EventType::KeyHeld); camera->subscribe_to_publisher(&input_handler, vr::Event::EventType::KeyPressed); camera->subscribe_to_publisher(&input_handler, vr::Event::EventType::MouseMoved); camera->subscribe_to_publisher(&input_handler, vr::Event::EventType::MouseButtonPressed); + // Start up a window handler which subscribes to input and listens for window closed events WindowHandler win_hand(&window); win_hand.subscribe_to_publisher(&input_handler, vr::Event::EventType::Closed); + win_hand.subscribe_to_publisher(&input_handler, vr::Event::EventType::KeyPressed); - float step_size = 0.0166f; - double frame_time = 0.0, - elapsed_time = 0.0, - delta_time = 0.0, - accumulator_time = 0.0, - current_time = 0.0; - // The sfml imgui wrapper I'm using requires Update be called with sf::Time // Might modify it to also accept seconds sf::Clock sf_delta_clock; fps_counter fps; + // vars for us to use with ImGUI float light_color[4] = { 0, 0, 0, 0 }; float light_pos[4] = { 100, 100, 30 }; char screenshot_buf[128]{0}; - bool paused = false; float camera_speed = 1.0; + // Game loop values + float step_size = 0.0166f; + double frame_time = 0.0, + elapsed_time = 0.0, + delta_time = 0.0, + accumulator_time = 0.0, + current_time = 0.0; + while (window.isOpen()) { + // Have the input handler empty the event stack, generate events for held keys, and then dispatch the events to listeners input_handler.consume_sf_events(&window); input_handler.handle_held_keys(); input_handler.dispatch_events(); @@ -205,15 +204,18 @@ int main() { ImGui::SFML::Update(window, sf_delta_clock.restart()); + // Pausing stops camera and light updates, as well as raycaster computes if (!paused) { camera->update(delta_time); - handle->update(delta_time); + light_handle->update(delta_time); // Run the raycast - raycaster->compute(); - + if (!raycaster->compute()) { + abort(); + }; } + // Let the raycaster draw it screen buffer raycaster->draw(&window); // Give the frame counter the frame time and draw the average frame time @@ -292,7 +294,7 @@ int main() { if (ImGui::SliderFloat4("Color", light_color, 0, 1)) { sf::Vector4f light(light_color[0], light_color[1], light_color[2], light_color[3]); - handle->set_rgbi(light); + light_handle->set_rgbi(light); } if (ImGui::SliderFloat("Camera Speed", &camera_speed, 0, 4)) { @@ -301,7 +303,7 @@ int main() { if (ImGui::SliderFloat3("Position", light_pos, 0, MAP_X)) { sf::Vector3f light(light_pos[0], light_pos[1], light_pos[2]); - handle->set_position(light); + light_handle->set_position(light); } if (ImGui::CollapsingHeader("Window options")) @@ -317,7 +319,8 @@ int main() { ImGui::Render(); - + // ImGUI messes up somthing in the SFML GL state, so we need a single draw call to right things + // then we can move on to flip the screen buffer via display window.draw(sf::CircleShape(0)); window.display(); diff --git a/src/map/Map.cpp b/src/map/Map.cpp index 761fb1e..57a442c 100644 --- a/src/map/Map.cpp +++ b/src/map/Map.cpp @@ -52,12 +52,10 @@ bool Map::test_oct_arr_traversal(sf::Vector3i dimensions) { } void Map::setVoxel(sf::Vector3i pos, int val) { - voxel_data[pos.x + OCT_DIM * (pos.y + OCT_DIM * pos.z)] = val; } char Map::getVoxel(sf::Vector3i pos){ - return octree.GetVoxel(pos).found; }