Graphics/CullingList: Improve culling list
- Now supports box culling - Removed branch - Removed complex hash combination and replaced it with a much faster algorithm - It now supports partial visibility
This commit is contained in:
parent
56873b92b0
commit
7bb6c84752
|
|
@ -217,7 +217,10 @@ namespace Ndk
|
||||||
if (camComponent.UpdateVisibility(visibilityHash) || m_forceRenderQueueInvalidation || forceInvalidation)
|
if (camComponent.UpdateVisibility(visibilityHash) || m_forceRenderQueueInvalidation || forceInvalidation)
|
||||||
{
|
{
|
||||||
renderQueue->Clear();
|
renderQueue->Clear();
|
||||||
for (const GraphicsComponent* gfxComponent : m_drawableCulling)
|
for (const GraphicsComponent* gfxComponent : m_drawableCulling.GetFullyVisibleResults())
|
||||||
|
gfxComponent->AddToRenderQueue(renderQueue);
|
||||||
|
|
||||||
|
for (const GraphicsComponent* gfxComponent : m_drawableCulling.GetPartiallyVisibleResults())
|
||||||
gfxComponent->AddToRenderQueue(renderQueue);
|
gfxComponent->AddToRenderQueue(renderQueue);
|
||||||
|
|
||||||
for (const Ndk::EntityHandle& light : m_lights)
|
for (const Ndk::EntityHandle& light : m_lights)
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,13 @@ namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<CullTest> class Entry;
|
template<CullTest> class Entry;
|
||||||
|
class BoxEntry;
|
||||||
class NoTestEntry;
|
class NoTestEntry;
|
||||||
class SphereEntry;
|
class SphereEntry;
|
||||||
class VolumeEntry;
|
class VolumeEntry;
|
||||||
|
|
||||||
template<CullTest> friend class Entry;
|
template<CullTest> friend class Entry;
|
||||||
|
friend BoxEntry;
|
||||||
friend NoTestEntry;
|
friend NoTestEntry;
|
||||||
friend SphereEntry;
|
friend SphereEntry;
|
||||||
friend VolumeEntry;
|
friend VolumeEntry;
|
||||||
|
|
@ -43,6 +45,10 @@ namespace Nz
|
||||||
|
|
||||||
std::size_t FillWithAllEntries(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);
|
NoTestEntry RegisterNoTest(const T* renderable);
|
||||||
SphereEntry RegisterSphereTest(const T* renderable);
|
SphereEntry RegisterSphereTest(const T* renderable);
|
||||||
VolumeEntry RegisterVolumeTest(const T* renderable);
|
VolumeEntry RegisterVolumeTest(const T* renderable);
|
||||||
|
|
@ -50,37 +56,24 @@ namespace Nz
|
||||||
CullingList& operator=(const CullingList& renderable) = delete;
|
CullingList& operator=(const CullingList& renderable) = delete;
|
||||||
CullingList& operator=(CullingList&& renderable) = delete;
|
CullingList& operator=(CullingList&& renderable) = delete;
|
||||||
|
|
||||||
// STL API
|
|
||||||
typename ResultContainer::iterator begin();
|
|
||||||
typename ResultContainer::const_iterator begin() const;
|
|
||||||
|
|
||||||
typename ResultContainer::const_iterator cbegin() const;
|
|
||||||
typename ResultContainer::const_iterator cend() const;
|
|
||||||
typename ResultContainer::const_reverse_iterator crbegin() const;
|
|
||||||
typename ResultContainer::const_reverse_iterator crend() const;
|
|
||||||
|
|
||||||
bool empty() const;
|
|
||||||
|
|
||||||
typename ResultContainer::iterator end();
|
|
||||||
typename ResultContainer::const_iterator end() const;
|
|
||||||
|
|
||||||
typename ResultContainer::reverse_iterator rbegin();
|
|
||||||
typename ResultContainer::const_reverse_iterator rbegin() const;
|
|
||||||
|
|
||||||
typename ResultContainer::reverse_iterator rend();
|
|
||||||
typename ResultContainer::const_reverse_iterator rend() const;
|
|
||||||
|
|
||||||
typename ResultContainer::size_type size() const;
|
|
||||||
|
|
||||||
NazaraSignal(OnCullingListRelease, CullingList* /*cullingList*/);
|
NazaraSignal(OnCullingListRelease, CullingList* /*cullingList*/);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
inline void NotifyBoxUpdate(std::size_t index, const Boxf& boundingVolume);
|
||||||
inline void NotifyForceInvalidation(CullTest type, std::size_t index);
|
inline void NotifyForceInvalidation(CullTest type, std::size_t index);
|
||||||
inline void NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr);
|
inline void NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr);
|
||||||
inline void NotifyRelease(CullTest type, std::size_t index);
|
inline void NotifyRelease(CullTest type, std::size_t index);
|
||||||
inline void NotifySphereUpdate(std::size_t index, const Spheref& sphere);
|
inline void NotifySphereUpdate(std::size_t index, const Spheref& sphere);
|
||||||
inline void NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume);
|
inline void NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume);
|
||||||
|
|
||||||
|
struct BoxVisibilityEntry
|
||||||
|
{
|
||||||
|
Boxf box;
|
||||||
|
BoxEntry* entry;
|
||||||
|
const T* renderable;
|
||||||
|
bool forceInvalidation;
|
||||||
|
};
|
||||||
|
|
||||||
struct NoTestVisibilityEntry
|
struct NoTestVisibilityEntry
|
||||||
{
|
{
|
||||||
NoTestEntry* entry;
|
NoTestEntry* entry;
|
||||||
|
|
@ -104,10 +97,12 @@ namespace Nz
|
||||||
bool forceInvalidation;
|
bool forceInvalidation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::vector<BoxVisibilityEntry> m_boxTestList;
|
||||||
std::vector<NoTestVisibilityEntry> m_noTestList;
|
std::vector<NoTestVisibilityEntry> m_noTestList;
|
||||||
std::vector<SphereVisibilityEntry> m_sphereTestList;
|
std::vector<SphereVisibilityEntry> m_sphereTestList;
|
||||||
std::vector<VolumeVisibilityEntry> m_volumeTestList;
|
std::vector<VolumeVisibilityEntry> m_volumeTestList;
|
||||||
ResultContainer m_results;
|
ResultContainer m_fullyVisibleResults;
|
||||||
|
ResultContainer m_partiallyVisibleResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -136,6 +131,24 @@ namespace Nz
|
||||||
CullingList* m_parent;
|
CullingList* m_parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class CullingList<T>::BoxEntry : public CullingList<T>::template Entry<CullTest::Box>
|
||||||
|
{
|
||||||
|
friend CullingList;
|
||||||
|
|
||||||
|
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>
|
template<typename T>
|
||||||
class CullingList<T>::NoTestEntry : public CullingList<T>::template Entry<CullTest::NoTest>
|
class CullingList<T>::NoTestEntry : public CullingList<T>::template Entry<CullTest::NoTest>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,48 @@ namespace Nz
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::size_t CullingList<T>::Cull(const Frustumf& frustum, bool* forceInvalidation)
|
std::size_t CullingList<T>::Cull(const Frustumf& frustum, bool* forceInvalidation)
|
||||||
{
|
{
|
||||||
m_results.clear();
|
m_fullyVisibleResults.clear();
|
||||||
|
m_partiallyVisibleResults.clear();
|
||||||
|
|
||||||
bool forcedInvalidation = false;
|
bool forcedInvalidation = false;
|
||||||
|
|
||||||
std::size_t visibleHash = 0U;
|
std::size_t fullyVisibleHash = 5U;
|
||||||
|
std::size_t partiallyVisibleHash = 5U;
|
||||||
|
|
||||||
|
auto CombineHash = [](std::size_t currentHash, std::size_t newHash)
|
||||||
|
{
|
||||||
|
return currentHash * 23 + newHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (BoxVisibilityEntry& entry : m_boxTestList)
|
||||||
|
{
|
||||||
|
switch (frustum.Intersect(entry.box))
|
||||||
|
{
|
||||||
|
case IntersectionSide_Inside:
|
||||||
|
m_fullyVisibleResults.push_back(entry.renderable);
|
||||||
|
CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||||
|
|
||||||
|
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||||
|
entry.forceInvalidation = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IntersectionSide_Intersecting:
|
||||||
|
m_partiallyVisibleResults.push_back(entry.renderable);
|
||||||
|
CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||||
|
|
||||||
|
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||||
|
entry.forceInvalidation = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IntersectionSide_Outside:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (NoTestVisibilityEntry& entry : m_noTestList)
|
for (NoTestVisibilityEntry& entry : m_noTestList)
|
||||||
{
|
{
|
||||||
m_results.push_back(entry.renderable);
|
m_fullyVisibleResults.push_back(entry.renderable);
|
||||||
Nz::HashCombine(visibleHash, entry.renderable);
|
CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||||
|
|
||||||
if (entry.forceInvalidation)
|
if (entry.forceInvalidation)
|
||||||
{
|
{
|
||||||
|
|
@ -36,33 +68,86 @@ namespace Nz
|
||||||
|
|
||||||
for (SphereVisibilityEntry& entry : m_sphereTestList)
|
for (SphereVisibilityEntry& entry : m_sphereTestList)
|
||||||
{
|
{
|
||||||
if (frustum.Contains(entry.sphere))
|
switch (frustum.Intersect(entry.sphere))
|
||||||
{
|
{
|
||||||
m_results.push_back(entry.renderable);
|
case IntersectionSide_Inside:
|
||||||
Nz::HashCombine(visibleHash, entry.renderable);
|
m_fullyVisibleResults.push_back(entry.renderable);
|
||||||
|
CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||||
|
|
||||||
if (entry.forceInvalidation)
|
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||||
{
|
|
||||||
forcedInvalidation = true;
|
|
||||||
entry.forceInvalidation = false;
|
entry.forceInvalidation = false;
|
||||||
}
|
break;
|
||||||
|
|
||||||
|
case IntersectionSide_Intersecting:
|
||||||
|
m_partiallyVisibleResults.push_back(entry.renderable);
|
||||||
|
CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||||
|
|
||||||
|
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||||
|
entry.forceInvalidation = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IntersectionSide_Outside:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (VolumeVisibilityEntry& entry : m_volumeTestList)
|
for (VolumeVisibilityEntry& entry : m_volumeTestList)
|
||||||
{
|
{
|
||||||
if (frustum.Contains(entry.volume))
|
switch (frustum.Intersect(entry.volume))
|
||||||
{
|
{
|
||||||
m_results.push_back(entry.renderable);
|
case IntersectionSide_Inside:
|
||||||
Nz::HashCombine(visibleHash, entry.renderable);
|
m_fullyVisibleResults.push_back(entry.renderable);
|
||||||
|
CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||||
|
|
||||||
if (entry.forceInvalidation)
|
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||||
|
entry.forceInvalidation = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IntersectionSide_Intersecting:
|
||||||
|
m_partiallyVisibleResults.push_back(entry.renderable);
|
||||||
|
CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||||
|
|
||||||
|
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||||
|
entry.forceInvalidation = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IntersectionSide_Outside:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forceInvalidation)
|
||||||
|
*forceInvalidation = forcedInvalidation;
|
||||||
|
|
||||||
|
return 5 + partiallyVisibleHash * 17 + fullyVisibleHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::size_t CullingList<T>::FillWithAllEntries(bool* forceInvalidation)
|
||||||
{
|
{
|
||||||
forcedInvalidation = true;
|
m_fullyVisibleResults.clear();
|
||||||
|
m_partiallyVisibleResults.clear();
|
||||||
|
|
||||||
|
bool forcedInvalidation = false;
|
||||||
|
|
||||||
|
std::size_t visibleHash = 5U;
|
||||||
|
|
||||||
|
auto FillWithList = [&](auto& testList)
|
||||||
|
{
|
||||||
|
for (auto& entry : testList)
|
||||||
|
{
|
||||||
|
m_fullyVisibleResults.push_back(entry.renderable);
|
||||||
|
visibleHash = visibleHash * 23 + std::hash<const T*>()(entry.renderable);
|
||||||
|
|
||||||
|
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||||
entry.forceInvalidation = false;
|
entry.forceInvalidation = false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
FillWithList(m_boxTestList);
|
||||||
|
FillWithList(m_noTestList);
|
||||||
|
FillWithList(m_sphereTestList);
|
||||||
|
FillWithList(m_volumeTestList);
|
||||||
|
|
||||||
if (forceInvalidation)
|
if (forceInvalidation)
|
||||||
*forceInvalidation = forcedInvalidation;
|
*forceInvalidation = forcedInvalidation;
|
||||||
|
|
@ -71,53 +156,24 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::size_t CullingList<T>::FillWithAllEntries(bool* forceInvalidation)
|
auto CullingList<T>::GetFullyVisibleResults() const -> const ResultContainer&
|
||||||
{
|
{
|
||||||
m_results.clear();
|
return m_fullyVisibleResults;
|
||||||
|
|
||||||
bool forcedInvalidation = false;
|
|
||||||
|
|
||||||
std::size_t visibleHash = 0U;
|
|
||||||
for (NoTestVisibilityEntry& entry : m_noTestList)
|
|
||||||
{
|
|
||||||
m_results.push_back(entry.renderable);
|
|
||||||
Nz::HashCombine(visibleHash, entry.renderable);
|
|
||||||
|
|
||||||
if (entry.forceInvalidation)
|
|
||||||
{
|
|
||||||
forcedInvalidation = true;
|
|
||||||
entry.forceInvalidation = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SphereVisibilityEntry& entry : m_sphereTestList)
|
template<typename T>
|
||||||
|
auto CullingList<T>::GetPartiallyVisibleResults() const -> const ResultContainer&
|
||||||
{
|
{
|
||||||
m_results.push_back(entry.renderable);
|
return m_partiallyVisibleResults;
|
||||||
Nz::HashCombine(visibleHash, entry.renderable);
|
|
||||||
|
|
||||||
if (entry.forceInvalidation)
|
|
||||||
{
|
|
||||||
forcedInvalidation = true;
|
|
||||||
entry.forceInvalidation = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (VolumeVisibilityEntry& entry : m_volumeTestList)
|
template<typename T>
|
||||||
|
auto CullingList<T>::RegisterBoxTest(const T* renderable) -> BoxEntry
|
||||||
{
|
{
|
||||||
m_results.push_back(entry.renderable);
|
BoxEntry newEntry(this, m_boxTestList.size());
|
||||||
Nz::HashCombine(visibleHash, entry.renderable);
|
m_boxTestList.emplace_back(BoxVisibilityEntry{ Nz::Boxf(), &newEntry, renderable, false }); //< Address of entry will be updated when moving
|
||||||
|
|
||||||
if (entry.forceInvalidation)
|
return newEntry;
|
||||||
{
|
|
||||||
forcedInvalidation = true;
|
|
||||||
entry.forceInvalidation = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (forceInvalidation)
|
|
||||||
*forceInvalidation = forcedInvalidation;
|
|
||||||
|
|
||||||
return visibleHash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -132,7 +188,7 @@ namespace Nz
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto CullingList<T>::RegisterSphereTest(const T* renderable) -> SphereEntry
|
auto CullingList<T>::RegisterSphereTest(const T* renderable) -> SphereEntry
|
||||||
{
|
{
|
||||||
SphereEntry newEntry(this, m_sphereTestList.size() - 1);
|
SphereEntry newEntry(this, m_sphereTestList.size());
|
||||||
m_sphereTestList.emplace_back(SphereVisibilityEntry{Nz::Spheref(), &newEntry, renderable, false}); //< Address of entry will be updated when moving
|
m_sphereTestList.emplace_back(SphereVisibilityEntry{Nz::Spheref(), &newEntry, renderable, false}); //< Address of entry will be updated when moving
|
||||||
|
|
||||||
return newEntry;
|
return newEntry;
|
||||||
|
|
@ -147,89 +203,10 @@ namespace Nz
|
||||||
return newEntry;
|
return newEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface STD
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename CullingList<T>::ResultContainer::iterator CullingList<T>::begin()
|
inline void CullingList<T>::NotifyBoxUpdate(std::size_t index, const Boxf& box)
|
||||||
{
|
{
|
||||||
return m_results.begin();
|
m_boxTestList[index].box = box;
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::const_iterator CullingList<T>::begin() const
|
|
||||||
{
|
|
||||||
return m_results.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::const_iterator CullingList<T>::cbegin() const
|
|
||||||
{
|
|
||||||
return m_results.cbegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::const_iterator CullingList<T>::cend() const
|
|
||||||
{
|
|
||||||
return m_results.cend();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::const_reverse_iterator CullingList<T>::crbegin() const
|
|
||||||
{
|
|
||||||
return m_results.crbegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::const_reverse_iterator CullingList<T>::crend() const
|
|
||||||
{
|
|
||||||
return m_results.crend();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool CullingList<T>::empty() const
|
|
||||||
{
|
|
||||||
return m_results.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::iterator CullingList<T>::end()
|
|
||||||
{
|
|
||||||
return m_results.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::const_iterator CullingList<T>::end() const
|
|
||||||
{
|
|
||||||
return m_results.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::reverse_iterator CullingList<T>::rbegin()
|
|
||||||
{
|
|
||||||
return m_results.rbegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::const_reverse_iterator CullingList<T>::rbegin() const
|
|
||||||
{
|
|
||||||
return m_results.rbegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::reverse_iterator CullingList<T>::rend()
|
|
||||||
{
|
|
||||||
return m_results.rend();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::const_reverse_iterator CullingList<T>::rend() const
|
|
||||||
{
|
|
||||||
return m_results.rend();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename CullingList<T>::ResultContainer::size_type CullingList<T>::size() const
|
|
||||||
{
|
|
||||||
return m_results.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -237,6 +214,12 @@ namespace Nz
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case CullTest::Box:
|
||||||
|
{
|
||||||
|
m_boxTestList[index].forceInvalidation = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CullTest::NoTest:
|
case CullTest::NoTest:
|
||||||
{
|
{
|
||||||
m_noTestList[index].forceInvalidation = true;
|
m_noTestList[index].forceInvalidation = true;
|
||||||
|
|
@ -268,6 +251,15 @@ namespace Nz
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case CullTest::Box:
|
||||||
|
{
|
||||||
|
BoxVisibilityEntry& entry = m_boxTestList[index];
|
||||||
|
NazaraAssert(entry.entry == oldPtr, "Invalid box entry");
|
||||||
|
|
||||||
|
entry.entry = static_cast<BoxEntry*>(newPtr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CullTest::NoTest:
|
case CullTest::NoTest:
|
||||||
{
|
{
|
||||||
NoTestVisibilityEntry& entry = m_noTestList[index];
|
NoTestVisibilityEntry& entry = m_noTestList[index];
|
||||||
|
|
@ -306,6 +298,14 @@ namespace Nz
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case CullTest::Box:
|
||||||
|
{
|
||||||
|
m_boxTestList[index] = std::move(m_boxTestList.back());
|
||||||
|
m_boxTestList[index].entry->UpdateIndex(index);
|
||||||
|
m_boxTestList.pop_back();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CullTest::NoTest:
|
case CullTest::NoTest:
|
||||||
{
|
{
|
||||||
m_noTestList[index] = std::move(m_noTestList.back());
|
m_noTestList[index] = std::move(m_noTestList.back());
|
||||||
|
|
@ -427,6 +427,26 @@ namespace Nz
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
CullingList<T>::BoxEntry::BoxEntry() :
|
||||||
|
Entry<CullTest::Box>()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
CullingList<T>::BoxEntry::BoxEntry(CullingList* parent, std::size_t index) :
|
||||||
|
Entry<CullTest::Box>(parent, index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void CullingList<T>::BoxEntry::UpdateBox(const Boxf& box)
|
||||||
|
{
|
||||||
|
this->m_parent->NotifyBoxUpdate(this->m_index, box);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
CullingList<T>::NoTestEntry::NoTestEntry() :
|
CullingList<T>::NoTestEntry::NoTestEntry() :
|
||||||
Entry<CullTest::NoTest>()
|
Entry<CullTest::NoTest>()
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ namespace Nz
|
||||||
|
|
||||||
enum class CullTest
|
enum class CullTest
|
||||||
{
|
{
|
||||||
|
Box,
|
||||||
NoTest,
|
NoTest,
|
||||||
Sphere,
|
Sphere,
|
||||||
Volume
|
Volume
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue