Prechádzať zdrojové kódy

Visibility bugfixes & submeshes opt & static geometry

Panagiotis Christopoulos Charitos 13 rokov pred
rodič
commit
f64e6867f3

+ 5 - 0
include/anki/scene/ModelNode.h

@@ -11,6 +11,9 @@
 
 namespace anki {
 
+/// @addtogroup Scene
+/// @{
+
 /// A fragment of the ModelNode
 class ModelPatchNode: public SceneNode, public Movable, public Renderable,
 	public Spatial
@@ -147,6 +150,8 @@ private:
 	ModelPatchNodes patches;
 };
 
+/// @}
+
 } // end namespace anki
 
 #endif

+ 34 - 5
include/anki/scene/Renderable.h

@@ -5,10 +5,10 @@
 #include "anki/scene/Common.h"
 #include "anki/gl/Ubo.h"
 #include "anki/resource/Material.h"
+#include "anki/resource/Model.h"
 
 namespace anki {
 
-class ModelPatchBase;
 class SceneNode;
 
 /// @addtogroup Scene
@@ -102,7 +102,7 @@ private:
 	BuildinMaterialVariableId buildinId;
 };
 
-/// XXX
+/// Renderable variable
 template<typename T>
 class RenderableVariableTemplate: public RenderableVariable
 {
@@ -188,20 +188,49 @@ public:
 	}
 	/// @}
 
-	U32 getSetsCount() const
+	U32 getSubMeshesCount() const
 	{
-		return 1;
+		return getRenderableModelPatchBase().getSubMeshesCount();
 	}
 
-	void setVisibleSetsMask(const SceneNode* frustumable, U64 mask);
+	/// Set the visibility mask of submeshes. This is called on visibility tests
+	void setVisibleSubMeshesMask(const SceneNode* frustumable, U64 mask);
+
+	/// Get the mask to render only the needed submeshess. Called on rendering
+	U64 getVisibleSubMeshsMask(const SceneNode& frustumable) const;
+
+	/// Reset on frame start
+	void resetFrame()
+	{
+		perframe = nullptr;
+	}
 
 protected:
 	/// The derived class needs to call that
 	void init(PropertyMap& pmap);
 
 private:
+	struct FrustumableMaskPair
+	{
+		const SceneNode* frustumable;
+		U64 mask;
+	};
+
+	/// Per frame data
+	struct PerFrame
+	{
+		PerFrame(const SceneAllocator<U8>& frameAlloc)
+			: pairs(frameAlloc)
+		{
+			pairs.reserve(3);
+		}
+
+		SceneFrameVector<FrustumableMaskPair> pairs;
+	};
+
 	RenderableVariables vars;
 	Ubo ubo;
+	PerFrame* perframe;
 };
 /// @}
 

+ 51 - 6
include/anki/scene/StaticGeometryNode.h

@@ -8,13 +8,16 @@
 
 namespace anki {
 
-/// Part of the static geometry
-class StaticGeometryPatchNode: public SceneNode, public Spatial
+/// @addtogroup Scene
+/// @{
+
+/// Part of the static geometry. Used only for visibility tests
+class StaticGeometrySpatialNode: public SceneNode, public Spatial
 {
 public:
 	/// @name Constructors/Destructor
 	/// @{
-	StaticGeometryPatchNode(const Obb& obb,
+	StaticGeometrySpatialNode(const Obb& obb,
 		const char* name, Scene* scene); // Scene
 	/// @}
 
@@ -32,15 +35,57 @@ public:
 	Obb obb;
 };
 
-/// XXX
-class StaticGeometryNode: public SceneNode, public Spatial, public Renderable
+/// Static geometry scene node
+class StaticGeometryPatchNode: public SceneNode, public Spatial,
+	public Renderable
 {
 public:
+	/// @name Constructors/Destructor
+	/// @{
+	StaticGeometryPatchNode(const ModelPatchBase* modelPatch,
+		const char* name, Scene* scene); // Scene
+	/// @}
+
+	/// @name SceneNode virtuals
+	/// @{
+
+	/// Override SceneNode::getSpatial()
+	Spatial* getSpatial()
+	{
+		return this;
+	}
+
+	/// Override SceneNode::getRenderable()
+	Renderable* getRenderable()
+	{
+		return this;
+	}
+	/// @}
+
+	/// @name Renderable virtuals
+	/// @{
+
+	/// Implements Renderable::getModelPatchBase
+	const ModelPatchBase& getRenderableModelPatchBase() const
+	{
+		return *modelPatch;
+	}
+
+	/// Implements  Renderable::getMaterial
+	const Material& getRenderableMaterial() const
+	{
+		return modelPatch->getMaterial();
+	}
+	/// @}
 
 private:
-	SceneVector<StaticGeometryPatchNode*> patches;
+	const ModelPatchBase* modelPatch;
+	Obb obb; ///< In world space
+	SceneVector<StaticGeometrySpatialNode*> spatials;
 };
 
+/// @}
+
 } // end namespace anki
 
 #endif

+ 1 - 1
include/anki/scene/Visibility.h

@@ -38,7 +38,7 @@ struct VisibilityTestResults
 	typedef SceneFrameVector<SceneNode*> Container;
 
 	/// Used to optimize the initial vector size a bit
-	static const AVERAGE_NUMBER_OF_VISIBLE_SCENE_NODES = 10;
+	static const U32 AVERAGE_NUMBER_OF_VISIBLE_SCENE_NODES = 10;
 
 	Container renderables;
 	Container lights;

+ 32 - 1
src/scene/Renderable.cpp

@@ -1,5 +1,5 @@
 #include "anki/scene/Renderable.h"
-#include "anki/resource/Material.h"
+#include "anki/scene/SceneNode.h"
 #include "anki/resource/TextureResource.h"
 #include "anki/gl/ShaderProgram.h"
 #include "anki/core/Logger.h"
@@ -132,4 +132,35 @@ void Renderable::init(PropertyMap& pmap)
 	}
 }
 
+//==============================================================================
+void Renderable::setVisibleSubMeshesMask(const SceneNode* frustumable, U64 mask)
+{
+	if(ANKI_UNLIKELY(perframe == nullptr))
+	{
+		perframe = ANKI_NEW(PerFrame, frustumable->getSceneFrameAllocator(),
+			frustumable->getSceneFrameAllocator());
+	}
+
+	perframe->pairs.push_back(FrustumableMaskPair{frustumable, mask});
+}
+
+//==============================================================================
+U64 Renderable::getVisibleSubMeshsMask(const SceneNode& frustumable) const
+{
+	ANKI_ASSERT(perframe);
+
+	SceneFrameVector<FrustumableMaskPair>::const_iterator it =
+		perframe->pairs.begin();
+	for(; it != perframe->pairs.end(); it++)
+	{
+		if(it->frustumable == &frustumable)
+		{
+			return it->mask;
+		}
+	}
+
+	ANKI_ASSERT("Shouldn't have come to this");
+	return 0;
+}
+
 }  // end namespace anki

+ 15 - 6
src/scene/Scene.cpp

@@ -65,7 +65,7 @@ void Scene::unregisterNode(SceneNode* node)
 }
 
 //==============================================================================
-void Scene::update(F32 prevUpdateTime, F32 crntTime, Renderer& r)
+void Scene::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 {
 	frameAlloc.reset();
 
@@ -104,22 +104,31 @@ void Scene::update(F32 prevUpdateTime, F32 crntTime, Renderer& r)
 
 		// Do some spatial stuff
 		Spatial* sp = n->getSpatial();
-		if(sp && sp->getSpatialTimestamp() == Timestamp::getTimestamp())
+		if(sp)
 		{
-			sectorGroup.placeSceneNode(n);
+			if(sp->getSpatialTimestamp() == Timestamp::getTimestamp())
+			{
+				sectorGroup.placeSceneNode(n);
+			}
+			sp->disableFlags(Spatial::SF_VISIBLE_ANY);
 		}
 
-		sp->disableFlags(Spatial::SF_VISIBLE_ANY);
-
 		// Do some frustumable stuff
 		Frustumable* fr = n->getFrustumable();
 		if(fr)
 		{
 			fr->setVisibilityTestResults(nullptr);
 		}
+
+		// Do some renderable stuff
+		Renderable* rb = n->getRenderable();
+		if(rb)
+		{
+			rb->resetFrame();
+		}
 	}
 
-	doVisibilityTests(*mainCam, *this, r);
+	doVisibilityTests(*mainCam, *this, renderer);
 
 	/*sectorGroup.doVisibilityTests(*mainCam,
 		VisibilityTest(VT_RENDERABLES | VT_LIGHTS), &r);*/

+ 36 - 2
src/scene/StaticGeometryNode.cpp

@@ -4,13 +4,47 @@
 namespace anki {
 
 //==============================================================================
-// StaticGeometryPatchNode                                                     =
+// StaticGeometrySpatialNode                                                   =
 //==============================================================================
 
 //==============================================================================
-StaticGeometryPatchNode::StaticGeometryPatchNode(const Obb& obb_,
+StaticGeometrySpatialNode::StaticGeometrySpatialNode(const Obb& obb_,
 	const char* name, Scene* scene)
 	: SceneNode(name, scene), Spatial(&obb), obb(obb_)
 {}
 
+//==============================================================================
+// StaticGeometryPatchNode                                                     =
+//==============================================================================
+
+//==============================================================================
+StaticGeometryPatchNode::StaticGeometryPatchNode(
+	const ModelPatchBase* modelPatch_, const char* name, Scene* scene)
+	:	SceneNode(name, scene),
+		Spatial(&obb),
+		Renderable(getSceneAllocator()),
+		modelPatch(modelPatch_)
+{
+	ANKI_ASSERT(modelPatch);
+	Renderable::init(*this);
+
+	obb = modelPatch->getBoundingShape();
+
+	if(modelPatch->getSubMeshesCount() > 1)
+	{
+		spatials.reserve(modelPatch->getSubMeshesCount());
+
+		for(U i = 0; i < modelPatch->getSubMeshesCount(); i++)
+		{
+			std::string aName = name + std::to_string(i);
+
+			StaticGeometrySpatialNode* node =
+				ANKI_NEW(StaticGeometrySpatialNode, getSceneAllocator(),
+				modelPatch->getBoundingShapeSub(i), aName.c_str(), scene);
+
+			spatials.push_back(node);
+		}
+	}
+}
+
 } // end namespace anki

+ 2 - 2
testapp/Main.cpp

@@ -243,7 +243,7 @@ void init()
 
 #if 1
 	ModelNode* sponzaModel = new ModelNode(
-		"data/maps/sponza/sponza_new.mdl",
+		"data/maps/sponza/sponza.mdl",
 		"sponza", &scene, Movable::MF_NONE, nullptr);
 
 	(void)sponzaModel;
@@ -453,7 +453,7 @@ void mainLoop()
 
 		// Sleep
 		//
-#if 1
+#if 0
 		timer.stop();
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		{