Bladeren bron

Octree, Sector and visibility

Panagiotis Christopoulos Charitos 13 jaren geleden
bovenliggende
commit
055210632f

+ 16 - 7
include/anki/scene/Octree.h

@@ -5,6 +5,7 @@
 #include "anki/util/Vector.h"
 #include "anki/util/Array.h"
 #include "anki/scene/Common.h"
+#include "anki/scene/VisibilityTestResults.h"
 #include <memory>
 
 namespace anki {
@@ -87,7 +88,7 @@ private:
 	void addChild(U pos, OctreeNode* child);
 };
 
-/// Octree node
+/// Root octree node. Its seperate because it holds pointer to the octree
 class RootOctreeNode: public OctreeNode
 {
 	friend class OctreeNode;
@@ -128,15 +129,23 @@ public:
 	{
 		return maxDepth;
 	}
+
+	Sector& getSector() 
+	{
+		return *sector;
+	}
+	const Sector& getSector() const
+	{
+		return *sector;
+	}
 	/// @}
 
 	/// Place a spatial in the tree
 	void placeSceneNode(SceneNode* sn);
 
 	/// Do the visibility tests
-	void getVisible(const Frustumable& fr,
-		SceneVector<SceneNode*>* renderableNodes,
-		SceneVector<SceneNode*>* lightNodes);
+	void doVisibilityTests(const Frustumable& fr, VisibilityTest test,
+		VisibilityTestResults& visibles);
 
 private:
 	Sector* sector;
@@ -153,9 +162,9 @@ private:
 	OctreeNode* place(const Aabb& aabb);
 
 	/// Recursive method
-	void doVisibilityTestsInternal(const Frustumable& fr,
-		SceneVector<SceneNode*>* renderableNodes,
-		SceneVector<SceneNode*>* lightNodes,
+	void doVisibilityTestsInternal(const Frustumable& fr, 
+		VisibilityTest test,
+		VisibilityTestResults& visibles,
 		OctreeNode& node);
 
 	void createChildren(OctreeNode& parent);

+ 1 - 8
include/anki/scene/Sector.h

@@ -60,13 +60,6 @@ private:
 class SectorGroup
 {
 public:
-	enum VisibilityTest
-	{
-		VT_RENDERABLES = 1 << 0,
-		VT_ONLY_SHADOW_CASTERS = 1 << 1,
-		VT_LIGHTS = 1 << 2
-	};
-
 	/// Default constructor
 	SectorGroup(Scene* scene);
 
@@ -87,7 +80,7 @@ public:
 	void placeSceneNode(SceneNode* sp);
 
 	/// XXX
-	void doVisibilityTests(Frustumable& fr, VisibilityTest test);
+	void doVisibilityTests(SceneNode& fr, VisibilityTest test);
 
 private:
 	Scene* scene; ///< Keep it here to access various allocators

+ 11 - 0
include/anki/scene/Spatial.h

@@ -72,6 +72,17 @@ public:
 	}
 
 	virtual const Vec3& getSpatialOrigin() const = 0;
+
+	OctreeNode& getOctreeNode()
+	{
+		ANKI_ASSERT(octreeNode != nullptr && "Not placed yet");
+		return *octreeNode;
+	}
+	const OctreeNode& getOctreeNode() const
+	{
+		ANKI_ASSERT(octreeNode != nullptr && "Not placed yet");
+		return *octreeNode;
+	}
 	/// @}
 
 	/// The derived class has to manually set when the collision shape got

+ 8 - 0
include/anki/scene/VisibilityTestResults.h

@@ -11,6 +11,14 @@ class SceneNode;
 /// @addtogroup Scene
 /// @{
 
+/// Visibility test type
+enum VisibilityTest
+{
+	VT_RENDERABLES = 1 << 0,
+	VT_ONLY_SHADOW_CASTERS = 1 << 1,
+	VT_LIGHTS = 1 << 2
+};
+
 /// Its actually a container for visible entities. It should be per frame
 struct VisibilityTestResults
 {

+ 17 - 15
src/scene/Octree.cpp

@@ -27,6 +27,9 @@ OctreeNode::OctreeNode(const Aabb& aabb_, OctreeNode* parent_,
 //==============================================================================
 OctreeNode::~OctreeNode()
 {
+	ANKI_ASSERT(sceneNodes.size() == 0 
+		&& "Deleting an OctreeNode with scene nodes");
+
 	SceneAllocator<U8> alloc = sceneNodes.get_allocator();
 
 	for(OctreeNode* onode : children)
@@ -48,7 +51,7 @@ void OctreeNode::addSceneNode(SceneNode* sn)
 
 	if(this == sp->octreeNode)
 	{
-		// Nothing to do
+		// Nothing changes. Nothing to do
 	}
 	else
 	{
@@ -257,19 +260,18 @@ void Octree::calcAabb(U i, U j, U k, const Aabb& paabb, Aabb& out) const
 }
 
 //==============================================================================
-void Octree::getVisible(const Frustumable& fr,
-	SceneVector<SceneNode*>* renderableNodes,
-	SceneVector<SceneNode*>* lightNodes)
+void Octree::doVisibilityTests(const Frustumable& fr, VisibilityTest test,
+	VisibilityTestResults& visibles)
 {
-	doVisibilityTestsInternal(fr, renderableNodes, lightNodes, root);
+	ANKI_ASSERT(fr.insideFrustum(root.getAabb()));
+	doVisibilityTestsInternal(fr, test, visibles, root);
 }
 
 //==============================================================================
-void Octree::doVisibilityTestsInternal(const Frustumable& fr,
-	SceneVector<SceneNode*>* renderableNodes,
-	SceneVector<SceneNode*>* lightNodes,
-	OctreeNode& node)
+void Octree::doVisibilityTestsInternal(const Frustumable& fr, 
+	VisibilityTest test, VisibilityTestResults& visible, OctreeNode& node)
 {
+	// Put my scene nodes
 	for(SceneNode* sn : node.sceneNodes)
 	{
 		Spatial* sp = sn->getSpatial();
@@ -278,15 +280,15 @@ void Octree::doVisibilityTestsInternal(const Frustumable& fr,
 		if(fr.insideFrustum(*sp))
 		{
 			Renderable* r = sn->getRenderable();
-			if(r != nullptr && renderableNodes != nullptr)
+			if(r != nullptr && (test & VT_RENDERABLES))
 			{
-				renderableNodes->push_back(sn);
+				visible.renderables.push_back(sn);
 			}
 
 			Light* l = sn->getLight();
-			if(l != nullptr && lightNodes != nullptr)
+			if(l != nullptr && (test & VT_LIGHTS))
 			{
-				lightNodes->push_back(sn);
+				visible.lights.push_back(sn);
 			}
 		}
 	}
@@ -294,9 +296,9 @@ void Octree::doVisibilityTestsInternal(const Frustumable& fr,
 	// Go to children
 	for(OctreeNode* onode : node.children)
 	{
-		if(onode != nullptr)
+		if(onode != nullptr && fr.insideFrustum(onode->getAabb()))
 		{
-			doVisibilityTestsInternal(fr, renderableNodes, lightNodes, *onode);
+			doVisibilityTestsInternal(fr, test, visible, *onode);
 		}
 	}
 }

+ 39 - 5
src/scene/Sector.cpp

@@ -43,7 +43,7 @@ Bool Sector::placeSceneNode(SceneNode* sn)
 }
 
 //==============================================================================
-// Sector                                                                      =
+// SectorGroup                                                                 =
 //==============================================================================
 
 //==============================================================================
@@ -116,16 +116,50 @@ void SectorGroup::placeSceneNode(SceneNode* sn)
 }
 
 //==============================================================================
-void SectorGroup::doVisibilityTests(Frustumable& fr, VisibilityTest test)
+void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test)
 {
+	Frustumable* fr = sn.getFrustumable();
+	ANKI_ASSERT(fr != nullptr);
+
+	//
+	// Find the visible sectors
+	//
+
+	SceneVector<Sector*> visibleSectors(scene->getFrameAllocator());
+
+	Spatial* sp = sn.getSpatial();
+	ANKI_ASSERT(sp != nullptr);
+
+	// Find the sector that contains the frustumable
+	Sector& containerSector = sp->getOctreeNode().getOctree().getSector();
+	visibleSectors.push_back(&containerSector);
+
+	// Loop all portals and add other sectors
+	for(Portal* portal : portals)
+	{
+		// Portal is visible
+		// XXX Add tiler test for portals
+		if(fr->insideFrustum(portal->shape))
+		{
+			if(portal->sectors[0] != &containerSector)
+			{
+				visibleSectors.push_back(portal->sectors[0]);
+			}
+			else
+			{
+				ANKI_ASSERT(portal->sectors[1] != &containerSector);
+				visibleSectors.push_back(portal->sectors[1]);
+			}
+		}
+	}
+
+
 	/// Create the visibility container
 	VisibilityTestResults* visible =
 		ANKI_NEW(VisibilityTestResults, scene->getFrameAllocator(),
 		scene->getFrameAllocator());
 
-	// Find the sectors
-
-	fr.visible = visible;
+	fr->visible = visible;
 }
 
 } // end namespace anki