Browse Source

Add the ability to use the rasterizer to test the octree nodes

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
19c4afe0af

+ 15 - 4
src/anki/scene/Octree.cpp

@@ -262,8 +262,12 @@ void Octree::removeInternal(OctreePlaceable& placeable)
 	}
 	}
 }
 }
 
 
-void Octree::gatherVisibleRecursive(
-	const Frustum& frustum, U32 testId, Leaf* leaf, DynamicArrayAuto<OctreePlaceable*>& out)
+void Octree::gatherVisibleRecursive(const Frustum& frustum,
+	U32 testId,
+	OctreeNodeVisibilityTestCallback testCallback,
+	void* testCallbackUserData,
+	Leaf* leaf,
+	DynamicArrayAuto<OctreePlaceable*>& out)
 {
 {
 	ANKI_ASSERT(leaf);
 	ANKI_ASSERT(leaf);
 
 
@@ -284,9 +288,16 @@ void Octree::gatherVisibleRecursive(
 		{
 		{
 			aabb.setMin(Vec4(child->m_aabbMin, 0.0f));
 			aabb.setMin(Vec4(child->m_aabbMin, 0.0f));
 			aabb.setMax(Vec4(child->m_aabbMax, 0.0f));
 			aabb.setMax(Vec4(child->m_aabbMax, 0.0f));
-			if(frustum.insideFrustum(aabb))
+
+			Bool inside = frustum.insideFrustum(aabb);
+			if(inside && testCallback != nullptr)
+			{
+				inside = testCallback(testCallbackUserData, aabb);
+			}
+
+			if(inside)
 			{
 			{
-				gatherVisibleRecursive(frustum, testId, child, out);
+				gatherVisibleRecursive(frustum, testId, testCallback, testCallbackUserData, child, out);
 			}
 			}
 		}
 		}
 	}
 	}

+ 21 - 4
src/anki/scene/Octree.h

@@ -22,6 +22,9 @@ class OctreePlaceable;
 /// @addtogroup scene
 /// @addtogroup scene
 /// @{
 /// @{
 
 
+/// Callback to determine if an octree node is visible.
+using OctreeNodeVisibilityTestCallback = Bool (*)(void* userData, const Aabb& box);
+
 /// Octree for visibility tests.
 /// Octree for visibility tests.
 class Octree : public NonCopyable
 class Octree : public NonCopyable
 {
 {
@@ -46,10 +49,20 @@ public:
 	void remove(OctreePlaceable& placeable);
 	void remove(OctreePlaceable& placeable);
 
 
 	/// Gather visible placeables.
 	/// Gather visible placeables.
+	/// @param frustum The frustum to test against.
+	/// @param testId A unique index for this test.
+	/// @param testCallback A ptr to a function that will be used to perform an additional test to the box of the
+	///                     Octree node. Can be nullptr.
+	/// @param testCallbackUserData Parameter to the testCallback. Can be nullptr.
+	/// @param out The output of the tests.
 	/// @note It's thread-safe against other gatherVisible calls.
 	/// @note It's thread-safe against other gatherVisible calls.
-	void gatherVisible(const Frustum& frustum, U32 testId, DynamicArrayAuto<OctreePlaceable*>& out)
+	void gatherVisible(const Frustum& frustum,
+		U32 testId,
+		OctreeNodeVisibilityTestCallback testCallback,
+		void* testCallbackUserData,
+		DynamicArrayAuto<OctreePlaceable*>& out)
 	{
 	{
-		gatherVisibleRecursive(frustum, testId, m_rootLeaf, out);
+		gatherVisibleRecursive(frustum, testId, testCallback, testCallbackUserData, m_rootLeaf, out);
 	}
 	}
 
 
 private:
 private:
@@ -192,8 +205,12 @@ private:
 	/// Remove a placeable from the tree.
 	/// Remove a placeable from the tree.
 	void removeInternal(OctreePlaceable& placeable);
 	void removeInternal(OctreePlaceable& placeable);
 
 
-	static void gatherVisibleRecursive(
-		const Frustum& frustum, U32 testId, Leaf* leaf, DynamicArrayAuto<OctreePlaceable*>& out);
+	static void gatherVisibleRecursive(const Frustum& frustum,
+		U32 testId,
+		OctreeNodeVisibilityTestCallback testCallback,
+		void* testCallbackUserData,
+		Leaf* leaf,
+		DynamicArrayAuto<OctreePlaceable*>& out);
 
 
 	/// Remove a leaf.
 	/// Remove a leaf.
 	void cleanupRecursive(Leaf* leaf, Bool& canDeleteLeafUponReturn);
 	void cleanupRecursive(Leaf* leaf, Bool& canDeleteLeafUponReturn);

+ 30 - 0
src/anki/scene/Visibility.cpp

@@ -212,6 +212,36 @@ void RasterizeTrianglesTask::rasterize()
 	}
 	}
 }
 }
 
 
