Panagiotis Christopoulos Charitos 13 年之前
父节点
当前提交
b30d1596e3

+ 4 - 0
include/anki/renderer/Dbg.h

@@ -41,6 +41,10 @@ public:
 	{
 		depthTest = enable;
 	}
+	void switchDepthTestEnabled()
+	{
+		depthTest = !depthTest;
+	}
 
 	DebugDrawer& getDebugDrawer()
 	{

+ 4 - 0
include/anki/scene/Common.h

@@ -19,6 +19,10 @@ typedef std::basic_string<char, std::char_traits<char>,
 template<typename T>
 using SceneVector = Vector<T, SceneAllocator<T>>;
 
+/// The same as SceneVector. Different name to show the difference
+template<typename T>
+using SceneFrameVector = Vector<T, SceneAllocator<T>>;
+
 } // end namespace anki
 
 #endif

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

@@ -96,7 +96,7 @@ private:
 class ModelNode: public SceneNode, public Movable
 {
 public:
-	typedef PtrVector<ModelPatchNode> ModelPatchNodes;
+	typedef SceneVector<ModelPatchNode*> ModelPatchNodes;
 
 	/// @name Constructors/Destructor
 	/// @{

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

@@ -2,7 +2,6 @@
 #define ANKI_SCENE_OCTREE_H
 
 #include "anki/collision/Aabb.h"
-#include "anki/util/Vector.h"
 #include "anki/util/Array.h"
 #include "anki/scene/Common.h"
 #include "anki/scene/VisibilityTestResults.h"

+ 5 - 3
include/anki/scene/ParticleEmitter.h

@@ -218,7 +218,7 @@ public:
 	/// Overrides Renderable::getRenderableWorldTransforms
 	const Transform* getRenderableWorldTransforms() const
 	{
-		return &instancingTransformations[0];
+		return &(*instancingTransformations)[0];
 	}
 
 	/// Overrides Renderable::getRenderableInstancesCount
@@ -237,7 +237,7 @@ public:
 
 private:
 	ParticleEmitterResourcePointer particleEmitterResource;
-	std::unique_ptr<btCollisionShape> collShape = nullptr;
+	btCollisionShape* collShape = nullptr;
 	SceneVector<ParticleBase*> particles;
 	F32 timeLeftForNextEmission;
 	/// The resource
@@ -249,7 +249,9 @@ private:
 
 	U32 instancesCount; ///< AKA alive count
 
-	Vector<Transform> instancingTransformations;
+	/// The transformations. Calculated on frameUpdate() and consumed on
+	/// rendering.
+	SceneFrameVector<Transform>* instancingTransformations;
 
 	RenderableVariable* alphaRenderableVar = nullptr;
 

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

@@ -3,7 +3,6 @@
 
 #include "anki/scene/Property.h"
 #include "anki/scene/Common.h"
-#include "anki/util/Vector.h"
 #include "anki/gl/Ubo.h"
 #include "anki/resource/Material.h"
 

+ 0 - 3
include/anki/scene/Scene.h

@@ -7,7 +7,6 @@
 #include "anki/scene/Sector.h"
 #include "anki/math/Math.h"
 #include "anki/util/Singleton.h"
-#include "anki/util/Vector.h"
 #include "anki/core/Timestamp.h"
 #include "anki/physics/PhysWorld.h"
 
@@ -135,8 +134,6 @@ public:
 	SceneNode& findSceneNode(const char* name);
 	SceneNode* tryFindSceneNode(const char* name);
 
-	PtrVector<Sector> sectors;
-
 private:
 	SceneAllocator<U8> alloc;
 	SceneAllocator<U8> frameAlloc;

+ 15 - 3
include/anki/scene/Sector.h

@@ -32,6 +32,9 @@ class Sector
 	friend class SectorGroup;
 
 public:
+	/// Used to reserve some space on the portals vector to save memory
+	static const U AVERAGE_PORTALS_PER_SECTOR = 3;
+
 	/// Default constructor
 	Sector(SectorGroup* group, const Aabb& box);
 
@@ -54,9 +57,9 @@ public:
 		return octree;
 	}
 
