Panagiotis Christopoulos Charitos 13 gadi atpakaļ
vecāks
revīzija
f620658028
3 mainītis faili ar 167 papildinājumiem un 75 dzēšanām
  1. 8 9
      include/anki/renderer/Tiler.h
  2. 6 17
      src/collision/Plane.cpp
  3. 153 49
      src/renderer/Tiler.cpp

+ 8 - 9
include/anki/renderer/Tiler.h

@@ -12,6 +12,8 @@ namespace anki {
 class Renderer;
 class Camera;
 class ShaderProgramUniformVariable;
+class Spatial;
+class Frustumable;
 
 /// Tiler used for visibility tests
 class Tiler
@@ -48,13 +50,7 @@ public:
 	Bool test(const CollisionShape& cs, 
 		const U32 tileId, const Bool skipNearPlaneCheck = false) const;
 
-	Bool test(
-		const Aabb& box,
-		const CollisionShape& cs,
-		const Mat4& projectionMatrix,
-		Bool skipNearPlaneCheck,
-		U32* tilesXAxisMask,
-		U32* tilesYAxisMask) const;
+	Bool test(const Spatial& sp, const Frustumable& fr) const;
 
 private:
 	/// A screen tile
@@ -104,7 +100,7 @@ private:
 	/// Main shader program
 	ShaderProgramResourcePointer prog;
 
-	const ShaderProgramUniformVariable* depthMapUniform;
+	const ShaderProgramUniformVariable* depthMapUniform; ///< Cache it
 
 	Renderer* r;
 	const Camera* prevCam;
@@ -114,10 +110,13 @@ private:
 	void initTiles();
 
 	void updateTilesInternal();
-	Vec2 updateTileMinMax(Tile_& tile);
+	Vec2 updateTileMinMax(Tile_& tile); ///< Recursive 
 
 	Bool testInternal(const CollisionShape& cs, const Tile& tile, 
 		const U startPlane) const;
+	void testTile(const Tile_& tile, const Vec2& a, const Vec2& b, 
+		const Vec2& objectMinMaxZ,
+		Array<U32, 2>& mask) const;
 };
 
 } // end namespace anki

+ 6 - 17
src/collision/Plane.cpp

@@ -39,23 +39,12 @@ void Plane::setFrom3Points(const Vec3& p0, const Vec3& p1, const Vec3& p2)
 //==============================================================================
 void Plane::setFromPlaneEquation(F32 a, F32 b, F32 c, F32 d)
 {
-	// normalize for cheap distance checks
-	F32 lensq = a * a + b * b + c * c;
+	normal = Vec3(a, b, c);
+
 	// length of normal had better not be zero
-	ANKI_ASSERT(!isZero(lensq));
-
-	// recover gracefully
-	if(isZero(lensq))
-	{
-		normal = Vec3(1.0, 0.0, 0.0);
-		offset = 0.0;
-	}
-	else
-	{
-		F32 recip = 1.0 / sqrt(lensq);
-		normal = Vec3(a * recip, b * recip, c * recip);
-		offset = d * recip;
-	}
+	ANKI_ASSERT(isZero(normal.getLength() - 1.0));
+
+	offset = d;
 }
 
 //==============================================================================
@@ -79,4 +68,4 @@ void Plane::toAabb(Aabb&) const
 	ANKI_ASSERT(0 && "Can't do that");
 }
 
-} // end namespace
+} // end namespace anki

+ 153 - 49
src/renderer/Tiler.cpp

@@ -3,6 +3,7 @@
 #include "anki/resource/ShaderProgramResource.h"
 #include "anki/core/ThreadPool.h"
 #include "anki/scene/Camera.h"
+#include "anki/scene/Spatial.h"
 
 // Default should be 0
 #define ALTERNATIVE_MIN_MAX 0
@@ -122,8 +123,10 @@ typedef Array<UpdateTilesPlanesPerspectiveCameraJob, ThreadPool::MAX_THREADS>
 	UpdateJobArray;
 
 //==============================================================================
-// Convex hull and other stuff
+// Statics                                                                     =
+//==============================================================================
 
+//==============================================================================
 struct ShortLexicographicallyFunctor
 {
 	Bool operator()(const Vec2& a, const Vec2& b)
@@ -132,51 +135,50 @@ struct ShortLexicographicallyFunctor
 	}
 };
 
-static F32 cross(const Vec2& o, const Vec2& a, const Vec2& b)
+//==============================================================================
+static Bool isLeft(const Vec2& p0, const Vec2& p1, const Vec2& p2)
 {
-	return (a.x() - o.x()) * (b.y() - o.y())
-		- (a.y() - o.y()) * (b.x() - o.x());
+	return (p1.x() - p0.x()) * (p2.y() - p0.y())
+		> (p2.x() - p0.x()) * (p1.y() - p0.y());
 }
 
-static void convexHull2D(Vec2* ANKI_RESTRICT p,
-	const U32 n, Vec2* ANKI_RESTRICT o, const U32 on, U32& outn)
+//==============================================================================
+static void convexHull2D(Vec2* ANKI_RESTRICT inPoints,
+	const U32 n, Vec2* ANKI_RESTRICT outPoints, const U32 on, U32& outn)
 {
 	ANKI_ASSERT(on > (2 * n) && "This algorithm needs some space");
 	I k = 0;
 
-	std::sort(&p[0], &p[n], ShortLexicographicallyFunctor());
+	std::sort(&inPoints[0], &inPoints[n], ShortLexicographicallyFunctor());
 
 	// Build lower hull
 	for(I i = 0; i < n; i++)
 	{
-		while(k >= 2 && cross(o[k - 2], o[k - 1], p[i]) <= 0.0)
+		while(k >= 2 
+			&& !isLeft(outPoints[k - 2], outPoints[k - 1], inPoints[i]))
 		{
 			--k;
 		}
 
-		o[k++] = p[i];
+		outPoints[k++] = inPoints[i];
 	}
 
 	// Build upper hull
 	for(I i = n - 2, t = k + 1; i >= 0; i--)
 	{
-		while(k >= t && cross(o[k - 2], o[k - 1], p[i]) <= 0.0)
+		while(k >= t 
+			&& !isLeft(outPoints[k - 2], outPoints[k - 1], inPoints[i]))
 		{
 			--k;
 		}
 
-		o[k++] = p[i];
+		outPoints[k++] = inPoints[i];
 	}
 
 	outn = k;
 }
 
-static Bool isLeft(const Vec2& p0, const Vec2& p1, const Vec2& p2)
-{
-	return (p1.x() - p0.x()) * (p2.y() - p0.y())
-		- (p2.x() - p0.x()) * (p1.y() - p0.y()) > 0.0;
-}
-
+//==============================================================================
 static U getTilesCount(U maxDepth)
 {
 	if(maxDepth == 0)
@@ -187,6 +189,7 @@ static U getTilesCount(U maxDepth)
 	return getTilesCount(maxDepth - 1) + pow(4, maxDepth);
 }
 
+//==============================================================================
 static U32 setNBits(U32 n)
 {
 	U32 res = 0;
@@ -199,6 +202,10 @@ static U32 setNBits(U32 n)
 	return res;
 }
 
+//==============================================================================
+// Tiler                                                                       =
+//==============================================================================
+
 //==============================================================================
 Tiler::Tiler()
 {}
@@ -519,59 +526,156 @@ Bool Tiler::testAll(const CollisionShape& cs,
 }
 
 //==============================================================================
