Panagiotis Christopoulos Charitos 10 лет назад
Родитель
Сommit
ceabc1382c

+ 4 - 1
include/anki/collision/Frustum.h

@@ -216,6 +216,9 @@ public:
 	/// Implements Frustum::calculateProjectionMatrix
 	Mat4 calculateProjectionMatrix() const override;
 
+	static void calculateProjectionMatrix(F32 fovX, F32 fovY, F32 near, F32 far,
+		Mat4& proj);
+
 private:
 	/// @name Viewing variables
 	/// @{
@@ -260,7 +263,7 @@ public:
 	/// Set all
 	OrthographicFrustum(F32 left, F32 right, F32 near,
 		F32 far, F32 top, F32 bottom)
-	:	OrthographicFrustum()
+		: OrthographicFrustum()
 	{
 		setAll(left, right, near, far, top, bottom);
 	}

+ 19 - 4
include/anki/scene/Clusterer.h

@@ -62,14 +62,18 @@ public:
 		m_clusters.destroy(m_alloc);
 	}
 
-	void init(U tileCountX, U tileCountY);
+	void init(U tileCountX, U tileCountY)
+	{
+		m_counts[0] = tileCountX;
+		m_counts[1] = tileCountY;
+	}
 
 	void initTempTestResults(const GenericMemoryPoolAllocator<U8>& alloc,
 		ClustererTestResult& rez) const;
 
 	void prepare(FrustumComponent* frc, const SArray<Vec2>& minMaxTileDepth);
 
-private:
+public:
 	class Cluster
 	{
 	public:
@@ -83,14 +87,25 @@ private:
 	/// [z][y][x]
 	DArray<Cluster> m_clusters;
 
-	FrustumComponent* m_frc = nullptr;
-	Timestamp m_frcTimestamp = 0;
+	F32 m_near = 0.0;
+	F32 m_far = 0.0;
+	F32 m_fovY = 0.0;
+	F32 m_fovX = 0.0;
 
 	Cluster& cluster(U x, U y, U z)
 	{
+		ANKI_ASSERT(x < m_counts[0]);
+		ANKI_ASSERT(y < m_counts[1]);
+		ANKI_ASSERT(z < m_counts[2]);
 		return m_clusters[m_counts[0] * (z * m_counts[1] + y) + x];
 	}
+
+	F32 calcNear(U k) const;
+
+	void initClusters();
 };
 /// @}
 
 } // end namespace anki
+
+

+ 38 - 51
src/collision/Frustum.cpp

@@ -114,7 +114,7 @@ void Frustum::update() const
 void Frustum::updateInternal()
 {
 	ANKI_ASSERT(m_frustumDirty);
-	m_frustumDirty = false;	
+	m_frustumDirty = false;
 	recalculate();
 
 	// Transform derived
@@ -204,51 +204,38 @@ void PerspectiveFrustum::recalculate()
 	m_pointsL[3] += Vec4(x, -y, z - m_near, 0.0); // bot right
 }
 
+//==============================================================================
+void PerspectiveFrustum::calculateProjectionMatrix(F32 fovX, F32 fovY, F32 near,
+	F32 far, Mat4& proj)
+{
+	ANKI_ASSERT(fovX != 0.0 && fovY != 0.0 && near != 0.0 && far != 0.0);
+	F32 g = near - far;
+
+	F32 f = 1.0 / tan(fovY * 0.5); // f = cot(m_fovY/2)
+
+	proj(0, 0) = f * fovY / fovX; // = f/aspectRatio;
+	proj(0, 1) = 0.0;
+	proj(0, 2) = 0.0;
+	proj(0, 3) = 0.0;
+	proj(1, 0) = 0.0;
+	proj(1, 1) = f;
+	proj(1, 2) = 0.0;
+	proj(1, 3) = 0.0;
+	proj(2, 0) = 0.0;
+	proj(2, 1) = 0.0;
+	proj(2, 2) = (far + near) / g;
+	proj(2, 3) = (2.0 * far * near) / g;
+	proj(3, 0) = 0.0;
+	proj(3, 1) = 0.0;
+	proj(3, 2) = -1.0;
+	proj(3, 3) = 0.0;
+}
+
 //==============================================================================
 Mat4 PerspectiveFrustum::calculateProjectionMatrix() const
 {
-	ANKI_ASSERT(m_fovX != 0.0 && m_fovY != 0.0 && m_near != 0.0);
 	Mat4 projectionMat;
-	F32 g = m_near - m_far;
-
-#if 0
-	projectionMat(0, 0) = 1.0 / tanf(m_fovX * 0.5);
-	projectionMat(0, 1) = 0.0;
-	projectionMat(0, 2) = 0.0;
-	projectionMat(0, 3) = 0.0;
-	projectionMat(1, 0) = 0.0;
-	projectionMat(1, 1) = 1.0 / tanf(m_fovY * 0.5);
-	projectionMat(1, 2) = 0.0;
-	projectionMat(1, 3) = 0.0;
-	projectionMat(2, 0) = 0.0;
-	projectionMat(2, 1) = 0.0;
-	projectionMat(2, 2) = (m_far + m_near) / g;
-	projectionMat(2, 3) = (2.0 * m_far * m_near) / g;
-	projectionMat(3, 0) = 0.0;
-	projectionMat(3, 1) = 0.0;
-	projectionMat(3, 2) = -1.0;
-	projectionMat(3, 3) = 0.0;
-#else
-	float f = 1.0 / tan(m_fovY * 0.5); // f = cot(m_fovY/2)
-
-	projectionMat(0, 0) = f * m_fovY / m_fovX; // = f/aspectRatio;
-	projectionMat(0, 1) = 0.0;
-	projectionMat(0, 2) = 0.0;
-	projectionMat(0, 3) = 0.0;
-	projectionMat(1, 0) = 0.0;
-	projectionMat(1, 1) = f;
-	projectionMat(1, 2) = 0.0;
-	projectionMat(1, 3) = 0.0;
-	projectionMat(2, 0) = 0.0;
-	projectionMat(2, 1) = 0.0;
-	projectionMat(2, 2) = (m_far + m_near) / g;
-	projectionMat(2, 3) = (2.0 * m_far * m_near) / g;
-	projectionMat(3, 0) = 0.0;
-	projectionMat(3, 1) = 0.0;
-	projectionMat(3, 2) = -1.0;
-	projectionMat(3, 3) = 0.0;
-#endif
-
+	calculateProjectionMatrix(m_fovX, m_fovY, m_near, m_far, projectionMat);
 	return projectionMat;
 }
 
@@ -280,7 +267,7 @@ OrthographicFrustum& OrthographicFrustum::operator=(
 //==============================================================================
 Mat4 OrthographicFrustum::calculateProjectionMatrix() const
 {
-	ANKI_ASSERT(m_right != 0.0 && m_left != 0.0 && m_top != 0.0 
+	ANKI_ASSERT(m_right != 0.0 && m_left != 0.0 && m_top != 0.0
 		&& m_bottom != 0.0 && m_near != 0.0 && m_far != 0.0);
 	F32 difx = m_right - m_left;
 	F32 dify = m_top - m_bottom;
@@ -314,23 +301,23 @@ Mat4 OrthographicFrustum::calculateProjectionMatrix() const
 void OrthographicFrustum::recalculate()
 {
 	// Planes
-	m_planesL[(U)PlaneType::LEFT] = 
+	m_planesL[(U)PlaneType::LEFT] =
 		Plane(Vec4(1.0, 0.0, 0.0, 0.0), m_left);
-	m_planesL[(U)PlaneType::RIGHT] = 
+	m_planesL[(U)PlaneType::RIGHT] =
 		Plane(Vec4(-1.0, 0.0, 0.0, 0.0), -m_right);
 
-	m_planesL[(U)PlaneType::NEAR] = 
+	m_planesL[(U)PlaneType::NEAR] =
 		Plane(Vec4(0.0, 0.0, -1.0, 0.0), m_near);
-	m_planesL[(U)PlaneType::FAR] = 
+	m_planesL[(U)PlaneType::FAR] =
 		Plane(Vec4(0.0, 0.0, 1.0, 0.0), -m_far);
-	m_planesL[(U)PlaneType::TOP] = 
+	m_planesL[(U)PlaneType::TOP] =
 		Plane(Vec4(0.0, -1.0, 0.0, 0.0), -m_top);
-	m_planesL[(U)PlaneType::BOTTOM] = 
+	m_planesL[(U)PlaneType::BOTTOM] =
 		Plane(Vec4(0.0, 1.0, 0.0, 0.0), m_bottom);
 
 	// OBB
-	Vec4 c((m_right + m_left) * 0.5, 
-		(m_top + m_bottom) * 0.5, 
+	Vec4 c((m_right + m_left) * 0.5,
+		(m_top + m_bottom) * 0.5,
 		-(m_far + m_near) * 0.5,
 		0.0);
 	Vec4 e = Vec4(m_right, m_top, -m_far, 0.0) - c;

+ 14 - 1
src/renderer/Dbg.cpp

@@ -19,6 +19,7 @@
 #include "anki/collision/ConvexHullShape.h"
 #include "anki/util/Rtti.h"
 #include "anki/Ui.h" /// XXX
+#include "anki/scene/Clusterer.h" /// XXX
 
 namespace anki {
 
@@ -125,7 +126,7 @@ Error Dbg::run(CommandBufferPtr& cmdb)
 		phyd.drawWorld(scene._getPhysicsWorld());
 	}
 
-#if 1
+#if 0
 	{
 		static Bool firstTime = true;
 		static UiInterfaceImpl* interface;
@@ -152,6 +153,18 @@ Error Dbg::run(CommandBufferPtr& cmdb)
 	}
 #endif
 
+#if 1
+	{
+		Clusterer c(getAllocator());
+
+		c.init(2, 2);
+		c.prepare(&camFr, SArray<Vec2>());
+
+		CollisionDebugDrawer cd(m_drawer);
+		camFr.getFrustum().accept(cd);
+	}
+#endif
+
 	return m_drawer->flush();
 }
 

+ 4 - 2
src/renderer/Ms.cpp

@@ -24,7 +24,9 @@ const PixelFormat Ms::DEPTH_RT_PIXEL_FORMAT(
 
 //==============================================================================
 Ms::~Ms()
-{}
+{
+	m_secondLevelCmdbs.destroy(getAllocator());
+}
 
 //==============================================================================
 Error Ms::createRt(U32 index, U32 samples)
@@ -127,7 +129,6 @@ Error Ms::run(CommandBufferPtr& cmdb)
 	FrustumComponent& frc = cam.getComponent<FrustumComponent>();
 	SArray<CommandBufferPtr> cmdbs(
 		&m_secondLevelCmdbs[0], m_secondLevelCmdbs.getSize());
-	//SArray<CommandBufferPtr> cmdbs(&cmdb, 1);
 	ANKI_CHECK(m_r->getSceneDrawer().render(
 		frc, RenderingStage::MATERIAL, Pass::MS_FS, cmdbs));
 
@@ -148,6 +149,7 @@ Error Ms::run(CommandBufferPtr& cmdb)
 		if(!m_secondLevelCmdbs[i]->isEmpty())
 		{
 			cmdb->pushSecondLevelCommandBuffer(m_secondLevelCmdbs[i]);
+			m_secondLevelCmdbs[i].reset(nullptr);
 		}
 	}
 

+ 69 - 15
src/scene/Clusterer.cpp

@@ -17,43 +17,55 @@ void Clusterer::initTempTestResults(const GenericMemoryPoolAllocator<U8>& alloc,
 	rez.m_alloc = alloc;
 }
 
+//==============================================================================
+F32 Clusterer::calcNear(U k) const
+{
+	F32 Sy = m_counts[1];
+	F32 theta = m_fovY / 2.0;
+	F32 a = 1.0 + (4.0 * tan(theta)) / Sy;
+	F32 neark = m_near * pow(a, F32(k));
+	return neark;
+}
+
 //==============================================================================
 void Clusterer::prepare(FrustumComponent* frc,
 	const SArray<Vec2>& minMaxTileDepth)
 {
 	ANKI_ASSERT(frc);
 
-	if(frc == m_frc && m_frc->getTimestamp() == m_frcTimestamp)
-	{
-		// Not dirty, early exit
-		return;
-	}
-
-	m_frc = frc;
-	m_frcTimestamp = m_frc->getTimestamp();
-
-	// Calc depth
+	// Get some things
 	ANKI_ASSERT(frc->getFrustum().getType() == Frustum::Type::PERSPECTIVE);
 	const PerspectiveFrustum& fr =
 		static_cast<const PerspectiveFrustum&>(frc->getFrustum());
 
 	F32 near = fr.getNear();
 	F32 far = fr.getFar();
-	F32 Sy = m_counts[1];
-	F32 theta = fr.getFovY() / 2.0;
-	F32 opt = 1.0 + (4.0 * tan(theta)) / Sy;
+	F32 fovY = fr.getFovY();
+	F32 fovX = fr.getFovX();
+
+	if(near == m_near && far == m_far && m_fovY == fovY && m_fovX == fovX)
+	{
+		// Not dirty, early exit
+		return;
+	}
 
+	m_fovY = fovY;
+	m_fovX = fovX;
+	m_near = near;
+	m_far = far;
+
+	// Calc depth
 	U k = 1;
 	while(1)
 	{
-		F32 neark = near * pow(opt, F32(k));
+		F32 neark = calcNear(k);
 		if(neark >= far)
 		{
 			break;
 		}
 		++k;
 	}
-	m_counts[2] = k;
+	m_counts[2] = k + 1;
 
 	// Alloc clusters
 	U clusterCount = m_counts[0] * m_counts[1] * m_counts[2];
@@ -63,4 +75,46 @@ void Clusterer::prepare(FrustumComponent* frc,
 	}
 }
 
+//==============================================================================
+void Clusterer::initClusters()
+{
+	for(U z = 0; z < U(m_counts[2] - 1); ++z)
+	{
+		for(U y = 0; y < m_counts[1]; ++y)
+		{
+			for(U x = 0; x < m_counts[0]; ++x)
+			{
+				// Compute projection matrix
+				F32 near = calcNear(z);
+				F32 far = calcNear(z + 1);
+
+				Mat4 proj;
+				PerspectiveFrustum::calculateProjectionMatrix(m_fovX, m_fovY,
+					near, far, proj);
+
+				Mat4 invProj = proj.getInverse();
+
+				// Project some points
+				Vec2 tileMin, tileMax;
+				tileMin.x() = F32(x) / m_counts[0];
+				tileMax.x() = F32(x + 1) / m_counts[0];
+				tileMin.y() = F32(y) / m_counts[1];
+				tileMax.y() = F32(y + 1) / m_counts[1];
+
+				tileMin = tileMin * 2.0 - 1.0;
+				tileMax = tileMax * 2.0 - 1.0;
+
+				Aabb box;
+				Vec4 a = invProj * Vec4(tileMin, 0.0, 1.0);
+				box.setMin(a.xyz0());
+				a = invProj * Vec4(tileMax, 1.0, 1.0);
+				box.setMax(a.xyz0());
+
+				cluster(x, y, z).m_box = box;
+			}
+		}
+	}
+}
+
 } // end namespace anki
+