Panagiotis Christopoulos Charitos 14 yıl önce
ebeveyn
işleme
426ca9f050
4 değiştirilmiş dosya ile 124 ekleme ve 403 silme
  1. 12 16
      anki/scene/Scene.cpp
  2. 56 13
      anki/scene/Scene.h
  3. 15 306
      anki/scene/VisibilityTester.cpp
  4. 41 68
      anki/scene/VisibilityTester.h

+ 12 - 16
anki/scene/Scene.cpp

@@ -10,9 +10,6 @@ namespace anki {
 Scene::Scene()
 {
 	ambientCol = Vec3(0.1, 0.05, 0.05) * 4;
-
-	//physPhysWorld.reset(new PhysWorld);
-	//visibilityTester.reset(new VisibilityTester(*this));
 }
 
 
@@ -24,26 +21,25 @@ Scene::~Scene()
 //==============================================================================
 void Scene::registerNode(SceneNode* node)
 {
-	if(nodeExists(node->getName().c_str()))
-	{
-		throw ANKI_EXCEPTION("Scene node already exists: " + node.getName());
-	}
-
-	nodes.push_back(node);
-	nameToNode[node->getName().c_str()] = node;
+	addC(nodes, node);
+	addDict(nameToNode, node);
 }
 
 
 //==============================================================================
 void Scene::unregisterNode(SceneNode* node)
 {
-	Types<SceneNode>::Iterator it;
-	for(it : nodes)
+	removeC(nodes, node);
+	removeDict(nameToNode, node);
+}
+
+
+//==============================================================================
+void Scene::update(float prevUpdateTime, float crntTime, int frame)
+{
+	for(SceneNode* n : nodes)
 	{
-		if(*it == node)
-		{
-			break;
-		}
+		n->frameUpdate(prevUpdateTime, crntTime, frame);
 	}
 }
 

+ 56 - 13
anki/scene/Scene.h

@@ -2,6 +2,7 @@
 #define ANKI_SCENE_SCENE_H
 
 #include "anki/scene/SceneNode.h"
+#include "anki/math/Math.h"
 #include <boost/range/iterator_range.hpp>
 #include <vector>
 
@@ -23,10 +24,9 @@ public:
 		typedef typename Container::const_iterator ConstIterator;
 		typedef boost::iterator_range<Iterator> MutableRange;
 		typedef boost::iterator_range<ConstIterator> ConstRange;
+		typedef typename ConstCharPtrHashMap<T*>::Type NameToItemMap;
 	};
 
-	typedef ConstCharPtrHashMap<SceneNode*>::Type NameToSceneNodeMap;
-
 	/// @name Constructors/Destructor
 	/// @{
 	Scene();
@@ -37,12 +37,12 @@ public:
 	void registerNode(SceneNode* node);
 	void unregisterNode(SceneNode* node);
 
-	void update(float prevUpdateTime, float crntTime);
+	void update(float prevUpdateTime, float crntTime, int frame);
 
-	void doVisibilityTests(Camera& cam)
+	/*void doVisibilityTests(Camera& cam)
 	{
 		//XXX visibilityTester->test(cam);
-	}
+	}*/
 
 	/// @name Accessors
 	/// @{
@@ -69,24 +69,67 @@ public:
 	}
 	/// @}
 
-	bool nodeExists(const char* name) const
-	{
-		return nameToNode.find(name) != nameToNode.end();
-	}
-
 private:
 	/// @name Containers of scene's data
 	/// @{
 	Types<SceneNode>::Container nodes;
-	Types<Movable>::Container movables;
+	/*Types<Movable>::Container movables;
 	Types<Renderable>::Container renderables;
 	Types<Spatial>::Container spatials;
-	Types<Frustumable>::Container frustumables;
+	Types<Frustumable>::Container frustumables;*/
 	/// @}
 
-	NameToSceneNodeMap nameToNode;
+	Types<SceneNode>::NameToItemMap nameToNode;
 
 	Vec3 ambientCol; ///< The global ambient color
+
+	/// XXX
+	template<typename T>
+	void addC(typename Types<T>::Container& c, T* ptr)
+	{
+		ANKI_ASSERT(std::find(c.begin(), c.end(), ptr) == c.end());
+		c.push_back(ptr);
+	}
+
+	/// XXX
+	template<typename T>
+	void addDict(typename Types<T>::NameToItemMap& d, T* ptr)
+	{
+		if(d.find(ptr->getName().c_str()) != d.end())
+		{
+			throw ANKI_EXCEPTION("Item already exists: " + ptr->getName());
+		}
+
+		d[ptr->getName().c_str()] = ptr;
+	}
+
+	/// XXX
+	template<typename T>
+	void removeC(typename Types<T>::Container& c, T* ptr)
+	{
+		typename Types<T>::Iterator it = c.begin();
+		for(; it != c.end(); ++it)
+		{
+			if(*it == ptr)
+			{
+				break;
+			}
+		}
+
+		ANKI_ASSERT(it != c.end());
+		c.erase(it);
+	}
+
+	/// XXX
+	template<typename T>
+	void removeDict(typename Types<T>::NameToItemMap& d, T* ptr)
+	{
+		typename Types<T>::NameToItemMap::iterator it =
+			d.find(ptr->getName().c_str());
+
+		ANKI_ASSERT(it != d.end());
+		d.erase(it);
+	}
 };
 
 

+ 15 - 306
anki/scene/VisibilityTester.cpp

@@ -1,338 +1,47 @@
 #include "anki/scene/VisibilityTester.h"
 #include "anki/scene/Scene.h"
-#include "anki/scene/ModelNode.h"
-#include "anki/scene/SkinNode.h"
-#include "anki/resource/Material.h"
-#include "anki/collision/Sphere.h"
-#include "anki/scene/PointLight.h"
-#include "anki/scene/SpotLight.h"
-#include "anki/core/ParallelManager.h"
-#include "anki/core/Logger.h"
-#include "anki/core/Globals.h"
-#include <boost/foreach.hpp>
+#include "anki/scene/Camera.h"
+#include "anki/scene/Renderable.h"
 
 
 namespace anki {
 
 
-//==============================================================================
-// Destructor                                                                  =
 //==============================================================================
 VisibilityTester::~VisibilityTester()
 {}
 
 
 //==============================================================================
-// CmpDistanceFromOrigin::operator()                                           =
-//==============================================================================
-bool VisibilityTester::CmpDistanceFromOrigin::operator()(const SceneNode* a,
-	const SceneNode* b) const
-{
-	return (a->getWorldTransform().getOrigin() - o).getLengthSquared() <
-		(b->getWorldTransform().getOrigin() - o).getLengthSquared();
-}
-
-
-//==============================================================================
-// Constructor                                                                 =
-//==============================================================================
-VisibilityTester::VisibilityTester(Scene& scene_):
-	scene(scene_)
-{}
-
-
-//==============================================================================
-// test                                                                        =
-//==============================================================================
-void VisibilityTester::test(Camera& cam)
-{
-	//
-	// Set all nodes to not visible
-	//
-	BOOST_FOREACH(SceneNode* node, scene.getAllNodes())
-	{
-		node->disableFlag(SceneNode::SNF_VISIBLE);
-	}
-
-	//
-	// Collect the lights for the main cam
-	//
-	cam.getVisiblePointLights().clear();
-	cam.getVisibleSpotLights().clear();
-
-	BOOST_FOREACH(Light* light, scene.getLights())
-	{
-		if(!light->isFlagEnabled(SceneNode::SNF_ACTIVE))
-		{
-			continue;
-		}
-
-		switch(light->getLightType())
-		{
-			// Point
-			case Light::LT_POINT:
-			{
-				PointLight* pointl = static_cast<PointLight*>(light);
-
-				Sphere sphere(pointl->getWorldTransform().getOrigin(),
-					pointl->getRadius());
-				if(cam.insideFrustum(sphere))
-				{
-					cam.getVisiblePointLights().push_back(pointl);
-					pointl->enableFlag(SceneNode::SNF_VISIBLE);
-				}
-				break;
-			}
-			// Spot
-			case Light::LT_SPOT:
-			{
-				SpotLight* spotl = static_cast<SpotLight*>(light);
-
-				if(cam.insideFrustum(*(spotl->getCamera().
-					getVisibilityCollisionShapeWorldSpace())))
-				{
-					cam.getVisibleSpotLights().push_back(spotl);
-					spotl->enableFlag(SceneNode::SNF_VISIBLE);
-					spotl->getCamera().enableFlag(SceneNode::SNF_VISIBLE);
-				}
-				break;
-			}
-		} // end switch
-	} // end for all lights
-
-	//
-	// Get the renderables for the main cam
-	//
-	getRenderableNodes(false, cam, cam);
-
-	//
-	// For every spot light camera collect the renderable nodes
-	//
-	BOOST_FOREACH(SpotLight* spot, cam.getVisibleSpotLights())
-	{
-		getRenderableNodes(true, spot->getCamera(), *spot);
-	}
-}
-
-
-//==============================================================================
-// test                                                                        =
-//==============================================================================
-template<typename Type>
-bool VisibilityTester::test(const Type& tested, const Camera& cam)
-{
-	return cam.insideFrustum(*tested.getVisibilityCollisionShapeWorldSpace());
-}
-
-
-//==============================================================================
-// getRenderableNodes                                                          =
-//==============================================================================
-void VisibilityTester::getRenderableNodes(bool skipShadowless,
-	const Camera& cam, VisibilityInfo& storage)
-{
-	storage.getVisibleMsRenderableNodes().clear();
-	storage.getVisibleBsRenderableNodes().clear();
-
-	// Run in parallel
-	VisJobParameters jobParameters;
-	jobParameters.cam = &cam;
-	jobParameters.skipShadowless = skipShadowless;
-	jobParameters.visibilityInfo = &storage;
-	jobParameters.scene = &scene;
-	jobParameters.msRenderableNodesMtx = &msRenderableNodesMtx;
-	jobParameters.bsRenderableNodesMtx = &bsRenderableNodesMtx;
-
-	for(uint i = 0;
-		i < ParallelManagerSingleton::get().getThreadsNum(); i++)
-	{
-		ParallelManagerSingleton::get().assignNewJob(i,
-			getRenderableNodesJobCallback, jobParameters);
-	}
-	ParallelManagerSingleton::get().waitForAllJobsToFinish();
-
-	//
-	// Sort the renderables from closest to the camera to the farthest
-	//
-	std::sort(storage.getVisibleMsRenderableNodes().begin(),
-		storage.getVisibleMsRenderableNodes().end(),
-		CmpDistanceFromOrigin(cam.getWorldTransform().getOrigin()));
-	std::sort(storage.getVisibleBsRenderableNodes().begin(),
-		storage.getVisibleBsRenderableNodes().end(),
-		CmpDistanceFromOrigin(cam.getWorldTransform().getOrigin()));
-}
-
-
-//==============================================================================
-// getRenderableNodesJobCallback                                               =
-//==============================================================================
-void VisibilityTester::getRenderableNodesJobCallback(
-	ParallelJobParameters& data,
-	const ParallelJob& job)
+void VisibilityTester::test(Frustumable& cam, Scene& scene,
+	VisibilityInfo& vinfo)
 {
-	VisJobParameters& jobParameters = static_cast<VisJobParameters&>(data);
-
-	uint id = job.getId();
-	uint threadsNum = job.getManager().getThreadsNum();
-
-	const Camera& cam = *jobParameters.cam;
-	bool skipShadowless = jobParameters.skipShadowless;
-	VisibilityInfo& visibilityInfo = *jobParameters.visibilityInfo;
-	Scene& scene = *jobParameters.scene;
-	boost::mutex& msRenderableNodesMtx = *jobParameters.msRenderableNodesMtx;
-	boost::mutex& bsRenderableNodesMtx = *jobParameters.bsRenderableNodesMtx;
-
-	uint count, from, to;
-	size_t nodesSize;
-
-	boost::array<RenderableNode*, Scene::MAX_VISIBLE_NODES> msVisibles,
-		bsVisibles;
-	uint msI = 0, bsI = 0;
-
-
-	//
-	// ModelNodes
-	//
-	nodesSize = scene.getModelNodes().size();
-	count = nodesSize / threadsNum;
-	from = count * id;
-	to = count * (id + 1);
-
-	if(id == threadsNum - 1) // The last job will get the rest
-	{
-		to = nodesSize;
-	}
-
-	for(uint i = from; i < to; i++)
-	{
-		ModelNode* node = scene.getModelNodes()[i];
-
-		if(!node->isFlagEnabled(SceneNode::SNF_ACTIVE))
-		{
-			continue;
-		}
-
-		// Skip if the ModeNode is not visible
-		if(!test(*node, cam))
-		{
-			continue;
-		}
-
-		node->enableFlag(SceneNode::SNF_VISIBLE);
-
-		// If visible test every patch individually
-		BOOST_FOREACH(ModelPatchNode* modelPatchNode,
-			node->getModelPatchNodes())
-		{
-			if(!modelPatchNode->isFlagEnabled(SceneNode::SNF_ACTIVE))
-			{
-				continue;
-			}
-
-			// Skip shadowless
-			if(skipShadowless &&
-				!modelPatchNode->getMaterialRuntime().getShadow())
-			{
-				continue;
-			}
-
-			// Test if visible by main camera
-			if(test(*modelPatchNode, cam))
-			{
-				if(modelPatchNode->getMaterialRuntime().
-					getRenderingStage() == 1)
-				{
-					bsVisibles[bsI++] = modelPatchNode;
-				}
-				else
-				{
-					msVisibles[msI++] = modelPatchNode;
-				}
-				modelPatchNode->enableFlag(SceneNode::SNF_VISIBLE);
-			}
-		}
-	}
-
-
-	//
-	// SkinNodes
-	//
-	nodesSize = scene.getSkinNodes().size();
-	count = nodesSize / threadsNum;
-	from = count * id;
-	to = count * (id + 1);
-
-	if(id == threadsNum - 1) // The last job will get the rest
-	{
-		to = nodesSize;
-	}
-
-	for(uint i = from; i < to; i++)
+	for(SceneNode* node : scene.getAllNodes())
 	{
-		SkinNode* node = scene.getSkinNodes()[i];
+		Renderable* r = node->getRenderable();
+		Frustumable* fr = node->getFrustumable();
+		Spatial* sp = node->getSpatial();
 
-		if(!node->isFlagEnabled(SceneNode::SNF_ACTIVE))
+		if(!sp || (!fr && !r))
 		{
 			continue;
 		}
 
-		// Skip if the SkinNode is not visible
-		if(!test(*node, cam))
+		if(!cam.insideFrustum(*sp))
 		{
 			continue;
 		}
 
-		node->enableFlag(SceneNode::SNF_VISIBLE);
 
-		// Put all the patches into the visible container
-		BOOST_FOREACH(SkinPatchNode* patchNode,
-			node->getPatchNodes())
+		if(fr)
 		{
-			if(!patchNode->isFlagEnabled(SceneNode::SNF_ACTIVE))
-			{
-				continue;
-			}
-
-			// Skip shadowless
-			if(skipShadowless &&
-				!patchNode->getMaterialRuntime().getShadow())
-			{
-				continue;
-			}
-
-			if(patchNode->getMaterialRuntime().getRenderingStage() == 1)
-			{
-				bsVisibles[bsI++] = patchNode;
-			}
-			else
-			{
-				msVisibles[msI++] = patchNode;
-			}
-			patchNode->enableFlag(SceneNode::SNF_VISIBLE);
-		}
-	}
-
-
-	//
-	// Copy the temps to the global
-	//
-	{
-		boost::mutex::scoped_lock lock(bsRenderableNodesMtx);
-
-		for(uint i = 0; i < bsI; i++)
-		{
-			visibilityInfo.getVisibleBsRenderableNodes().push_back(
-				bsVisibles[i]);
+			vinfo.frustumables.push_back(fr);
 		}
-	}
-
-	{
-		boost::mutex::scoped_lock lock(msRenderableNodesMtx);
 
-		for(uint i = 0; i < msI; i++)
+		if(r)
 		{
-			visibilityInfo.getVisibleMsRenderableNodes().push_back(
-				msVisibles[i]);
+			r->enableFlag(Renderable::RF_VISIBLE);
+			vinfo.renderables.push_back(r);
 		}
 	}
 }

+ 41 - 68
anki/scene/VisibilityTester.h

@@ -1,10 +1,8 @@
 #ifndef ANKI_SCENE_VISIBILITY_TESTER_H
 #define ANKI_SCENE_VISIBILITY_TESTER_H
 
-#include "anki/math/Math.h"
-#include "anki/core/ParallelJob.h"
-#include <deque>
-#include <boost/thread.hpp>
+#include <vector>
+#include <boost/range/iterator_range.hpp>
 
 
 namespace anki {
@@ -13,76 +11,51 @@ namespace anki {
 class Camera;
 class Scene;
 class Renderable;
-class SpotLight;
-class PointLight;
-class SceneNode;
-class VisibilityInfo;
+class Frustumable;
+
+
+/// XXX
+class VisibilityInfo
+{
+	friend class VisibilityTester;
+
+public:
+	typedef std::vector<Renderable*> Renderables;
+	typedef std::vector<Frustumable*> Frustumables;
+
+	boost::iterator_range<Renderables::iterator> getRenderables()
+	{
+		return boost::iterator_range<Renderables::iterator>(
+			renderables.begin(), renderables.end());
+	}
+
+	boost::iterator_range<Frustumables::iterator> getFrustumable()
+	{
+		return boost::iterator_range<Frustumables::iterator>(
+			frustumables.begin(), frustumables.end());
+	}
+
+private:
+	Renderables renderables;
+	std::vector<Frustumable*> frustumables;
+};
 
 
 /// Performs visibility determination tests and fills a few containers with the
 /// visible scene nodes
 class VisibilityTester
 {
-	public:
-		/// Constructor
-		VisibilityTester(Scene& scene);
-		~VisibilityTester();
-
-		/// This method:
-		/// - Gets the visible renderable nodes
-		/// - Sort them from the closest to the farthest
-		/// - Get the visible lights
-		/// - For every spot light that casts shadow get the visible renderables
-		void test(Camera& cam);
-
-	private:
-		/// Used in sorting. Compare the length of 2 nodes from the camera
-		struct CmpDistanceFromOrigin
-		{
-			Vec3 o; ///< The camera origin
-			CmpDistanceFromOrigin(const Vec3& o_): o(o_) {}
-			bool operator()(const SceneNode* a, const SceneNode* b) const;
-		};
-
-		/// The JobParameters that we feed in the ParallelManager
-		struct VisJobParameters: ParallelJobParameters
-		{
-			const Camera* cam;
-			bool skipShadowless;
-			VisibilityInfo* visibilityInfo;
-			Scene* scene;
-			boost::mutex* msRenderableNodesMtx;
-			boost::mutex* bsRenderableNodesMtx;
-		};
-
-		Scene& scene; ///< Know your father
-
-		/// @name Needed by getRenderableNodesJobCallback
-		/// The vars of this group are needed by the static
-		/// getRenderableNodesJobCallback and kept here so it can access them
-		/// @{
-		boost::mutex msRenderableNodesMtx;
-		boost::mutex bsRenderableNodesMtx;
-		/// @}
-
-		/// Test a node against the camera frustum
-		template<typename Type>
-		static bool test(const Type& tested, const Camera& cam);
-
-		/// Get renderable nodes for a given camera
-		/// @param[in] skipShadowless Skip shadowless nodes. If the cam is a
-		/// light cam
-		/// @param[in] cam The camera to test and gather renderable nodes
-		/// @param[out] storage The VisibilityInfo of where we will store the
-		/// visible nodes
-		void getRenderableNodes(bool skipShadowless, const Camera& cam,
-			VisibilityInfo& storage);
-
-		/// This static method will be fed into the ParallelManager
-		/// @param data This is actually a pointer to VisibilityTester
-		static void getRenderableNodesJobCallback(
-			ParallelJobParameters& data,
-			const ParallelJob& job);
+public:
+	/// Constructor
+	VisibilityTester()
+	{}
+
+	~VisibilityTester();
+
+	/// This method:
+	/// - Gets the visible renderables and frustumables
+	/// - For every frustumable perform tests
+	void test(Frustumable& cam, Scene& scene, VisibilityInfo& vinfo);
 };