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
This commit is contained in:
Joseph Aquino 2025-04-17 03:41:14 -04:00
parent 3941a59b0d
commit 5d3df8e1b9
4 changed files with 105 additions and 134 deletions

View File

@ -9,24 +9,26 @@ void Light::draw(sf::RenderWindow& window)
if (hasFlags(Flags::drawRays)) 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) 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].position = ray.position;
tempRay[end].color = m_rayColor;
window.draw(tempRay); window.draw(tempRay);
} }
} }
if (hasFlags(Flags::drawEndPoints)) if (hasFlags(Flags::drawEndPoints))
{ {
sf::CircleShape endPoint(5.f, 20u);
endPoint.setOrigin({ 5, 5 });
endPoint.setFillColor(m_endPointColor);
for (auto& ray : m_rays) for (auto& ray : m_rays)
{ {
sf::CircleShape endPoint(5.f, 20u);
endPoint.setOrigin({ 5, 5 });
endPoint.setFillColor(m_endPointColor);
endPoint.setPosition(ray.position); endPoint.setPosition(ray.position);
window.draw(endPoint); window.draw(endPoint);
} }
@ -86,22 +88,23 @@ void Light::createAndSortRays(const std::vector<sf::VertexArray>& polygons)
if (m_rayCount > 0) if (m_rayCount > 0)
{ {
float angleIncrement = 360.f / (float)m_rayCount; 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 (auto& poly : polygons)
{ {
for (std::size_t i = 0; i < poly.getVertexCount() - 1; i++) for (std::size_t i = 0; i < poly.getVertexCount() - 1; i++)
{ {
if (distanceBetween(m_origin, poly[i].position) <= m_rayLength or hasFlags(Flags::infiniteLength)) if (hasFlags(Flags::infiniteLength) ? false : distanceBetween(m_origin, poly[i].position) >= m_rayLength) continue;
{
sf::Angle 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 }); 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{ 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<sf::VertexArray>& polygons)
void Light::createAndSortRays(const std::vector<sf::VertexArray>& polygons, sf::Angle lowerAngleBounds, sf::Angle upperAngleBounds) void Light::createAndSortRays(const std::vector<sf::VertexArray>& 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 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 upperBound{ constructVector( m_origin, upperAngleBounds, m_rayLength + (5000.f * hasFlags(Flags::infiniteLength)) ), m_lightColor };
auto lowerBoundVector = lowerBound.position - m_origin; auto lowerBoundVector = lowerBound.position - m_origin;
auto upperBoundVector = upperBound.position - m_origin; auto upperBoundVector = upperBound.position - m_origin;
if (not hasFlags(Flags::infiniteLength)) 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; temp = sf::Vertex{ constructVector(m_origin, sf::degrees(angleIncrement * i), m_rayLength), m_lightColor };
for (int i = 0; i < m_rayCount; i++)
{
sf::Vertex temp{ constructVector(m_origin, sf::degrees(angleIncrement * i), m_rayLength), m_lightColor };
if (withinBounds(temp.position - m_origin, lowerBoundVector, upperBoundVector)) if (withinBounds(temp.position - m_origin, lowerBoundVector, upperBoundVector)) m_rays.emplace_back(temp);
{
m_rays.emplace_back(temp);
}
}
} }
} }
m_rays.emplace_back(lowerBound); constexpr float infiniteLength = 5000.f;
sf::Angle angle;
for (auto& poly : polygons) for (auto& poly : polygons)
{ {
@ -142,45 +141,46 @@ void Light::createAndSortRays(const std::vector<sf::VertexArray>& polygons, sf::
{ {
if (poly[i].position == m_origin) continue;// cannot pass zero vector to sf::Vector2::angleTo() 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 (hasFlags(Flags::infiniteLength) ? false : distanceBetween(m_origin, poly[i].position) >= m_rayLength) continue;
{
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));
m_rays.emplace_back(sf::Vertex{ poly[i].position, m_lightColor }); if (not withinBounds(poly[i].position - m_origin, lowerBoundVector, upperBoundVector)) continue;
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 }); 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 + (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(); }); 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<sf::VertexArray>& polygons) void Light::calculateIntersects(const std::vector<sf::VertexArray>& polygons)
{ {
std::optional<sf::Vector2f> currentIntersect{};
for (auto& ray : m_rays) for (auto& ray : m_rays)
{ {
sf::Vector2f closestIntersection = ray.position; sf::Vector2f closestIntersection = ray.position;
std::optional<sf::Vector2f> currentIntersect{}; currentIntersect.reset();
for (auto& poly : polygons) 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 }); currentIntersect = lineIntersect({ m_origin, ray.position }, { poly[i - 1].position , poly[i].position });
if (currentIntersect)
{ if (not currentIntersect) continue;
if ((closestIntersection - m_origin).length() > (currentIntersect.value() - m_origin).length()) if ((closestIntersection - m_origin).length() < (currentIntersect.value() - m_origin).length()) continue;
{
closestIntersection = currentIntersect.value(); closestIntersection = currentIntersect.value();
}
}
} }
} }
ray.position = closestIntersection; ray.position = closestIntersection;
} }
@ -190,3 +190,4 @@ bool Light::withinBounds(sf::Vector2f point, sf::Vector2f lower, sf::Vector2f up
{ {
return point.angleTo(upper).wrapUnsigned().asRadians() < (lower).angleTo(upper).wrapUnsigned().asRadians(); return point.angleTo(upper).wrapUnsigned().asRadians() < (lower).angleTo(upper).wrapUnsigned().asRadians();
} }

42
Light.h
View File

@ -10,38 +10,26 @@
#include <imgui.h> #include <imgui.h>
#include "Utility.hpp" #include "Utility.hpp"
#include "Ray.h"
class Light class Light
{ {
public: 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}); m_light.push_back(sf::Vertex{ m_origin, m_lightColor});
if (visible) visible ? setFlags(Flags::visibility) : unsetFlags(Flags::visibility);
{
setFlags(Flags::visibility);
}
else
{
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_center(center)
, m_offset(offset) , m_offset(offset)
, m_origin(origin)
{ {
m_light.push_back(sf::Vertex{}); m_light.push_back(sf::Vertex{ m_origin, m_lightColor });
if (visible) visible ? setFlags(Flags::visibility) : unsetFlags(Flags::visibility);
{
setFlags(Flags::visibility);
}
else
{
unsetFlags(Flags::visibility);
}
} }
enum class Flags enum class Flags
@ -99,21 +87,31 @@ private:
std::vector<sf::Vertex> m_rays{}; std::vector<sf::Vertex> m_rays{};
std::optional<sf::Angle> m_center{}; std::optional<sf::Angle> m_center{};
std::optional<sf::Angle> m_offset{}; std::optional<sf::Angle> m_offset{};
sf::Vector2f m_origin{};
sf::Color m_lightColor{ sf::Color::Yellow }; sf::Color m_lightColor{ sf::Color::Yellow };
sf::Color m_endPointColor{ sf::Color::Magenta }; sf::Color m_endPointColor{ sf::Color::Magenta };
sf::Color m_rayColor{ sf::Color::Red }; sf::Color m_rayColor{ sf::Color::Red };
sf::Vector2f m_origin{};
float m_rayLength{ 500.f }; float m_rayLength{ 500.f };
int m_rayCount{ 500 }; int m_rayCount{ 500 };
int m_flags{}; int m_flags{};
enum
{
start,
end
};//used for sf::VertexArray index
private: private:
void constructFullLight(const std::vector<sf::VertexArray>& polygons); void constructFullLight(const std::vector<sf::VertexArray>& polygons);
void constructPartialLight(const std::vector<sf::VertexArray>& polygons); void constructPartialLight(const std::vector<sf::VertexArray>& polygons);
void createAndSortRays(const std::vector<sf::VertexArray>& polygons); void createAndSortRays(const std::vector<sf::VertexArray>& polygons);
void createAndSortRays(const std::vector<sf::VertexArray>& polygons, sf::Angle lowerAngleBounds, sf::Angle upperAngleBounds);// for bounded light void createAndSortRays(const std::vector<sf::VertexArray>& polygons, sf::Angle lowerAngleBounds, sf::Angle upperAngleBounds);// for bounded light
void calculateIntersects(const std::vector<sf::VertexArray>& polygons); void calculateIntersects(const std::vector<sf::VertexArray>& polygons);
bool withinBounds(sf::Vector2f point, sf::Vector2f lower, sf::Vector2f upper); bool withinBounds(sf::Vector2f point, sf::Vector2f lower, sf::Vector2f upper);
}; };