-Bool Tiler::test(const Aabb& box,
-	const CollisionShape &cs,
-	const Mat4& projectionMatrix,
-	Bool skipNearPlaneCheck,
-	U32* tilesXAxisMask,
-	U32* tilesYAxisMask) const
+Bool Tiler::test(const Spatial& sp, const Frustumable& fr) const
 {
-#if 0
 	//
-	// Get the points
+	// Get points from sp
 	//
-	const Vec3& min = box.getMin();
-	const Vec3& max = box.getMax();
-
-	Array<Vec4, 8> boxPoints = {{
-		Vec4(max.x(), max.y(), max.z(), 1.0),   // right top front
-		Vec4(min.x(), max.y(), max.z(), 1.0),   // left top front
-		Vec4(min.x(), min.y(), max.z(), 1.0),   // left bottom front
-		Vec4(max.x(), min.y(), max.z(), 1.0),   // right bottom front
-		Vec4(max.x(), max.y(), min.z(), 1.0),   // right top back
-		Vec4(min.x(), max.y(), min.z(), 1.0),   // left top back
-		Vec4(min.x(), min.y(), min.z(), 1.0),   // left bottom back
-		Vec4(max.x(), min.y(), min.z(), 1.0)}}; // right bottom back
+	Array<Vec4, 8> points;
+	U pointsCount = 0;
+
+	const CollisionShape& cs = sp.getSpatialCollisionShape();
+	if(cs.getCollisionShapeType() != CollisionShape::CST_FRUSTUM)
+	{
+		const Aabb& aabb = sp.getAabb();
+		const Vec3& min = aabb.getMin();
+		const Vec3& max = aabb.getMax();
+
+		points[0] = Vec4(max.x(), max.y(), max.z(), 1.0); // right top front
+		points[1] = Vec4(min.x(), max.y(), max.z(), 1.0); // left top front
+		points[2] = Vec4(min.x(), min.y(), max.z(), 1.0); // left bottom front
+		points[3] = Vec4(max.x(), min.y(), max.z(), 1.0); // right bottom front
+		points[4] = Vec4(max.x(), max.y(), min.z(), 1.0); // right top back
+		points[5] = Vec4(min.x(), max.y(), min.z(), 1.0); // left top back
+		points[6] = Vec4(min.x(), min.y(), min.z(), 1.0); // left bottom back
+		points[7] = Vec4(max.x(), min.y(), min.z(), 1.0); // right bottom back
+
+		pointsCount = 0;
+	}
+	else
+	{
+		// XXX
+	}
 
 	//
-	// Project the points
+	// Transform those shapes
 	//
+	const Mat4& mat = fr.getViewProjectionMatrix();
 	Array<Vec2, 8> points2D;
 
-	for(U i = 0; i < 8; i++)
+	Vec2 minMax(10.0, -10.0); // The min and max z of the transformed shape
+	for(U i = 0; i < pointsCount; i++)
 	{
-		Vec4 point = mat * boxPoints[i];
-		points2D[i] = point.xy() / point.w();
+		Vec4 point = mat * points[i];
+		Vec3 v3 = point.xyz() / point.w();
+		points2D[i] = v3.xy();
+
+		minMax.x() = std::min(minMax.x(), v3.z());
+		minMax.y() = std::max(minMax.y(), v3.z());
 	}
 
 	//
 	// Calc the convex hull
 	//
-	Array<Vec2, 8 * 2> hullPoints2D;
-	U32 edgesCount;
-	convexHull2D(&points2D[0], points2D.getSize(),
-		&hullPoints2D[0], hullPoints2D.getSize(), edgesCount);
+	Array<Vec2, 8 * 2> convPoints;
+	U32 convPointsCount;
+	convexHull2D(&points2D[0], pointsCount, 
+			&convPoints[0], convPoints.getSize(), convPointsCount);
 
 	//
+	// Run the algorithm for every edge
 	//
-	//
-	for(U i = 0; i < edgesCount; i++)
+	Array<U32, 2> mask = {{0, 0}};
+	for(U i = 0; i < convPointsCount - 1; i++)
 	{
+		testTile(tiles_[0], minMax, convPoints[i], convPoints[i + 1], mask);
+	}
+
+	return mask[0] != 0 && mask[1] != 0;
+}
 
+//==============================================================================
+void Tiler::testTile(const Tile_& tile, const Vec2& a, const Vec2& b, 
+	const Vec2& objectMinMaxZ, Array<U32, 2>& mask) const
+{
+	// If edge not inside return
+	/*for(U i = 0; i < 2; i++)
+	{
+		if(a[i] < tile.min[i] || a[i] > tile.max[i])
+		{
+			return;
+		}
+
+		if(b[i] < tile.min[i] || b[i] > tile.max[i])
+		{
+			return;
+		}
+	}*/
+
+	Bool final = tile.children[0] == -1;
+
+	U inside = 0;
+
+	if(isLeft(a, b, Vec2(tile.max.x(), tile.max.y())))
+	{
+		if(final)
+		{
+			goto allIn;
+		}
+		++inside;
 	}
-#endif
 
-	return false;
+	if(isLeft(a, b, Vec2(tile.min.x(), tile.max.y())))
+	{
+		if(final)
+		{
+			goto allIn;
+		}
+		++inside;
+	}
+
+	if(!isLeft(a, b, Vec2(tile.min.x(), tile.min.y())))
+	{
+		if(final)
+		{
+			goto allIn;
+		}
+		++inside;
+	}
+
+	if(!isLeft(a, b, Vec2(tile.max.x(), tile.min.y())))
+	{
+		if(final)
+		{
+			goto allIn;
+		}
+		++inside;
+	}
+
+	// None inside
+	if(inside == 0)
+	{
+		return;
+	}
+	else if(inside == 4) // All inside
+	{
+		goto allIn;
+	}
+	else // Some inside
+	{
+		ANKI_ASSERT(!final);
+
+		for(U i = 0; i < 4; i++)
+		{
+			testTile(tiles_[tile.children[i]], a, b, objectMinMaxZ, mask);
+		}
+	}
+
+	return;
+
+allIn:
+	mask[0] |= tile.mask[0];
+	mask[1] |= tile.mask[1];
 }
 
 } // end namespace anki