From 5d3df8e1b93498bffe8a7cd2dd638e5662549d40 Mon Sep 17 00:00:00 2001 From: Joseph Aquino Date: Thu, 17 Apr 2025 03:41:14 -0400 Subject: [PATCH] minor code update -changed if statments in Light.cpp to avoid deep nesting -move temporary local variables out of loops to avoid constant creation and deletion -added some constexpr variables to the imgui variable to get rid of magic numbers --- Light.cpp | 99 ++++++++++++++++++++++++++++--------------------------- Light.h | 42 +++++++++++------------ imgui.ini | 2 +- main.cpp | 96 +++++++++++++++++++---------------------------------- 4 files changed, 105 insertions(+), 134 deletions(-) diff --git a/Light.cpp b/Light.cpp index 03ca58d..ab3fba5 100644 --- a/Light.cpp +++ b/Light.cpp @@ -9,24 +9,26 @@ void Light::draw(sf::RenderWindow& window) if (hasFlags(Flags::drawRays)) { + sf::VertexArray tempRay(sf::PrimitiveType::Lines, 2); + tempRay[start].position = m_origin; + tempRay[start].color = m_rayColor; + tempRay[end].color = m_rayColor; + for (auto& ray : m_rays) { - sf::VertexArray tempRay(sf::PrimitiveType::Lines, 2); - tempRay[start].position = m_origin; - tempRay[start].color = m_rayColor; tempRay[end].position = ray.position; - tempRay[end].color = m_rayColor; window.draw(tempRay); } } if (hasFlags(Flags::drawEndPoints)) { + sf::CircleShape endPoint(5.f, 20u); + endPoint.setOrigin({ 5, 5 }); + endPoint.setFillColor(m_endPointColor); + for (auto& ray : m_rays) { - sf::CircleShape endPoint(5.f, 20u); - endPoint.setOrigin({ 5, 5 }); - endPoint.setFillColor(m_endPointColor); endPoint.setPosition(ray.position); window.draw(endPoint); } @@ -86,22 +88,23 @@ void Light::createAndSortRays(const std::vector& polygons) if (m_rayCount > 0) { float angleIncrement = 360.f / (float)m_rayCount; - for (int i = 0; i < m_rayCount; i++) m_rays.emplace_back(sf::Vertex{ constructVector(m_origin, sf::degrees(angleIncrement * i), m_rayLength), m_lightColor }); + for (int i = 0; i < m_rayCount; i++) m_rays.emplace_back(sf::Vertex{ constructVector( m_origin, sf::degrees(angleIncrement * i), m_rayLength ), m_lightColor }); } } + sf::Angle angle; + for (auto& poly : polygons) { for (std::size_t i = 0; i < poly.getVertexCount() - 1; i++) { - if (distanceBetween(m_origin, poly[i].position) <= m_rayLength or hasFlags(Flags::infiniteLength)) - { - sf::Angle angle = sf::radians(std::atan2f(poly[i].position.y - m_origin.y, poly[i].position.x - m_origin.x)); + if (hasFlags(Flags::infiniteLength) ? false : distanceBetween(m_origin, poly[i].position) >= m_rayLength) continue; + + angle = sf::radians(std::atan2f(poly[i].position.y - m_origin.y, poly[i].position.x - m_origin.x)); - m_rays.emplace_back(sf::Vertex{ poly[i].position, m_lightColor }); - m_rays.emplace_back(sf::Vertex{ constructVector( m_origin, angle + sf::radians(.00001f), m_rayLength + (5000.f * hasFlags(Flags::infiniteLength)) ), m_lightColor }); - m_rays.emplace_back(sf::Vertex{ constructVector( m_origin, angle - sf::radians(.00001f), m_rayLength + (5000.f * hasFlags(Flags::infiniteLength)) ), m_lightColor }); - } + m_rays.emplace_back(sf::Vertex{ poly[i].position, m_lightColor }); + m_rays.emplace_back(sf::Vertex{ constructVector( m_origin, angle + sf::radians(.00001f), m_rayLength + (5000.f * hasFlags(Flags::infiniteLength)) ), m_lightColor }); + m_rays.emplace_back(sf::Vertex{ constructVector( m_origin, angle - sf::radians(.00001f), m_rayLength + (5000.f * hasFlags(Flags::infiniteLength)) ), m_lightColor }); } } @@ -112,29 +115,25 @@ void Light::createAndSortRays(const std::vector& polygons) void Light::createAndSortRays(const std::vector& polygons, sf::Angle lowerAngleBounds, sf::Angle upperAngleBounds) { - sf::Vertex lowerBound{ constructVector(m_origin, lowerAngleBounds, m_rayLength + (5000.f * hasFlags(Flags::infiniteLength))), m_lightColor }; - sf::Vertex upperBound{ constructVector(m_origin, upperAngleBounds, m_rayLength + (5000.f * hasFlags(Flags::infiniteLength))), m_lightColor }; + sf::Vertex lowerBound{ constructVector( m_origin, lowerAngleBounds, m_rayLength + (5000.f * hasFlags(Flags::infiniteLength)) ), m_lightColor }; + sf::Vertex upperBound{ constructVector( m_origin, upperAngleBounds, m_rayLength + (5000.f * hasFlags(Flags::infiniteLength)) ), m_lightColor }; auto lowerBoundVector = lowerBound.position - m_origin; auto upperBoundVector = upperBound.position - m_origin; if (not hasFlags(Flags::infiniteLength)) { - if (m_rayCount > 0) + sf::Vertex temp; + float angleIncrement = 360.f / (float)m_rayCount; + for (int i = 0; i < m_rayCount; i++) { - float angleIncrement = 360.f / (float)m_rayCount; - for (int i = 0; i < m_rayCount; i++) - { - sf::Vertex temp{ constructVector(m_origin, sf::degrees(angleIncrement * i), m_rayLength), m_lightColor }; + temp = sf::Vertex{ constructVector(m_origin, sf::degrees(angleIncrement * i), m_rayLength), m_lightColor }; - if (withinBounds(temp.position - m_origin, lowerBoundVector, upperBoundVector)) - { - m_rays.emplace_back(temp); - } - } + if (withinBounds(temp.position - m_origin, lowerBoundVector, upperBoundVector)) m_rays.emplace_back(temp); } } - m_rays.emplace_back(lowerBound); + constexpr float infiniteLength = 5000.f; + sf::Angle angle; for (auto& poly : polygons) { @@ -142,45 +141,46 @@ void Light::createAndSortRays(const std::vector& polygons, sf:: { if (poly[i].position == m_origin) continue;// cannot pass zero vector to sf::Vector2::angleTo() - if (distanceBetween(m_origin, poly[i].position) <= m_rayLength or hasFlags(Flags::infiniteLength)) - { - if (withinBounds(poly[i].position - m_origin, lowerBoundVector, upperBoundVector)) - { - sf::Angle angle = sf::radians(std::atan2f(poly[i].position.y - m_origin.y, poly[i].position.x - m_origin.x)); + if (hasFlags(Flags::infiniteLength) ? false : distanceBetween(m_origin, poly[i].position) >= m_rayLength) continue; + + if (not withinBounds(poly[i].position - m_origin, lowerBoundVector, upperBoundVector)) continue; + + angle = sf::radians(std::atan2f(poly[i].position.y - m_origin.y, poly[i].position.x - m_origin.x)); - m_rays.emplace_back(sf::Vertex{ poly[i].position, m_lightColor }); - m_rays.emplace_back(sf::Vertex{ constructVector(m_origin, angle + sf::radians(.00001f), m_rayLength + (5000.f * hasFlags(Flags::infiniteLength))), m_lightColor }); - m_rays.emplace_back(sf::Vertex{ constructVector(m_origin, angle - sf::radians(.00001f), m_rayLength + (5000.f * hasFlags(Flags::infiniteLength))), m_lightColor }); - } - } + m_rays.emplace_back(sf::Vertex{ poly[i].position, m_lightColor }); + m_rays.emplace_back(sf::Vertex{ constructVector( m_origin, angle + sf::radians(.00001f), m_rayLength + (infiniteLength * hasFlags(Flags::infiniteLength)) ), m_lightColor }); + m_rays.emplace_back(sf::Vertex{ constructVector( m_origin, angle - sf::radians(.00001f), m_rayLength + (infiniteLength * hasFlags(Flags::infiniteLength)) ), m_lightColor }); } } - m_rays.emplace_back(upperBound); + m_rays.emplace_back(lowerBound); + m_rays.emplace_back(upperBound); std::sort(m_rays.begin(), m_rays.end(), [&](const auto& lhs, const auto& rhs) { return (lhs.position - m_origin).angleTo(upperBoundVector).wrapUnsigned().asRadians() < (rhs.position - m_origin).angleTo(upperBoundVector).wrapUnsigned().asRadians(); }); } void Light::calculateIntersects(const std::vector& polygons) { + std::optional currentIntersect{}; for (auto& ray : m_rays) { sf::Vector2f closestIntersection = ray.position; - std::optional currentIntersect{}; + currentIntersect.reset(); + for (auto& poly : polygons) { - for (std::size_t i = 1; i <= poly.getVertexCount() - 1; i++) { + for (std::size_t i = 1; i <= poly.getVertexCount() - 1; i++) + { currentIntersect = lineIntersect({ m_origin, ray.position }, { poly[i - 1].position , poly[i].position }); - if (currentIntersect) - { - if ((closestIntersection - m_origin).length() > (currentIntersect.value() - m_origin).length()) - { - closestIntersection = currentIntersect.value(); - } - } + + if (not currentIntersect) continue; + if ((closestIntersection - m_origin).length() < (currentIntersect.value() - m_origin).length()) continue; + + closestIntersection = currentIntersect.value(); } } + ray.position = closestIntersection; } @@ -189,4 +189,5 @@ void Light::calculateIntersects(const std::vector& polygons) bool Light::withinBounds(sf::Vector2f point, sf::Vector2f lower, sf::Vector2f upper) { return point.angleTo(upper).wrapUnsigned().asRadians() < (lower).angleTo(upper).wrapUnsigned().asRadians(); -} \ No newline at end of file +} + diff --git a/Light.h b/Light.h index abeb318..1a0f30a 100644 --- a/Light.h +++ b/Light.h @@ -10,38 +10,26 @@ #include #include "Utility.hpp" -#include "Ray.h" class Light { public: + Light() = default; - Light(bool visible = true) + Light(sf::Vector2f origin, bool visible = true) + : m_origin(origin) { - m_light.push_back(sf::Vertex{ {0.f,0.f}, m_lightColor}); - if (visible) - { - setFlags(Flags::visibility); - } - else - { - unsetFlags(Flags::visibility); - } + m_light.push_back(sf::Vertex{ m_origin, m_lightColor}); + visible ? setFlags(Flags::visibility) : unsetFlags(Flags::visibility); } - Light(sf::Angle center, sf::Angle offset, bool visible = true) + Light(sf::Vector2f origin, sf::Angle center, sf::Angle offset, bool visible = true) : m_center(center) , m_offset(offset) + , m_origin(origin) { - m_light.push_back(sf::Vertex{}); - if (visible) - { - setFlags(Flags::visibility); - } - else - { - unsetFlags(Flags::visibility); - } + m_light.push_back(sf::Vertex{ m_origin, m_lightColor }); + visible ? setFlags(Flags::visibility) : unsetFlags(Flags::visibility); } enum class Flags @@ -99,21 +87,31 @@ private: std::vector m_rays{}; std::optional m_center{}; std::optional m_offset{}; + sf::Vector2f m_origin{}; sf::Color m_lightColor{ sf::Color::Yellow }; sf::Color m_endPointColor{ sf::Color::Magenta }; sf::Color m_rayColor{ sf::Color::Red }; - sf::Vector2f m_origin{}; float m_rayLength{ 500.f }; int m_rayCount{ 500 }; int m_flags{}; + + enum + { + start, + end + };//used for sf::VertexArray index + private: void constructFullLight(const std::vector& polygons); void constructPartialLight(const std::vector& polygons); + void createAndSortRays(const std::vector& polygons); void createAndSortRays(const std::vector& polygons, sf::Angle lowerAngleBounds, sf::Angle upperAngleBounds);// for bounded light + void calculateIntersects(const std::vector& polygons); + bool withinBounds(sf::Vector2f point, sf::Vector2f lower, sf::Vector2f upper); }; diff --git a/imgui.ini b/imgui.ini index 98c0119..b7410a7 100644 --- a/imgui.ini +++ b/imgui.ini @@ -3,6 +3,6 @@ Pos=60,60 Size=400,400 [Window][Config] -Pos=7,11 +Pos=6,12 Size=670,442 diff --git a/main.cpp b/main.cpp index 829013f..5e90175 100644 --- a/main.cpp +++ b/main.cpp @@ -22,10 +22,16 @@ 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] = { 3u, 10u }; -int averageSize{ 100u }; +int vertexBounds[2] = { 3, 10 }; +int averageSize{ 100 }; float rayLength{ 500.f }; imguiColor rayColor = constructImguiColor(sf::Color::Red); imguiColor lightColor = constructImguiColor(sf::Color::Yellow); @@ -35,8 +41,8 @@ bool drawLight{ true }; bool drawEndPoints{ false }; bool boundedLight{ false }; bool infiniteRayLength{ false }; -int lightCenterAngle{ 0 }; -int lightOffsetAngle{ 45 }; +float lightCenterAngle{ 0.f }; +float lightOffsetAngle{ 45.f }; void GUI(); void userInput(); @@ -44,6 +50,11 @@ 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); + 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; @@ -88,62 +99,34 @@ void GUI() ImGui::Unindent(); if (ImGui::Checkbox("Render rays", &drawRays)) { - if (drawRays) - { - light.setFlags(Light::Flags::drawRays); - } - else - { - light.unsetFlags(Light::Flags::drawRays); - } + light.toggleFlags(Light::Flags::drawRays); } ImGui::SameLine(); if (ImGui::Checkbox("Render end points", &drawEndPoints)) { - if (drawEndPoints) - { - light.setFlags(Light::Flags::drawEndPoints); - } - else - { - light.unsetFlags(Light::Flags::drawEndPoints); - } + light.toggleFlags(Light::Flags::drawEndPoints); } ImGui::SameLine(); if (ImGui::Checkbox("Render light", &drawLight)) { - if (drawLight) - { - light.setFlags(Light::Flags::visibility); - } - else - { - light.unsetFlags(Light::Flags::visibility); - } + light.toggleFlags(Light::Flags::visibility); } if (ImGui::Checkbox("Infinite ray length", &infiniteRayLength)) { - if (infiniteRayLength) - { - light.setFlags(Light::Flags::infiniteLength); - } - else - { - light.unsetFlags(Light::Flags::infiniteLength); - } + light.toggleFlags(Light::Flags::infiniteLength); } if (not infiniteRayLength) { - ImGui::SliderInt("number of rays", &numRays, 5, 500); + ImGui::SliderInt("number of rays", &numRays, numRaysBounds[0], numRaysBounds[1]); light.setRayCount(numRays); if (ImGui::InputFloat("Ray Length", &rayLength)) { - rayLength = std::clamp(rayLength, 5.f, 10000.f); + rayLength = std::clamp(rayLength, rayLengthBounds[0], rayLengthBounds[1]); } light.setRayLength(rayLength); } @@ -168,36 +151,21 @@ void GUI() if(ImGui::Checkbox("Light is bounded", &boundedLight)) { - if (boundedLight) - { - light.addAngleBounds(sf::degrees((float)lightCenterAngle), sf::degrees((float)lightOffsetAngle)); - } - else - { - light.removeAngleBounds(); - } + boundedLight ? light.addAngleBounds(sf::degrees(lightCenterAngle), sf::degrees(lightOffsetAngle)) : light.removeAngleBounds(); } + if (boundedLight) { - ImGui::SliderInt("Light direction", &lightCenterAngle, 0, 359); - light.setCenterAngle(sf::degrees((float)lightCenterAngle)); + ImGui::SliderFloat("Light direction", &lightCenterAngle, 0.f, 359.f, "%.0f", ImGuiSliderFlags_::ImGuiSliderFlags_AlwaysClamp); + light.setCenterAngle(sf::degrees(lightCenterAngle)); - if (ImGui::InputInt("Offset size", &lightOffsetAngle)) - { - if (lightOffsetAngle > 175) - { - lightOffsetAngle = 175; - } - if (lightOffsetAngle < 5) - { - lightOffsetAngle = 5; - } - } - light.setOffsetAngle(sf::degrees((float)lightOffsetAngle)); + 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, 3, 20)) + if (ImGui::SliderInt2("vertex count lower/upper bounds", vertexBounds, vertexMin, vertexMax)) { if (vertexBounds[0] > vertexBounds[1]) vertexBounds[0] = vertexBounds[1]; @@ -269,7 +237,11 @@ void userInput() { case sf::Mouse::Wheel::Vertical: if (boundedLight) - lightCenterAngle = std::clamp(lightCenterAngle += (int)mouseWheelScrolled->delta, 0, 360); + { + lightCenterAngle += mouseWheelScrolled->delta * rotationSpeedScale; + if (lightCenterAngle > 359.f) lightCenterAngle = 0.f; + if (lightCenterAngle < 0.f) lightCenterAngle = 359.f; + } break; default: