Browse Source

Sector and visibility

Panagiotis Christopoulos Charitos 13 years ago
parent
commit
a98c02b407

+ 2 - 0
CMakeLists.txt

@@ -76,6 +76,8 @@ MESSAGE("++ AnKi window backend: ${ANKI_WINDOW_BACKEND}")
 # Common compiler flags
 # Common compiler flags
 #
 #
 
 
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -static-libstdc++")
+
 # Build type
 # Build type
 IF(CMAKE_BUILD_TYPE STREQUAL Debug)
 IF(CMAKE_BUILD_TYPE STREQUAL Debug)
 ELSE()
 ELSE()

+ 9 - 0
include/anki/scene/Sector.h

@@ -67,6 +67,8 @@ public:
 	/// Destructor
 	/// Destructor
 	~SectorGroup();
 	~SectorGroup();
 
 
+	/// @name Accessors
+	/// @{
 	const Scene& getScene() const
 	const Scene& getScene() const
 	{
 	{
 		return *scene;
 		return *scene;
@@ -75,6 +77,7 @@ public:
 	{
 	{
 		return *scene;
 		return *scene;
 	}
 	}
+	/// @}
 
 
 	/// Called when a node was moved or a change in shape happened. The node 
 	/// Called when a node was moved or a change in shape happened. The node 
 	/// must be Spatial
 	/// must be Spatial
@@ -83,6 +86,12 @@ public:
 	/// XXX
 	/// XXX
 	void doVisibilityTests(SceneNode& fr, VisibilityTest test, Renderer* r);
 	void doVisibilityTests(SceneNode& fr, VisibilityTest test, Renderer* r);
 
 
+	/// The owner of the pointer is the sector group
+	Sector* createNewSector(const Aabb& aabb);
+
+	/// The owner of the pointer is the sector group
+	Portal* createNewPortal(Sector* a, Sector* b, const Obb& collisionShape);
+
 private:
 private:
 	Scene* scene; ///< Keep it here to access various allocators
 	Scene* scene; ///< Keep it here to access various allocators
 	SceneVector<Sector*> sectors;
 	SceneVector<Sector*> sectors;

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

@@ -32,6 +32,7 @@ struct VisibilityTestResults
 		: renderables(frameAlloc), lights(frameAlloc)
 		: renderables(frameAlloc), lights(frameAlloc)
 	{}
 	{}
 };
 };
+
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 10 - 0
include/anki/util/Memory.h

@@ -194,11 +194,21 @@ struct DeleteArray
 	New<Type_, decltype(alloc_)::rebind<Type_>::other>{}( \
 	New<Type_, decltype(alloc_)::rebind<Type_>::other>{}( \
 		1, alloc_, ## __VA_ARGS__)
 		1, alloc_, ## __VA_ARGS__)
 
 
+/// Allocate memory using an allocator
+#define ANKI_NEW_0(Type_, alloc_) \
+	New<Type_, decltype(alloc_)::rebind<Type_>::other>{}( \
+		1, alloc_)
+
 /// Allocate memory using an allocator
 /// Allocate memory using an allocator
 #define ANKI_NEW_ARRAY(Type_, alloc_, n_, ...) \
 #define ANKI_NEW_ARRAY(Type_, alloc_, n_, ...) \
 	New<Type_, decltype(alloc_)::rebind<Type_>::other>{}( \
 	New<Type_, decltype(alloc_)::rebind<Type_>::other>{}( \
 		n_, alloc_, ## __VA_ARGS__)
 		n_, alloc_, ## __VA_ARGS__)
 
 
+/// Allocate memory using an allocator
+#define ANKI_NEW_ARRAY_0(Type_, alloc_, n_) \
+	New<Type_, decltype(alloc_)::rebind<Type_>::other>{}( \
+		n_, alloc_)
+
 /// Delete memory allocated by #ANKI_NEW
 /// Delete memory allocated by #ANKI_NEW
 #define ANKI_DELETE(ptr_, alloc_) \
 #define ANKI_DELETE(ptr_, alloc_) \
 	Delete<RemovePointer<decltype(ptr_)>::Type, \
 	Delete<RemovePointer<decltype(ptr_)>::Type, \

+ 3 - 3
include/anki/util/Object.h

@@ -5,6 +5,7 @@
 #include "anki/util/Vector.h"
 #include "anki/util/Vector.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/Allocator.h"
 #include "anki/util/Allocator.h"
+#include "anki/util/NonCopyable.h"
 #include <algorithm>
 #include <algorithm>
 
 
 namespace anki {
 namespace anki {
@@ -16,7 +17,7 @@ namespace anki {
 
 
 /// A hierarchical object
 /// A hierarchical object
 template<typename T, typename Alloc = Allocator<T>>
 template<typename T, typename Alloc = Allocator<T>>
-class Object
+class Object: public NonCopyable
 {
 {
 public:
 public:
 	typedef T Value;
 	typedef T Value;
@@ -24,13 +25,12 @@ public:
 
 
 	/// Calls addChild if parent is not nullptr
 	/// Calls addChild if parent is not nullptr
 	Object(Value* parent_, const Alloc& alloc = Alloc())
 	Object(Value* parent_, const Alloc& alloc = Alloc())
-		: childs(alloc)
+		: parent(nullptr), childs(alloc)
 	{
 	{
 		if(parent_ != nullptr)
 		if(parent_ != nullptr)
 		{
 		{
 			parent_->addChild(getSelf());
 			parent_->addChild(getSelf());
 		}
 		}
-		parent = parent_;
 	}
 	}
 
 
 	/// Delete children from the last entered to the first and update parent
 	/// Delete children from the last entered to the first and update parent

+ 6 - 1
src/scene/Octree.cpp

@@ -6,6 +6,7 @@
 #include "anki/scene/Scene.h"
 #include "anki/scene/Scene.h"
 #include "anki/util/Exception.h"
 #include "anki/util/Exception.h"
 #include "anki/core/Logger.h"
 #include "anki/core/Logger.h"
+#include "anki/scene/Renderable.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -282,7 +283,11 @@ void Octree::doVisibilityTestsInternal(const Frustumable& fr,
 			Renderable* r = sn->getRenderable();
 			Renderable* r = sn->getRenderable();
 			if(r != nullptr && (test & VT_RENDERABLES))
 			if(r != nullptr && (test & VT_RENDERABLES))
 			{
 			{
-				visible.renderables.push_back(sn);
+				if((test & VT_ONLY_SHADOW_CASTERS) == false
+					|| r->getRenderableMaterial().getShadow())
+				{
+					visible.renderables.push_back(sn);
+				}
 			}
 			}
 
 
 			Light* l = sn->getLight();
 			Light* l = sn->getLight();

+ 123 - 2
src/scene/Sector.cpp

@@ -1,6 +1,7 @@
 #include "anki/scene/Sector.h"
 #include "anki/scene/Sector.h"
 #include "anki/scene/Spatial.h"
 #include "anki/scene/Spatial.h"
 #include "anki/scene/SceneNode.h"
 #include "anki/scene/SceneNode.h"
+#include "anki/scene/Light.h"
 #include "anki/scene/VisibilityTestResults.h"
 #include "anki/scene/VisibilityTestResults.h"
 #include "anki/scene/Frustumable.h"
 #include "anki/scene/Frustumable.h"
 #include "anki/scene/Scene.h"
 #include "anki/scene/Scene.h"
@@ -68,6 +69,28 @@ SectorGroup::~SectorGroup()
 	}
 	}
 }
 }
 
 
+//==============================================================================
+Sector* SectorGroup::createNewSector(const Aabb& aabb)
+{
+	Sector* out = ANKI_NEW(Sector, scene->getAllocator(), this, aabb);
+	sectors.push_back(out);
+	return out;
+}
+
+//==============================================================================
+Portal* SectorGroup::createNewPortal(Sector* a, Sector* b, 
+	const Obb& collisionShape)
+{
+	ANKI_ASSERT(a && b);
+	Portal* out = ANKI_NEW_0(Portal, scene->getAllocator());
+
+	out->sectors[0] = a;
+	out->sectors[1] = b;
+	out->shape = collisionShape;
+
+	return out;
+}
+
 //==============================================================================
 //==============================================================================
 void SectorGroup::placeSceneNode(SceneNode* sn)
 void SectorGroup::placeSceneNode(SceneNode* sn)
 {
 {
@@ -121,7 +144,7 @@ void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 	Renderer* r)
 	Renderer* r)
 {
 {
 	Frustumable* fr = sn.getFrustumable();
 	Frustumable* fr = sn.getFrustumable();
-	ANKI_ASSERT(fr != nullptr);
+	ANKI_ASSERT(fr != nullptr && "sn should be frustumable");
 
 
 	//
 	//
 	// Find the visible sectors
 	// Find the visible sectors
@@ -151,6 +174,7 @@ void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 			ANKI_ASSERT(portal->sectors[1] == &containerSector);
 			ANKI_ASSERT(portal->sectors[1] == &containerSector);
 			testAgainstSector = portal->sectors[0];
 			testAgainstSector = portal->sectors[0];
 		}
 		}
+		ANKI_ASSERT(testAgainstSector != nullptr);
 
 
 		// Search if portal is in the container from another portal
 		// Search if portal is in the container from another portal
 		SceneVector<Sector*>::iterator it = std::find(visibleSectors.begin(),
 		SceneVector<Sector*>::iterator it = std::find(visibleSectors.begin(),
@@ -171,13 +195,110 @@ void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 		}
 		}
 	}
 	}
 
 
+	//
+	// For all visible sectors do the tests
+	//
+
+	// Create a few VisibilityTestResults to pass to every octree
+	SceneVector<VisibilityTestResults> testResults(scene->getFrameAllocator());
+	testResults.resize(visibleSectors.size(), 
+		VisibilityTestResults(scene->getFrameAllocator()));
+	U renderablesCount = 0;
+	U lightsCount = 0;
 
 
-	/// Create the visibility container
+	// Run tests for every octree
+	for(U i = 0; i < visibleSectors.size(); i++)
+	{
+		Sector* sector = visibleSectors[i];
+
+		sector->octree.doVisibilityTests(*fr, test, testResults[i]);
+
+		renderablesCount += testResults[i].renderables.size();
+		lightsCount += testResults[i].lights.size();
+	}
+
+	// If you don't want lights then the octree should do tests with them
+	ANKI_ASSERT(!((test & VT_LIGHTS) == 0 && lightsCount != 0));
+	// Same as ^
+	ANKI_ASSERT(!((test & VT_RENDERABLES) == 0 && renderablesCount != 0));
+
+	//
+	// Combine test results and try doing renderer tests
+	//
+
+	// Create the visibility container
 	VisibilityTestResults* visible =
 	VisibilityTestResults* visible =
 		ANKI_NEW(VisibilityTestResults, scene->getFrameAllocator(),
 		ANKI_NEW(VisibilityTestResults, scene->getFrameAllocator(),
 		scene->getFrameAllocator());
 		scene->getFrameAllocator());
 
 
+	// Set the sizes to save some moves
+	visible->renderables.reserve(renderablesCount);
+	visible->lights.reserve(lightsCount);
+
+	// Iterate previous test results and append to the combined one
+	if(r != nullptr)
+	{
+		for(VisibilityTestResults& testResult : testResults)
+		{
+			visible->renderables.insert(
+				visible->renderables.end(), 
+				testResult.renderables.begin(), 
+				testResult.renderables.end());
+
+			visible->lights.insert(
+				visible->lights.end(), 
+				testResult.lights.begin(), 
+				testResult.lights.end());
+		}
+	}
+	else
+	{
+		for(VisibilityTestResults& testResult : testResults)
+		{
+			// First the renderables
+			for(SceneNode* renderable : testResult.renderables)
+			{
+				if(r->doVisibilityTests(
+					renderable->getSpatial()->getOptimalCollisionShape()))
+				{
+					visible->renderables.push_back(renderable);
+				}
+			}
+
+			// Then the lights
+			for(SceneNode* light : testResult.lights)
+			{
+				if(r->doVisibilityTests(
+					light->getSpatial()->getOptimalCollisionShape()))
+				{
+					visible->lights.push_back(light);
+				}
+			}
+		}
+	}
+
+	// The given frustumable is finished
 	fr->visible = visible;
 	fr->visible = visible;
+
+	//
+	// Continue with testing the lights
+	//
+
+	for(SceneNode* lsn : visible->lights)
+	{
+		Light* l = lsn->getLight();
+		ANKI_ASSERT(l != nullptr);
+
+		if(l->getShadowEnabled())
+		{
+			Frustumable* lfr = lsn->getFrustumable();
+			ANKI_ASSERT(lfr != nullptr);
+
+			doVisibilityTests(*lsn, 
+				(VisibilityTest)(VT_RENDERABLES | VT_ONLY_SHADOW_CASTERS),
+				nullptr);
+		}
+	}
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki