Browse Source

Sector work

Panagiotis Christopoulos Charitos 10 years ago
parent
commit
69bc0288b4

+ 5 - 5
include/anki/scene/BodyComponent.h

@@ -19,6 +19,11 @@ namespace anki {
 class BodyComponent: public SceneComponent
 {
 public:
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::BODY;
+	}
+
 	BodyComponent(SceneNode* node, PhysicsBody* body)
 	:	SceneComponent(Type::BODY, node), 
 		m_body(body)
@@ -45,11 +50,6 @@ public:
 	}
 	/// @}
 
-	static constexpr Type getClassType()
-	{
-		return Type::BODY;
-	}
-
 private:
 	PhysicsBody* m_body;
 	Transform m_trf;

+ 5 - 5
include/anki/scene/FrustumComponent.h

@@ -30,6 +30,11 @@ public:
 		U32 m_lightsCount = 0;
 	};
 
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::FRUSTUM;
+	}
+
 	/// Pass the frustum here so we can avoid the virtuals
 	FrustumComponent(SceneNode* node, Frustum* frustum)
 	:	SceneComponent(Type::FRUSTUM, node), 
@@ -133,11 +138,6 @@ public:
 	}
 	/// @}
 
-	static constexpr Type getClassType()
-	{
-		return Type::FRUSTUM;
-	}
-
 private:
 	enum Flags
 	{

+ 5 - 5
include/anki/scene/InstanceNode.h

@@ -17,14 +17,14 @@ namespace anki {
 class InstanceComponent: public SceneComponent
 {
 public:
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::INSTANCE;
+	}
+
 	InstanceComponent(SceneNode* node)
 	:	SceneComponent(Type::INSTANCE, node)
 	{}
-
-	static constexpr Type getClassType()
-	{
-		return Type::INSTANCE;
-	}
 };
 
 /// Instance scene node

+ 5 - 5
include/anki/scene/LensFlareComponent.h

@@ -20,6 +20,11 @@ namespace anki {
 class LensFlareComponent final: public SceneComponent
 {
 public:
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::LENS_FLARE;
+	}
+
 	LensFlareComponent(SceneNode* node)
 	:	SceneComponent(Type::LENS_FLARE, node),
 		m_node(node)
@@ -91,11 +96,6 @@ public:
 	}
 	/// @}
 
-	static constexpr Type getClassType()
-	{
-		return Type::LENS_FLARE;
-	}
-
 private:
 	TextureResourcePointer m_tex; ///< Array of textures.
 	U8 m_flareCount = 0; ///< Cache the flare count.

+ 5 - 5
include/anki/scene/LightComponent.h

@@ -18,6 +18,11 @@ namespace anki {
 class LightComponent: public SceneComponent
 {
 public:
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::LIGHT;
+	}
+
 	enum class LightType: U8
 	{
 		POINT,
@@ -131,11 +136,6 @@ public:
 
 	ANKI_USE_RESULT Error update(SceneNode&, F32, F32, Bool& updated) override;
 
-	static constexpr Type getClassType()
-	{
-		return Type::LIGHT;
-	}
-
 private:
 	LightType m_type;
 	Vec4 m_diffColor = Vec4(0.5);

+ 5 - 5
include/anki/scene/MoveComponent.h

@@ -38,6 +38,11 @@ class MoveComponent: public SceneComponent, public Bitset<MoveComponentFlag>
 public:
 	using Flag = MoveComponentFlag;
 
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::MOVE;
+	}
+
 	/// The one and only constructor
 	/// @param node The scene node to steal it's allocators
 	/// @param flags The flags
@@ -165,11 +170,6 @@ public:
 	}
 	/// @}
 
-	static constexpr Type getClassType()
-	{
-		return Type::MOVE;
-	}
-
 private:
 	SceneNode* m_node;
 

+ 5 - 5
include/anki/scene/PlayerControllerComponent.h

@@ -18,6 +18,11 @@ namespace anki {
 class PlayerControllerComponent: public SceneComponent
 {
 public:
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::PLAYER_CONTROLLER;
+	}
+
 	PlayerControllerComponent(SceneNode* node, PhysicsPlayerController* player)
 	:	SceneComponent(Type::PLAYER_CONTROLLER, node),
 		m_player(player)
@@ -48,11 +53,6 @@ public:
 	}
 	/// @}
 
-	static constexpr Type getClassType()
-	{
-		return Type::PLAYER_CONTROLLER;
-	}
-
 private:
 	PhysicsPlayerController* m_player;
 	Transform m_trf;

+ 5 - 5
include/anki/scene/RenderComponent.h

@@ -224,6 +224,11 @@ class RenderComponent: public SceneComponent
 public:
 	typedef SceneDArray<RenderComponentVariable*> Variables;
 
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::RENDER;
+	}
+
 	/// @param node Pass node to steal it's allocator
 	RenderComponent(SceneNode* node);
 
@@ -285,11 +290,6 @@ public:
 		return err;
 	}
 
-	static constexpr Type getClassType()
-	{
-		return Type::RENDER;
-	}
-
 private:
 	SceneAllocator<U8> m_alloc;
 	Variables m_vars;

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

@@ -78,14 +78,6 @@ public:
 	ANKI_USE_RESULT Error updateReal(
 		SceneNode& node, F32 prevTime, F32 crntTime, Bool& updated);
 
-	template<typename TComponent>
-	TComponent& downCast()
-	{
-		ANKI_ASSERT(TComponent::getClassType() == getType());
-		TComponent* out = staticCastPtr<TComponent*>(this);
-		return *out;
-	}
-
 	void setAutomaticCleanup(Bool enable)
 	{
 		m_flags.enableBits(AUTOMATIC_CLEANUP, enable);	

+ 7 - 9
include/anki/scene/SceneNode.h

@@ -8,6 +8,7 @@
 
 #include "anki/scene/Common.h"
 #include "anki/util/Hierarchy.h"
+#include "anki/util/Rtti.h"
 #include "anki/scene/SceneComponent.h"
 
 namespace anki {
@@ -102,15 +103,14 @@ public:
 	ANKI_USE_RESULT Error iterateComponentsOfType(Func func)
 	{
 		Error err = ErrorCode::NONE;
-		SceneComponent::Type type = Component::getClassType();
 		auto it = m_components.getBegin();
 		auto end = it + m_componentsCount;
 		for(; !err && it != end; ++it)
 		{
 			SceneComponent* comp = *it;
-			if(comp->getType() == type)
+			if(isa<Component>(comp))
 			{
-				err = func(comp->downCast<Component>());
+				err = func(*dcast<Component*>(comp));
 			}
 		}
 
@@ -121,13 +121,12 @@ public:
 	template<typename Component>
 	Component* tryGetComponent()
 	{
-		SceneComponent::Type type = Component::getClassType();
 		U count = m_componentsCount;
 		while(count-- != 0)
 		{
-			if(m_components[count]->getType() == type)
+			if(isa<Component>(m_components[count]))
 			{
-				return &m_components[count]->downCast<Component>();
+				return dcast<Component*>(m_components[count]);
 			}
 		}
 		return nullptr;
@@ -137,13 +136,12 @@ public:
 	template<typename Component>
 	const Component* tryGetComponent() const
 	{
-		SceneComponent::Type type = Component::getClassType();
 		U count = m_componentsCount;
 		while(count-- != 0)
 		{
-			if(m_components[count]->getType() == type)
+			if(isa<Component>(m_components[count]))
 			{
-				return &m_components[count]->downCast<Component>();
+				return dcast<const Component*>(m_components[count]);
 			}
 		}
 		return nullptr;

+ 20 - 5
include/anki/scene/Sector.h

@@ -16,6 +16,7 @@ namespace anki {
 class SceneNode;
 class Sector;
 class SectorGroup;
+class FrustumComponent;
 
 /// @addtogroup Scene
 /// @{
@@ -72,8 +73,9 @@ public:
 
 	ANKI_USE_RESULT Error addPortal(Portal* portal);
 
-	ANKI_USE_RESULT Error addSceneNode(SceneNode* node);
-	void removeSceneNode(SceneNode* node);
+	ANKI_USE_RESULT Error tryAddSpatialComponent(SpatialComponent* sp);
+
+	void tryRemoveSpatialComponent(SpatialComponent* sp);
 
 private:
 	SectorGroup* m_group; ///< Know your father
@@ -81,9 +83,14 @@ private:
 	DArray<Vec4> m_shapeStorage;
 
 	List<Portal*> m_portals;
-	List<SceneNode*> m_nodes;
+	List<SpatialComponent*> m_spatials;
+
+	SpinLock m_lock;
+
+	Bool m_dirty = true;
 
-	List<SceneNode*>::Iterator findSceneNode(SceneNode* node);
+	List<SpatialComponent*>::Iterator findSpatialComponent(
+		SpatialComponent* sp);
 };
 
 /// Sector group. This is supposed to represent the whole scene
@@ -108,9 +115,13 @@ public:
 
 	ANKI_USE_RESULT Error bake();
 
+	ANKI_USE_RESULT Error spatialUpdated(SpatialComponent* sp);
+	void spatialDeleted(SpatialComponent* sp);
+
 	/// @privatesection
 	/// @{
-	ConvexHullShape* createConvexHull(const SArray<Vec4>& vertPositions,
+	ConvexHullShape* createConvexHull(
+		const SArray<Vec4>& vertPositions,
 		DArray<Vec4>& shapeStorage);
 	/// @}
 
@@ -118,6 +129,10 @@ private:
 	SceneGraph* m_scene; ///< Keep it here to access various allocators
 	List<Sector*> m_sectors;
 	List<Portal*> m_portals;
+
+	ANKI_USE_RESULT Error doVisibilityTests(
+		const FrustumComponent& frc, 
+		DArray<Sector*>& visibleSectors);
 };
 /// @}
 

+ 15 - 5
include/anki/scene/SpatialComponent.h

@@ -11,9 +11,13 @@
 #include "anki/Collision.h"
 #include "anki/util/Bitset.h"
 #include "anki/util/Enum.h"
+#include "anki/util/List.h"
 
 namespace anki {
 
+// Forward
+class Sector;
+
 /// @addtogroup scene
 /// @{
 
@@ -45,6 +49,11 @@ class SpatialComponent: public SceneComponent,
 public:
 	using Flag = SpatialComponentFlag;
 
+	static Bool classof(const SceneComponent& c)
+	{
+		return c.getType() == Type::SPATIAL;
+	}
+
 	SpatialComponent(
 		SceneNode* node, 
 		const CollisionShape* shape, 
@@ -62,6 +71,11 @@ public:
 		return m_aabb;
 	}
 
+	List<Sector*>& getSectorInfo()
+	{
+		return m_sectorInfo;
+	}
+
 	/// Get optimal collision shape for visibility tests
 	const CollisionShape& getVisibilityCollisionShape()
 	{
@@ -104,15 +118,11 @@ public:
 	void reset() override;
 	/// @}
 
-	static constexpr Type getClassType()
-	{
-		return Type::SPATIAL;
-	}
-
 private:
 	const CollisionShape* m_shape;
 	Aabb m_aabb; ///< A faster shape
 	Vec4 m_origin = Vec4(MAX_F32, MAX_F32, MAX_F32, 0.0);
+	List<Sector*> m_sectorInfo;
 };
 /// @}
 

+ 111 - 15
src/scene/Sector.cpp

@@ -63,7 +63,7 @@ Sector::~Sector()
 	}
 
 	m_portals.destroy(alloc);
-	m_nodes.destroy(alloc);
+	m_spatials.destroy(alloc);
 }
 
 //==============================================================================
@@ -81,30 +81,86 @@ Error Sector::addPortal(Portal* portal)
 }
 
 //==============================================================================
-Error Sector::addSceneNode(SceneNode* node)
+Error Sector::tryAddSpatialComponent(SpatialComponent* sp)
 {
-	ANKI_ASSERT(node);
-	ANKI_ASSERT(findSceneNode(node) == m_nodes.getEnd());
-	return m_nodes.pushBack(m_group->getAllocator(), node);
+	ANKI_ASSERT(sp);
+
+	// Find sector in spatial
+	auto itsp = sp->getSectorInfo().getBegin();
+	auto endsp = sp->getSectorInfo().getEnd();
+	for(; itsp != endsp; ++itsp)
+	{
+		if(*itsp == this)
+		{
+			break;
+		}
+	}
+	
+	Error err = ErrorCode::NONE;
+	if(itsp == endsp)
+	{
+		// Not found so add it
+
+		// Lock since this might be dont from a thread
+		LockGuard<SpinLock> g(m_lock);
+
+		ANKI_ASSERT(findSpatialComponent(sp) == m_spatials.getEnd());
+
+		m_dirty = true;
+		Error err = m_spatials.pushBack(m_group->getAllocator(), sp);
+
+		if(!err)
+		{
+			err = sp->getSectorInfo().pushBack(m_group->getAllocator(), this);
+		}
+	}
+
+	return err;
 }
 
 //==============================================================================
-void Sector::removeSceneNode(SceneNode* node)
+void Sector::tryRemoveSpatialComponent(SpatialComponent* sp)
 {
-	ANKI_ASSERT(node);
-	auto it = findSceneNode(node);
-	ANKI_ASSERT(it != m_nodes.getEnd());
-	m_nodes.erase(m_group->getAllocator(), it);
+	ANKI_ASSERT(sp);
+	
+	// Find sector in spatial
+	auto itsp = sp->getSectorInfo().getBegin();
+	auto endsp = sp->getSectorInfo().getEnd();
+	for(; itsp != endsp; ++itsp)
+	{
+		if(*itsp == this)
+		{
+			break;
+		}
+	}
+
+	if(itsp != endsp)
+	{
+		// Found, remove
+
+		// Lock since this might be dont from a thread
+		LockGuard<SpinLock> g(m_lock);
+
+		m_dirty = true;
+
+		sp->getSectorInfo().erase(m_group->getAllocator(), itsp);
+
+		auto it = findSpatialComponent(sp);
+		ANKI_ASSERT(it != m_spatials.getEnd());
+		m_spatials.erase(m_group->getAllocator(), it);
+	}
 }
 
 //==============================================================================
-List<SceneNode*>::Iterator Sector::findSceneNode(SceneNode* node)
+List<SpatialComponent*>::Iterator Sector::findSpatialComponent(
+	SpatialComponent* sp)
 {
-	ANKI_ASSERT(node);
-	auto it = m_nodes.getBegin();
-	for(; it != m_nodes.getEnd(); ++it)
+	ANKI_ASSERT(sp);
+	auto it = m_spatials.getBegin();
+	auto end = m_spatials.getEnd();
+	for(; it != end; ++it)
 	{
-		if(*it == node)
+		if(*it == sp)
 		{
 			break;
 		}
@@ -227,4 +283,44 @@ Error SectorGroup::bake()
 	return ErrorCode::NONE;
 }
 
+//==============================================================================
+Error SectorGroup::spatialUpdated(SpatialComponent* sp)
+{
+	Error err = ErrorCode::NONE;
+
+	// Iterate all sectors and bin the spatial
+	auto it = m_sectors.getBegin();
+	auto end = m_sectors.getEnd();
+	for(; it != end && !err; ++it)
+	{
+		Sector& sector = *(*it);
+
+		Bool collide = testCollisionShapes(
+			sector.getCollisionShape(), sp->getSpatialCollisionShape());
+
+		if(collide)	
+		{
+			err = sector.tryAddSpatialComponent(sp);
+		}
+		else
+		{
+			sector.tryRemoveSpatialComponent(sp);
+		}
+	}
+
+	return err;
+}
+
+//==============================================================================
+void SectorGroup::spatialDeleted(SpatialComponent* sp)
+{
+	auto it = m_sectors.getBegin();
+	auto end = m_sectors.getEnd();
+	for(; it != end; ++it)
+	{
+		Sector& sector = *(*it);
+		sector.tryRemoveSpatialComponent(sp);
+	}
+}
+
 } // end namespace anki