Skip to content

Instantly share code, notes, and snippets.

@andraantariksa
Created October 22, 2020 12:33
Show Gist options
  • Save andraantariksa/5b5ec0e03f9876432c252f068e0c5806 to your computer and use it in GitHub Desktop.
Save andraantariksa/5b5ec0e03f9876432c252f068e0c5806 to your computer and use it in GitHub Desktop.
#include "RenderSystem.hpp"
#include <SFML/Graphics.hpp>
#include <entt/entt.hpp>
#include <glm/glm.hpp>
#include <cmath>
#include "../Component/TransformComponent.hpp"
#include "../Component/SphereComponent.hpp"
#include "../Util/Logger.hpp"
#define PI 3.14159265358979323846f
#define RAD 0.0174533f
RenderSystem::RenderSystem() :
m_MatTransform(1.0f)
{
const float scaleX = 1.0f;
const float scaleY = 1.0f;
const float translateX = 300.0f;
const float translateY = 300.0f;
const float zc = 500.0f;
// TODO
// Fix perspective projection
// St
m_MatTransform = glm::mat4(
glm::vec4(scaleX, 0.0f, 0.0f, 0.0f),
glm::vec4(0.0f, -scaleY, 0.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
glm::vec4(translateX, translateY, 0.0f, 1.0f)
);
// Vt
m_MatTransform = glm::mat4(
glm::vec4(1.0f, 0.0f, 0.0f, 0.0f),
glm::vec4(0.0f, 1.0f, 0.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.0f, -1.0f / zc),
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)
) * m_MatTransform;
}
void RenderSystem::Render(entt::registry& registry, sf::RenderWindow& window)
{
registry.view<SphereComponent, TransformComponent>().each([&](auto entity, SphereComponent& sphere, const TransformComponent& transform)
{
// Draw the vertices
/*
auto circle = sf::CircleShape(2.0f);
circle.setFillColor(sf::Color::Red);
for (glm::vec4& vertex : m_EntitySphere.m_Vertices)
{
auto s = Normalize3DToProjectionSFML(vertex, transform);
circle.setPosition(s);
window.draw(circle);
}
*/
// TODO
// Parallelize the code?
// https://en.cppreference.com/w/cpp/algorithm/execution_policy_tag_t
// https://docs.microsoft.com/en-us/cpp/parallel/concrt/how-to-write-a-parallel-for-loop?view=vs-2019
// Toggle backface cull
if (sphere.m_IsCullBackface)
{
const glm::vec3 dop(0.0f, 0.0f, -1.0f);
// In case you want to use surface
//sf::ConvexShape convex(3);
//convex.setFillColor(sf::Color::Green);
//convex.setOutlineColor(sf::Color::Green);
//convex.setOutlineThickness(1.0f);
// Bottom part
for (size_t i = 0; i < sphere.m_NLongitude - 1; ++i)
{
const glm::vec3 v1 = Normalize3DToProjection(sphere.m_Vertices[i + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[i + 2], transform);
const glm::vec3 v2 = Normalize3DToProjection(sphere.m_Vertices[0], transform) - Normalize3DToProjection(sphere.m_Vertices[i + 1], transform);
if (glm::cross(v1, v2).z < 0.0f)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[i + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[0], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[0], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[i + 2], transform))
};
window.draw(line, 6, sf::Lines);
// In case you want to use surface
//convex.setPoint(0, Normalize3DToProjectionSFML(m_EntitySphere.m_Vertices[0], transform));
//convex.setPoint(1, Normalize3DToProjectionSFML(m_EntitySphere.m_Vertices[i + 1], transform));
//convex.setPoint(2, Normalize3DToProjectionSFML(m_EntitySphere.m_Vertices[i + 2], transform));
//window.draw(convex);
}
}
const glm::vec3 v1 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude], transform) - Normalize3DToProjection(sphere.m_Vertices[1], transform);
const glm::vec3 v2 = Normalize3DToProjection(sphere.m_Vertices[0], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude], transform);
if (glm::cross(v1, v2).z < 0.0f)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[0], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[0], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[1], transform))
};
window.draw(line, 6, sf::Lines);
}
// Middle part
for (size_t i = 1; i < sphere.m_NLatitude * 2 - 1; ++i)
{
for (size_t j = 0; j < sphere.m_NLongitude - 1; ++j)
{
const glm::vec3 v1 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform);
const glm::vec3 v2 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform);
if (glm::dot(glm::cross(v1, v2), dop) > 0.0f)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
};
window.draw(line, 6, sf::Lines);
}
const glm::vec3 v3 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 2], transform);
const glm::vec3 v4 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform);
if (glm::dot(glm::cross(v3, v4), dop) > 0.0f)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 2], transform))
};
window.draw(line, 6, sf::Lines);
}
}
const size_t j = sphere.m_NLongitude - 1;
const glm::vec3 v1 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform);
const glm::vec3 v2 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform);
if (glm::cross(v1, v2).z < 0.0f)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform))
};
window.draw(line, 6, sf::Lines);
}
const glm::vec3 v3 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + 1], transform);
const glm::vec3 v4 = Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform);
if (glm::cross(v3, v4).z < 0.0f)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + 1], transform))
};
window.draw(line, 6, sf::Lines);
}
}
// Top part
const size_t topMostVertex = sphere.m_NLongitude * (sphere.m_NLatitude * 2 - 1) + 2 - 1;
for (size_t i = 0; i < sphere.m_NLongitude - 1; ++i)
{
const glm::vec3 v1 = Normalize3DToProjection(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i], transform);
const glm::vec3 v2 = Normalize3DToProjection(sphere.m_Vertices[topMostVertex], transform) - Normalize3DToProjection(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i + 1], transform);
if (glm::cross(v1, v2).z < 0.0f)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i], transform))
};
window.draw(line, 6, sf::Lines);
}
}
const glm::vec3 v3 = Normalize3DToProjection(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + 1], transform) - Normalize3DToProjection(sphere.m_Vertices[topMostVertex - 1], transform);
const glm::vec3 v4 = Normalize3DToProjection(sphere.m_Vertices[topMostVertex], transform) - Normalize3DToProjection(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + 1], transform);
if (glm::cross(v3, v4).z < 0.0f)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - 1], transform))
};
window.draw(line, 6, sf::Lines);
}
}
else
{
// Bottom part
for (size_t i = 0; i < sphere.m_NLongitude - 1; ++i)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[i + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[0], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[0], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[i + 2], transform))
};
window.draw(line, 6, sf::Lines);
// In case you want to use surface
//convex.setPoint(0, Normalize3DToProjection(m_EntitySphere.m_Vertices[0], transform));
//convex.setPoint(1, Normalize3DToProjection(m_EntitySphere.m_Vertices[i + 1], transform));
//convex.setPoint(2, Normalize3DToProjection(m_EntitySphere.m_Vertices[i + 2], transform));
//window.draw(convex);
}
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[0], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[0], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[1], transform))
};
window.draw(line, 6, sf::Lines);
// Middle part
for (size_t i = 1; i < sphere.m_NLatitude * 2 - 1; ++i)
{
for (size_t j = 0; j < sphere.m_NLongitude - 1; ++j)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 2], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 2], transform))
};
window.draw(line, 12, sf::Lines);
}
const size_t j = sphere.m_NLongitude - 1;
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + j + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[sphere.m_NLongitude * (i - 1) + 1], transform))
};
window.draw(line, 12, sf::Lines);
}
// Top part
const size_t topMostVertex = sphere.m_NLongitude * (sphere.m_NLatitude * 2 - 1) + 2 - 1;
for (size_t i = 0; i < sphere.m_NLongitude - 1; ++i)
{
sf::Vertex line[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + i], transform))
};
window.draw(line, 6, sf::Lines);
}
sf::Vertex line2[] =
{
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - sphere.m_NLongitude + 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex - 1], transform)),
sf::Vertex(Normalize3DToProjectionSFML(sphere.m_Vertices[topMostVertex], transform))
};
window.draw(line, 6, sf::Lines);
/*auto circle = sf::CircleShape(2.0f);
circle.setFillColor(sf::Color::Red);
for (glm::vec4& vertex : sphere.m_Vertices)
{
auto s = Normalize3DToProjectionSFML(vertex, transform);
circle.setPosition(s);
window.draw(circle);
}*/
}
});
}
// TODO
// Remove debug
int once = 10;
inline sf::Vector2f RenderSystem::Normalize3DToProjectionSFML(const glm::vec4& v, const TransformComponent& transform)
{
if (once > 0)
{
std::cout << v.x << " " << v.y << " " << v.z << " " << v.w << '\n';
}
const glm::vec4& result = Normalize3DToProjection(v, transform);
if (once-- > 0)
{
std::cout << result.x << " " << result.y << " " << result.z << " " << result.w << '\n';
if (once == 1)
{
std::cout << glm::to_string(m_MatTransform) << '\n';
}
}
// TODO
// Remove manual translation
return sf::Vector2f(result.x / result.w, result.y / result.w);
}
inline glm::vec4 RenderSystem::Normalize3DToProjection(const glm::vec4& v, const TransformComponent& transform)
{
if (once == 1)
{
std::cout << glm::to_string(transform.m_MatTransform) << '\n';
}
return std::move(m_MatTransform * transform.m_MatTransform * v);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment