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

@ -8,25 +8,27 @@ void Light::draw(sf::RenderWindow& window)
}
if (hasFlags(Flags::drawRays))
{
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;
for (auto& ray : m_rays)
{
tempRay[end].position = ray.position;
window.draw(tempRay);
}
}
if (hasFlags(Flags::drawEndPoints))
{
for (auto& ray : m_rays)
{
sf::CircleShape endPoint(5.f, 20u);
endPoint.setOrigin({ 5, 5 });
endPoint.setFillColor(m_endPointColor);
for (auto& ray : m_rays)
{
endPoint.setPosition(ray.position);
window.draw(endPoint);
}
@ -86,24 +88,25 @@ void Light::createAndSortRays(const std::vector<sf::VertexArray>& 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 });
}
}
}
std::sort(m_rays.begin(), m_rays.end(), [&](const auto& lhs, const auto& rhs) { return (lhs.position - m_origin).angle().wrapUnsigned().asRadians() < (rhs.position - m_origin).angle().wrapUnsigned().asRadians(); });
}
@ -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)
{
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++)
{
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<sf::VertexArray>& 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{ 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<sf::VertexArray>& polygons)
{
std::optional<sf::Vector2f> currentIntersect{};
for (auto& ray : m_rays)
{
sf::Vector2f closestIntersection = ray.position;
std::optional<sf::Vector2f> 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())
{
if (not currentIntersect) continue;
if ((closestIntersection - m_origin).length() < (currentIntersect.value() - m_origin).length()) continue;
closestIntersection = currentIntersect.value();
}
}
}
}
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();
}

42
Light.h
View File

@ -10,38 +10,26 @@
#include <imgui.h>
#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<sf::Vertex> m_rays{};
std::optional<sf::Angle> m_center{};
std::optional<sf::Angle> 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<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, sf::Angle lowerAngleBounds, sf::Angle upperAngleBounds);// for bounded light
void calculateIntersects(const std::vector<sf::VertexArray>& polygons);
bool withinBounds(sf::Vector2f point, sf::Vector2f lower, sf::Vector2f upper);
};

View File

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

View File

@ -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));
boundedLight ? light.addAngleBounds(sf::degrees(lightCenterAngle), sf::degrees(lightOffsetAngle)) : light.removeAngleBounds();
}
else
{
light.removeAngleBounds();
}
}
if (boundedLight)
{
ImGui::SliderInt("Light direction", &lightCenterAngle, 0, 359);
light.setCenterAngle(sf::degrees((float)lightCenterAngle));
if (ImGui::InputInt("Offset size", &lightOffsetAngle))
if (boundedLight)
{
if (lightOffsetAngle > 175)
{
lightOffsetAngle = 175;
}
if (lightOffsetAngle < 5)
{
lightOffsetAngle = 5;
}
}
light.setOffsetAngle(sf::degrees((float)lightOffsetAngle));
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, 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: