major code rewrite.
-rays are now handled inside class Ray -constructRay function removed as the functionality is replaced by Ray's constructor - added an unnamed enum to make indexing Ray::m_points more clear - Ray::angle is used to keep track of the angle to +x, is updated when any point in Ray::m_points is updated - Helper.hpp has been renamed to Utility.hpp -all functions that were above main() are now in Utility.hpp -rays now behave like a light source -rays get sorted by angle and get placed into a TriangleFan which is drawn as the light source -added additional options to the imgui menu
This commit is contained in:
parent
b9ea5bd951
commit
637dc7e821
43
Helper.hpp
43
Helper.hpp
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// a collection of useful funtions that i use across projects
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <tuple>
|
|
||||||
#include <SFML/Graphics.hpp>
|
|
||||||
#include <imgui-SFML.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
#include "Random.h"
|
|
||||||
|
|
||||||
template<typename T, typename U, typename V>
|
|
||||||
T getRandomNumber(U min, V max)
|
|
||||||
{
|
|
||||||
return static_cast<T>(Random::get(min, max));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename U, typename V, typename W>
|
|
||||||
inline sf::Color createColor(T r, U g, V b, W a)
|
|
||||||
{
|
|
||||||
return sf::Color(static_cast<std::uint8_t>(r), static_cast<std::uint8_t>(g), static_cast<std::uint8_t>(b), static_cast<std::uint8_t>(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename U, typename V>
|
|
||||||
inline sf::Color createColor(T r, U g, V b, std::uint8_t a = 255u)
|
|
||||||
{
|
|
||||||
return sf::Color(static_cast<std::uint8_t>(r), static_cast<std::uint8_t>(g), static_cast<std::uint8_t>(b), a);
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Color getRandomColor()
|
|
||||||
{
|
|
||||||
return sf::Color(getRandomNumber<std::uint8_t>(0u, 255u), getRandomNumber<std::uint8_t>(0u, 255u), getRandomNumber<std::uint8_t>(0u, 255u));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T signage(T in)
|
|
||||||
{
|
|
||||||
T zero{};
|
|
||||||
if (in > zero) return ++zero;
|
|
||||||
if (in < zero) return --zero;
|
|
||||||
return zero;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
#include "Ray.h"
|
||||||
|
|
||||||
|
Ray::Ray(sf::Vector2f startPoint, sf::Vector2f endPoint, sf::Color color)
|
||||||
|
{
|
||||||
|
m_points[start].position = startPoint;
|
||||||
|
m_points[start].color = color;
|
||||||
|
m_points[end].position = endPoint;
|
||||||
|
m_points[end].color = color;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ray::Ray(sf::Vector2f startPoint, float length, sf::Angle angle, sf::Color color)
|
||||||
|
{
|
||||||
|
m_points[start].position = startPoint;
|
||||||
|
m_points[start].color = color;
|
||||||
|
m_points[end].position = constructVector(startPoint, angle, length);
|
||||||
|
m_points[end].color = color;
|
||||||
|
m_angle = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ray::Ray(const Ray& ray)
|
||||||
|
{
|
||||||
|
auto& newPoints = ray.points();
|
||||||
|
m_points[start].position = newPoints[start].position;
|
||||||
|
m_points[start].color = newPoints[start].color;
|
||||||
|
m_points[end].position = newPoints[end].position;
|
||||||
|
m_points[end].color = newPoints[end].color;
|
||||||
|
m_angle = ray.angle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::change(const Ray& ray, bool copyColor)
|
||||||
|
{
|
||||||
|
auto& newPoints = ray.points();
|
||||||
|
m_points[start].position = newPoints[start].position;
|
||||||
|
m_points[end].position = newPoints[end].position;
|
||||||
|
if (copyColor)
|
||||||
|
{
|
||||||
|
m_points[start].color = newPoints[start].color;
|
||||||
|
m_points[end].color = newPoints[0].color;
|
||||||
|
}
|
||||||
|
m_angle = ray.angle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::change(sf::Vector2f startPoint, sf::Vector2f endPoint)
|
||||||
|
{
|
||||||
|
m_points[start].position = startPoint;
|
||||||
|
m_points[end].position = endPoint;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::change(sf::Vector2f startPoint, sf::Vector2f endPoint, sf::Color color)
|
||||||
|
{
|
||||||
|
m_points[start].position = startPoint;
|
||||||
|
m_points[start].color = color;
|
||||||
|
m_points[end].position = endPoint;
|
||||||
|
m_points[end].color = color;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::changeStart(sf::Vector2f startPoint, sf::Color color)
|
||||||
|
{
|
||||||
|
m_points[start].position = startPoint;
|
||||||
|
m_points[start].color = color;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::changeStart(sf::Vector2f startPoint)
|
||||||
|
{
|
||||||
|
m_points[start].position = startPoint;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::changeStart(const Ray& ray, bool copyColor)
|
||||||
|
{
|
||||||
|
auto& newStart = ray.points()[0];
|
||||||
|
m_points[start].position = newStart.position;
|
||||||
|
if (copyColor) m_points[start].color = newStart.color;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::changeEnd(sf::Vector2f endPoint, sf::Color color)
|
||||||
|
{
|
||||||
|
m_points[end].position = endPoint;
|
||||||
|
m_points[end].color = color;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::changeEnd(sf::Vector2f endPoint)
|
||||||
|
{
|
||||||
|
m_points[end].position = endPoint;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::changeEnd(const Ray& ray, bool copyColor)
|
||||||
|
{
|
||||||
|
auto& newEnd = ray.points()[end];
|
||||||
|
m_points[end].position = newEnd.position;
|
||||||
|
if (copyColor) m_points[end].color = newEnd.color;
|
||||||
|
if (m_points[start].position - m_points[end].position == sf::Vector2f{ 0.f, 0.f })
|
||||||
|
{
|
||||||
|
m_angle = sf::Angle::Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_angle = sf::radians(std::atan2f(m_points[end].position.y - m_points[start].position.y, m_points[end].position.x - m_points[start].position.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ray::changeColor(sf::Color color)
|
||||||
|
{
|
||||||
|
m_points[start].color = color;
|
||||||
|
m_points[end].color = color;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
#pragma once
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <imgui-SFML.h>
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "Utility.hpp"
|
||||||
|
|
||||||
|
//used for sf::VertexArray index
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
};
|
||||||
|
|
||||||
|
class Ray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Ray(sf::Vector2f startPoint, sf::Vector2f endPoint, sf::Color color = sf::Color::Red);
|
||||||
|
Ray(sf::Vector2f startPoint, float length, sf::Angle angle, sf::Color color = sf::Color::Red);
|
||||||
|
Ray(const Ray& ray);
|
||||||
|
|
||||||
|
~Ray() = default;
|
||||||
|
|
||||||
|
const sf::Angle& angle() const { return m_angle; }
|
||||||
|
const sf::VertexArray& points() const { return m_points; }
|
||||||
|
|
||||||
|
void change(const Ray& ray, bool copyColor = false);
|
||||||
|
void change(sf::Vector2f startPoint, sf::Vector2f endPoint);
|
||||||
|
void change(sf::Vector2f startPoint, sf::Vector2f endPoint, sf::Color color);
|
||||||
|
|
||||||
|
void changeStart(sf::Vector2f startPoint, sf::Color color);
|
||||||
|
void changeStart(sf::Vector2f startPoint);
|
||||||
|
void changeStart(const Ray& ray, bool copyColor = false);
|
||||||
|
|
||||||
|
void changeEnd(sf::Vector2f endPoint, sf::Color color);
|
||||||
|
void changeEnd(sf::Vector2f endPoint);
|
||||||
|
void changeEnd(const Ray& ray, bool copyColor = false);
|
||||||
|
|
||||||
|
void changeColor(sf::Color color);
|
||||||
|
|
||||||
|
bool operator== (const Ray& rhs)
|
||||||
|
{
|
||||||
|
return m_points[start].position == rhs.points()[start].position and m_points[end].position == rhs.points()[end].position;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ray operator+ (const Ray& rhs)
|
||||||
|
{
|
||||||
|
return Ray(this->m_points[start].position + rhs.m_points[start].position, this->m_points[end].position + rhs.m_points[end].position);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ray operator- (const Ray& rhs)
|
||||||
|
{
|
||||||
|
return Ray(this->m_points[start].position - rhs.m_points[start].position, this->m_points[end].position - rhs.m_points[end].position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
sf::VertexArray m_points{ sf::PrimitiveType::Lines, 2 };//points[0] = origin of ray, points[1] = end of ray
|
||||||
|
sf::Angle m_angle{};
|
||||||
|
};
|
||||||
|
|
||||||
|
using RayVector = std::vector<Ray>;
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <tuple>
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <imgui-SFML.h>
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "Random.h"
|
||||||
|
#include "Ray.h"
|
||||||
|
|
||||||
|
template<typename T, typename U, typename V>
|
||||||
|
inline T getRandomNumber(U min, V max)
|
||||||
|
{
|
||||||
|
return static_cast<T>(Random::get(min, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U, typename V, typename W>
|
||||||
|
inline sf::Color createColor(T r, U g, V b, W a)
|
||||||
|
{
|
||||||
|
return sf::Color(static_cast<std::uint8_t>(r), static_cast<std::uint8_t>(g), static_cast<std::uint8_t>(b), static_cast<std::uint8_t>(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U, typename V>
|
||||||
|
inline sf::Color createColor(T r, U g, V b, std::uint8_t a = 255u)
|
||||||
|
{
|
||||||
|
return sf::Color(static_cast<std::uint8_t>(r), static_cast<std::uint8_t>(g), static_cast<std::uint8_t>(b), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sf::Color getRandomColor()
|
||||||
|
{
|
||||||
|
return sf::Color(getRandomNumber<std::uint8_t>(0u, 255u), getRandomNumber<std::uint8_t>(0u, 255u), getRandomNumber<std::uint8_t>(0u, 255u));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline T signage(T in)
|
||||||
|
{
|
||||||
|
T zero{};
|
||||||
|
if (in > zero) return ++zero;
|
||||||
|
if (in < zero) return --zero;
|
||||||
|
return zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LineSegment
|
||||||
|
{
|
||||||
|
sf::Vector2f startPoint{};
|
||||||
|
|
||||||
|
sf::Vector2f endPoint{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct imguiColor
|
||||||
|
{
|
||||||
|
float r{};
|
||||||
|
float g{};
|
||||||
|
float b{};
|
||||||
|
float a{ 1.f };
|
||||||
|
|
||||||
|
sf::Color asSfColor()
|
||||||
|
{
|
||||||
|
return sf::Color(std::uint8_t(r * 255.f), std::uint8_t(g * 255.f), std::uint8_t(b * 255.f), std::uint8_t(a * 255.f));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline imguiColor constructImguiColor(sf::Color color)
|
||||||
|
{
|
||||||
|
return imguiColor((float)color.r / 255.f, (float)color.g / 255.f, (float)color.b / 255.f, (float)color.a / 255.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::optional<sf::Vector2f> lineIntersect(LineSegment first, LineSegment second)
|
||||||
|
{
|
||||||
|
sf::Vector2f firstVector = (first.endPoint - first.startPoint);
|
||||||
|
sf::Vector2f secondVector = (second.endPoint - second.startPoint);
|
||||||
|
|
||||||
|
float lengthCrossProduct = firstVector.cross(secondVector);
|
||||||
|
|
||||||
|
sf::Vector2f fms = second.startPoint - first.startPoint; //first line start point minus second
|
||||||
|
|
||||||
|
float firstScalar = fms.cross(secondVector) / lengthCrossProduct;
|
||||||
|
float secondScalar = fms.cross(firstVector) / lengthCrossProduct;
|
||||||
|
|
||||||
|
if ((firstScalar >= 0 and firstScalar <= 1) and (secondScalar >= 0 and secondScalar <= 1))
|
||||||
|
return sf::Vector2f(first.startPoint.x + (firstScalar * firstVector.x), first.startPoint.y + (firstScalar * firstVector.y));
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sf::VertexArray constructRectangle(sf::Vector2f center, sf::Vector2f size, sf::Color color = sf::Color::Black)
|
||||||
|
{
|
||||||
|
sf::VertexArray rectangle(sf::PrimitiveType::LineStrip, 5);
|
||||||
|
rectangle[0].color = color;
|
||||||
|
rectangle[1].color = color;
|
||||||
|
rectangle[2].color = color;
|
||||||
|
rectangle[3].color = color;
|
||||||
|
rectangle[4].color = color;
|
||||||
|
|
||||||
|
rectangle[0].position = { center.x - size.x, center.y - size.y };
|
||||||
|
rectangle[1].position = { center.x + size.x, center.y - size.y };
|
||||||
|
rectangle[2].position = { center.x + size.x, center.y + size.y };
|
||||||
|
rectangle[3].position = { center.x - size.x, center.y + size.y };
|
||||||
|
rectangle[4].position = rectangle[0].position;
|
||||||
|
|
||||||
|
return rectangle;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sf::Vector2f constructVector(sf::Vector2f startPoint, sf::Angle angle, float length)
|
||||||
|
{
|
||||||
|
return { startPoint.x + (length * std::cos(angle.asRadians())), startPoint.y + (length * std::sin(angle.asRadians())) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sf::VertexArray constructRandomPolygon(sf::Vector2f center, int vertexLowerBound, int vertexUpperBound, int averageSize, sf::Color color = sf::Color::Black)
|
||||||
|
{
|
||||||
|
std::size_t vertexCount = getRandomNumber<std::size_t>(vertexLowerBound, vertexUpperBound);
|
||||||
|
sf::VertexArray polygon(sf::PrimitiveType::LineStrip, vertexCount);
|
||||||
|
|
||||||
|
float angleIncrement = 360.f / (float)(vertexCount - 1);
|
||||||
|
float angleStart = getRandomNumber<float>(0, 360);
|
||||||
|
|
||||||
|
for (int i = 0; i < vertexCount - 1; i++)
|
||||||
|
{
|
||||||
|
float angleOffset = getRandomNumber<float>(-(90 / (int)vertexCount), (90 / (int)vertexCount));
|
||||||
|
polygon[i].color = color;
|
||||||
|
polygon[i].position = constructVector(center, sf::degrees(angleStart + (angleIncrement * i) + angleOffset), getRandomNumber<float>((averageSize - 50), (averageSize + 50)));
|
||||||
|
}
|
||||||
|
polygon[vertexCount - 1].position = polygon[0].position;
|
||||||
|
polygon[vertexCount - 1].color = color;
|
||||||
|
return polygon;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float distanceBetween(sf::Vector2f startPoint, sf::Vector2f endPoint)
|
||||||
|
{
|
||||||
|
return sqrtf(powf(endPoint.x - startPoint.x, 2) + powf(endPoint.y - startPoint.y, 2));
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,6 @@ Pos=60,60
|
||||||
Size=400,400
|
Size=400,400
|
||||||
|
|
||||||
[Window][Config]
|
[Window][Config]
|
||||||
Pos=7,8
|
Pos=7,7
|
||||||
Size=705,277
|
Size=710,322
|
||||||
|
|
||||||
|
|
|
||||||
212
main.cpp
212
main.cpp
|
|
@ -1,111 +1,15 @@
|
||||||
#include <SFML/Graphics.hpp>
|
|
||||||
#include <imgui-SFML.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#include "Helper.hpp"
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <imgui-SFML.h>
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
struct LineSegment
|
#include "Utility.hpp"
|
||||||
{
|
#include "Ray.h"
|
||||||
sf::Vector2f startPoint{};
|
|
||||||
|
|
||||||
sf::Vector2f endPoint{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct imguiColor
|
|
||||||
{
|
|
||||||
float r{};
|
|
||||||
float g{};
|
|
||||||
float b{};
|
|
||||||
float a{1.f};
|
|
||||||
|
|
||||||
sf::Color asSfColor()
|
|
||||||
{
|
|
||||||
return sf::Color(std::uint8_t(r * 255.f), std::uint8_t(g * 255.f), std::uint8_t(b * 255.f), std::uint8_t(a * 255.f));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
imguiColor constructImguiColor(sf::Color color)
|
|
||||||
{
|
|
||||||
return imguiColor((float)color.r / 255.f, (float)color.g / 255.f, (float)color.b / 255.f, (float)color.a / 255.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<sf::Vector2f> lineIntersect(LineSegment first, LineSegment second)
|
|
||||||
{
|
|
||||||
sf::Vector2f firstVector = (first.endPoint - first.startPoint);
|
|
||||||
sf::Vector2f secondVector = (second.endPoint - second.startPoint);
|
|
||||||
|
|
||||||
float lengthCrossProduct = firstVector.cross(secondVector);
|
|
||||||
|
|
||||||
sf::Vector2f fms = second.startPoint - first.startPoint; //first line start point minus second
|
|
||||||
|
|
||||||
float firstScalar = fms.cross(secondVector) / lengthCrossProduct;
|
|
||||||
float secondScalar = fms.cross(firstVector) / lengthCrossProduct;
|
|
||||||
|
|
||||||
if ((firstScalar >= 0 and firstScalar <= 1) and (secondScalar >= 0 and secondScalar <= 1))
|
|
||||||
return sf::Vector2f(first.startPoint.x + (firstScalar * firstVector.x), first.startPoint.y + (firstScalar * firstVector.y));
|
|
||||||
else
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::VertexArray constructRectangle(sf::Vector2f center, sf::Vector2f size, sf::Color color = sf::Color::Black)
|
|
||||||
{
|
|
||||||
sf::VertexArray rectangle(sf::PrimitiveType::LineStrip, 5);
|
|
||||||
rectangle[0].color = color;
|
|
||||||
rectangle[1].color = color;
|
|
||||||
rectangle[2].color = color;
|
|
||||||
rectangle[3].color = color;
|
|
||||||
rectangle[4].color = color;
|
|
||||||
|
|
||||||
rectangle[0].position = { center.x - size.x, center.y - size.y };
|
|
||||||
rectangle[1].position = { center.x + size.x, center.y - size.y };
|
|
||||||
rectangle[2].position = { center.x + size.x, center.y + size.y };
|
|
||||||
rectangle[3].position = { center.x - size.x, center.y + size.y };
|
|
||||||
rectangle[4].position = { center.x - size.x, center.y - size.y };
|
|
||||||
|
|
||||||
return rectangle;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Vector2f constructVector(sf::Vector2f startPoint, sf::Angle angle, float length)
|
|
||||||
{
|
|
||||||
return { startPoint.x + (length * std::cos(angle.asRadians())), startPoint.y + (length * std::sin(angle.asRadians())) };
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::VertexArray constructRandomPolygon(sf::Vector2f center, int vertexLowerBound, int vertexUpperBound, int averageSize, sf::Color color = sf::Color::Black)
|
|
||||||
{
|
|
||||||
size_t vertexCount = getRandomNumber<size_t>(vertexLowerBound, vertexUpperBound);
|
|
||||||
sf::VertexArray polygon(sf::PrimitiveType::LineStrip, vertexCount);
|
|
||||||
|
|
||||||
float angleIncrement = 360.f / (float)(vertexCount - 1);
|
|
||||||
float angleStart = getRandomNumber<float>(0, 360);
|
|
||||||
|
|
||||||
for (int i = 0; i < vertexCount - 1; i++)
|
|
||||||
{
|
|
||||||
float angleOffset = getRandomNumber<float>(-(90 / (int)vertexCount), (90 / (int)vertexCount));
|
|
||||||
polygon[i].color = color;
|
|
||||||
polygon[i].position = constructVector(center, sf::degrees(angleStart + (angleIncrement * i) + angleOffset), getRandomNumber<float>((averageSize - 50), (averageSize + 50)));
|
|
||||||
}
|
|
||||||
polygon[vertexCount - 1].position = polygon[0].position;
|
|
||||||
polygon[vertexCount - 1].color = color;
|
|
||||||
return polygon;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::VertexArray constructRay(sf::Vector2f start, float length, sf::Angle angle, sf::Color color = sf::Color::Red)
|
|
||||||
{
|
|
||||||
sf::VertexArray ray(sf::PrimitiveType::Lines, 2);
|
|
||||||
|
|
||||||
ray[0].position = start;
|
|
||||||
ray[0].color = color;
|
|
||||||
ray[1].position = constructVector(start, angle, length);
|
|
||||||
ray[1].color = color;
|
|
||||||
|
|
||||||
return ray;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|
@ -123,28 +27,26 @@ int main()
|
||||||
|
|
||||||
//imGui Variables
|
//imGui Variables
|
||||||
float polySize[2] = { 100.f, 100.f };
|
float polySize[2] = { 100.f, 100.f };
|
||||||
int numRays{ 10 };
|
int numRays{ 500 };
|
||||||
int vertexBounds[2] = { 3u, 10u };
|
int vertexBounds[2] = { 3u, 10u };
|
||||||
int averageSize{ 100u };
|
int averageSize{ 100u };
|
||||||
float rayLength{ 5000.f };
|
float rayLength{ 500.f };
|
||||||
imguiColor rayColor = constructImguiColor(sf::Color::Red);
|
imguiColor rayColor = constructImguiColor(sf::Color::Red);
|
||||||
|
imguiColor lightColor = constructImguiColor(sf::Color::Red);
|
||||||
|
bool drawRays{ false };
|
||||||
|
bool drawLight{ true };
|
||||||
|
|
||||||
|
|
||||||
//initalize vectors
|
//initalize vectors
|
||||||
std::vector<sf::VertexArray> rays;
|
RayVector rays;
|
||||||
|
|
||||||
{
|
|
||||||
float i = 0.f, angleIncrement = 360.f / (float)numRays;
|
|
||||||
for (int i = 0; i < numRays; i++) rays.push_back(constructRay(mousePos, rayLength, sf::degrees(angleIncrement * i), rayColor.asSfColor()));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<sf::VertexArray> polygons;
|
std::vector<sf::VertexArray> polygons;
|
||||||
polygons.push_back(constructRectangle(center, center));//outer bounds of the window
|
polygons.push_back(constructRectangle(center, center));
|
||||||
|
|
||||||
|
|
||||||
//main game loop
|
//main game loop
|
||||||
while (window.isOpen())
|
while (window.isOpen())
|
||||||
{
|
{
|
||||||
|
rays.clear();
|
||||||
//handle input
|
//handle input
|
||||||
while (const std::optional event = window.pollEvent())
|
while (const std::optional event = window.pollEvent())
|
||||||
{
|
{
|
||||||
|
|
@ -161,13 +63,16 @@ int main()
|
||||||
{
|
{
|
||||||
case sf::Keyboard::Scancode::C:
|
case sf::Keyboard::Scancode::C:
|
||||||
polygons.clear();
|
polygons.clear();
|
||||||
polygons.push_back(constructRectangle(center, center));//outer bounds of the window
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sf::Keyboard::Scancode::R:
|
case sf::Keyboard::Scancode::R:
|
||||||
polygons.push_back(constructRandomPolygon(mousePos, vertexBounds[0] + 1, vertexBounds[1] + 1, averageSize));
|
polygons.push_back(constructRandomPolygon(mousePos, vertexBounds[0] + 1, vertexBounds[1] + 1, averageSize));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case sf::Keyboard::Scancode::Escape:
|
||||||
|
window.close();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -186,44 +91,72 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rays.empty()) continue;
|
|
||||||
if (const auto* mouseMoved = event->getIf<sf::Event::MouseMoved>())
|
if (const auto* mouseMoved = event->getIf<sf::Event::MouseMoved>())
|
||||||
{
|
{
|
||||||
mousePos = (sf::Vector2f)mouseMoved->position;
|
mousePos = (sf::Vector2f)mouseMoved->position;
|
||||||
for (auto& ray : rays) ray[0].position = mousePos;
|
for (auto& ray : rays) ray.changeStart(mousePos);
|
||||||
}
|
}
|
||||||
}// end user input loop
|
}// end user input loop
|
||||||
|
|
||||||
|
if (numRays > 0)
|
||||||
{
|
{
|
||||||
float i = 0, angleIncrement = 360.f / (float)rays.size();
|
float i = 0.f, angleIncrement = 360.f / (float)numRays;
|
||||||
for (auto& ray : rays)
|
for (int i = 0; i < numRays; i++) rays.push_back(Ray(mousePos, rayLength, sf::degrees(angleIncrement * i), rayColor.asSfColor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& poly : polygons)
|
||||||
{
|
{
|
||||||
ray[1].position = constructVector(ray[0].position, sf::degrees(i * angleIncrement), rayLength);
|
for (std::size_t i = 0; i < poly.getVertexCount() - 1; i++)
|
||||||
i++;
|
{
|
||||||
|
if (distanceBetween(mousePos, poly[i].position) <= rayLength)
|
||||||
|
{
|
||||||
|
sf::Angle angle = sf::radians(std::atan2f(poly[i].position.y - mousePos.y, poly[i].position.x - mousePos.x));
|
||||||
|
rays.push_back(Ray(mousePos, poly[i].position, rayColor.asSfColor()));
|
||||||
|
rays.push_back(Ray(mousePos, rayLength, angle + sf::radians(.00001f), rayColor.asSfColor()));
|
||||||
|
rays.push_back(Ray(mousePos, rayLength, angle - sf::radians(.00001f), rayColor.asSfColor()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& ray : rays)
|
for (auto& ray : rays)
|
||||||
{
|
{
|
||||||
sf::Vector2f closestIntersection = ray[1].position;
|
auto& rayPoints = ray.points();
|
||||||
|
sf::Vector2f closestIntersection = rayPoints[end].position;
|
||||||
std::optional<sf::Vector2f> currentIntersect{};
|
std::optional<sf::Vector2f> currentIntersect{};
|
||||||
for (auto& poly : polygons)
|
for (auto& poly : polygons)
|
||||||
{
|
{
|
||||||
for (int i = 1; i <= poly.getVertexCount() - 1; i++) {
|
for (int i = 1; i <= poly.getVertexCount() - 1; i++) {
|
||||||
currentIntersect = lineIntersect({ ray[0].position, ray[1].position }, { poly[i - 1].position , poly[i].position });
|
currentIntersect = lineIntersect({ rayPoints[start].position, rayPoints[end].position }, { poly[i - 1].position , poly[i].position });
|
||||||
if (currentIntersect)
|
if (currentIntersect)
|
||||||
{
|
{
|
||||||
if ((closestIntersection - ray[0].position).length() > (currentIntersect.value() - ray[0].position).length())
|
if ((closestIntersection - rayPoints[start].position).length() > (currentIntersect.value() - rayPoints[start].position).length())
|
||||||
{
|
{
|
||||||
closestIntersection = currentIntersect.value();
|
closestIntersection = currentIntersect.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ray.changeEnd(closestIntersection);
|
||||||
ray[1].position = closestIntersection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::sort(rays.begin(), rays.end(), [](const auto& lhs, const auto& rhs) { return lhs.angle().wrapUnsigned().asRadians() < rhs.angle().wrapUnsigned().asRadians(); });
|
||||||
|
|
||||||
|
sf::VertexArray light(sf::PrimitiveType::TriangleFan, 1);
|
||||||
|
if (not rays.empty())
|
||||||
|
{
|
||||||
|
light[0].position = mousePos;
|
||||||
|
light[0].color = lightColor.asSfColor();
|
||||||
|
for (auto& ray : rays)
|
||||||
|
{
|
||||||
|
light.append(ray.points()[end]);
|
||||||
|
}
|
||||||
|
light.append(rays.front().points()[end]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < light.getVertexCount(); i++)
|
||||||
|
light[i].color = lightColor.asSfColor();
|
||||||
|
|
||||||
|
|
||||||
ImGui::SFML::Update(window, clock.restart());
|
ImGui::SFML::Update(window, clock.restart());
|
||||||
|
|
||||||
ImGui::Begin("Config");
|
ImGui::Begin("Config");
|
||||||
|
|
@ -233,24 +166,28 @@ int main()
|
||||||
ImGui::Text("R: place a randomly sized polygon at mouse position");
|
ImGui::Text("R: place a randomly sized polygon at mouse position");
|
||||||
ImGui::Text("C: clear all polygons");
|
ImGui::Text("C: clear all polygons");
|
||||||
ImGui::Unindent();
|
ImGui::Unindent();
|
||||||
if (ImGui::SliderInt("number of rays", &numRays, 0, 50))
|
ImGui::Checkbox("Render rays", &drawRays);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Checkbox("Render light", &drawLight);
|
||||||
|
if (ImGui::SliderInt("number of rays", &numRays, 5, 500))
|
||||||
{
|
{
|
||||||
rays.clear();
|
rays.clear();
|
||||||
|
|
||||||
{
|
{
|
||||||
float i = 0.f, angleIncrement = 360.f / (float)numRays;
|
float i = 0.f, angleIncrement = 360.f / (float)numRays;
|
||||||
for (int i = 0; i < numRays; i++) rays.push_back(constructRay(mousePos, rayLength, sf::degrees(angleIncrement * i), rayColor.asSfColor()));
|
for (int i = 0; i < numRays; i++) rays.push_back(Ray(mousePos, rayLength, sf::degrees(angleIncrement * i), rayColor.asSfColor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ImGui::InputFloat("Ray Length", &rayLength);
|
ImGui::InputFloat("Ray Length", &rayLength);
|
||||||
if (ImGui::ColorEdit3("Ray color", &rayColor.r))
|
if (ImGui::ColorEdit3("Ray color", &rayColor.r))
|
||||||
{
|
{
|
||||||
for (auto& ray : rays)
|
for (auto& ray : rays) ray.changeColor(rayColor.asSfColor());
|
||||||
{
|
|
||||||
ray[0].color = rayColor.asSfColor();
|
|
||||||
ray[1].color = rayColor.asSfColor();
|
|
||||||
}
|
}
|
||||||
|
if (ImGui::ColorEdit3("Light color", &lightColor.r))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < light.getVertexCount(); i++)
|
||||||
|
light[i].color = lightColor.asSfColor();
|
||||||
}
|
}
|
||||||
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: ");
|
||||||
|
|
@ -263,7 +200,7 @@ int main()
|
||||||
vertexBounds[0] = vertexBounds[1];
|
vertexBounds[0] = vertexBounds[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ImGui::InputInt("Average size", &averageSize))
|
if (ImGui::InputInt("Average size", &averageSize))
|
||||||
{
|
{
|
||||||
if (averageSize < 20)
|
if (averageSize < 20)
|
||||||
{
|
{
|
||||||
|
|
@ -276,18 +213,23 @@ int main()
|
||||||
window.clear(sf::Color::White);
|
window.clear(sf::Color::White);
|
||||||
|
|
||||||
//render entities
|
//render entities
|
||||||
for (auto& poly : polygons)
|
for (auto& poly : polygons) window.draw(poly);
|
||||||
window.draw(poly);
|
|
||||||
|
|
||||||
|
if (drawRays)
|
||||||
|
{
|
||||||
for (auto& ray : rays)
|
for (auto& ray : rays)
|
||||||
{
|
{
|
||||||
|
auto& rayPoints = ray.points();
|
||||||
sf::CircleShape endPoint(5.f, 20u);
|
sf::CircleShape endPoint(5.f, 20u);
|
||||||
endPoint.setOrigin({ 5, 5 });
|
endPoint.setOrigin({ 5, 5 });
|
||||||
endPoint.setFillColor(rayColor.asSfColor());
|
endPoint.setFillColor(rayColor.asSfColor());
|
||||||
endPoint.setPosition(ray[1].position);
|
endPoint.setPosition(rayPoints[end].position);
|
||||||
window.draw(ray);
|
window.draw(rayPoints);
|
||||||
window.draw(endPoint);
|
window.draw(endPoint);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawLight) window.draw(light);
|
||||||
|
|
||||||
ImGui::SFML::Render(window);
|
ImGui::SFML::Render(window);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,10 +143,12 @@
|
||||||
<ClCompile Include="..\..\..\..\..\dev\libraries\imgui\imgui_tables.cpp" />
|
<ClCompile Include="..\..\..\..\..\dev\libraries\imgui\imgui_tables.cpp" />
|
||||||
<ClCompile Include="..\..\..\..\..\dev\libraries\imgui\imgui_widgets.cpp" />
|
<ClCompile Include="..\..\..\..\..\dev\libraries\imgui\imgui_widgets.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="Ray.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Helper.hpp" />
|
<ClInclude Include="Utility.hpp" />
|
||||||
<ClInclude Include="Random.h" />
|
<ClInclude Include="Random.h" />
|
||||||
|
<ClInclude Include="Ray.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,12 @@
|
||||||
<Filter Include="Source Files\Imgui-sfml Files">
|
<Filter Include="Source Files\Imgui-sfml Files">
|
||||||
<UniqueIdentifier>{20b9a3b4-eb7c-4baa-be0b-c6e0d295c347}</UniqueIdentifier>
|
<UniqueIdentifier>{20b9a3b4-eb7c-4baa-be0b-c6e0d295c347}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes">
|
||||||
|
<UniqueIdentifier>{fe3c7015-3de6-4e35-adea-c623dcb78c0a}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\Classes">
|
||||||
|
<UniqueIdentifier>{a5f9e058-615a-4f77-a4a5-50a0c3ab5cd7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
|
|
@ -36,13 +42,19 @@
|
||||||
<ClCompile Include="..\..\..\..\..\dev\libraries\imgui\imgui-SFML.cpp">
|
<ClCompile Include="..\..\..\..\..\dev\libraries\imgui\imgui-SFML.cpp">
|
||||||
<Filter>Source Files\Imgui-sfml Files</Filter>
|
<Filter>Source Files\Imgui-sfml Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Ray.cpp">
|
||||||
|
<Filter>Source Files\Classes</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Helper.hpp">
|
<ClInclude Include="Utility.hpp">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Random.h">
|
<ClInclude Include="Random.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Ray.h">
|
||||||
|
<Filter>Header Files\Classes</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
Loading…
Reference in New Issue