Commit 0bdf6069 authored by unknown's avatar unknown
Browse files

Cleaned up quite some stuff

parent 94a72f77
#ifndef __GLARE_INCLUDE_ADVANCED
#define __GLARE_INCLUDE_ADVANCED
#include <advanced/BVH.h>
#include <advanced/IntersectionTests.h>
#include <advanced/KdTree.h>
#include <advanced/LineSpace.h>
#include <advanced/LineSpaceMath.h>
#include <advanced/LineSpaceMaskGenerator.h>
#include <advanced/Photonmapper.h>
#include <advanced/RayGenerator.h>
#include <advanced/Raytracer.h>
#include <advanced/SceneCollector.h>
#include <advanced/TreeVoxelizer.h>
#include <advanced/MeshBVH.h>
#include <advanced/MeshCollector.h>
#include <advanced/MeshSceneCollector.h>
#include <advanced/linespace/LineSpaceMath.h>
#include <advanced/linespace/LineSpaceMaskGenerator.h>
#include <advanced/tracer/RayGenerator.h>
#include <advanced/tracer/Raytracer.h>
#include <advanced/meshlocal/LocalBVH.h>
#include <advanced/meshlocal/LocalCollector.h>
#include <advanced/meshlocal/SceneCollector.h>
#endif //!__GLARE_INCLUDE_ADVANCED
\ No newline at end of file
#include "Application.h"
#include <advanced/FlatVoxelizer.h>
#include <engine/graphics/ImageTexture2DMultisample.h>
#include <components/Rotator.h>
......@@ -47,24 +46,13 @@ namespace glare
//Create a skybox from cube map.
m_skybox = std::make_shared<core::Skybox>(core::Skybox::collectFilesFrom(core::asset("/textures/ryfjallet/")));
initializeScene(core::asset("/meshes/scenery/Spheres.dae"), 1.f);
initializeScene(core::asset("/meshes/s.dae"), 1.f);
initializeRenderRequirements();
initializeAdvanced();
initializeGUI();
gl::setEnabled(gl::EnableParameter::eMultisample, true);
#ifdef DEBUG__ADD_ROTATOR
for (auto &&node : m_scene_root)
{
if (auto&& mesh = node->getComponent<core::MeshRenderer>())
{
mesh->getOwner()->addComponent(std::make_shared<component::Rotator>());
break;
}
}
#endif
glare::core::EngineState::opengl_core->loop([&](double delta)
{
//General state updates (camera and so on)
......@@ -108,7 +96,7 @@ namespace glare
}
drawGUI();
drawVoxelController();
//drawVoxelController();
ImGui::End();
drawSceneSelector();
......@@ -153,6 +141,25 @@ namespace glare
}
cam_node->makeComponent<component::PlayerController>();
m_scene_root->makeComponent<component::FramerateCounter>();
#define DEBUG__ADD_ROTATOR
#ifdef DEBUG__ADD_ROTATOR
for (auto &&node : m_scene_root)
{
Log_Info << node->name();
std::string name = "#Cylinder-mesh";
if (auto&& mesh = node->getComponent<core::MeshRenderer>())
{
if (mesh->getOwner()->name() == name) {
mesh->getOwner()->addComponent(std::make_shared<component::Rotator>());
break;
}
}
}
#endif
}
void Application::initializeRenderRequirements()
......@@ -172,18 +179,18 @@ namespace glare
void Application::initializeAdvanced()
{
m_mesh_collector = std::make_shared<advanced::MeshSceneCollector>(m_scene_root);
m_collector = std::make_shared<advanced::SceneCollector>(m_scene_root);
//Initialize Raytracer
m_raytracer = std::make_shared<advanced::Raytracer>(m_mesh_collector, std::make_shared<advanced::RayGeneratorDefault>());
m_raytracer = std::make_shared<advanced::Raytracer>(m_collector, std::make_shared<advanced::RayGeneratorDefault>());
m_raytracer->setSkybox(m_skybox);
}
void Application::updateAdvanced()
{
m_mesh_collector->setDirty(advanced::MeshSceneCollector::DirtyFlags::eAll);
m_mesh_collector->collect(m_scene_root);
m_raytracer->initialize(m_mesh_collector);
m_collector->setDirty(advanced::SceneCollector::DirtyFlags::eAll);
m_collector->collect(m_scene_root);
m_raytracer->initialize(m_collector);
}
void Application::initializeGUI()
......@@ -257,10 +264,10 @@ namespace glare
if (spfr != m_raytracer->samplesPerFrame())
m_raytracer->setSamplesPerFrame(spfr);
bool collector_active = m_mesh_collector->isActive();
bool collector_active = m_collector->isActive();
ImGui::Checkbox("Collector active", &collector_active);
if (collector_active != m_mesh_collector->isActive())
m_mesh_collector->setActive(collector_active);
if (collector_active != m_collector->isActive())
m_collector->setActive(collector_active);
if (ImGui::Button("Save Render"))
{
......@@ -294,7 +301,7 @@ namespace glare
ImGui::Begin("Scenes", nullptr, ImVec2(200, 300));
ImGui::Title(m_current_scene_root.string().c_str());
ImGui::DragFloat("Scale", &m_import_scale, 0.01f, 0.01f, 1.0f);
ImGui::DragFloat("Scale", &m_import_scale, 0.01f, 0.01f, 100.0f);
ImGui::BeginGroup();
if (ImGui::Button("..", ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
{
......
......@@ -13,6 +13,8 @@
namespace glare
{
namespace fs = std::experimental::filesystem;
enum class AppRenderState
{
eLines = 0,
......@@ -62,11 +64,8 @@ namespace glare
std::shared_ptr<core::TextureRenderer> m_texture_renderer_default;
//Advanced
std::shared_ptr<advanced::MeshSceneCollector> m_mesh_collector;
std::shared_ptr<advanced::TreeVoxelizer> m_voxelizer;
std::shared_ptr<advanced::SceneCollector> m_collector;
std::shared_ptr<advanced::Raytracer> m_raytracer;
std::unique_ptr<advanced::TreeVoxelRenderer> m_voxel_renderer;
std::unique_ptr<advanced::LineSpace> m_linespace;
AppRenderState m_render_state = AppRenderState::eDefault;
AppRayGenState m_ray_gen_state = AppRayGenState::eDefault;
......
......@@ -4,7 +4,7 @@ namespace glare
{
namespace advanced
{
void IntersectionUtilities::sortTriangleLongestAxis(math::Triangle &triangle)
void Intersections::sortTriangleLongestAxis(math::Triangle &triangle)
{
math::Bounds bounds;
bounds.expand(triangle.a);
......@@ -16,7 +16,7 @@ namespace glare
sortByAxis(triangle.a, triangle.b, triangle.c, largest_component);
}
bool IntersectionUtilities::planeBoxOverlap(const glm::vec3 &n, const glm::vec3 &v0, const glm::vec3 &halfsize)
bool Intersections::planeBoxOverlap(const glm::vec3 &n, const glm::vec3 &v0, const glm::vec3 &halfsize)
{
glm::vec3 vMin, vMax;
float v;
......
......@@ -6,156 +6,158 @@
#include <glm/ext.hpp>
#include <engine/Math.h>
//Sorry, had to do this for the ease of use.
#define d_intersects_impl(One, Other) template<> static bool intersects<Other, One>(const Other &other, const One &one) \
{\
return intersects<One, Other>(one, other); \
}\
template<> static bool intersects<One, Other> \
namespace glare
{
namespace advanced
{
constexpr float TRIANGLE_UV_BIAS = 1e-5f;
enum Axis
/**
* Class containing all intersection tests between objects as template functions.
*/
class Intersections
{
X = 0,
Y = 1,
Z = 2
};
public:
class IntersectionUtilities
{
friend class Intersections;
/**
* @brief Template function for intersecting an object from type One to one from type Other.
* @tparam One One intersection candidate type.
* @tparam Other The other intersection candidate type.
*/
template<typename One, typename Other>
static bool intersects(const One &one, const Other &other) {
}
/**
* @brief (Specialization) Triangle-AABB intersection test. Two implementation for parameter bidirectionality.
*/
template<> static bool intersects<math::Triangle, math::Bounds>(const math::Triangle &c_triangle, const math::Bounds &bounds);
template<> static bool intersects<math::Bounds, math::Triangle>(const math::Bounds &bounds, const math::Triangle &c_triangle);
private:
static void sortTriangleLongestAxis(math::Triangle &triangle);
static bool planeBoxOverlap(const glm::vec3 &n, const glm::vec3 &v0, const glm::vec3 &bounds_halfsize);
template<typename VecType>
static void sortByAxis(VecType &a, VecType &b, VecType &c, int axis)
{
if (a[axis] < b[axis]) std::swap(a, b);
if (b[axis] < c[axis]) std::swap(b, c);
if (a[axis] < b[axis]) std::swap(a, b);
}
static void sortByAxis(VecType &a, VecType &b, VecType &c, int axis);
};
class Intersections
template<typename VecType>
static void Intersections::sortByAxis(VecType &a, VecType &b, VecType &c, int axis)
{
public:
if (a[axis] < b[axis]) std::swap(a, b);
if (b[axis] < c[axis]) std::swap(b, c);
if (a[axis] < b[axis]) std::swap(a, b);
}
template<typename One, typename Other>
static bool intersects(const One &one, const Other &other)
{
Log_Warn << "No intersection specialized between " << typeid(One).name() << " and " << typeid(Other).name();
template<>
static bool Intersections::intersects<math::Bounds, math::Triangle>(const math::Bounds &bounds, const math::Triangle &c_triangle)
{
return intersects(c_triangle, bounds);
}
template<>
static bool Intersections::intersects<math::Triangle, math::Bounds>(const math::Triangle &c_triangle, const math::Bounds &bounds)
{
// SAT: Separating Axis Theorem
// Two convex polyhedra A and B are disjoint, if they can be separated along either an axis parallel to a normal of a face of either A or B,
// or along an Axis formed from the cross product of an edge from A widh an edge from B.
// ------------------------------------------------------------------------------------------------------------------------------------------
// 1) Project triangle points on x, y and z min and max plane normals. Quit if disjoint.
// 2) Project AABB points on triangle normal. Quit if disjoint.
// ------------------------------------------------------------------------------------------------------------------------------------------
// Projection procedure: Calculate vector cp from plane center (eg x max = bounds.max-vec3(0, half[y], half[z])) to triangle point.
// Then check dot(cp, plane_normal) < 0.
math::Triangle triangle = c_triangle;
glm::vec3 bounds_halfsize = bounds.size().xyz * 0.5f;
glm::vec3 mid = bounds.min.xyz + bounds_halfsize;
glm::vec3 mid_distances[3] = { (triangle.a.xyz - mid), (triangle.b.xyz - mid), (triangle.c.xyz - mid) };
Intersections::sortTriangleLongestAxis(triangle);
// --------------------------------------- NEEDED ----------------------------------------------------
float sidedness_max;
float sidedness_min;
int i;
// ---------------------------------------------------------------------------------------------------
// --------------------------------------- X AXIS ----------------------------------------------------
// Check separating min and max planes on x-plane
glm::vec3 plane_max = bounds.max.xyz - glm::vec3(0, bounds_halfsize[1], bounds_halfsize[2]);
glm::vec3 plane_min = bounds.min.xyz + glm::vec3(0, bounds_halfsize[1], bounds_halfsize[2]);
bool separate_min = true;
bool separate_max = true;
for (i = 0; i < 3; i++) {
sidedness_max = glm::dot(triangle[i].xyz - plane_max, glm::vec3(1, 0, 0));
sidedness_min = glm::dot(triangle[i].xyz - plane_min, glm::vec3(-1, 0, 0));
//separate is true, if all sidedness values are >1.
separate_max &= sidedness_max > 0;
separate_min &= sidedness_min > 0;
}
if (separate_min || separate_max)
return false;
// ---------------------------------------------------------------------------------------------------
// --------------------------------------- Y AXIS ----------------------------------------------------
// Check separating min and max planes on y-plane
plane_max = bounds.max.xyz - glm::vec3(bounds_halfsize[0], 0, bounds_halfsize[2]);
plane_min = bounds.min.xyz + glm::vec3(bounds_halfsize[0], 0, bounds_halfsize[2]);
separate_min = true;
separate_max = true;
for (i = 0; i < 3; i++) {
sidedness_max = glm::dot(triangle[i].xyz - plane_max, glm::vec3(0, 1, 0));
sidedness_min = glm::dot(triangle[i].xyz - plane_min, glm::vec3(0, -1, 0));
//separate is true, if all sidedness values are >1.
separate_max &= sidedness_max > 0;
separate_min &= sidedness_min > 0;
}
d_intersects_impl(math::Triangle, math::Bounds)(const math::Triangle &c_triangle, const math::Bounds &bounds)
{
// SAT: Separating Axis Theorem
// Two convex polyhedra A and B are disjoint, if they can be separated along either an axis parallel to a normal of a face of either A or B,
// or along an Axis formed from the cross product of an edge from A widh an edge from B.
// ------------------------------------------------------------------------------------------------------------------------------------------
// 1) Project triangle points on x, y and z min and max plane normals. Quit if disjoint.
// 2) Project AABB points on triangle normal. Quit if disjoint.
// ------------------------------------------------------------------------------------------------------------------------------------------
// Projection procedure: Calculate vector cp from plane center (eg x max = bounds.max-vec3(0, half[y], half[z])) to triangle point.
// Then check dot(cp, plane_normal) < 0.
math::Triangle triangle = c_triangle;
glm::vec3 bounds_halfsize = bounds.size().xyz * 0.5f;
glm::vec3 mid = bounds.min.xyz + bounds_halfsize;
glm::vec3 mid_distances[3] = { (triangle.a.xyz - mid), (triangle.b.xyz - mid), (triangle.c.xyz - mid) };
IntersectionUtilities::sortTriangleLongestAxis(triangle);
// --------------------------------------- NEEDED ----------------------------------------------------
float sidedness_max;
float sidedness_min;
int i;
// ---------------------------------------------------------------------------------------------------
// --------------------------------------- X AXIS ----------------------------------------------------
// Check separating min and max planes on x-plane
glm::vec3 plane_max = bounds.max.xyz - glm::vec3(0, bounds_halfsize[Y], bounds_halfsize[Z]);
glm::vec3 plane_min = bounds.min.xyz + glm::vec3(0, bounds_halfsize[Y], bounds_halfsize[Z]);
bool separate_min = true;
bool separate_max = true;
for (i = 0; i < 3; i++) {
sidedness_max = glm::dot(triangle[i].xyz - plane_max, glm::vec3(1, 0, 0));
sidedness_min = glm::dot(triangle[i].xyz - plane_min, glm::vec3(-1, 0, 0));
//separate is true, if all sidedness values are >1.
separate_max &= sidedness_max > 0;
separate_min &= sidedness_min > 0;
}
if (separate_min || separate_max)
return false;
// ---------------------------------------------------------------------------------------------------
// --------------------------------------- Y AXIS ----------------------------------------------------
// Check separating min and max planes on y-plane
plane_max = bounds.max.xyz - glm::vec3(bounds_halfsize[X], 0, bounds_halfsize[Z]);
plane_min = bounds.min.xyz + glm::vec3(bounds_halfsize[X], 0, bounds_halfsize[Z]);
separate_min = true;
separate_max = true;
for (i = 0; i < 3; i++) {
sidedness_max = glm::dot(triangle[i].xyz - plane_max, glm::vec3(0, 1, 0));
sidedness_min = glm::dot(triangle[i].xyz - plane_min, glm::vec3(0, -1, 0));
//separate is true, if all sidedness values are >1.
separate_max &= sidedness_max > 0;
separate_min &= sidedness_min > 0;
}
if (separate_min || separate_max)
return false;
// ---------------------------------------------------------------------------------------------------
// --------------------------------------- Z AXIS ----------------------------------------------------
// Check separating min and max planes on z-plane
plane_max = bounds.max.xyz - glm::vec3(bounds_halfsize[X], bounds_halfsize[Y], 0);
plane_min = bounds.min.xyz + glm::vec3(bounds_halfsize[X], bounds_halfsize[Y], 0);
separate_min = true;
separate_max = true;
for (i = 0; i < 3; i++) {
sidedness_max = glm::dot(triangle[i].xyz - plane_max, glm::vec3(0, 0, 1));
sidedness_min = glm::dot(triangle[i].xyz - plane_min, glm::vec3(0, 0, -1));
//separate is true, if all sidedness values are >1.
separate_max &= sidedness_max > 0;
separate_min &= sidedness_min > 0;
}
if (separate_min || separate_max)
return false;
// ---------------------------------------------------------------------------------------------------
// -------------------------------------- TRIANGLE ---------------------------------------------------
// Check separating from triangle
glm::vec3 normal = triangle.normal().xyz;
separate_min = true;
separate_max = true;
for (int sign : {-1, 1}) {
for (i = -1; i < 3; i++)
if (separate_min || separate_max)
return false;
// ---------------------------------------------------------------------------------------------------
// --------------------------------------- Z AXIS ----------------------------------------------------
// Check separating min and max planes on z-plane
plane_max = bounds.max.xyz - glm::vec3(bounds_halfsize[0], bounds_halfsize[1], 0);
plane_min = bounds.min.xyz + glm::vec3(bounds_halfsize[0], bounds_halfsize[1], 0);
separate_min = true;
separate_max = true;
for (i = 0; i < 3; i++) {
sidedness_max = glm::dot(triangle[i].xyz - plane_max, glm::vec3(0, 0, 1));
sidedness_min = glm::dot(triangle[i].xyz - plane_min, glm::vec3(0, 0, -1));
//separate is true, if all sidedness values are >1.
separate_max &= sidedness_max > 0;
separate_min &= sidedness_min > 0;
}
if (separate_min || separate_max)
return false;
// ---------------------------------------------------------------------------------------------------
// -------------------------------------- TRIANGLE ---------------------------------------------------
// Check separating from triangle
glm::vec3 normal = triangle.normal().xyz;
separate_min = true;
separate_max = true;
for (int sign : {-1, 1}) {
for (i = -1; i < 3; i++)
{
glm::vec3 corner = bounds[(sign + 1) / 2].xyz;
if (i >= 0)
{
glm::vec3 corner = bounds[(sign + 1) / 2].xyz;
if (i >= 0)
{
corner[i] += 2 * sign * bounds_halfsize[i];
}
sidedness_min = glm::dot(corner - triangle.a.xyz, normal);
separate_min &= sidedness_min < 0;
separate_max &= sidedness_min > 0;
corner[i] += 2 * sign * bounds_halfsize[i];
}
sidedness_min = glm::dot(corner - triangle.a.xyz, normal);
separate_min &= sidedness_min < 0;
separate_max &= sidedness_min > 0;
}
if (separate_min || separate_max)
return false;
// ---------------------------------------------------------------------------------------------------
return true;
}
};
if (separate_min || separate_max)
return false;
// ---------------------------------------------------------------------------------------------------
return true;
}
}
}
......
......@@ -12,6 +12,15 @@ namespace glare
{
namespace advanced
{
enum class KdNodeType : uint32_t
{
eInner = 0,
eLeaf = 1
};
/**
* @brief Contains the data and according 3D-position of the KD node.
*/
template<typename T>
struct KdDataContainer
{
......@@ -19,12 +28,10 @@ namespace glare
T data;
};
enum class KdNodeType : uint32_t
{
eInner = 0,
eLeaf = 1
};
/**
* @brief A KD node containing it's split axis, the split median value on this axis, the type and it's location in the KDtree
* by it's parent and children. The latter ones can either be buffer positions of further nodes, or just the KdDataContainer indices.
*/
struct KdNode
{
uint32_t axis = 0;
......@@ -37,6 +44,9 @@ namespace glare
uint32_t padding[2];
};
/**
* @brief Helper struct for parallelization of the KD tree construction.
*/
struct KdTreeAtomicContainer
{
std::atomic_int active_node_calculations;
......@@ -44,15 +54,22 @@ namespace glare
std::atomic_int node_position;
};
/**
* @brief Kind of a utility class for generating a KD-Tree
*/
template<typename T>
class KdTreeCreator
{
public:
/**
* @brief Creates a KD-Tree into the linear node buffer. The dataset will be sorted accordingly.
* @param data The input data set. (non-const, will be reordered in the process)
* @nodes The vector in which you want to store the resulting KD-Tree
*/
static void makeKdTree(std::vector<KdDataContainer<T>>& data, std::vector<KdNode>& nodes);
private:
static void sort(uint32_t node_index, std::vector<KdDataContainer<T>>& data, std::vector<KdNode>& nodes, KdTreeAtomicContainer& container);
static uint8_t getLongestAxis(typename std::vector<KdDataContainer<T>>::iterator begin, typename std::vector<KdDataContainer<T>>::iterator end, glm::vec4& size);
};
......
#include "LineSpaceMaskGenerator.h"
#include <engine/Log.h>
#include <engine/Time.h>
#include <set>
#include <fstream>
#include <io/AlignedCompress.h>
namespace glare
{
namespace advanced
{
LineSpaceHelper::LineSpaceHelper(size_t resolution)
{
m_resolution = resolution;
m_resolution2 = m_resolution * m_resolution;
m_resolution2_6 = 6 * m_resolution2;
m_face_mirrored = { 3, 4, 5, 0, 1, 2 };
m_face_dim_axis_mirrored = {
{-1, 0, 1},
{0, -1, 1},
{0, 1, -1},
{-1, 0, 1},
{0, -1, 1},
{0, 1, -1}
};
}
void LineSpaceHelper::getDimensionFromShaftNum(int num, int &face, int &dimA, int &dimB) const
{
face = int(num / m_resolution2);
dimB = int((num % m_resolution2) / m_resolution);
dimA = int(num % m_resolution);
}
void LineSpaceHelper::getDimensionsFromShaftNum(int num, int &sface, int &sdimA, int &sdimB, int &eface, int &edimA, int &edimB) const
{
getDimensionFromShaftNum(int(num / m_resolution2_6), sface, sdimA, sdimB);
getDimensionFromShaftNum(int(num % m_resolution2_6), eface, edimA, edimB);
}
int LineSpaceHelper::getShaftNumFromDimension(int face, int dimA, int dimB) const
{
return int(face * m_resolution2 + dimB * m_resolution + dimA);
}
int LineSpaceHelper::getShaftNumFromDimensions(int sface, int sdimA, int sdimB, int eface, int edimA, int edimB) const
{
return int(getShaftNumFromDimension(sface, sdimA, sdimB) * m_resolution2_6 + getShaftNumFromDimension(eface, edimA, edimB));
}
void LineSpaceHelper::mirrorDimension(int &face, int &dimA, int &dimB, int axis)
{
if ((axis == face) || (axis == m_face_mirrored[face]))
face = m_face_mirrored[face];
else