NazaraEngine/include/Nazara/Graphics/CullingList.hpp

216 lines
5.3 KiB
C++

// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CULLINGLIST_HPP
#define NAZARA_CULLINGLIST_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Math/BoundingVolume.hpp>
#include <Nazara/Math/Frustum.hpp>
#include <Nazara/Math/Sphere.hpp>
#include <vector>
namespace Nz
{
template<typename T>
class CullingList
{
public:
template<CullTest> class Entry;
class BoxEntry;
class NoTestEntry;
class SphereEntry;
class VolumeEntry;
template<CullTest> friend class Entry;
friend BoxEntry;
friend NoTestEntry;
friend SphereEntry;
friend VolumeEntry;
using ResultContainer = std::vector<const T*>;
CullingList() = default;
CullingList(const CullingList& renderable) = delete;
CullingList(CullingList&& renderable) = delete;
~CullingList();
std::size_t Cull(const Frustumf& frustum, bool* forceInvalidation = nullptr);
std::size_t FillWithAllEntries(bool* forceInvalidation = nullptr);
const ResultContainer& GetFullyVisibleResults() const;
const ResultContainer& GetPartiallyVisibleResults() const;
BoxEntry RegisterBoxTest(const T* renderable);
NoTestEntry RegisterNoTest(const T* renderable);
SphereEntry RegisterSphereTest(const T* renderable);
VolumeEntry RegisterVolumeTest(const T* renderable);
CullingList& operator=(const CullingList& renderable) = delete;
CullingList& operator=(CullingList&& renderable) = delete;
NazaraSignal(OnCullingListRelease, CullingList* /*cullingList*/);
private:
inline void NotifyBoxUpdate(std::size_t index, const Boxf& boundingVolume);
inline void NotifyForceInvalidation(CullTest type, std::size_t index);
inline void NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr);
inline void NotifyRelease(CullTest type, std::size_t index);
inline void NotifySphereUpdate(std::size_t index, const Spheref& sphere);
inline void NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume);
struct BoxVisibilityEntry
{
Boxf box;
BoxEntry* entry;
const T* renderable;
bool forceInvalidation;
};
struct NoTestVisibilityEntry
{
NoTestEntry* entry;
const T* renderable;
bool forceInvalidation;
};
struct SphereVisibilityEntry
{
Spheref sphere;
SphereEntry* entry;
const T* renderable;
bool forceInvalidation;
};
struct VolumeVisibilityEntry
{
BoundingVolumef volume;
VolumeEntry* entry;
const T* renderable;
bool forceInvalidation;
};
std::vector<BoxVisibilityEntry> m_boxTestList;
std::vector<NoTestVisibilityEntry> m_noTestList;
std::vector<SphereVisibilityEntry> m_sphereTestList;
std::vector<VolumeVisibilityEntry> m_volumeTestList;
ResultContainer m_fullyVisibleResults;
ResultContainer m_partiallyVisibleResults;
};
template<typename T>
template<CullTest Type>
class CullingList<T>::Entry
{
public:
Entry();
Entry(const Entry&) = delete;
Entry(Entry&& entry);
~Entry();
void ForceInvalidation();
CullingList* GetParent() const;
void UpdateIndex(std::size_t index);
Entry& operator=(const Entry&) = delete;
Entry& operator=(Entry&& entry);
protected:
Entry(CullingList* parent, std::size_t index);
std::size_t m_index;
CullingList* m_parent;
};
template<typename T>
class CullingList<T>::BoxEntry : public CullingList<T>::template Entry<CullTest::Box>
{
friend CullingList;
using ParentType = Entry<CullTest::Box>;
public:
BoxEntry();
BoxEntry(BoxEntry&&) = default;
~BoxEntry() = default;
void UpdateBox(const Boxf& box);
BoxEntry& operator=(BoxEntry&&) = default;
private:
BoxEntry(CullingList* parent, std::size_t index);
};
template<typename T>
class CullingList<T>::NoTestEntry : public CullingList<T>::template Entry<CullTest::NoTest>
{
friend CullingList;
using ParentType = Entry<CullTest::NoTest>;
public:
NoTestEntry();
NoTestEntry(NoTestEntry&&) = default;
~NoTestEntry() = default;
NoTestEntry& operator=(NoTestEntry&&) = default;
private:
NoTestEntry(CullingList* parent, std::size_t index);
};
template<typename T>
class CullingList<T>::SphereEntry : public CullingList<T>::template Entry<CullTest::Sphere>
{
friend CullingList;
using ParentType = Entry<CullTest::Sphere>;
public:
SphereEntry();
SphereEntry(SphereEntry&&) = default;
~SphereEntry() = default;
void UpdateSphere(const Spheref& sphere);
SphereEntry& operator=(SphereEntry&&) = default;
private:
SphereEntry(CullingList* parent, std::size_t index);
};
template<typename T>
class CullingList<T>::VolumeEntry : public CullingList<T>::template Entry<CullTest::Volume>
{
friend CullingList;
using ParentType = Entry<CullTest::Volume>;
public:
VolumeEntry();
VolumeEntry(VolumeEntry&&) = default;
~VolumeEntry() = default;
void UpdateVolume(const BoundingVolumef& sphere);
VolumeEntry& operator=(VolumeEntry&&) = default;
private:
VolumeEntry(CullingList* parent, std::size_t index);
};
}
#include <Nazara/Graphics/CullingList.inl>
#endif // NAZARA_CULLINGLIST_HPP