+void GatherVisiblesFromOctreeTask::gather()
+{
+	ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_OCTREE);
+
+	U testIdx = m_visCtx->m_testsCount.fetchAdd(1);
+
+	// Extra tests callback
+	auto testCallback = [](void* rasterizer, const Aabb& box) -> Bool {
+		ANKI_ASSERT(rasterizer);
+		SoftwareRasterizer* r = static_cast<SoftwareRasterizer*>(rasterizer);
+		return r->visibilityTest(box, box);
+	};
+
+	// Test
+	DynamicArrayAuto<OctreePlaceable*> arr(m_visCtx->m_scene->getFrameAllocator());
+	m_visCtx->m_scene->getOctree().gatherVisible(m_frc->getFrustum(), testIdx, testCallback, m_rasterizer, arr);
+
+	// Store results
+	if(arr.getSize() > 0)
+	{
+		OctreePlaceable** data;
+		PtrSize size;
+		PtrSize storage;
+		arr.moveAndReset(data, size, storage);
+
+		ANKI_ASSERT(data && size);
+		m_octreePlaceables = WeakArray<OctreePlaceable*>(data, size);
+	}
+}
+
 void VisibilityTestTask::test(ThreadHive& hive)
 void VisibilityTestTask::test(ThreadHive& hive)
 {
 {
 	ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_TEST);
 	ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_TEST);

+ 2 - 19
src/anki/scene/VisibilityInternal.h

@@ -184,6 +184,7 @@ class GatherVisiblesFromOctreeTask
 public:
 public:
 	VisibilityContext* m_visCtx ANKI_DBG_NULLIFY;
 	VisibilityContext* m_visCtx ANKI_DBG_NULLIFY;
 	FrustumComponent* m_frc ANKI_DBG_NULLIFY; ///< What to test against.
 	FrustumComponent* m_frc ANKI_DBG_NULLIFY; ///< What to test against.
+	SoftwareRasterizer* m_rasterizer ANKI_DBG_NULLIFY;
 	WeakArray<OctreePlaceable*> m_octreePlaceables; ///< The results of the task.
 	WeakArray<OctreePlaceable*> m_octreePlaceables; ///< The results of the task.
 
 
 	/// Thread hive task.
 	/// Thread hive task.
@@ -194,25 +195,7 @@ public:
 	}
 	}
 
 
 private:
 private:
-	void gather()
-	{
-		ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_OCTREE);
-		U testIdx = m_visCtx->m_testsCount.fetchAdd(1);
-
-		DynamicArrayAuto<OctreePlaceable*> arr(m_visCtx->m_scene->getFrameAllocator());
-		m_visCtx->m_scene->getOctree().gatherVisible(m_frc->getFrustum(), testIdx, arr);
-
-		if(arr.getSize() > 0)
-		{
-			OctreePlaceable** data;
-			PtrSize size;
-			PtrSize storage;
-			arr.moveAndReset(data, size, storage);
-
-			ANKI_ASSERT(data && size);
-			m_octreePlaceables = WeakArray<OctreePlaceable*>(data, size);
-		}
-	}
+	void gather();
 };
 };
 
 
 /// ThreadHive task to get visible nodes from sectors.
 /// ThreadHive task to get visible nodes from sectors.

+ 1 - 1
tests/scene/Octree.cpp

@@ -55,7 +55,7 @@ ANKI_TEST(Scene, Octree)
 				}
 				}
 
 
 				DynamicArrayAuto<OctreePlaceable*> arr(alloc);
 				DynamicArrayAuto<OctreePlaceable*> arr(alloc);
-				octree.gatherVisible(frustum, 0, arr);
+				octree.gatherVisible(frustum, 0, nullptr, nullptr, arr);
 
 
 				ANKI_TEST_EXPECT_EQ(arr.getSize(), placed.size());
 				ANKI_TEST_EXPECT_EQ(arr.getSize(), placed.size());
 				for(U32 idx : placed)
 				for(U32 idx : placed)