View File

@ -3,6 +3,6 @@ Pos=60,60
Size=400,400 Size=400,400
[Window][Config] [Window][Config]
Pos=7,11 Pos=6,12
Size=670,442 Size=670,442

View File

@ -22,10 +22,16 @@ sf::Vector2f mousePos{};
sf::Vector2f center{ 1920.f / 2.f, 1080.f / 2.f }; sf::Vector2f center{ 1920.f / 2.f, 1080.f / 2.f };
//imGui Variables //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 }; float polySize[2] = { 100.f, 100.f };
int numRays{ 500 }; int numRays{ 500 };
int vertexBounds[2] = { 3u, 10u }; int vertexBounds[2] = { 3, 10 };
int averageSize{ 100u }; int averageSize{ 100 };
float rayLength{ 500.f }; float rayLength{ 500.f };
imguiColor rayColor = constructImguiColor(sf::Color::Red); imguiColor rayColor = constructImguiColor(sf::Color::Red);
imguiColor lightColor = constructImguiColor(sf::Color::Yellow); imguiColor lightColor = constructImguiColor(sf::Color::Yellow);
@ -35,8 +41,8 @@ bool drawLight{ true };
bool drawEndPoints{ false }; bool drawEndPoints{ false };
bool boundedLight{ false }; bool boundedLight{ false };
bool infiniteRayLength{ false }; bool infiniteRayLength{ false };
int lightCenterAngle{ 0 }; float lightCenterAngle{ 0.f };
int lightOffsetAngle{ 45 }; float lightOffsetAngle{ 45.f };
void GUI(); void GUI();
void userInput(); void userInput();
@ -44,6 +50,11 @@ void render();
int main() 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 //sfml setup
sf::Clock clock; sf::Clock clock;
@ -88,62 +99,34 @@ void GUI()
ImGui::Unindent(); ImGui::Unindent();
if (ImGui::Checkbox("Render rays", &drawRays)) if (ImGui::Checkbox("Render rays", &drawRays))
{ {
if (drawRays) light.toggleFlags(Light::Flags::drawRays);
{
light.setFlags(Light::Flags::drawRays);
}
else
{
light.unsetFlags(Light::Flags::drawRays);
}
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Checkbox("Render end points", &drawEndPoints)) if (ImGui::Checkbox("Render end points", &drawEndPoints))
{ {
if (drawEndPoints) light.toggleFlags(Light::Flags::drawEndPoints);
{
light.setFlags(Light::Flags::drawEndPoints);
}
else
{
light.unsetFlags(Light::Flags::drawEndPoints);
}
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Checkbox("Render light", &drawLight)) if (ImGui::Checkbox("Render light", &drawLight))
{ {
if (drawLight) light.toggleFlags(Light::Flags::visibility);
{
light.setFlags(Light::Flags::visibility);
}
else
{
light.unsetFlags(Light::Flags::visibility);
}
} }
if (ImGui::Checkbox("Infinite ray length", &infiniteRayLength)) if (ImGui::Checkbox("Infinite ray length", &infiniteRayLength))
{ {
if (infiniteRayLength) light.toggleFlags(Light::Flags::infiniteLength);
{
light.setFlags(Light::Flags::infiniteLength);
}
else
{
light.unsetFlags(Light::Flags::infiniteLength);
}
} }
if (not infiniteRayLength) if (not infiniteRayLength)
{ {
ImGui::SliderInt("number of rays", &numRays, 5, 500); ImGui::SliderInt("number of rays", &numRays, numRaysBounds[0], numRaysBounds[1]);
light.setRayCount(numRays); light.setRayCount(numRays);
if (ImGui::InputFloat("Ray Length", &rayLength)) 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); light.setRayLength(rayLength);
} }
@ -168,36 +151,21 @@ void GUI()
if(ImGui::Checkbox("Light is bounded", &boundedLight)) if(ImGui::Checkbox("Light is bounded", &boundedLight))
{ {
if (boundedLight) boundedLight ? light.addAngleBounds(sf::degrees(lightCenterAngle), sf::degrees(lightOffsetAngle)) : light.removeAngleBounds();
{
light.addAngleBounds(sf::degrees((float)lightCenterAngle), sf::degrees((float)lightOffsetAngle));
}
else
{
light.removeAngleBounds();
}
} }
if (boundedLight) if (boundedLight)
{ {
ImGui::SliderInt("Light direction", &lightCenterAngle, 0, 359); ImGui::SliderFloat("Light direction", &lightCenterAngle, 0.f, 359.f, "%.0f", ImGuiSliderFlags_::ImGuiSliderFlags_AlwaysClamp);
light.setCenterAngle(sf::degrees((float)lightCenterAngle)); light.setCenterAngle(sf::degrees(lightCenterAngle));
if (ImGui::InputInt("Offset size", &lightOffsetAngle)) ImGui::SliderFloat("Offset size", &lightOffsetAngle, offsetAngleBounds[0], offsetAngleBounds[1], "%.0f", ImGuiSliderFlags_::ImGuiSliderFlags_AlwaysClamp);
{ light.setOffsetAngle(sf::degrees(lightOffsetAngle));
if (lightOffsetAngle > 175)
{
lightOffsetAngle = 175;
}
if (lightOffsetAngle < 5)
{
lightOffsetAngle = 5;
}
}
light.setOffsetAngle(sf::degrees((float)lightOffsetAngle));
} }
ImGui::InputFloat2("rectangle Size (X,Y)", polySize, "%.1f"); ImGui::InputFloat2("rectangle Size (X,Y)", polySize, "%.1f");
ImGui::Text("Random polygon config: "); 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]) if (vertexBounds[0] > vertexBounds[1])
vertexBounds[0] = vertexBounds[1]; vertexBounds[0] = vertexBounds[1];
@ -269,7 +237,11 @@ void userInput()
{ {
case sf::Mouse::Wheel::Vertical: case sf::Mouse::Wheel::Vertical:
if (boundedLight) 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; break;
default: default: