Browse Source

Scene rework. WONT COMPILE

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
327fdecf55
2 changed files with 102 additions and 176 deletions
  1. 6 17
      include/anki/scene/Visibility.h
  2. 96 159
      src/scene/Visibility.cpp

+ 6 - 17
include/anki/scene/Visibility.h

@@ -36,29 +36,18 @@ enum VisibleBy
 struct VisibleNode
 {
 	SceneNode* node;
-	/// An array of the visible sub spatials. Allocated but never deallocated
-	/// because it lives in the scene frame mem pool
-	U32* subSpatialIndices;
-	U32 subSpatialIndicesCount;
+	/// An array of the visible spatials.
+	Array<U32, ANKI_MAX_MULTIDRAW_PRIMITIVES> spatialIndices;
+	U32 spatialsCount;
 
 	VisibleNode()
-		: node(nullptr), subSpatialIndices(nullptr), subSpatialIndicesCount(0)
+		: node(nullptr), subSpatialIndicesCount(0)
 	{}
 
-	VisibleNode(SceneNode* node_, U32* subSpatialIndices_, 
-		U32 subSpatialIndicesCount_)
-		:	node(node_), 
-			subSpatialIndices(subSpatialIndices_), 
-			subSpatialIndicesCount(subSpatialIndicesCount_)
+	VisibleNode(const VisibleNode& other)
 	{
-		ANKI_ASSERT(node);
+		memcpy(this, &other, sizeof(VisibleNode));
 	}
-
-	VisibleNode(const VisibleNode& other)
-		:	node(other.node), 
-			subSpatialIndices(other.subSpatialIndices),
-			subSpatialIndicesCount(other.subSpatialIndicesCount)
-	{}
 };
 
 /// Its actually a container for visible entities. It should be per frame

+ 96 - 159
src/scene/Visibility.cpp

@@ -8,207 +8,145 @@
 namespace anki {
 
 //==============================================================================
-/// Sort spatial scene nodes on distance
-struct SortSubspatialsFunctor
-{
-	Vec3 origin; ///< The pos of the frustum
-	SpatialComponent* sp;
-
-	Bool operator()(U32 a, U32 b)
-	{
-		ANKI_ASSERT(a != b 
-			&& a < sp->getSubSpatialsCount()
-			&& b < sp->getSubSpatialsCount());
-
-		const SpatialComponent& spa = sp->getSubSpatial(a);
-		const SpatialComponent& spb = sp->getSubSpatial(b);
-
-		F32 dist0 = 
-			origin.getDistanceSquared(spa.getSpatialOrigin());
-		F32 dist1 = 
-			origin.getDistanceSquared(spb.getSpatialOrigin());
-
-		return dist0 < dist1;
-	}
-};
-
-//==============================================================================
-struct VisibilityTestJob: ThreadpoolTask
+struct VisibilityTestTask: ThreadpoolTask
 {
 	U nodesCount = 0;
 	SceneGraph* scene = nullptr;
 	SceneNode* frustumableSn = nullptr;
-	Tiler* tiler = nullptr;
 	SceneFrameAllocator<U8> frameAlloc;
 
-	VisibilityTestResults* visible;
+	VisibilityTestResults* cameraVisible; // out
 
-	/// Handle sub spatials
-	Bool handleSubspatials(
-		const FrustumComponent& fr,
-		SpatialComponent& sp,
-		U32*& subSpatialIndices,
-		U32& subSpatialIndicesCount)
+	/// Test a frustum component
+	void test(SceneNode& testedNode, Bool isLight, 
+		ThreadId threadId, U threadsCount)
 	{
-		Bool fatherSpVisible = true;
-		subSpatialIndices = nullptr;
-		subSpatialIndicesCount = 0;
+		ANKI_ASSERT(isLight == testedNode.tryGetComponent<LightComponent>());
 
-		// Have subspatials?
-		if(sp.getSubSpatialsCount())
-		{
-			subSpatialIndices = 
-				frameAlloc.newArray<U32>(sp.getSubSpatialsCount());
-
-			U i = 0;
-			sp.visitChildren([&](SpatialComponent& subsp)
-			{	
-				// Check
-				if(fr.insideFrustum(subsp))
-				{
-					subSpatialIndices[subSpatialIndicesCount++] = i;
-					subsp.enableBits(SpatialComponent::SF_VISIBLE_CAMERA);
-				}
-				++i;
-			});
+		VisibilityTestResults* visible = 
+			frameAlloc.newInstance<VisibilityTestResults>(frameAlloc);
 
-			// Sort them
-			SortSubspatialsFunctor functor;
-			functor.origin = fr.getFrustumOrigin();
-			functor.sp = &sp;
-			std::sort(subSpatialIndices, 
-				subSpatialIndices + subSpatialIndicesCount,
-				functor);
-
-			// The subSpatialIndicesCount == 0 then the camera is looking 
-			// something in between all sub spatials
-			fatherSpVisible = subSpatialIndicesCount != 0;
-		}
+		FrustumComponent& testedFr = 
+			testedNode->getComponent<FrustumComponent>();
 
-		return fatherSpVisible;
-	}
-
-	/// Do the tests
-	void operator()(ThreadId threadId, U threadsCount)
-	{
+		// Chose the test range and a few other things
 		U64 start, end;
-		choseStartEnd(threadId, threadsCount, nodesCount, start, end);
-
-		visible = frameAlloc.newInstance<VisibilityTestResults>(frameAlloc);
-
-		FrustumComponent* frustumable = frustumableSn->getFrustumComponent();
-		ANKI_ASSERT(frustumable);
+		if(!isLight)
+		{
+			choseStartEnd(threadId, threadsCount, nodesCount, start, end);
+			cameraVisible = visible;
+		}
+		else
+		{
+			// Is light
+			start = 0;
+			end = nodesCount;
+			testedFr.setVisibilityTestResults(visible);
+		}
 
+		// Iterate range of nodes
 		scene->iterateSceneNodes(start, end, [&](SceneNode& node)
 		{
-			FrustumComponent* fr = node.getFrustumComponent();
+			FrustumComponent* fr = node.tryGetComponent<FrustumComponent>();
 
 			// Skip if it is the same
-			if(ANKI_UNLIKELY(frustumable == fr))
+			if(ANKI_UNLIKELY(&testedFr == fr))
 			{
 				return;
 			}
 
-			SpatialComponent* sp = node.getSpatialComponent();
-			if(!sp)
+			VisibleNode visibleNode;
+			visibleNode.node = &node;
+
+			// Test all spatial components of that node
+			struct SpatialTemp
 			{
-				return;
-			}
+				SpatialComponent* sp;
+				U32 idx;
+			};
+			Array<SpatialTemp, ANKI_MAX_MULTIDRAW_PRIMITIVES> sps;
+
+			U32 i = 0;
+			U count = 0;
+			node.iterateComponentsOfType<SpatialComponent>(
+				[&](SpatialComponent& sp)
+			{
+				if(testedFr.insideFrustum(sp))
+				{
+					// Inside
+					sps[count++] = SpatialTemp{&sp, i};
+
+					sp->enableBits(isLight 
+						? SpatialComponent::SF_VISIBLE_LIGHT 
+						: SpatialComponent::SF_VISIBLE_CAMERA);
+				}
 
-			if(!frustumable->insideFrustum(*sp))
+				++i;
+			});
+
+			if(count == 0)
 			{
 				return;
 			}
 
-			// Hierarchical spatial => check subspatials
-			U32* subSpatialIndices = nullptr;
-			U32 subSpatialIndicesCount = 0;
-			if(!handleSubspatials(*frustumable, *sp, subSpatialIndices, 
-				subSpatialIndicesCount))
+			// Sort spatials
+			Vec3 origin = frustumable.getFrustumOrigin();
+			std::sort(sps.begin(), sps.begin() + count, 
+				[&](const SpatialTemp& a, const SpatialTemp& b) -> Bool
 			{
-				return;
+				Vec3 spa = a.sp->getSpatialOrigin();
+				Vec3 spb = b.sp->getSpatialOrigin();
+
+				F32 dist0 = origin.getDistanceSquared(spa);
+				F32 dist1 = origin.getDistanceSquared(spb);
+
+				return dist0 < dist1;
+			});
+
+			// Update the visibleNode
+			visibleNode.spatialsCount = count;
+			for(i = 0; i < count; i++)
+			{
+				visibleNode.spatialIndices[i] = sps[i].idx;
 			}
 
-			// renderable
-			RenderComponent* r = node.getRenderComponent();
-			if(r)
+			// Do something with the result
+			RenderComponent* r = node.tryGetComponent<RenderComponent>();
+			if(isLight)
 			{
-				visible->renderables.push_back(VisibleNode(
-					&node, subSpatialIndices, subSpatialIndicesCount));
+				if(r && r->castsShadow())
+				{
+					visible->renderables.push_back(visibleNode);
+				}
 			}
 			else
 			{
-				Light* l = node.getLight();
-				if(l)
+				if(r)
 				{
-					visible->lights.push_back(VisibleNode(&node, nullptr, 0));
-
-					if(l->getShadowEnabled() && fr)
-					{
-						testLight(node);
-					}
+					visible->renderables.push_back(visibleNode);
 				}
 				else
 				{
-					return;
+					LightComponent* l = node.tryGetComponent<LightComponent>();
+					if(l)
+					{
+						visible->lights.push_back(
+							VisibleNode(&node, nullptr, 0));
+
+						if(l->getShadowEnabled() && fr)
+						{
+							test(node, true);
+						}
+					}
 				}
 			}
-
-			sp->enableBits(SpatialComponent::SF_VISIBLE_CAMERA);
 		}); // end for
 	}
 
-	/// Test an individual light
-	void testLight(SceneNode& lightSn)
+	/// Do the tests
+	void operator()(ThreadId threadId, U threadsCount)
 	{
-		ANKI_ASSERT(lightSn.getFrustumComponent() != nullptr);
-		FrustumComponent& ref = *lightSn.getFrustumComponent();
-
-		// Allocate new visibles
-		VisibilityTestResults* lvisible = 
-			frameAlloc.newInstance<VisibilityTestResults>(frameAlloc);
-
-		ref.setVisibilityTestResults(lvisible);
-
-		scene->iterateSceneNodes([&](SceneNode& node)
-		{
-			FrustumComponent* fr = node.getFrustumComponent();
-			RenderComponent* r = node.getRenderComponent();
-
-			// Wont check the same
-			if(ANKI_UNLIKELY(&ref == fr))
-			{
-				return;
-			}
-
-			SpatialComponent* sp = node.getSpatialComponent();
-			if(!sp)
-			{
-				return;
-			}
-
-			if(!ref.insideFrustum(*sp))
-			{
-				return;
-			}
-
-			// Hierarchical spatial => check subspatials
-			U32* subSpatialIndices = nullptr;
-			U32 subSpatialIndicesCount = 0;
-			if(!handleSubspatials(ref, *sp, subSpatialIndices, 
-				subSpatialIndicesCount))
-			{
-				return;
-			}
-
-			sp->enableBits(SpatialComponent::SF_VISIBLE_LIGHT);
-
-			if(r && r->castsShadow())
-			{
-				lvisible->renderables.push_back(VisibleNode(
-					&node, subSpatialIndices, subSpatialIndicesCount));
-			}
-		}); // end lambda
+		test(*frustumableSn, threadId, threadsCount);
 	}
 };
 
@@ -223,13 +161,12 @@ void doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 	// Do the tests in parallel
 	//
 	Threadpool& threadPool = ThreadpoolSingleton::get();
-	VisibilityTestJob jobs[Threadpool::MAX_THREADS];
+	VisibilityTestTask jobs[Threadpool::MAX_THREADS];
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	{
 		jobs[i].nodesCount = scene.getSceneNodesCount();
 		jobs[i].scene = &scene;
 		jobs[i].frustumableSn = &fsn;
-		jobs[i].tiler = &r.getTiler();
 		jobs[i].frameAlloc = scene.getFrameAllocator();
 
 		threadPool.assignNewTask(i, &jobs[i]);