-	Bool isVisible() const
+	U8 getVisibleByMask() const
 	{
-		return visible;
+		return visibleBy;
 	}
 
 	/// Called when a node was moved or a change in shape happened
@@ -66,7 +69,13 @@ private:
 	SectorGroup* group; ///< Know your father
 	Octree octree;
 	SceneVector<Portal*> portals;
-	Bool8 visible;
+	U8 visibleBy;
+
+	/// Sector does not take ownership of the portal
+	void addNewPortal(Portal* portal);
+
+	/// Remove a Portal from the portals container
+	void removePortal(Portal* portal);
 };
 
 /// Sector group. This is supposed to represent the whole scene
@@ -118,6 +127,9 @@ private:
 	Scene* scene; ///< Keep it here to access various allocators
 	SceneVector<Sector*> sectors;
 	SceneVector<Portal*> portals;
+
+	void doVisibilityTestsInternal(SceneNode& fr, VisibilityTest test,
+		Renderer* r, VisibleBy visibleBy);
 };
 
 /// @}

+ 4 - 6
include/anki/scene/Spatial.h

@@ -79,15 +79,13 @@ public:
 		return origin;
 	}
 
-	OctreeNode& getOctreeNode()
+	OctreeNode* getOctreeNode()
 	{
-		ANKI_ASSERT(octreeNode != nullptr && "Not placed yet");
-		return *octreeNode;
+		return octreeNode;
 	}
-	const OctreeNode& getOctreeNode() const
+	const OctreeNode* getOctreeNode() const
 	{
-		ANKI_ASSERT(octreeNode != nullptr && "Not placed yet");
-		return *octreeNode;
+		return octreeNode;
 	}
 	/// @}
 

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

@@ -19,10 +19,18 @@ enum VisibilityTest
 	VT_LIGHTS = 1 << 2
 };
 
+/// Visible by
+enum VisibleBy
+{
+	VB_NONE = 0,
+	VB_CAMERA = 1 << 0,
+	VB_LIGHT = 1 << 1
+};
+
 /// Its actually a container for visible entities. It should be per frame
 struct VisibilityTestResults
 {
-	typedef SceneVector<SceneNode*> Container;
+	typedef SceneFrameVector<SceneNode*> Container;
 
 	Container renderables;
 	Container lights;

+ 15 - 1
src/renderer/DebugDrawer.cpp

@@ -542,7 +542,21 @@ void SceneDebugDrawer::draw(const OctreeNode& octnode, U32 depth,
 void SceneDebugDrawer::draw(const Sector& sector)
 {
 	// Draw the sector
-	dbg->setColor(Vec3(0.5, 0.5, 1.0));
+	if(sector.getVisibleByMask() == VB_NONE)
+	{
+		dbg->setColor(Vec3(1.0, 0.5, 0.5));
+	}
+	else
+	{
+		if(sector.getVisibleByMask() & VB_CAMERA)
+		{
+			dbg->setColor(Vec3(0.5, 1.0, 0.5));
+		}
+		else
+		{
+			dbg->setColor(Vec3(0.5, 0.5, 1.0));
+		}
+	}
 	CollisionDebugDrawer v(dbg);
 	sector.getAabb().accept(v);
 

+ 14 - 5
src/scene/ModelNode.cpp

@@ -12,7 +12,7 @@ namespace anki {
 ModelPatchNode::ModelPatchNode(const ModelPatch* modelPatch_,
 	const char* name, Scene* scene,
 	U32 movableFlags, Movable* movParent)
-	: SceneNode(name, scene),
+	:	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
 		Renderable(getSceneAllocator()),
 		Spatial(&obb), modelPatch(modelPatch_)
@@ -29,16 +29,20 @@ ModelNode::ModelNode(const char* modelFname,
 	const char* name, Scene* scene,
 	uint movableFlags, Movable* movParent)
 	: 	SceneNode(name, scene),
-		Movable(movableFlags, movParent, *this, getSceneAllocator())
+		Movable(movableFlags, movParent, *this, getSceneAllocator()),
+		patches(getSceneAllocator())
 {
 	model.load(modelFname);
 
-	uint i = 0;
+	patches.reserve(model->getModelPatches().size());
+
+	U i = 0;
 	for(const ModelPatch* patch : model->getModelPatches())
 	{
 		std::string name_ = name + std::to_string(i);
 
-		ModelPatchNode* mpn = new ModelPatchNode(patch, name_.c_str(),
+		ModelPatchNode* mpn = ANKI_NEW(ModelPatchNode, getSceneAllocator(),
+			patch, name_.c_str(),
 			scene, Movable::MF_IGNORE_LOCAL_TRANSFORM, this);
 
 		patches.push_back(mpn);
@@ -48,6 +52,11 @@ ModelNode::ModelNode(const char* modelFname,
 
 //==============================================================================
 ModelNode::~ModelNode()
-{}
+{
+	for(ModelPatchNode* patch : patches)
+	{
+		ANKI_DELETE(patch, getSceneAllocator());
+	}
+}
 
 } // end namespace anki

+ 19 - 9
src/scene/ParticleEmitter.cpp

@@ -267,8 +267,10 @@ ParticleEmitter::~ParticleEmitter()
 {
 	for(ParticleBase* part : particles)
 	{
-		delete part;
+		ANKI_DELETE(part, getSceneAllocator());
 	}
+
+	ANKI_DELETE(collShape, getSceneAllocator());
 }
 
 //==============================================================================
@@ -294,10 +296,10 @@ void ParticleEmitter::movableUpdate()
 //==============================================================================
 void ParticleEmitter::createParticlesSimulation(Scene* scene)
 {
-	collShape.reset(new btSphereShape(particle.size));
+	collShape = ANKI_NEW(btSphereShape, getSceneAllocator(), particle.size);
 
 	RigidBody::Initializer binit;
-	binit.shape = collShape.get();
+	binit.shape = collShape;
 	binit.group = PhysWorld::CG_PARTICLE;
 	binit.mask = PhysWorld::CG_MAP;
 
@@ -307,7 +309,7 @@ void ParticleEmitter::createParticlesSimulation(Scene* scene)
 	{
 		binit.mass = getRandom(particle.mass, particle.massDeviation);
 
-		Particle* part = new Particle(
+		Particle* part = ANKI_NEW(Particle, getSceneAllocator(),
 			(getName() + std::to_string(i)).c_str(), scene,
 			Movable::MF_NONE, nullptr,
 			&scene->getPhysics(), binit);
@@ -325,7 +327,7 @@ void ParticleEmitter::createParticlesSimpleSimulation(Scene* scene)
 {
 	for(U i = 0; i < maxNumOfParticles; i++)
 	{
-		ParticleSimple* part = new ParticleSimple(
+		ParticleSimple* part = ANKI_NEW(ParticleSimple, getSceneAllocator(),
 			(getName() + std::to_string(i)).c_str(),
 			scene, Movable::MF_NONE, nullptr);
 
@@ -348,8 +350,16 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	Vec3 aabbmin(std::numeric_limits<F32>::max());
 	Vec3 aabbmax(-std::numeric_limits<F32>::max());
 
-	instancingTransformations.clear();
-	Vector<F32> alpha;
+	// Create the transformations vector
+	instancingTransformations = ANKI_NEW(SceneFrameVector<Transform>,
+		getSceneFrameAllocator(), getSceneFrameAllocator());
+
+	instancingTransformations->reserve(particles.size());
+
+	// Create the alpha vectors
+	SceneFrameVector<F32> alpha(getSceneFrameAllocator());
+	alpha.reserve(particles.size());
+
 	for(ParticleBase* p : particles)
 	{
 		if(p->isDead())
@@ -385,7 +395,7 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 			trf.setScale(
 				p->size + (lifePercent * particle.sizeAnimation));
 
-			instancingTransformations.push_back(trf);
+			instancingTransformations->push_back(trf);
 
 			// Set alpha
 			if(alphaRenderableVar)
@@ -397,7 +407,7 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 		}
 	}
 
-	instancesCount = instancingTransformations.size();
+	instancesCount = instancingTransformations->size();
 	if(instancesCount != 0)
 	{
 		aabb = Aabb(aabbmin - particle.size, aabbmax + particle.size);

+ 78 - 21
src/scene/Sector.cpp

@@ -93,7 +93,10 @@ Portal::Portal()
 Sector::Sector(SectorGroup* group_, const Aabb& box)
 	: group(group_), octree(this, box, 3),
 		portals(group->getScene().getAllocator())
-{}
+{
+	// Reserve some space for portals
+	portals.reserve(AVERAGE_PORTALS_PER_SECTOR);
+}
 
 //==============================================================================
 Bool Sector::placeSceneNode(SceneNode* sn)
@@ -109,6 +112,28 @@ Bool Sector::placeSceneNode(SceneNode* sn)
 	return true;
 }
 
+//==============================================================================
+void Sector::addNewPortal(Portal* portal)
+{
+	ANKI_ASSERT(portal);
+	ANKI_ASSERT(
+		std::find(portals.begin(), portals.end(), portal) == portals.end()
+		&& "Portal found in the container");
+
+	portals.push_back(portal);
+}
+
+//==============================================================================
+void Sector::removePortal(Portal* portal)
+{
+	ANKI_ASSERT(portal);
+	SceneVector<Portal*>::iterator it =
+		std::find(portals.begin(), portals.end(), portal);
+
+	ANKI_ASSERT(it != portals.end());
+	portals.erase(it);
+}
+
 //==============================================================================
 // SectorGroup                                                                 =
 //==============================================================================
@@ -157,6 +182,9 @@ Portal* SectorGroup::createNewPortal(Sector* a, Sector* b,
 
 	portals.push_back(out);
 
+	a->addNewPortal(out);
+	b->addNewPortal(out);
+
 	return out;
 }
 
@@ -166,14 +194,29 @@ void SectorGroup::placeSceneNode(SceneNode* sn)
 	ANKI_ASSERT(sn != nullptr);
 	Spatial* sp = sn->getSpatial();
 	ANKI_ASSERT(sp);
-	const Aabb& spAabb = sp->getAabb();
+	const Vec3& spPos = sp->getSpatialOrigin();
 
 	// Find the candidates first. Sectors overlap, chose the smaller(??!!??)
 	Sector* sector = nullptr;
 	for(Sector* s : sectors)
 	{
-		// Spatial inside the sector?
-		if(s->getAabb().collide(spAabb))
+		// Find if the spatia's position is inside the sector
+		Bool inside = true;
+		for(U i = 0; i < 3; i++)
+		{
+			if(spPos[i] > s->getAabb().getMax()[i]
+				|| spPos[i] < s->getAabb().getMin()[i])
+			{
+				inside = false;
+				continue;
+			}
+		}
+
+		if(!inside)
+		{
+			// continue
+		}
+		else
 		{
 			// No other candidate?
 			if(sector == nullptr)
@@ -194,7 +237,7 @@ void SectorGroup::placeSceneNode(SceneNode* sn)
 					sector = s;
 				}
 			}
-		}
+		} // end if inside
 	}
 
 	// Ask the octree to place it
@@ -211,32 +254,46 @@ void SectorGroup::placeSceneNode(SceneNode* sn)
 //==============================================================================
 void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 	Renderer* r)
+{
+	// Set all sectors to not visible
+	for(Sector* sector : sectors)
+	{
+		sector->visibleBy = VB_NONE;
+	}
+
+	doVisibilityTestsInternal(sn, test, r, VB_CAMERA);
+}
+
+//==============================================================================
+void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
+	Renderer* r, VisibleBy visibleBy)
 {
 	Frustumable* fr = sn.getFrustumable();
 	ANKI_ASSERT(fr != nullptr && "sn should be frustumable");
+	fr->visible = nullptr;
 
-	// Set all sectors to not visible
-	for(Sector* sector : sectors)
+	Spatial* sp = sn.getSpatial();
+	ANKI_ASSERT(sp != nullptr && "sn should be spatial as well");
+
+	// sn is not placed in any octree
+	if(sp->getOctreeNode() == nullptr)
 	{
-		sector->visible = false;
+		return;
 	}
 
 	//
 	// Find the visible sectors
 	//
 
-	SceneVector<Sector*> visibleSectors(scene->getFrameAllocator());
-
-	Spatial* sp = sn.getSpatial();
-	ANKI_ASSERT(sp != nullptr);
+	SceneFrameVector<Sector*> visibleSectors(scene->getFrameAllocator());
 
 	// Find the sector that contains the frustumable
-	Sector& containerSector = sp->getOctreeNode().getOctree().getSector();
-	containerSector.visible = true;
+	Sector& containerSector = sp->getOctreeNode()->getOctree().getSector();
+	containerSector.visibleBy |= visibleBy;
 	visibleSectors.push_back(&containerSector);
 
-	// Loop all portals and add other sectors
-	for(Portal* portal : portals)
+	// Loop all sector portals and add other sectors
+	for(Portal* portal : containerSector.portals)
 	{
 		if(ANKI_UNLIKELY(!portal->open))
 		{
@@ -268,9 +325,9 @@ void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 			// Portal is visible
 			if(fr->insideFrustum(portal->shape))
 			{
-				if(r == nullptr || r->doVisibilityTests(portal->shape))
+				/*if(r == nullptr || r->doVisibilityTests(portal->shape))*/
 				{
-					testAgainstSector->visible = true;
+					testAgainstSector->visibleBy |= visibleBy;
 					visibleSectors.push_back(testAgainstSector);
 				}
 			}
@@ -389,7 +446,7 @@ void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 	threadPool.waitForAllJobsToFinish();
 
 	//
-	// Continue with testing the lights
+	// Continue by testing the lights
 	//
 
 	for(SceneNode* lsn : visible->lights)
@@ -401,9 +458,9 @@ void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 		{
 			ANKI_ASSERT(lsn->getFrustumable() != nullptr);
 
-			doVisibilityTests(*lsn, 
+			doVisibilityTestsInternal(*lsn,
 				(VisibilityTest)(VT_RENDERABLES | VT_ONLY_SHADOW_CASTERS),
-				nullptr);
+				nullptr, VB_LIGHT);
 		}
 	}
 }

+ 14 - 5
testapp/Main.cpp

@@ -249,18 +249,23 @@ void init()
 	(void)sponzaModel;
 #endif
 
-	(void)sponzaModel;
-
 	//initPhysics();
 
 	// Sectors
 	SectorGroup& sgroup = scene.getSectorGroup();
 
-	Sector* sectorA = sgroup.createNewSector(Aabb(Vec3(-10), Vec3(10)));
+	Sector* sectorA = sgroup.createNewSector(
+		Aabb(Vec3(-38, -3, -20), Vec3(38, 27, 20)));
 	Sector* sectorB = sgroup.createNewSector(Aabb(Vec3(-5), Vec3(5)));
 
-	sgroup.createNewPortal(sectorA, sectorB, Obb(Vec3(0.0, 1.0, 0.0),
-		Mat3::getIdentity(), Vec3(2.0, 2.0, 1.0)));
+	sgroup.createNewPortal(sectorA, sectorB, Obb(Vec3(0.0, 3.0, 0.0),
+		Mat3::getIdentity(), Vec3(1.0, 2.0, 2.0)));
+
+	Sector* sectorC = sgroup.createNewSector(
+		Aabb(Vec3(-30, -10, -35), Vec3(30, 10, -25)));
+
+	sgroup.createNewPortal(sectorA, sectorC, Obb(Vec3(-1.1, 2.0, -11.0),
+		Mat3::getIdentity(), Vec3(1.3, 1.8, 0.5)));
 }
 
 //==============================================================================
@@ -369,6 +374,10 @@ void mainLoopExtra()
 		MainRendererSingleton::get().getDbg().switchFlags(
 			Dbg::DF_OCTREE);
 	}
+	if(in.getKey(KC_F12) == 1)
+	{
+		MainRendererSingleton::get().getDbg().switchDepthTestEnabled();
+	}
 
 	if(in.getKey(KC_UP)) mover->rotateLocalX(ang);
 	if(in.getKey(KC_DOWN)) mover->rotateLocalX(-ang);