#include #include #include #include #include #include #include #include #include "Utility.hpp" #include "Light.h" auto window = sf::RenderWindow(sf::VideoMode({ 1920u, 1080u }), "Ray Casting Test"); Light light; std::vector polygons; sf::CircleShape circle{}; sf::Vector2f mousePos{}; sf::Vector2f center{ 1920.f / 2.f, 1080.f / 2.f }; //imGui Variables constexpr int numRaysBounds[2] = { 5, 500 }; constexpr float rayLengthBounds[2] = {5.f, 5000.f}; constexpr float offsetAngleBounds[2] = { 5.f, 175.f }; constexpr int vertexMin{ 3 }; constexpr int vertexMax{ 20 }; constexpr float rotationSpeedScale{ 3.f }; float polySize[2] = { 100.f, 100.f }; int numRays{ 500 }; int vertexBounds[2] = { 3, 10 }; int averageSize{ 100 }; float rayLength{ 500.f }; imguiColor rayColor = constructImguiColor(sf::Color::Red); imguiColor lightColor = constructImguiColor(sf::Color::Yellow); imguiColor endPointColor = constructImguiColor(sf::Color::Magenta); bool drawRays{ false }; bool drawLight{ true }; bool drawEndPoints{ false }; bool boundedLight{ false }; bool infiniteRayLength{ false }; float lightCenterAngle{ 0.f }; float lightOffsetAngle{ 45.f }; void GUI(); void userInput(); void render(); int main() { //configure light with default imgui vatiables drawRays ? light.setFlags(Light::Flags::drawRays) : light.unsetFlags(Light::Flags::drawRays); drawLight ? light.setFlags(Light::Flags::visibility) : light.unsetFlags(Light::Flags::visibility); boundedLight ? light.addAngleBounds(sf::degrees(lightCenterAngle), sf::degrees(lightOffsetAngle)) : light.removeAngleBounds(); drawEndPoints ? light.setFlags(Light::Flags::drawEndPoints) : light.unsetFlags(Light::Flags::drawEndPoints); infiniteRayLength ? light.setFlags(Light::Flags::infiniteLength) : light.unsetFlags(Light::Flags::infiniteLength); //sfml setup sf::Clock clock; window.setFramerateLimit(144); if (!ImGui::SFML::Init(window)) return -1; mousePos = center; polygons.emplace_back(constructRectangle(center, center)); circle.setOrigin({0,0}); circle.setPosition(center); circle.setRadius(200.f); circle.setPointCount(30u); polygons.emplace_back(constructVertexArray(circle)); //main game loop while (window.isOpen()) { ImGui::SFML::Update(window, clock.restart()); light.clearRays(); userInput(); GUI(); light.setOrigin(mousePos); light.processRays(polygons); render(); } ImGui::SFML::Shutdown(); } void GUI() { ImGui::Begin("Config"); ImGui::Text("Controls:"); ImGui::Indent(); ImGui::Text("Right Click: place rectangle at mouse position"); ImGui::Text("R: place a randomly sized polygon at mouse position"); ImGui::Text("C: clear all polygons"); ImGui::Text("Scroll wheel: increase/decrease light direction (if light is bounded)"); ImGui::Unindent(); if (ImGui::Checkbox("Render rays", &drawRays)) { light.toggleFlags(Light::Flags::drawRays); } ImGui::SameLine(); if (ImGui::Checkbox("Render end points", &drawEndPoints)) { light.toggleFlags(Light::Flags::drawEndPoints); } ImGui::SameLine(); if (ImGui::Checkbox("Render light", &drawLight)) { light.toggleFlags(Light::Flags::visibility); } if (ImGui::Checkbox("Infinite ray length", &infiniteRayLength)) { light.toggleFlags(Light::Flags::infiniteLength); } if (not infiniteRayLength) { ImGui::SliderInt("number of rays", &numRays, numRaysBounds[0], numRaysBounds[1]); light.setRayCount(numRays); if (ImGui::InputFloat("Ray Length", &rayLength)) { rayLength = std::clamp(rayLength, rayLengthBounds[0], rayLengthBounds[1]); } light.setRayLength(rayLength); } if (drawRays) { ImGui::ColorEdit4("Ray color", &rayColor.r); } if (drawLight) { ImGui::ColorEdit4("Light color", &lightColor.r); } if (drawEndPoints) { ImGui::ColorEdit4("End point color", &endPointColor.r); } light.changeLightColor(lightColor.asSfColor()); light.changeEndPointColor(endPointColor.asSfColor()); light.changeRayColor(rayColor.asSfColor()); if(ImGui::Checkbox("Light is bounded", &boundedLight)) { boundedLight ? light.addAngleBounds(sf::degrees(lightCenterAngle), sf::degrees(lightOffsetAngle)) : light.removeAngleBounds(); } if (boundedLight) { ImGui::SliderFloat("Light direction", &lightCenterAngle, 0.f, 359.f, "%.0f", ImGuiSliderFlags_::ImGuiSliderFlags_AlwaysClamp); light.setCenterAngle(sf::degrees(lightCenterAngle)); ImGui::SliderFloat("Offset size", &lightOffsetAngle, offsetAngleBounds[0], offsetAngleBounds[1], "%.0f", ImGuiSliderFlags_::ImGuiSliderFlags_AlwaysClamp); light.setOffsetAngle(sf::degrees(lightOffsetAngle)); } ImGui::InputFloat2("rectangle Size (X,Y)", polySize, "%.1f"); ImGui::Text("Random polygon config: "); if (ImGui::SliderInt2("vertex count lower/upper bounds", vertexBounds, vertexMin, vertexMax)) { if (vertexBounds[0] > vertexBounds[1]) vertexBounds[0] = vertexBounds[1]; if (vertexBounds[1] < vertexBounds[0]) vertexBounds[0] = vertexBounds[1]; } if (ImGui::InputInt("Average size", &averageSize)) { if (averageSize < 20) { averageSize = 20; } } ImGui::End(); } void userInput() { while (const std::optional event = window.pollEvent()) { ImGui::SFML::ProcessEvent(window, *event); if (event->is()) { window.close(); } if (const auto* buttonPressed = event->getIf()) { switch (buttonPressed->scancode) { case sf::Keyboard::Scancode::C: polygons.clear(); polygons.emplace_back(constructRectangle(center, center)); break; case sf::Keyboard::Scancode::R: polygons.emplace_back(constructRandomPolygon(mousePos, vertexBounds[0] + 1, vertexBounds[1] + 1, averageSize)); break; case sf::Keyboard::Scancode::Escape: window.close(); break; default: break; } } if (const auto* mousePressed = event->getIf()) { switch (mousePressed->button) { case sf::Mouse::Button::Right: polygons.emplace_back(constructRectangle((sf::Vector2f)mousePressed->position, { polySize[0], polySize[1] }, sf::Color::Black)); break; default: break; } } if (const auto* mouseWheelScrolled = event->getIf()) { switch (mouseWheelScrolled->wheel) { case sf::Mouse::Wheel::Vertical: if (boundedLight) { lightCenterAngle += mouseWheelScrolled->delta * rotationSpeedScale; if (lightCenterAngle > 359.f) lightCenterAngle = 0.f; if (lightCenterAngle < 0.f) lightCenterAngle = 359.f; } break; default: break; } } if (const auto* mouseMoved = event->getIf()) { mousePos = (sf::Vector2f)mouseMoved->position; } } } void render() { window.clear(sf::Color::White); light.draw(window); for (auto& poly : polygons) window.draw(poly); ImGui::SFML::Render(window); window.display(); }