Browse Source

New faster tiler is up. Adding cool events

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
c07005da47

+ 23 - 2
docs/drafts/tiler_optimized.txt

@@ -4,11 +4,32 @@ Update planes
 
 planetrf = 22* 14+
 
-updatealltileplanes = planetrf * (16 + 16 + 256 * 2)
+updatealltileplanes = planetrf * (15 + 15 + 256 * 2)
 
-sum = 11968* 7616+
+sum = 11924* 7588+
 
 
+=============
+transform everything else
+=============
+
+100 lights
+1000 other spatials
+
+trfaabb = 30* 27+
+
+lighttrf = 900* 600+
+otherspatialstrf = 30000* 27000+
+
+=============
+transform them for 2D checks
+=============
+
+mat4mulvec4 = 16* 12+
+
+alllights = 3200* 2400+
+otherspatial = 128000* 96000+
+
 
 
 function create_tiles

+ 1 - 1
include/anki/event/Event.h

@@ -81,6 +81,6 @@ private:
 	EventManager* manager = nullptr; ///< Keep it here to access allocators etc
 };
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 11 - 0
include/anki/event/EventManager.h

@@ -11,7 +11,12 @@ namespace anki {
 
 // Forward
 class SceneGraph;
+
 class SceneAmbientColorEvent;
+class LightEvent;
+class LightEventData;
+class MovableEvent;
+class MovableEventData;
 
 /// This manager creates the events ands keeps tracks of them
 class EventManager
@@ -33,6 +38,12 @@ public:
 
 	std::shared_ptr<Event> newSceneAmbientColorEvent(
 		F32 startTime, F32 duration, const Vec3& finalColor);
+
+	std::shared_ptr<Event> newLightEvent(
+		F32 startTime, F32 duration, const LightEventData& data);
+
+	std::shared_ptr<Event> newMovableEvent(
+		F32 startTime, F32 duration, const MovableEventData& data);
 	/// @}
 
 	/// Update

+ 23 - 8
include/anki/event/LightEvent.h

@@ -2,14 +2,24 @@
 #define ANKI_EVENT_LIGHT_EVENT_H
 
 #include "anki/event/Event.h"
+#include "anki/math/Math.h"
 
 namespace anki {
 
-/// @addtogroup event
-/// @{
+// Forward
+class Light;
 
-/// Light event
-class LightEvent: public Event
+/// Helper class
+struct LightEventData
+{
+	Light* light = nullptr;
+	F32 radiusMultiplier = 0.0;
+	Vec4 intensityMultiplier = Vec4(0.0);
+	Vec4 specularIntensityMultiplier = Vec4(0.0);
+};
+
+/// An event for light animation
+class LightEvent: public Event, private LightEventData
 {
 public:
 	/// @name Constructors/Destructor
@@ -17,12 +27,17 @@ public:
 
 	/// Constructor
 	LightEvent(F32 startTime, F32 duration, EventManager* manager,
-		const std::smart_ptr<SceneNode>& lightSn,
-		const F32* radiusFrom, const F32* radiusTo);
+		U8 flags, const LightEventData& data);
 	/// @}
-};
 
-/// @}
+	/// Implements Event::update
+	void update(F32 prevUpdateTime, F32 crntTime);
+
+private:
+	F32 originalRadius;
+	Vec4 originalDiffColor;
+	Vec4 originalSpecColor;
+};
 
 } // end namespace anki
 

+ 42 - 0
include/anki/event/MovableEvent.h

@@ -0,0 +1,42 @@
+#ifndef ANKI_EVENT_MOVABLE_EVENT_H
+#define ANKI_EVENT_MOVABLE_EVENT_H
+
+#include "anki/event/Event.h"
+#include "anki/math/Math.h"
+
+namespace anki {
+
+// Forward
+class SceneNode;
+
+/// Helper class
+struct MovableEventData
+{
+	SceneNode* movableSceneNode = nullptr;
+	Vec3 posMin;
+	Vec3 posMax;
+};
+
+/// An event for simple movable animations
+class MovableEvent: public Event, private MovableEventData
+{
+public:
+	/// @name Constructors/Destructor
+	/// @{
+
+	/// Constructor
+	MovableEvent(F32 startTime, F32 duration, EventManager* manager,
+		U8 flags, const MovableEventData& data);
+	/// @}
+
+	/// Implements Event::update
+	void update(F32 prevUpdateTime, F32 crntTime);
+
+private:
+	Vec3 originalPos;
+	Vec3 newPos;
+};
+
+} // end namespace anki
+
+#endif

+ 0 - 3
include/anki/renderer/Renderer.h

@@ -278,9 +278,6 @@ public:
 		return distance / lodDistance;
 	}
 
-	/// Use the tiler to do visibility tests
-	Bool doVisibilityTests(const CollisionShape& cs) const;
-
 	/// On some GPUs its optimal to clean after binding to an FBO and there is
 	/// no use for it's previous contents. For other GPUs the clear will be 
 	/// skipped

+ 4 - 65
include/anki/renderer/Tiler.h

@@ -27,9 +27,9 @@ public:
 	// mind that there are size limitations in uniform blocks.
 	static const U TILES_X_COUNT = 16;
 	static const U TILES_Y_COUNT = 16;
-	static const U TILES_COUNT = TILES_X_COUNT * TILES_X_COUNT;
+	static const U TILES_COUNT = TILES_X_COUNT * TILES_Y_COUNT;
 
-	typedef std::bitset<TILES_X_COUNT * TILES_X_COUNT> Bitset;
+	typedef std::bitset<TILES_COUNT> Bitset;
 
 	Tiler();
 	~Tiler();
@@ -43,24 +43,6 @@ public:
 	void updateTiles(Camera& cam);
 
 	/// Test against all tiles
-	Bool testAll(const CollisionShape& cs,
- 		const Bool skipNearPlaneCheck = false) const;
-
-	/// Test against all tiles and return affected tiles
-	Bool testAll(const CollisionShape& cs,
- 		U32* tileIds, U32& tilesCount, 
-		const Bool skipNearPlaneCheck = false) const;
- 
-	/// Test on a specific tile
-	Bool test(const CollisionShape& cs, 
-		const U32 tileId, const Bool skipNearPlaneCheck = false) const;
-
-	Bool test(
-		const CollisionShape& cs, 
-		const Aabb& aabb, 
-		Bool nearPlane,
-		Bitset* mask) const;
-
 	Bool test2(
 		const CollisionShape& cs,
 		const Aabb& aabb,
@@ -68,30 +50,10 @@ public:
 		Bitset* mask) const;
 
 private:
-	/// A screen tile
-	struct Tile
-	{
-		/// @name Frustum planes
-		/// @{
-		Array<Plane, Frustum::FP_COUNT> planes; ///< In local space
-		Array<Plane, Frustum::FP_COUNT> planesWSpace; ///< In world space
-		/// @}
-	};
-
-	/// XXX
-	struct Tile_
-	{
-		Vec3 min;
-		Vec3 max;
-		Array<U32, 2> mask;
-		Array<I16, 4> children; ///< Use small index to save memory
-	};
-
+	/// Tile planes
 	Vector<Plane> allPlanes;
 	Plane* planesI = nullptr;
 	Plane* planesJ = nullptr;
-	Plane* nearPlanes = nullptr;
-	Plane* farPlanes = nullptr;
 	Plane* planesIW = nullptr;
 	Plane* planesJW = nullptr;
 	Plane* nearPlanesW = nullptr;
@@ -99,16 +61,6 @@ private:
 
 	typedef F32 PixelArray[TILES_Y_COUNT][TILES_X_COUNT][2];
 
-	/// @note The [0][0] is the bottom left tile
-	union
-	{
-		Array<Array<Tile, TILES_X_COUNT>, TILES_Y_COUNT> tiles;
-		Array<Tile, TILES_X_COUNT * TILES_Y_COUNT> tiles1d;
-	};
-
-	Vector<Tile_> tiles_;
-	Tile_* tiles0 = nullptr; ///< Tiles last level
-
 	/// The timestamp of the 4 planes update
 	U32 planes4UpdateTimestamp = Timestamp::getTimestamp();
 
@@ -130,20 +82,7 @@ private:
 	Renderer* r = nullptr;
 	const Camera* prevCam = nullptr;
 
-	void initInternal(Renderer* r);
-	Tile_* initTilesInDepth(Tile_* tiles, U depth);
-	void initTiles();
-
-	void updateTilesInternal();
-	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 Array<Vec3, 2>& objMinMax, Bitset& bitset) const;
-
-	void updateBitset(const Tile_& tile, Bitset& bitset) const;
+	void initInternal(Renderer* r_);
 
 	void testRange(const CollisionShape& cs, Bool nearPlane,
 		U iFrom, U iTo, U jFrom, U jTo, Bitset& bitset) const;

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

@@ -6,6 +6,7 @@
 #include "anki/math/Math.h"
 #include "anki/core/Timestamp.h"
 #include "anki/scene/Common.h"
+#include <algorithm> // For std::find
 
 namespace anki {
 

+ 9 - 0
include/anki/scene/SceneGraph.h

@@ -122,6 +122,15 @@ public:
 		return physics;
 	}
 
+	EventManager& getEventManager()
+	{
+		return events;
+	}
+	const EventManager& getEventManager() const
+	{
+		return events;
+	}
+
 	SectorGroup& getSectorGroup()
 	{
 		return sectorGroup;

+ 38 - 0
include/anki/util/Object.h

@@ -141,6 +141,44 @@ private:
 	}
 };
 
+/// XXX
+template<typename T, typename Alloc = Allocator<T>>
+class CleanupObject: public Object<T, Alloc>
+{
+public:
+	typedef T Value;
+	typedef Object<Value, Alloc> Base;
+
+	/// @see Object::Object
+	CleanupObject(Value* parent_, const Alloc& alloc = Alloc())
+		: Base(parent_, alloc)
+	{}
+
+	virtual ~CleanupObject()
+	{
+		if(Base::parent != nullptr)
+		{
+			Base::parent->removeChild(Base::getSelf());
+			Base::parent = nullptr;
+		}
+
+		Alloc alloc = Base::childs.get_allocator();
+
+		// Delete all children
+		for(Value* child : Base::childs)
+		{
+			// Set parent to null to prevent the child from removing itself
+			child->parent = nullptr;
+
+			// Destroy
+			alloc.destroy(child);
+			alloc.deallocate(child, 1);
+		}
+
+		Base::childs.clear();
+	}
+};
+
 /// @}
 /// @}
 

+ 3 - 3
shaders/IsLpGeneric.glsl

@@ -13,7 +13,7 @@
 
 #define ATTENUATION_FINE 0
 
-#define ATTENUATION_BOOST (0.1)
+#define ATTENUATION_BOOST (0.05)
 
 /// @name Uniforms
 /// @{
@@ -290,7 +290,7 @@ void main()
 	fColor *= dot(normal, groundLightDir.xyz) + 1.0;
 #endif
 
-#if 1
+#if 0
 	if(tiles[vInstanceId].lightsCount[3] > 0)
 	{
 		fColor += vec3(0.0, 0.2, 0.0);
@@ -328,7 +328,7 @@ void main()
 	}
 #endif
 
-#if 1
+#if 0
 	vec3 tmpc = vec3((vInstanceId % 4) / 3.0, (vInstanceId % 3) / 2.0, 
 		(vInstanceId % 2));
 	fColor += tmpc / 40.0;

+ 20 - 1
src/event/EventManager.cpp

@@ -1,7 +1,10 @@
 #include "anki/event/EventManager.h"
-#include "anki/event/SceneAmbientColorEvent.h"
 #include "anki/scene/SceneGraph.h"
 
+#include "anki/event/SceneAmbientColorEvent.h"
+#include "anki/event/LightEvent.h"
+#include "anki/event/MovableEvent.h"
+
 namespace anki {
 
 //==============================================================================
@@ -106,4 +109,20 @@ std::shared_ptr<Event> EventManager::newSceneAmbientColorEvent(
 		finalColor, scene));
 }
 
+//==============================================================================
+std::shared_ptr<Event> EventManager::newLightEvent(
+	F32 startTime, F32 duration, const LightEventData& data)
+{
+	return registerEvent(new LightEvent(startTime, duration, this,
+		Event::EF_NONE, data));
+}
+
+//==============================================================================
+std::shared_ptr<Event> EventManager::newMovableEvent(
+	F32 startTime, F32 duration, const MovableEventData& data)
+{
+	return registerEvent(new MovableEvent(startTime, duration, this,
+		Event::EF_NONE, data));
+}
+
 } // end namespace anki

+ 60 - 0
src/event/LightEvent.cpp

@@ -0,0 +1,60 @@
+#include "anki/event/LightEvent.h"
+#include "anki/scene/Light.h"
+
+namespace anki {
+
+//==============================================================================
+LightEvent::LightEvent(F32 startTime, F32 duration, EventManager* manager,
+	U8 flags, const LightEventData& data)
+	: Event(startTime, duration, manager, flags)
+{
+	*static_cast<LightEventData*>(this) = data;
+
+	switch(light->getLightType())
+	{
+	case Light::LT_POINT:
+		{
+			PointLight* plight = static_cast<PointLight*>(light);
+			originalRadius = plight->getRadius();
+		}
+		break;
+	case Light::LT_SPOT:
+		ANKI_ASSERT("TODO");
+		break;
+	default:
+		ANKI_ASSERT(0);
+		break;
+	}
+
+	originalDiffColor = light->getDiffuseColor();
+	originalSpecColor = light->getSpecularColor();
+}
+
+//==============================================================================
+void LightEvent::update(F32 prevUpdateTime, F32 crntTime)
+{
+	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
+
+	switch(light->getLightType())
+	{
+	case Light::LT_POINT:
+		{
+			PointLight* plight = static_cast<PointLight*>(light);
+			plight->setRadius(
+				factor * radiusMultiplier + originalRadius);
+		}
+		break;
+	case Light::LT_SPOT:
+		ANKI_ASSERT("TODO");
+		break;
+	default:
+		ANKI_ASSERT(0);
+		break;
+	}
+
+	light->setDiffuseColor(originalDiffColor + factor * intensityMultiplier);
+	light->setSpecularColor(
+		originalSpecColor + factor * specularIntensityMultiplier);
+}
+
+} // end namespace anki

+ 39 - 0
src/event/MovableEvent.cpp

@@ -0,0 +1,39 @@
+#include "anki/event/MovableEvent.h"
+#include "anki/scene/SceneNode.h"
+#include "anki/scene/Movable.h"
+#include "anki/util/Functions.h"
+
+namespace anki {
+
+//==============================================================================
+MovableEvent::MovableEvent(F32 startTime, F32 duration, EventManager* manager,
+	U8 flags, const MovableEventData& data)
+	: Event(startTime, duration, manager, flags)
+{
+	ANKI_ASSERT(data.movableSceneNode.getMovable());
+
+	*static_cast<MovableEventData*>(this) = data;
+
+	originalPos =
+		movableSceneNode->getMovable()->getLocalTransform().getOrigin();
+
+	for(U i = 0; i < 3; i++)
+	{
+		newPos[i] = randRange(posMin[i], posMax[i]);
+	}
+	newPos += movableSceneNode->getMovable()->getLocalTransform().getOrigin();
+}
+
+//==============================================================================
+void MovableEvent::update(F32 prevUpdateTime, F32 crntTime)
+{
+	Transform trf = movableSceneNode->getMovable()->getLocalTransform();
+
+	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
+
+	trf.getOrigin() = interpolate(originalPos, newPos, factor);
+
+	movableSceneNode->getMovable()->setLocalTransform(trf);
+}
+
+} // end namespace anki

+ 0 - 218
src/renderer/Dbg.cpp

@@ -39,116 +39,6 @@ void Dbg::init(const Renderer::Initializer& initializer)
 }
 
 //==============================================================================
-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());
-}
-
-void calcConvexHull2D(const Vec2* ANKI_RESTRICT points, 
-	const U32 n, Vec2* ANKI_RESTRICT opoints, U32& on)
-{
-	const U maxPoints = 9;
-	ANKI_ASSERT(n <= maxPoints && n > 3);
-	Array<Vec2, maxPoints * 2 + 1> deque;
-
-	// initial bottom and top deque indices
-	U bot = n - 2, top = bot + 3;
-	// 3rd vertex is at both bot and top
-	deque[bot] = deque[top] = points[2];
-
-	if(isLeft(points[0], points[1], points[2]))
-	{
-		deque[bot + 1] = points[0];
-		deque[bot + 2] = points[1]; // ccw vertices are: 2, 0, 1, 2
-	}
-	else
-	{
-		deque[bot + 1] = points[1];
-		deque[bot + 2] = points[0]; // ccw vertices are: 2, 1, 0, 2
-	}
-
-	// compute the hull on the deque D[]
-	for(U i = 3; i < n; i++)
-	{
-		// test if next vertex is inside the deque hull
-		if ((isLeft(deque[bot], deque[bot + 1], points[i]))
-			&& (isLeft(deque[top - 1], deque[top], points[i])))
-		{
-			continue; // skip an interior vertex
-		}
-
-		while(!isLeft(deque[top - 1], deque[top], points[i]))
-		{
-			--top;
-		}
-		++top;
-		deque[top] = points[i];
-
-		while(!isLeft(deque[bot], deque[bot + 1], points[i]))
-		{
-			++bot;
-		}
-		--bot; 
-		deque[bot] = points[i];
-	}
-
-	// transcribe deque to the output hull array opoints
-	U h;  // hull vertex counter
-	for(h = 0; h < (top - bot); h++)
-	{
-		opoints[h] = deque[bot + h];
-	}
-
-	on = h;
-}
-
-struct ShortLexicographicallyFunctor
-{
-	Bool operator()(const Vec2& a, const Vec2& b)
-	{
-		return a.x() < b.x() || (a.x() == b.x() && a.y() < b.y());
-	}
-};
-
-F32 cross(const Vec2& o, const Vec2& a, const Vec2& b)
-{
-	return (a.x() - o.x()) * (b.y() - o.y()) 
-		- (a.y() - o.y()) * (b.x() - o.x());
-}
-
-void calcConvexHull2D_(Vec2* ANKI_RESTRICT p, 
-	const U32 n, Vec2* ANKI_RESTRICT o, U32& outn)
-{
-	I k = 0;
-
-	std::sort(&p[0], &p[n], ShortLexicographicallyFunctor());
-	
-	// Build lower hull
-	for(I i = 0; i < n; i++)
-	{
-		while(k >= 2 && !isLeft(o[k - 2], o[k - 1], p[i])) 
-		{
-			--k;
-		}
-
-		o[k++] = p[i];
-	}
- 
-	// Build upper hull
-	for(I i = n - 2, t = k + 1; i >= 0; i--)
-	{
-		while(k >= t && !isLeft(o[k - 2], o[k - 1], p[i])) 
-		{
-			--k;
-		}
-
-		o[k++] = p[i];
-	}
-
-	outn = k;
-}
-
 void Dbg::run()
 {
 	ANKI_ASSERT(enabled);
@@ -162,7 +52,6 @@ void Dbg::run()
 	drawer->setModelMatrix(Mat4::getIdentity());
 	//drawer->drawGrid();
 
-#if 1
 	SceneGraph& scene = r->getSceneGraph();
 
 	for(auto it = scene.getSceneNodesBegin();
@@ -198,113 +87,6 @@ void Dbg::run()
 	{
 		scene.getPhysics().debugDraw();
 	}
-#endif
-
-	if(0)
-	{
-		drawer->setColor(Vec3(1, 0.0, 0));
-		Sphere s(Vec3(1.0, 0.1, 0.0), 2.0);
-
-		CollisionDebugDrawer coldrawer(drawer.get());
-
-		s.accept(coldrawer);
-
-		const Camera& cam = r->getSceneGraph().getActiveCamera();
-		Mat4 vm = cam.getViewMatrix();
-
-		Vec4 p(s.getCenter(), 1.0);
-		F32 r = s.getRadius();
-		Vec4 a(p.xyz() + vm.getTransposed().getColumn(1).xyz() * r, 1.0);
-		Mat4 vp = cam.getViewProjectionMatrix();
-
-		p = vp * p;
-		p /= p.w();
-		a = vp * a;
-		a /= a.w();
-
-		drawer->setViewProjectionMatrix(Mat4::getIdentity());
-		drawer->setModelMatrix(Mat4::getIdentity());
-
-		drawer->setColor(Vec3(1, 1.0, 1));
-		drawer->begin();
-		drawer->pushBackVertex(p.xyz());
-		drawer->pushBackVertex(a.xyz());
-		drawer->end();
-	}
-
-	if(0)
-	{
-		drawer->setColor(Vec3(0.1, 0.1, 0.1));
-		Aabb box(Vec3(-1.0, 1.0, -1.0), Vec3(1.5, 2.0, 1.5));
-		CollisionDebugDrawer coldrawer(drawer.get());
-
-		box.accept(coldrawer);
-
-		drawer->setColor(Vec3(1.0));
-
-		const Vec3& min = box.getMin();
-		const Vec3& max = box.getMax();
-
-		Array<Vec4, 8> points = {{
-			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
-
-		drawer->setViewProjectionMatrix(Mat4::getIdentity());
-		drawer->setModelMatrix(Mat4::getIdentity());
-
-		const Mat4& mat = r->getViewProjectionMatrix();
-
-		Array<Vec2, 8> points2D;
-		Array<Vec2, 8 * 2> hullPoints2D;
-		static const Array<Vec3, 9> colors = {{
-			Vec3(1.0, 0.0, 0.0),
-			Vec3(0.0, 1.0, 0.0),
-			Vec3(0.0, 0.0, 1.0),
-			Vec3(1.0, 0.0, 1.0),
-			Vec3(1.0, 1.0, 0.0),
-			Vec3(0.0, 1.0, 1.0),
-			Vec3(1.0, 1.0, 1.0),
-			Vec3(1.0, 0.5, 1.0),
-			Vec3(1.0, 0.5, 0.5)
-		}};
-
-		drawer->begin();
-		for(U i = 0; i < 8; i++)
-		{
-			Vec4& point = points[i];
-			point = mat * point;
-			point /= point.w();
-
-			points2D[i] = point.xy();
-
-			/*drawer->setColor(colors[i]);
-			drawer->pushBackVertex(Vec3(point.x(), point.y(), -0.1));*/
-		}
-		drawer->end();
-
-		U32 outPoints;
-		calcConvexHull2D_(&points2D[0], 8, &hullPoints2D[0], outPoints);
-
-		drawer->begin();
-		for(U i = 0; i < outPoints - 1; i++)
-		{
-			drawer->setColor(colors[i]);
-			drawer->pushBackVertex(Vec3(hullPoints2D[i], -0.1));
-			drawer->setColor(colors[i] / 2.0);
-			drawer->pushBackVertex(Vec3(hullPoints2D[i + 1], -0.1));
-		}
-
-		/*drawer->pushBackVertex(Vec3(hullPoints2D[outPoints - 1], -0.1));
-		drawer->pushBackVertex(Vec3(hullPoints2D[0], -0.1));*/
-
-		drawer->end();
-	}
 
 	drawer->flush();
 }

+ 2 - 22
src/renderer/Is.cpp

@@ -196,41 +196,21 @@ struct WriteTilesUboJob: ThreadJob
 	void doTile(U tileId, ShaderTile& stile)
 	{
 		auto& lightIndices = stile.lightIndices;
-		const Tiler& tiler = is->r->getTiler();
 
 		// Point lights
 		//
-
-		stile.lightsCount[3] = 0; // XXX remove
-
 		U pointLightsInTileCount = 0;
 		for(U i = 0; i < visiblePointLightsCount; i++)
 		{
 			const PointLight& light = *visiblePointLights[i];
 
-			if(tiler.test(light.getSphere(), tileId))
+			if(light.getTilerBitset().test(tileId))
 			{
 				// Use % to avoid overflows
 				const U id = pointLightsInTileCount % Is::MAX_LIGHTS_PER_TILE;
 				lightIndices[id] = i;
 				++pointLightsInTileCount;
 			}
-
-			// XXX
-				{
-					const Tiler::Bitset& bitset = light.getTilerBitset();
-
-					//std::cout << std::bitset<32>(mask[0]) << std::endl;
-
-					if(bitset.test(tileId))
-					{
-						stile.lightsCount[3] = 333;
-					}
-					else
-					{
-						stile.lightsCount[3] = 0;
-					}
-				}
 		}
 
 		stile.lightsCount[0] = pointLightsInTileCount;
@@ -244,7 +224,7 @@ struct WriteTilesUboJob: ThreadJob
 		{
 			const SpotLight& light = *visibleSpotLights[i];
 
-			if(tiler.test(light.getFrustum(), tileId))
+			if(light.getTilerBitset().test(tileId))
 			{
 				const U id = (pointLightsInTileCount + spotLightsInTileCount 
 					+ spotLightsShadowInTileCount) 

+ 0 - 7
src/renderer/Renderer.cpp

@@ -215,13 +215,6 @@ void Renderer::calcLimitsOfNearPlane(const PerspectiveCamera& pcam,
 	limitsOfNearPlane.x() = tan(0.5 * pcam.getFovX());
 }
 
-
-//==============================================================================
-Bool Renderer::doVisibilityTests(const CollisionShape& cs) const
-{
-	return tiler.testAll(cs, true);
-}
-
 //==============================================================================
 void Renderer::clearAfterBindingFbo(const GLenum cap)
 {

+ 37 - 702
src/renderer/Tiler.cpp

@@ -10,118 +10,6 @@
 
 namespace anki {
 
-//==============================================================================
-/// Job that updates the left, right, top and buttom tile planes
-struct UpdateTilesPlanesPerspectiveCameraJob: ThreadJob
-{
-	Tiler* tiler;
-	PerspectiveCamera* cam;
-	Bool frustumChanged;
-	const Tiler::PixelArray* pixels;
-
-	void operator()(U threadId, U threadsCount)
-	{
-		U64 start, end;
-		choseStartEnd(threadId, threadsCount, 
-			Tiler::TILES_X_COUNT * Tiler::TILES_Y_COUNT, start, end);
-
-		// Precalculate some stuff for update4Planes()
-		F32 l = 0.0, l6 = 0.0, o = 0.0, o6 = 0.0;
-
-		if(frustumChanged)
-		{
-			const F32 fx = cam->getFovX();
-			const F32 fy = cam->getFovY();
-			const F32 n = cam->getNear();
-
-			l = 2.0 * n * tan(fx / 2.0);
-			l6 = l / Tiler::TILES_X_COUNT;
-			o = 2.0 * n * tan(fy / 2.0);
-			o6 = o / Tiler::TILES_Y_COUNT;
-		}
-
-		// Precalculate some stuff for update2Planes()
-		Vec2 planes;
-		Renderer::calcPlanes(Vec2(cam->getNear(), cam->getFar()), planes);
-
-		Transform trf = Transform(cam->getWorldTransform());
-
-		for(U64 k = start; k < end; k++)
-		{
-			if(frustumChanged)
-			{
-				update4Planes(l, l6, o, o6, k);
-			}
-
-			update2Planes(k, planes);
-
-			// Transform planes
-			Tiler::Tile& tile = tiler->tiles1d[k];
-			for(U i = 0; i < Frustum::FP_COUNT; i++)
-			{
-				tile.planesWSpace[i] = tile.planes[i].getTransformed(trf);
-			}
-		}
-	}
-
-	void update4Planes(
-		const F32 l, const F32 l6, const F32 o, const F32 o6,
-		const U k)
-	{
-		Vec3 a, b;
-		const F32 n = cam->getNear();
-		Array<Plane, Frustum::FP_COUNT>& planes = tiler->tiles1d[k].planes;
-		const U i = k % Tiler::TILES_X_COUNT;
-		const U j = k / Tiler::TILES_X_COUNT;
-
-		// left
-		a = Vec3((I(i) - I(Tiler::TILES_X_COUNT) / 2) * l6, 0.0, -n);
-		b = a.cross(Vec3(0.0, 1.0, 0.0));
-		b.normalize();
-
-		planes[Frustum::FP_LEFT] = Plane(b, 0.0);
-
-		// right
-		a = Vec3((I(i) - I(Tiler::TILES_X_COUNT) / 2 + 1) * l6, 0.0, -n);
-		b = Vec3(0.0, 1.0, 0.0).cross(a);
-		b.normalize();
-
-		planes[Frustum::FP_RIGHT] = Plane(b, 0.0);
-
-		// bottom
-		a = Vec3(0.0, (I(j) - I(Tiler::TILES_Y_COUNT) / 2) * o6, -n);
-		b = Vec3(1.0, 0.0, 0.0).cross(a);
-		b.normalize();
-
-		planes[Frustum::FP_BOTTOM] = Plane(b, 0.0);
-
-		// bottom
-		a = Vec3(0.0, (I(j) - I(Tiler::TILES_Y_COUNT) / 2 + 1) * o6, -n);
-		b = a.cross(Vec3(1.0, 0.0, 0.0));
-		b.normalize();
-
-		planes[Frustum::FP_TOP] = Plane(b, 0.0);
-	}
-
-	void update2Planes(const U k, const Vec2& planes)
-	{
-		U i = k % Tiler::TILES_X_COUNT;
-		U j = k / Tiler::TILES_X_COUNT;
-		Tiler::Tile& tile = tiler->tiles1d[k];
-
-		// Calculate depth as you do it for the vertex position inside
-		// the shaders
-		F32 minZ = planes.y() / (planes.x() + (*pixels)[j][i][0]);
-		F32 maxZ = planes.y() / (planes.x() + (*pixels)[j][i][1]);
-
-		tile.planes[Frustum::FP_NEAR] = Plane(Vec3(0.0, 0.0, -1.0), minZ);
-		tile.planes[Frustum::FP_FAR] = Plane(Vec3(0.0, 0.0, 1.0), -maxZ);
-	}
-};
-
-typedef Array<UpdateTilesPlanesPerspectiveCameraJob, ThreadPool::MAX_THREADS>
-	UpdateJobArray;
-
 //==============================================================================
 #define CHECK_PLANE_PTR(p_) \
 	ANKI_ASSERT(p_ < &tiler->allPlanes[tiler->allPlanes.size()]);
@@ -131,13 +19,14 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 {
 	Tiler* tiler = nullptr;
 	PerspectiveCamera* cam = nullptr;
-	Bool frustumChanged = nullptr;
+	Bool frustumChanged;
 	const Tiler::PixelArray* pixels = nullptr;
 
 	void operator()(U threadId, U threadsCount)
 	{
-		U64 start, end;
+		ANKI_ASSERT(tiler && cam && pixels);
 
+		U64 start, end;
 		Transform trf = Transform(cam->getWorldTransform());
 
 		if(frustumChanged)
@@ -164,7 +53,7 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 				tiler->planesIW[i] = tiler->planesI[i].getTransformed(trf);
 			}
 
-			// Then the left looking planes
+			// Then the right looking planes
 			choseStartEnd(
 				threadId, threadsCount, Tiler::TILES_X_COUNT - 1, start, end);
 
@@ -192,7 +81,7 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 				tiler->planesIW[i] = tiler->planesI[i].getTransformed(trf);
 			}
 
-			// Then the left looking planes
+			// Then the right looking planes
 			choseStartEnd(
 				threadId, threadsCount, Tiler::TILES_X_COUNT - 1, start, end);
 
@@ -211,10 +100,8 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 		choseStartEnd(
 			threadId, threadsCount, Tiler::TILES_COUNT, start, end);
 
-		Plane* nearPlanes = tiler->nearPlanes;
-		Plane* farPlanes = tiler->farPlanes;
-		Plane* nearPlanesW = tiler->nearPlanesW;
-		Plane* farPlanesW = tiler->farPlanesW;
+		Plane* nearPlanesW = tiler->nearPlanesW + start;
+		Plane* farPlanesW = tiler->farPlanesW + start;
 		for(U k = start; k < end; ++k)
 		{
 			U j = k % Tiler::TILES_X_COUNT;
@@ -226,20 +113,16 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 			F32 maxZ = rplanes.y() / (rplanes.x() + (*pixels)[i][j][1]);
 
 			// Calc the planes
-			CHECK_PLANE_PTR(nearPlanes);
-			*nearPlanes = Plane(Vec3(0.0, 0.0, -1.0), minZ);
-			CHECK_PLANE_PTR(farPlanes);
-			*farPlanes = Plane(Vec3(0.0, 0.0, 1.0), -maxZ);
+			Plane nearPlane = Plane(Vec3(0.0, 0.0, -1.0), minZ);
+			Plane farPlane = Plane(Vec3(0.0, 0.0, 1.0), -maxZ);
 
 			// Tranform them
 			CHECK_PLANE_PTR(nearPlanesW);
-			*nearPlanesW = nearPlanes->getTransformed(trf);
+			*nearPlanesW = nearPlane.getTransformed(trf);
 			CHECK_PLANE_PTR(farPlanesW);
-			*farPlanesW = farPlanes->getTransformed(trf);
+			*farPlanesW = farPlane.getTransformed(trf);
 
 			// Advance
-			++nearPlanes;
-			++farPlanes;
 			++nearPlanesW;
 			++farPlanesW;
 		}
@@ -253,19 +136,19 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 		Plane& plane = tiler->planesI[i];
 		CHECK_PLANE_PTR(&plane);
 
-		a = Vec3(0.0, (I(i + 1) - I(Tiler::TILES_Y_COUNT) / 2 + 1) * o6, -n);
-		b = a.cross(Vec3(1.0, 0.0, 0.0));
+		a = Vec3(0.0, (I(i + 1) - I(Tiler::TILES_Y_COUNT) / 2) * o6, -n);
+		b = Vec3(1.0, 0.0, 0.0).cross(a);
 		b.normalize();
 
 		plane = Plane(b, 0.0);
 	}
 
-	/// Calculate and set a left looking plane
+	/// Calculate and set a right looking plane
 	void calcPlaneJ(U j, const F32 l6)
 	{
 		Vec3 a, b;
 		const F32 n = cam->getNear();
-		Plane& plane = tiler->planesI[j];
+		Plane& plane = tiler->planesJ[j];
 		CHECK_PLANE_PTR(&plane);
 
 		a = Vec3((I(j + 1) - I(Tiler::TILES_X_COUNT) / 2) * l6, 0.0, -n);
@@ -278,87 +161,6 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 
 #undef CHECK_PLANE_PTR
 
-//==============================================================================
-// Statics                                                                     =
-//==============================================================================
-
-//==============================================================================
-struct ShortLexicographicallyFunctor
-{
-	Bool operator()(const Vec2& a, const Vec2& b)
-	{
-		return a.x() < b.x() || (a.x() == b.x() && a.y() < b.y());
-	}
-};
-
-//==============================================================================
-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());
-}
-
-//==============================================================================
-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");
-	ANKI_ASSERT(n > 4);
-	I k = 0;
-
-	std::sort(&inPoints[0], &inPoints[n], ShortLexicographicallyFunctor());
-
-	// Build lower hull
-	for(I i = 0; i < n; i++)
-	{
-		while(k >= 2 
-			&& !isLeft(outPoints[k - 2], outPoints[k - 1], inPoints[i]))
-		{
-			--k;
-		}
-
-		outPoints[k++] = inPoints[i];
-	}
-
-	// Build upper hull
-	for(I i = n - 2, t = k + 1; i >= 0; i--)
-	{
-		while(k >= t 
-			&& !isLeft(outPoints[k - 2], outPoints[k - 1], inPoints[i]))
-		{
-			--k;
-		}
-
-		outPoints[k++] = inPoints[i];
-	}
-
-	outn = k;
-}
-
-//==============================================================================
-static U getTilesCount(U maxDepth)
-{
-	if(maxDepth == 0)
-	{
-		return 1;
-	}
-
-	return getTilesCount(maxDepth - 1) + pow(4, maxDepth);
-}
-
-//==============================================================================
-static U32 setNBits(U32 n)
-{
-	U32 res = 0;
-
-	for(U32 i = 0; i < n; i++)
-	{
-		res |= 0x80000000 >> i;
-	}
-
-	return res;
-}
-
 //==============================================================================
 // Tiler                                                                       =
 //==============================================================================
@@ -419,104 +221,19 @@ void Tiler::initInternal(Renderer* r_)
 
 	// Init planes
 	U planesCount = 
-		(TILES_X_COUNT - 1) // planes J
-		+ (TILES_Y_COUNT - 1)  // planes I
+		(TILES_X_COUNT - 1) * 2 // planes J
+		+ (TILES_Y_COUNT - 1) * 2  // planes I
 		+ (TILES_COUNT * 2); // near far planes
 
-	allPlanes.resize(planesCount * 2);
+	allPlanes.resize(planesCount);
 
 	planesJ = &allPlanes[0];
 	planesI = planesJ + TILES_X_COUNT - 1;
-	nearPlanes = planesI + TILES_Y_COUNT - 1;
-	farPlanes = nearPlanes + TILES_COUNT;
 
-	planesJW = farPlanes + TILES_COUNT;
+	planesJW = planesI + TILES_Y_COUNT - 1;
 	planesIW = planesJW + TILES_X_COUNT - 1;
 	nearPlanesW = planesIW + TILES_Y_COUNT - 1;
 	farPlanesW = nearPlanesW + TILES_COUNT;
-
-	// Tiles
-	initTiles();
-}
-
-//==============================================================================
-void Tiler::initTiles()
-{
-	// Init tiles
-	U maxDepth = log2(TILES_X_COUNT);
-	tiles_.resize(getTilesCount(maxDepth));
-
-	Tile_* tmpTiles = &tiles_[0];
-	for(U d = 0; d < maxDepth + 1; d++)
-	{
-		tiles0 = tmpTiles;
-		tmpTiles = initTilesInDepth(tmpTiles, d);
-	}
-	ANKI_ASSERT(tiles_.size() - (tiles0 - &tiles_[0]) == TILES_COUNT);
-
-	// Init hierarchy
-	U offset = 0;
-	tmpTiles = &tiles_[0];
-	for(U d = 0; d < maxDepth; d++)
-	{
-		U axisCount = pow(2, d);
-
-		U count = axisCount * axisCount;
-		offset += count;
-
-		for(U j = 0; j < axisCount; j++)
-		{
-			for(U i = 0; i < axisCount; i++)
-			{
-				U k = j * axisCount + i;
-				Tile_& tile = tmpTiles[k];
-
-				for(U j_ = 0; j_ < 2; j_++)
-				{
-					for(U i_ = 0; i_ < 2; i_++)
-					{
-						tile.children[j_ * 2 + i_] =
-							(2 * j + j_) * axisCount * 2 + (2 * i + i_)
-							+ offset;
-					}
-				}
-			}
-		}
-
-		tmpTiles = tmpTiles + count;
-	}
-}
-
-//==============================================================================
-Tiler::Tile_* Tiler::initTilesInDepth(Tile_* tiles, U depth)
-{
-	U crntDepthAxisCount = pow(2, depth);
-
-	F32 dim = (1.0 - (-1.0)) / crntDepthAxisCount;
-
-	const U bits = TILES_X_COUNT / crntDepthAxisCount;
-	const U32 maskOfTile = setNBits(bits);
-
-	for(U j = 0; j < crntDepthAxisCount; j++)
-	{
-		for(U i = 0; i < crntDepthAxisCount; i++)
-		{
-			Tile_& tile = tiles[j * crntDepthAxisCount + i];
-
-			tile.min[0] = -1.0 + i * dim;
-			tile.min[1] = -1.0 + j * dim;
-			tile.max[0] = tile.min[0] + dim;
-			tile.max[1] = tile.min[1] + dim;
-
-			tile.mask[0] = (maskOfTile >> (i * bits));
-			tile.mask[1] = (maskOfTile >> (j * bits));
-
-			tile.children[0] = tile.children[1] = tile.children[2] =
-				tile.children[3] = -1;
-		}
-	}
-
-	return tiles + (crntDepthAxisCount * crntDepthAxisCount);
 }
 
 //==============================================================================
@@ -541,69 +258,11 @@ void Tiler::runMinMax(const Texture& depthMap)
 	pbo.unbind();
 }
 
-//==============================================================================
-void Tiler::updateTilesInternal()
-{
-	//
-	// Read the results from the minmax job
-	//
-	Array<F32, TILES_X_COUNT * TILES_X_COUNT * 2> pixels;
-	pbo.read(&pixels[0]);
-
-	//
-	// Set the Z of the level 0 tiles
-	//
-	ANKI_ASSERT(tiles0);
-	Tile_* tile = tiles0;
-	Tile_* tileEnd = tile + TILES_COUNT;
-	F32* pixel = &pixels[0];
-	for(; tile != tileEnd; ++tile)
-	{
-		tile->min.z() = pixel[0];
-		tile->max.z() = pixel[1];
-		ANKI_ASSERT(tile->max.z() >= tile->min.z());
-
-		// Convert to NDC (undo the viewport transform)
-		tile->min.z() = tile->min.z() * 2.0 - 1.0;
-		tile->max.z() = tile->max.z() * 2.0 - 1.0;
-
-		pixel += 2;
-	}
-
-	//
-	// Move to the other levels
-	//
-	updateTileMinMax(tiles_[0]);
-}
-
-//==============================================================================
-Vec2 Tiler::updateTileMinMax(Tile_& tile)
-{
-	// Have children?
-	if(tile.children[0] == -1)
-	{
-		return Vec2(tile.min.z(), tile.max.z());
-	}
-
-	Vec2 minMax(10.0, -10.0);
-	for(U i = 0; i < 4; i++)
-	{
-		Vec2 in = updateTileMinMax(tiles_[tile.children[i]]);
-		minMax.x() = std::min(minMax.x(), in.x());
-		minMax.y() = std::max(minMax.y(), in.y());
-	}
-
-	tile.min.z() = minMax.x();
-	tile.max.z() = minMax.y();
-
-	return minMax;
-}
-
 //==============================================================================
 void Tiler::updateTiles(Camera& cam)
 {
 	//
-	// Read the results from the minmax job
+	// Read the results from the minmax job. It will block
 	//
 	PixelArray pixels;
 	pbo.read(&pixels[0][0]);
@@ -611,18 +270,15 @@ void Tiler::updateTiles(Camera& cam)
 	//
 	// Issue parallel jobs
 	//
-	UpdateJobArray jobs;
-
+	Array<UpdatePlanesPerspectiveCameraJob, ThreadPool::MAX_THREADS> jobs;
 	U32 camTimestamp = cam.getFrustumable()->getFrustumableTimestamp();
 
 	// Transform only the planes when:
 	// - it is the same camera as before and
 	// - the camera frustum have not changed
-	Bool update4Planes =
+	Bool frustumChanged =
 		camTimestamp >= planes4UpdateTimestamp || prevCam != &cam;
 
-	// Update the planes in parallel
-	//
 	ThreadPool& threadPool = ThreadPoolSingleton::get();
 
 	switch(cam.getCameraType())
@@ -630,10 +286,10 @@ void Tiler::updateTiles(Camera& cam)
 	case Camera::CT_PERSPECTIVE:
 		for(U i = 0; i < threadPool.getThreadsCount(); i++)
 		{
-			jobs[i].pixels = &pixels;
 			jobs[i].tiler = this;
 			jobs[i].cam = static_cast<PerspectiveCamera*>(&cam);
-			jobs[i].frustumChanged = update4Planes;
+			jobs[i].pixels = &pixels;
+			jobs[i].frustumChanged = frustumChanged;
 			threadPool.assignNewJob(i, &jobs[i]);
 		}
 		break;
@@ -642,343 +298,17 @@ void Tiler::updateTiles(Camera& cam)
 		break;
 	}
 
-	if(update4Planes)
+	if(frustumChanged)
 	{
 		planes4UpdateTimestamp = Timestamp::getTimestamp();
 	}
 
 	threadPool.waitForAllJobsToFinish();
 
-	//
-	// XXX
-	//
-#if 1
-	{
-		Array<UpdatePlanesPerspectiveCameraJob, ThreadPool::MAX_THREADS> jobs;
-
-		ThreadPool& threadPool = ThreadPoolSingleton::get();
-
-
-		switch(cam.getCameraType())
-		{
-		case Camera::CT_PERSPECTIVE:
-			for(U i = 0; i < threadPool.getThreadsCount(); i++)
-			{
-				jobs[i].tiler = this;
-				jobs[i].cam = static_cast<PerspectiveCamera*>(&cam);
-				jobs[i].pixels = &pixels;
-				jobs[i].frustumChanged = true;
-				threadPool.assignNewJob(i, &jobs[i]);
-			}
-			break;
-		default:
-			ANKI_ASSERT(0 && "Unimplemented");
-			break;
-		}
-
-		threadPool.waitForAllJobsToFinish();
-	}
-#endif
-
 	// 
 	// Misc
 	// 
 	prevCam = &cam;
-
-	//updateTilesInternal();
-}
-
-//==============================================================================
-Bool Tiler::testInternal(const CollisionShape& cs, const Tile& tile, 
-	const U startPlane) const
-{
-	for(U j = startPlane; j < Frustum::FP_COUNT; j++)
-	{
-		if(cs.testPlane(tile.planesWSpace[j]) < 0.0)
-		{
-			return false;
-		}
-	}
-	return true;
-}
-
-//==============================================================================
-Bool Tiler::test(const CollisionShape& cs, const U32 tileId,
-	const Bool skipNearPlaneCheck) const
-{
-	return testInternal(cs, tiles1d[tileId], (skipNearPlaneCheck) ? 1 : 0);
-}
-
-//==============================================================================
-Bool Tiler::testAll(const CollisionShape& cs, 
-	const Bool skipNearPlaneCheck) const
-{
-	static_assert(Frustum::FP_NEAR == 0, "Frustum::FP_NEAR should be 0");
-
-	U startPlane = (skipNearPlaneCheck) ? 1 : 0;
-
-	for(const Tile& tile : tiles1d)
-	{
-		if(testInternal(cs, tile, startPlane))
-		{
-			return true;
-		}
-	}
-
-	return false;
-}
-
-//==============================================================================
-Bool Tiler::testAll(const CollisionShape& cs,
- 	U32* tileIds, U32& tilesCount, const Bool skipNearPlaneCheck) const
-{
-	U startPlane = (skipNearPlaneCheck) ? 1 : 0;
-	tilesCount = 0;
-
-	for(U i = 0; i < tiles1d.getSize(); i++)
-	{
-		const Tile& tile = tiles1d[i];
-
-		if(testInternal(cs, tile, startPlane))
-		{
-			tileIds[tilesCount++] = i;
-		}
-	}
-
-	return tilesCount > 0;
-}
-
-//==============================================================================
-Bool Tiler::test(
-	const CollisionShape& cs, 
-	const Aabb& aabb, 
-	Bool nearPlane,
-	Bitset* outBitset) const
-{
-	//
-	// Get points from sp
-	//
-	Array<Vec4, 8> points;
-	U pointsCount = 0;
-
-	if(cs.getCollisionShapeType() != CollisionShape::CST_FRUSTUM)
-	{
-		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 = 8;
-	}
-	else
-	{
-		// XXX
-	}
-
-	//
-	// Transform those shapes
-	//
-	Array<Vec2, 8> points2D;
-	ANKI_ASSERT(prevCam);
-	const Mat4& projection = prevCam->getViewProjectionMatrix();
-	Array<Vec3, 2> minMax = {{Vec3(10.0), Vec3(-10.0)}};
-
-	for(U i = 0; i < pointsCount; i++)
-	{
-		Vec4 point = projection * points[i];
-		Vec3 v3 = point.xyz() / point.w();
-		points2D[i] = v3.xy();
-
-		// Min z
-		minMax[0].z() = std::min(minMax[0].z(), v3.z());
-		// Max z
-		minMax[1].z() = std::max(minMax[1].z(), v3.z());
-	}
-
-	//
-	// Calc the convex hull
-	//
-	Array<Vec2, 8 * 2 + 1> convPoints;
-	U32 convPointsCount;
-	convexHull2D(&points2D[0], pointsCount,
-		&convPoints[0], convPoints.getSize(), convPointsCount);
-
-	// Calc the x,y of the min max
-	minMax[0].x() = minMax[1].x() = convPoints[0].x();
-	minMax[0].y() = minMax[1].y() = convPoints[0].y();
-	for(U i = 1; i < convPointsCount - 1; i++)
-	{
-		for(U j = 0; j < 2; j++)
-		{
-			minMax[0][j] = std::min(minMax[0][j], convPoints[i][j]);
-			minMax[1][j] = std::max(minMax[1][j], convPoints[i][j]);
-		}
-	}
-
-	//
-	// Run the algorithm for every edge
-	//
-	Bitset bitset;
-	for(U i = 0; i < convPointsCount - 1; i++)
-	{
-		Bitset edgebitset;
-		testTile(tiles_[0], convPoints[i], convPoints[i + 1],
-			minMax, edgebitset);
-
-		if(i != 0)
-		{
-			bitset &= edgebitset;
-		}
-		else
-		{
-			bitset = edgebitset;
-		}
-
-	}
-
-	//
-	// Check the z
-	//
-	for(U i = 0; i < TILES_COUNT; i++)
-	{
-		// If tile is visible
-		if(bitset.test(i))
-		{
-			ANKI_ASSERT(i < tiles_.size());
-
-			// Check far plane
-			if(tiles0[i].max.z() > minMax[0].z())
-			{
-				if(nearPlane)
-				{
-					// Check inear plane
-					if(tiles0[i].min.z() < minMax[1].z())
-					{
-						// Keep it
-					}
-					else
-					{
-						bitset.set(i, false);
-					}
-				}
-			}
-			else
-			{
-				bitset.set(i, false);
-			}
-		}
-	}
-
-	if(outBitset)
-	{
-		*outBitset = bitset;
-	}
-
-	return bitset.any();
-}
-
-//==============================================================================
-void Tiler::testTile(const Tile_& tile, const Vec2& a, const Vec2& b, 
-	const Array<Vec3, 2>& objMinMax, Bitset& bitset) const
-{
-	// If edge not inside return
-	for(U i = 0; i < 2; i++)
-	{
-		const F32 min = objMinMax[0][i];
-		const F32 max = objMinMax[1][i];
-
-		if(max < tile.min[i] || min > tile.max[i])
-		{
-			return;
-		}
-	}
-
-	// Continue
-	Bool final = tile.children[0] == -1;
-
-	if(!final)
-	{
-		U inside = 0;
-
-		if(isLeft(a, b, tile.max.xy()))
-		{
-			inside |= 1;
-		}
-
-		if(isLeft(a, b, Vec2(tile.min.x(), tile.max.y())))
-		{
-			inside |= 2;
-		}
-
-		if(isLeft(a, b, tile.min.xy()))
-		{
-			inside |= 4;
-		}
-
-		if(isLeft(a, b, Vec2(tile.max.x(), tile.min.y())))
-		{
-			inside |= 8;
-		}
-
-		// None inside
-		if(inside == 0)
-		{
-			return;
-		}
-		else if(inside == 0xF) // All inside
-		{
-			goto allIn;
-		}
-		else // Some inside
-		{
-			ANKI_ASSERT(!final);
-
-			for(U i = 0; i < 4; i++)
-			{
-				testTile(tiles_[tile.children[i]], a, b, objMinMax, bitset);
-			}
-		}
-	}
-	else
-	{
-		if(isLeft(a, b, tile.max.xy())
-			|| isLeft(a, b, Vec2(tile.min.x(), tile.max.y()))
-			|| isLeft(a, b, tile.min.xy())
-			|| isLeft(a, b, Vec2(tile.max.x(), tile.min.y())))
-		{
-			goto allIn;
-		}
-	}
-
-	return;
-
-allIn:
-	updateBitset(tile, bitset);
-}
-
-//==============================================================================
-void Tiler::updateBitset(const Tile_& tile, Bitset &bitset) const
-{
-	if(tile.children[0] != -1)
-	{
-		for(U i = 0; i < 4; i++)
-		{
-			updateBitset(tiles_[tile.children[i]], bitset);
-		}
-	}
-	else
-	{
-		U tileId = &tile - tiles0;
-		ANKI_ASSERT(tileId < TILES_COUNT);
-		bitset.set(tileId);
-	}
 }
 
 //==============================================================================
@@ -1007,12 +337,14 @@ void Tiler::testRange(const CollisionShape& cs, Bool nearPlane,
 	U mi = (iTo - iFrom) / 2;
 	U mj = (jTo - jFrom) / 2;
 
+	ANKI_ASSERT(mi == mj && "Change the algorithm if they are not the same");
+
 	// Handle final
 	if(mi == 0 || mj == 0)
 	{
 		U tileId = iFrom * TILES_X_COUNT + jFrom;
 
-		Bool inside = false;
+		Bool inside = true;
 
 		if(cs.testPlane(farPlanesW[tileId]) >= 0.0)
 		{
@@ -1046,7 +378,7 @@ void Tiler::testRange(const CollisionShape& cs, Bool nearPlane,
 	// Find the correct top lookin plane (i)
 	const Plane& topPlane = planesIW[iFrom + mi - 1];
 
-	// Find the correct right plane (j)
+	// Find the correct right looking plane (j)
 	const Plane& rightPlane = planesJW[jFrom + mj - 1];
 
 	// Do the checks
@@ -1075,7 +407,7 @@ void Tiler::testRange(const CollisionShape& cs, Bool nearPlane,
 		}
 	}
 
-	// Left looking plane check
+	// Right looking plane check
 	test = cs.testPlane(rightPlane);
 	if(test < 0.0)
 	{
@@ -1095,10 +427,13 @@ void Tiler::testRange(const CollisionShape& cs, Bool nearPlane,
 	{
 		for(U j = 0; j < 2; j++)
 		{
-			testRange(cs, nearPlane,
-				iFrom + (i * mi), iFrom + ((i + 1) * mi),
-				jFrom + (j * mi), iFrom + ((j + 1) * mj),
-				bitset);
+			if(inside[i][j])
+			{
+				testRange(cs, nearPlane,
+					iFrom + (i * mi), iFrom + ((i + 1) * mi),
+					jFrom + (j * mj), jFrom + ((j + 1) * mj),
+					bitset);
+			}
 		}
 	}
 }

+ 1 - 0
src/scene/SceneGraph.cpp

@@ -135,6 +135,7 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 	// XXX Do that in parallel
 	physics.update(prevUpdateTime, crntTime);
 	renderer.getTiler().updateTiles(*mainCam);
+	events.updateAllEvents(prevUpdateTime, crntTime);
 
 #if 0
 	// First do the movable updates

+ 4 - 4
src/scene/Sector.cpp

@@ -335,8 +335,8 @@ void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
 			// First the renderables
 			for(SceneNode* renderable : testResult.renderables)
 			{
-				if(r->doVisibilityTests(
-					renderable->getSpatial()->getOptimalCollisionShape()))
+				/*XXX if(r->getTiler().test2(
+					renderable->getSpatial()->getOptimalCollisionShape()))*/
 				{
 					visible->renderables.push_back(renderable);
 				}
@@ -345,8 +345,8 @@ void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
 			// Then the lights
 			for(SceneNode* light : testResult.lights)
 			{
-				if(r->doVisibilityTests(
-					light->getSpatial()->getOptimalCollisionShape()))
+				/*XXX if(r->doVisibilityTests(
+					light->getSpatial()->getOptimalCollisionShape()))*/
 				{
 					visible->lights.push_back(light);
 				}

+ 11 - 6
src/scene/Visibility.cpp

@@ -60,8 +60,9 @@ struct VisibilityTestJob: ThreadJob
 				Spatial* subsp = *it;
 	
 				if(frustumable->insideFrustum(*subsp)
-					/*&& renderer->doVisibilityTests(
-					subsp->getOptimalCollisionShape())*/)
+					&& tiler->test2(
+					subsp->getSpatialCollisionShape(),
+					subsp->getAabb(), false, nullptr))
 				{
 					subSpatialsMask |= 1 << i;
 					subsp->enableBits(Spatial::SF_VISIBLE_CAMERA);
@@ -78,11 +79,12 @@ struct VisibilityTestJob: ThreadJob
 			Renderable* r = node->getRenderable();
 			if(r)
 			{
-				/*if(!renderer->doVisibilityTests(
-					sp->getOptimalCollisionShape()))
+				if(!tiler->test2(
+					sp->getSpatialCollisionShape(),
+					sp->getAabb(), false, nullptr))
 				{
 					continue;
-				}*/
+				}
 				visible->renderables.push_back(node);
 
 				// Inform the renderable for the mask
@@ -100,7 +102,6 @@ struct VisibilityTestJob: ThreadJob
 					&& tiler->test2(sp->getSpatialCollisionShape(),
 					sp->getAabb(), true, &tilerBitset))
 				{
-					std::cout << "asdf" << std::endl;
 					visible->lights.push_back(node);
 
 					sp->setTilerBitset(tilerBitset);
@@ -110,6 +111,10 @@ struct VisibilityTestJob: ThreadJob
 						testLight(*node);
 					}
 				}
+				else
+				{
+					continue;
+				}
 			}
 
 			sp->enableBits(Spatial::SF_VISIBLE_CAMERA);

+ 21 - 9
testapp/Main.cpp

@@ -30,6 +30,8 @@
 #include "anki/core/NativeWindow.h"
 #include "anki/util/Functions.h"
 #include "anki/scene/Scene.h"
+#include "anki/event/LightEvent.h"
+#include "anki/event/MovableEvent.h"
 
 using namespace anki;
 
@@ -164,12 +166,7 @@ void init()
 	}
 #endif
 
-	PointLight* point = new PointLight("ll", &scene,
-		Movable::MF_NONE, nullptr);
-	point->setLocalTranslation(Vec3(1.0, 0.1, 0.0));
-	point->setRadius(2.0);
-
-#if 0
+#if 1
 	SpotLight* spot = new SpotLight("spot0", &scene, Movable::MF_NONE, nullptr);
 	spot->setOuterAngle(toRad(45.0));
 	spot->setInnerAngle(toRad(15.0));
@@ -194,7 +191,7 @@ void init()
 	spot->setShadowEnabled(true);
 #endif
 
-#if 0
+#if 1
 	// Vase point lights
 	F32 x = 8.5;
 	F32 y = 2.25;
@@ -210,9 +207,24 @@ void init()
 			&scene, Movable::MF_NONE, nullptr);
 		point->setRadius(2.0);
 		point->setLocalTranslation(lightPos);
-		point->setDiffuseColor(Vec4(3.0, 0.0, 0.0, 0.0));
+		point->setDiffuseColor(Vec4(3.0, 0.2, 0.0, 0.0));
 		point->setSpecularColor(Vec4(1.0, 1.0, 0.0, 0.0));
 
+		LightEventData eventData;
+		eventData.light = point;
+		eventData.radiusMultiplier = 0.2;
+		eventData.intensityMultiplier = Vec4(-1.2, 0.0, 0.0, 0.0);
+		eventData.specularIntensityMultiplier = Vec4(0.1, 0.1, 0.0, 0.0);
+		auto event = scene.getEventManager().newLightEvent(0.0, 0.8, eventData);
+		event->enableBits(Event::EF_REANIMATE);
+
+		MovableEventData moveData;
+		moveData.movableSceneNode = point;
+		moveData.posMin = Vec3(-0.5, 0.0, -0.5);
+		moveData.posMax = Vec3(0.5, 0.0, 0.5);
+		auto mevent = scene.getEventManager().newMovableEvent(0.0, 2.0, moveData);
+		mevent->enableBits(Event::EF_REANIMATE);
+
 		ParticleEmitter* pe = new ParticleEmitter(
 			"data/particles/smoke.particles",
 			("pe" + std::to_string(i)).c_str(), &scene,
@@ -227,7 +239,7 @@ void init()
 	}
 #endif
 
-#if 0
+#if 1
 	// horse
 	horse = new ModelNode("data/models/horse/horse.mdl", "horse", &scene,
 		Movable::MF_NONE, nullptr);