Browse Source

- Moving all the plane tests in a single file
- Optimizing the method calls (removing a few virtuals)

Panagiotis Christopoulos Charitos 14 years ago
parent
commit
17d92347d0

+ 0 - 40
anki/collision/Aabb.cpp

@@ -6,46 +6,6 @@
 namespace anki {
 
 
-//==============================================================================
-float Aabb::testPlane(const Plane& plane) const
-{
-	Vec3 diagMin, diagMax;
-	// set min/max values for x,y,z direction
-	for(int i = 0; i < 3; i++)
-	{
-		if(plane.getNormal()[i] >= 0.0)
-		{
-			diagMin[i] = min[i];
-			diagMax[i] = max[i];
-		}
-		else
-		{
-			diagMin[i] = max[i];
-			diagMax[i] = min[i];
-		}
-	}
-
-	// minimum on positive side of plane, box on positive side
-	float test = plane.test(diagMin);
-	if(test > 0.0)
-	{
-		return test;
-	}
-
-	test = plane.test(diagMax);
-	// min on non-positive side, max on non-negative side, intersection
-	if(test >= 0.0)
-	{
-		return 0.0;
-	}
-	// max on negative side, box on negative side
-	else
-	{
-		return test;
-	}
-}
-
-
 //==============================================================================
 Aabb Aabb::getTransformed(const Transform& transform) const
 {

+ 12 - 4
anki/collision/Aabb.h

@@ -63,14 +63,22 @@ class Aabb: public CollisionShape
 		}
 		/// @}
 
-		/// @copydoc CollisionShape::accept
-		void accept(Visitor& v)
+		/// Implements CollisionShape::accept
+		void accept(MutableVisitor& v)
+		{
+			v.visit(*this);
+		}
+		/// Implements CollisionShape::accept
+		void accept(ConstVisitor& v)
 		{
 			v.visit(*this);
 		}
 
-		/// Implements CollisionShape::testPlane
-		float testPlane(const Plane& plane) const;
+		/// Overrides CollisionShape::testPlane
+		float testPlane(const Plane& p) const
+		{
+			return PlaneTests::test(p, *this);
+		}
 
 		Aabb getTransformed(const Transform& transform) const;
 

+ 109 - 54
anki/collision/CollisionAlgorithmsMatrix.cpp

@@ -8,13 +8,68 @@
 namespace anki {
 
 
+//==============================================================================
+template<typename T>
+bool CollisionAlgorithmsMatrix::tcollide(const CollisionShape& a,
+	const CollisionShape& b)
+{
+	const T& t = static_cast<const T&>(a);
+
+	switch(b.getCollisionShapeType())
+	{
+		case CollisionShape::CST_LINE_SEG:
+			return collide(t, static_cast<const LineSegment&>(b));
+		case CollisionShape::CST_RAY:
+			return collide(t, static_cast<const Ray&>(b));
+		case CollisionShape::CST_PLANE:
+			return collide(t, static_cast<const Plane&>(b));
+		case CollisionShape::CST_SPHERE:
+			return collide(t, static_cast<const Sphere&>(b));
+		case CollisionShape::CST_AABB:
+			return collide(t, static_cast<const Aabb&>(b));
+		case CollisionShape::CST_OBB:
+			return collide(t, static_cast<const Obb&>(b));
+		case CollisionShape::CST_PERSPECTIVE_CAMERA_FRUSTRUM:
+			return collide(t, static_cast<const PerspectiveCameraShape&>(b));
+		default:
+			ASSERT(0 && "Forgot something");
+	}
+}
+
+
+//==============================================================================
+bool CollisionAlgorithmsMatrix::collide(const CollisionShape& a,
+	const CollisionShape& b)
+{
+	switch(a.getCollisionShapeType())
+	{
+		case CollisionShape::CST_LINE_SEG:
+			return tcollide<LineSegment>(a, b);
+		case CollisionShape::CST_RAY:
+			return tcollide<Ray>(a, b);
+		case CollisionShape::CST_PLANE:
+			return tcollide<Plane>(a, b);
+		case CollisionShape::CST_SPHERE:
+			return tcollide<Sphere>(a, b);
+		case CollisionShape::CST_AABB:
+			return tcollide<Aabb>(a, b);
+		case CollisionShape::CST_OBB:
+			return tcollide<Obb>(a, b);
+		case CollisionShape::CST_PERSPECTIVE_CAMERA_FRUSTRUM:
+			return tcollide<PerspectiveCameraShape>(a, b);
+		default:
+			ASSERT(0 && "Forgot something");
+	}
+}
+
+
 //==============================================================================
 // 1st row                                                                     =
 //==============================================================================
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
-	const Ls& /*b*/) const
+bool CollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
+	const Ls& /*b*/)
 {
 	ASSERT(0 && "Not worth implementing");
 	return false;
@@ -22,8 +77,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& ls,
-	const Obb& obb) const
+bool CollisionAlgorithmsMatrix::collide(const Ls& ls,
+	const Obb& obb)
 {
 	float maxS = std::numeric_limits<float>::min();
 	float minT = std::numeric_limits<float>::max();
@@ -86,8 +141,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& ls,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
-	const Pcs& /*b*/) const
+bool CollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
+	const Pcs& /*b*/)
 {
 	ASSERT(0 && "Not implemented yet");
 	return false;
@@ -95,15 +150,15 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& ls, const Plane& p) const
+bool CollisionAlgorithmsMatrix::collide(const Ls& ls, const Plane& p)
 {
 	return ls.testPlane(p) == 0.0;
 }
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
-	const Ray& /*b*/) const
+bool CollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
+	const Ray& /*b*/)
 {
 	ASSERT(0 && "Not worth implementing");
 	return false;
@@ -111,8 +166,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& /*a*/,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& ls,
-	const Sphere& s) const
+bool CollisionAlgorithmsMatrix::collide(const Ls& ls,
+	const Sphere& s)
 {
 	const Vec3& v = ls.getDirection();
 	Vec3 w0 = s.getCenter() - ls.getOrigin();
@@ -139,8 +194,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& ls,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& ls,
-	const Aabb& aabb) const
+bool CollisionAlgorithmsMatrix::collide(const Ls& ls,
+	const Aabb& aabb)
 {
 	float maxS = std::numeric_limits<float>::min();
 	float minT = std::numeric_limits<float>::max();
@@ -200,8 +255,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ls& ls,
 //==============================================================================
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& o0,
-	const Obb& o1) const
+bool CollisionAlgorithmsMatrix::collide(const Obb& o0,
+	const Obb& o1)
 {
 	// extent vectors
 	const Vec3& a = o0.getExtend();
@@ -381,7 +436,7 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& o0,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& a, const Pcs& b) const
+bool CollisionAlgorithmsMatrix::collide(const Obb& a, const Pcs& b)
 {
 	ASSERT(0 && "Not impelented yet");
 	return false;
@@ -389,16 +444,16 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& a, const Pcs& b) const
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& a,
-	const Plane& b) const
+bool CollisionAlgorithmsMatrix::collide(const Obb& a,
+	const Plane& b)
 {
 	return a.testPlane(b) == 0.0;
 }
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& obb,
-	const Ray& r) const
+bool CollisionAlgorithmsMatrix::collide(const Obb& obb,
+	const Ray& r)
 {
 	Aabb aabb_(-obb.getExtend(), obb.getExtend());
 	Ray newray;
@@ -412,8 +467,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& obb,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& obb,
-	const Sphere& s) const
+bool CollisionAlgorithmsMatrix::collide(const Obb& obb,
+	const Sphere& s)
 {
 	Aabb aabb_(-obb.getExtend(), obb.getExtend()); // aabb_ is in "this" frame
 	Vec3 newCenter = obb.getRotation().getTransposed() *
@@ -425,8 +480,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& obb,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& obb,
-	const Aabb& aabb) const
+bool CollisionAlgorithmsMatrix::collide(const Obb& obb,
+	const Aabb& aabb)
 {
 	Vec3 center_ = (aabb.getMax() + aabb.getMin()) * 0.5;
 	Vec3 extends_ = (aabb.getMax() - aabb.getMin()) * 0.5;
@@ -441,8 +496,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Obb& obb,
 //==============================================================================
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
-	const Pcs& b) const
+bool CollisionAlgorithmsMatrix::collide(const Pcs& a,
+	const Pcs& b)
 {
 	ASSERT(0 && "Not implemented yet");
 	return false;
@@ -450,8 +505,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
-	const Plane& b) const
+bool CollisionAlgorithmsMatrix::collide(const Pcs& a,
+	const Plane& b)
 {
 	ASSERT(0 && "Not implemented yet");
 	return false;
@@ -459,8 +514,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
-	const Ray& b) const
+bool CollisionAlgorithmsMatrix::collide(const Pcs& a,
+	const Ray& b)
 {
 	ASSERT(0 && "Not implemented yet");
 	return false;
@@ -468,8 +523,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
-	const Sphere& b) const
+bool CollisionAlgorithmsMatrix::collide(const Pcs& a,
+	const Sphere& b)
 {
 	ASSERT(0 && "Not implemented yet");
 	return false;
@@ -477,8 +532,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
-	const Aabb& b) const
+bool CollisionAlgorithmsMatrix::collide(const Pcs& a,
+	const Aabb& b)
 {
 	ASSERT(0 && "Not implemented yet");
 	return false;
@@ -490,32 +545,32 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Pcs& a,
 //==============================================================================
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Plane& p0,
-	const Plane& p1) const
+bool CollisionAlgorithmsMatrix::collide(const Plane& p0,
+	const Plane& p1)
 {
 	return p0.getNormal() != p1.getNormal();
 }
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Plane& p,
-	const Ray& r) const
+bool CollisionAlgorithmsMatrix::collide(const Plane& p,
+	const Ray& r)
 {
 	return r.testPlane(p) == 0.0;
 }
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Plane& p,
-	const Sphere& s) const
+bool CollisionAlgorithmsMatrix::collide(const Plane& p,
+	const Sphere& s)
 {
 	return s.testPlane(p) == 0.0;
 }
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Plane& p,
-	const Aabb& aabb) const
+bool CollisionAlgorithmsMatrix::collide(const Plane& p,
+	const Aabb& aabb)
 {
 	return aabb.testPlane(p) == 0.0;
 }
@@ -526,8 +581,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Plane& p,
 //==============================================================================
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ray& a,
-	const Ray& b) const
+bool CollisionAlgorithmsMatrix::collide(const Ray& a,
+	const Ray& b)
 {
 	ASSERT(0 && "Not worth implementing");
 	return false;
@@ -535,8 +590,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ray& a,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ray& r,
-	const Sphere& s) const
+bool CollisionAlgorithmsMatrix::collide(const Ray& r,
+	const Sphere& s)
 {
 	Vec3 w(s.getCenter() - r.getOrigin());
 	const Vec3& v = r.getDirection();
@@ -556,8 +611,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ray& r,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Ray& r,
-	const Aabb& aabb) const
+bool CollisionAlgorithmsMatrix::collide(const Ray& r,
+	const Aabb& aabb)
 {
 	float maxS = std::numeric_limits<float>::min();
 	float minT = std::numeric_limits<float>::max();
@@ -618,8 +673,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Ray& r,
 //==============================================================================
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Sphere& a,
-	const Sphere& b) const
+bool CollisionAlgorithmsMatrix::collide(const Sphere& a,
+	const Sphere& b)
 {
 	float tmp = a.getRadius() + b.getRadius();
 	return (a.getCenter() - b.getCenter()).getLengthSquared() <= tmp * tmp;
@@ -627,8 +682,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Sphere& a,
 
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Sphere& s,
-	const Aabb& aabb) const
+bool CollisionAlgorithmsMatrix::collide(const Sphere& s,
+	const Aabb& aabb)
 {
 	const Vec3& c = s.getCenter();
 
@@ -673,8 +728,8 @@ bool DefaultCollisionAlgorithmsMatrix::collide(const Sphere& s,
 //==============================================================================
 
 //==============================================================================
-bool DefaultCollisionAlgorithmsMatrix::collide(const Aabb& a,
-	const Aabb& b) const
+bool CollisionAlgorithmsMatrix::collide(const Aabb& a,
+	const Aabb& b)
 {
 	// if separated in x direction
 	if(a.getMin().x() > b.getMax().x() || b.getMin().x() > a.getMax().x())

+ 60 - 96
anki/collision/CollisionAlgorithmsMatrix.h

@@ -7,6 +7,9 @@
 namespace anki {
 
 
+/// @addtogroup Collision
+/// @{
+///
 /// Provides the collision algorithms that detect collision between collision
 /// shapes
 ///
@@ -33,180 +36,141 @@ class CollisionAlgorithmsMatrix
 		typedef PerspectiveCameraShape Pcs;
 		typedef LineSegment Ls;
 
+		/// Generic collide function. It doesn't uses visitor pattern for
+		/// speed reasons
+		static bool collide(const CollisionShape& a, const CollisionShape& b);
+
 		// 1st line (LS)
-		virtual bool collide(const Ls& a, const Ls& b) const = 0;
-		virtual bool collide(const Ls& a, const Obb& b) const = 0;
-		virtual bool collide(const Ls& a, const Pcs& b) const = 0;
-		virtual bool collide(const Ls& a, const Plane& b) const = 0;
-		virtual bool collide(const Ls& a, const Ray& b) const = 0;
-		virtual bool collide(const Ls& a, const Sphere& b) const = 0;
-		virtual bool collide(const Ls& a, const Aabb& b) const = 0;
+		static bool collide(const Ls& a, const Ls& b);
+		static bool collide(const Ls& a, const Obb& b);
+		static bool collide(const Ls& a, const Pcs& b);
+		static bool collide(const Ls& a, const Plane& b);
+		static bool collide(const Ls& a, const Ray& b);
+		static bool collide(const Ls& a, const Sphere& b);
+		static bool collide(const Ls& a, const Aabb& b);
 
 		// 2nd line (OBB)
-		bool collide(const Obb& a, const Ls& b) const
+		static bool collide(const Obb& a, const Ls& b)
 		{
 			return collide(b, a);
 		}
-		virtual bool collide(const Obb& a, const Obb& b) const = 0;
-		virtual bool collide(const Obb& a, const Pcs& b) const = 0;
-		virtual bool collide(const Obb& a, const Plane& b) const = 0;
-		virtual bool collide(const Obb& a, const Ray& b) const = 0;
-		virtual bool collide(const Obb& a, const Sphere& b) const = 0;
-		virtual bool collide(const Obb& a, const Aabb& b) const = 0;
+		static bool collide(const Obb& a, const Obb& b);
+		static bool collide(const Obb& a, const Pcs& b);
+		static bool collide(const Obb& a, const Plane& b);
+		static bool collide(const Obb& a, const Ray& b);
+		static bool collide(const Obb& a, const Sphere& b);
+		static bool collide(const Obb& a, const Aabb& b);
 
 		// 3rd line (PCS)
-		bool collide(const Pcs& a, const Ls& b) const
+		static bool collide(const Pcs& a, const Ls& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Pcs& a, const Obb& b) const
+		static bool collide(const Pcs& a, const Obb& b)
 		{
 			return collide(b, a);
 		}
-		virtual bool collide(const Pcs& a, const Pcs& b) const = 0;
-		virtual bool collide(const Pcs& a, const Plane& b) const = 0;
-		virtual bool collide(const Pcs& a, const Ray& b) const = 0;
-		virtual bool collide(const Pcs& a, const Sphere& b) const = 0;
-		virtual bool collide(const Pcs& a, const Aabb& b) const = 0;
+		static bool collide(const Pcs& a, const Pcs& b);
+		static bool collide(const Pcs& a, const Plane& b);
+		static bool collide(const Pcs& a, const Ray& b);
+		static bool collide(const Pcs& a, const Sphere& b);
+		static bool collide(const Pcs& a, const Aabb& b);
 
 		// 4th line (P)
-		bool collide(const Plane& a, const Ls& b) const
+		static bool collide(const Plane& a, const Ls& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Plane& a, const Obb& b) const
+		static bool collide(const Plane& a, const Obb& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Plane& a,const Pcs& b) const
+		static bool collide(const Plane& a,const Pcs& b)
 		{
 			return collide(b, a);
 		}
-		virtual bool collide(const Plane& a, const Plane& b) const = 0;
-		virtual bool collide(const Plane& a, const Ray& b) const = 0;
-		virtual bool collide(const Plane& a, const Sphere& b) const = 0;
-		virtual bool collide(const Plane& a, const Aabb& b) const = 0;
+		static bool collide(const Plane& a, const Plane& b);
+		static bool collide(const Plane& a, const Ray& b);
+		static bool collide(const Plane& a, const Sphere& b);
+		static bool collide(const Plane& a, const Aabb& b);
 
 		// 5th line (R)
-		bool collide(const Ray& a, const Ls& b) const
+		static bool collide(const Ray& a, const Ls& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Ray& a, const Obb& b) const
+		static bool collide(const Ray& a, const Obb& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Ray& a, const Pcs& b) const
+		static bool collide(const Ray& a, const Pcs& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Ray& a, const Plane& b) const
+		static bool collide(const Ray& a, const Plane& b)
 		{
 			return collide(b, a);
 		}
-		virtual bool collide(const Ray& a, const Ray& b) const = 0;
-		virtual bool collide(const Ray& a, const Sphere& b) const = 0;
-		virtual bool collide(const Ray& a, const Aabb& b) const = 0;
+		static bool collide(const Ray& a, const Ray& b);
+		static bool collide(const Ray& a, const Sphere& b);
+		static bool collide(const Ray& a, const Aabb& b);
 
 		// 6th line (S)
-		bool collide(const Sphere& a, const Ls& b) const
+		static bool collide(const Sphere& a, const Ls& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Sphere& a, const Obb& b) const
+		static bool collide(const Sphere& a, const Obb& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Sphere& a, const Pcs& b) const
+		static bool collide(const Sphere& a, const Pcs& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Sphere& a, const Plane& b) const
+		static bool collide(const Sphere& a, const Plane& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Sphere& a, const Ray& b) const
+		static bool collide(const Sphere& a, const Ray& b)
 		{
 			return collide(b, a);
 		}
-		virtual bool collide(const Sphere& a, const Sphere& b) const = 0;
-		virtual bool collide(const Sphere& a, const Aabb& b) const = 0;
+		static bool collide(const Sphere& a, const Sphere& b);
+		static bool collide(const Sphere& a, const Aabb& b);
 
 		// 7th line (AABB)
-		bool collide(const Aabb& a, const Ls& b) const
+		static bool collide(const Aabb& a, const Ls& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Aabb& a, const Obb& b) const
+		static bool collide(const Aabb& a, const Obb& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Aabb& a, const Pcs& b) const
+		static bool collide(const Aabb& a, const Pcs& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Aabb& a, const Plane& b) const
+		static bool collide(const Aabb& a, const Plane& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Aabb& a, const Ray& b) const
+		static bool collide(const Aabb& a, const Ray& b)
 		{
 			return collide(b, a);
 		}
-		bool collide(const Aabb& a, const Sphere& b) const
+		static bool collide(const Aabb& a, const Sphere& b)
 		{
 			return collide(b, a);
 		}
-		virtual bool collide(const Aabb& a, const Aabb& b) const = 0;
-};
-
-
-/// The default implementation of collision algorithms
-class DefaultCollisionAlgorithmsMatrix: public CollisionAlgorithmsMatrix
-{
-	public:
-		// 1st line (LS)
-		virtual bool collide(const Ls& a, const Ls& b) const;
-		virtual bool collide(const Ls& a, const Obb& b) const;
-		virtual bool collide(const Ls& a, const Pcs& b) const;
-		virtual bool collide(const Ls& a, const Plane& b) const;
-		virtual bool collide(const Ls& a, const Ray& b) const;
-		virtual bool collide(const Ls& a, const Sphere& b) const;
-		virtual bool collide(const Ls& a, const Aabb& b) const;
-
-		// 2nd line (OBB)
-		virtual bool collide(const Obb& a, const Obb& b) const;
-		virtual bool collide(const Obb& a, const Pcs& b) const;
-		virtual bool collide(const Obb& a, const Plane& b) const;
-		virtual bool collide(const Obb& a, const Ray& b) const;
-		virtual bool collide(const Obb& a, const Sphere& b) const;
-		virtual bool collide(const Obb& a, const Aabb& b) const;
+		static bool collide(const Aabb& a, const Aabb& b);
 
-		// 3rd line (PCS)
-		virtual bool collide(const Pcs& a, const Pcs& b) const;
-		virtual bool collide(const Pcs& a, const Plane& b) const;
-		virtual bool collide(const Pcs& a, const Ray& b) const;
-		virtual bool collide(const Pcs& a, const Sphere& b) const;
-		virtual bool collide(const Pcs& a, const Aabb& b) const;
-
-		// 4th line (P)
-		virtual bool collide(const Plane& a, const Plane& b) const;
-		virtual bool collide(const Plane& a, const Ray& b) const;
-		virtual bool collide(const Plane& a, const Sphere& b) const;
-		virtual bool collide(const Plane& a, const Aabb& b) const;
-
-		// 5th line (R)
-		virtual bool collide(const Ray& a, const Ray& b) const;
-		virtual bool collide(const Ray& a, const Sphere& b) const;
-		virtual bool collide(const Ray& a, const Aabb& b) const;
-
-		// 6th line (S)
-		virtual bool collide(const Sphere& a, const Sphere& b) const;
-		virtual bool collide(const Sphere& a, const Aabb& b) const;
-
-		// 7th line (AABB)
-		virtual bool collide(const Aabb& a, const Aabb& b) const;
+	private:
+		template<typename T>
+		static bool tcollide(const CollisionShape& a, const CollisionShape& b);
 };
+/// @}
 
 
 } // end namespace

+ 24 - 8
anki/collision/CollisionShape.h

@@ -2,6 +2,7 @@
 #define ANKI_COLLISION_COLLISION_SHAPE
 
 #include "anki/collision/Forward.h"
+#include "anki/collision/PlaneTests.h"
 
 
 namespace anki {
@@ -26,8 +27,8 @@ class CollisionShape
 			CST_PERSPECTIVE_CAMERA_FRUSTRUM
 		};
 
-		/// Generic visitor
-		class Visitor
+		/// Generic mutable visitor
+		class MutableVisitor
 		{
 			public:
 				virtual void visit(LineSegment&) = 0;
@@ -39,6 +40,19 @@ class CollisionShape
 				virtual void visit(Aabb&) = 0;
 		};
 
+		/// Generic const visitor
+		class ConstVisitor
+		{
+			public:
+				virtual void visit(const LineSegment&) = 0;
+				virtual void visit(const Obb&) = 0;
+				virtual void visit(const PerspectiveCameraShape&) = 0;
+				virtual void visit(const Plane&) = 0;
+				virtual void visit(const Ray&) = 0;
+				virtual void visit(const Sphere&) = 0;
+				virtual void visit(const Aabb&) = 0;
+		};
+
 		CollisionShape(CollisionShapeType cid_)
 		:	cid(cid_)
 		{}
@@ -49,13 +63,15 @@ class CollisionShape
 		}
 
 		/// Visitor accept
-		virtual void accept(Visitor& v) = 0;
+		virtual void accept(MutableVisitor& v) = 0;
+		/// Visitor accept
+		virtual void accept(ConstVisitor& v) = 0;
 
-		/// If the bounding volume intersects with the plane then the func
-		/// returns 0, else it returns the distance. If the distance is < 0
-		/// then the collision shape lies behind the plane and if > 0 then in
-		/// front of it
-		virtual float testPlane(const Plane& p) const = 0;
+		/// See declaration of PlaneTests class
+		float testPlane(const Plane& p) const
+		{
+			return PlaneTests::test(p, *this);
+		}
 
 	private:
 		CollisionShapeType cid;

+ 2 - 0
anki/collision/Forward.h

@@ -5,6 +5,8 @@
 namespace anki {
 
 
+class CollisionShape;
+
 class LineSegment;
 class Obb;
 class PerspectiveCameraShape;

+ 0 - 36
anki/collision/LineSegment.cpp

@@ -18,40 +18,4 @@ LineSegment LineSegment::getTransformed(const Transform& transform) const
 }
 
 
-//==============================================================================
-// testPlane                                                                   =
-//==============================================================================
-float LineSegment::testPlane(const Plane& plane) const
-{
-	const Vec3& p0 = origin;
-	Vec3 p1 = origin + dir;
-
-	float dist0 = plane.test(p0);
-	float dist1 = plane.test(p1);
-
-	if(dist0 > 0.0)
-	{
-		if(dist1 > 0.0)
-		{
-			return std::min(dist0, dist1);
-		}
-		else
-		{
-			return 0.0;
-		}
-	}
-	else
-	{
-		if(dist1 < 0.0)
-		{
-			return std::max(dist0, dist1);
-		}
-		else
-		{
-			return 0.0;
-		}
-	}
-}
-
-
 } // end namespace

+ 12 - 4
anki/collision/LineSegment.h

@@ -64,16 +64,24 @@ class LineSegment: public CollisionShape
 		}
 		/// @}
 
-		/// @copydoc CollisionShape::accept
-		void accept(Visitor& v)
+		/// Implements CollisionShape::accept
+		void accept(MutableVisitor& v)
+		{
+			v.visit(*this);
+		}
+		/// Implements CollisionShape::accept
+		void accept(ConstVisitor& v)
 		{
 			v.visit(*this);
 		}
 
 		LineSegment getTransformed(const Transform& transform) const;
 
-		/// Implements CollisionShape::testPlane @see CollisionShape::testPlane
-		float testPlane(const Plane& plane) const;
+		/// Overrides CollisionShape::testPlane
+		float testPlane(const Plane& p) const
+		{
+			return PlaneTests::test(p, *this);
+		}
 
 	private:
 		/// @name Data

+ 0 - 27
anki/collision/Obb.cpp

@@ -58,33 +58,6 @@ Obb Obb::getCompoundShape(const Obb& b) const
 }
 
 
-//==============================================================================
-float Obb::testPlane(const Plane& plane) const
-{
-	Vec3 xNormal = rotation.getTransposed() * plane.getNormal();
-
-	// maximum extent in direction of plane normal
-	float r = fabs(extends.x() * xNormal.x()) +
-		fabs(extends.y() * xNormal.y()) + fabs(extends.z() * xNormal.z());
-	// signed distance between box center and plane
-	float d = plane.test(center);
-
-	// return signed distance
-	if(fabs(d) < r)
-	{
-		return 0.0;
-	}
-	else if(d < 0.0)
-	{
-		return d + r;
-	}
-	else
-	{
-		return d - r;
-	}
-}
-
-
 //==============================================================================
 void Obb::getExtremePoints(boost::array<Vec3, 8>& points) const
 {

+ 12 - 4
anki/collision/Obb.h

@@ -67,8 +67,13 @@ class Obb: public CollisionShape
 		}
 		/// @}
 
-		/// @copydoc CollisionShape::accept
-		void accept(Visitor& v)
+		/// Implements CollisionShape::accept
+		void accept(MutableVisitor& v)
+		{
+			v.visit(*this);
+		}
+		/// Implements CollisionShape::accept
+		void accept(ConstVisitor& v)
 		{
 			v.visit(*this);
 		}
@@ -79,8 +84,11 @@ class Obb: public CollisionShape
 		/// very accurate
 		Obb getCompoundShape(const Obb& b) const;
 
-		/// @see CollisionShape::testPlane
-		float testPlane(const Plane& plane) const;
+		/// Overrides CollisionShape::testPlane
+		float testPlane(const Plane& p) const
+		{
+			return PlaneTests::test(p, *this);
+		}
 
 		/// Calculate from a set of points
 		template<typename Container>

+ 0 - 27
anki/collision/PerspectiveCameraShape.cpp

@@ -44,31 +44,4 @@ PerspectiveCameraShape PerspectiveCameraShape::getTransformed(
 }
 
 
-//==============================================================================
-float PerspectiveCameraShape::testPlane(const Plane& p) const
-{
-	float o = 0.0;
-
-	for(uint i = 0; i < 4; i++)
-	{
-		float t = LineSegment(eye, dirs[i]).testPlane(p);
-
-		if(t == 0)
-		{
-			return 0.0;
-		}
-		else if(t < 0.0)
-		{
-			o = std::max(o, t);
-		}
-		else
-		{
-			o = std::min(o, t);
-		}
-	}
-
-	return o;
-}
-
-
 } // end namespace

+ 25 - 4
anki/collision/PerspectiveCameraShape.h

@@ -27,14 +27,35 @@ class PerspectiveCameraShape: public CollisionShape
 			setAll(fovX, fovY, zNear, zFar, trf);
 		}
 
-		/// @copydoc CollisionShape::accept
-		void accept(Visitor& v)
+		/// @name Accessors
+		/// @{
+		const Vec3& getEye() const
+		{
+			return eye;
+		}
+
+		const boost::array<Vec3, 4>& getDirections() const
+		{
+			return dirs;
+		}
+		/// @{
+
+		/// Implements CollisionShape::accept
+		void accept(MutableVisitor& v)
+		{
+			v.visit(*this);
+		}
+		/// Implements CollisionShape::accept
+		void accept(ConstVisitor& v)
 		{
 			v.visit(*this);
 		}
 
-		/// @copydoc CollisionShape::testPlane
-		float testPlane(const Plane& p) const;
+		/// Overrides CollisionShape::testPlane
+		float testPlane(const Plane& p) const
+		{
+			return PlaneTests::test(p, *this);
+		}
 
 		PerspectiveCameraShape getTransformed(const Transform& trf) const;
 

+ 1 - 1
anki/collision/Plane.cpp

@@ -73,7 +73,7 @@ Plane Plane::getTransformed(const Transform& trf) const
 	Plane plane;
 
 	// the normal
-	plane.normal = trf.getRotation()* normal;
+	plane.normal = trf.getRotation() * normal;
 
 	// the offset
 	Vec3 newTrans = trf.getRotation().getTransposed() * trf.getOrigin();

+ 19 - 4
anki/collision/Plane.h

@@ -73,8 +73,13 @@ class Plane: public CollisionShape
 		}
 		/// @}
 
-		/// @copydoc CollisionShape::accept
-		void accept(Visitor& v)
+		/// Implements CollisionShape::accept
+		void accept(MutableVisitor& v)
+		{
+			v.visit(*this);
+		}
+		/// Implements CollisionShape::accept
+		void accept(ConstVisitor& v)
 		{
 			v.visit(*this);
 		}
@@ -97,8 +102,18 @@ class Plane: public CollisionShape
 			return point - normal * test(point);
 		}
 
-		/// Do nothing
-		float testPlane(const Plane&) const {return 0.0;}
+		/// Overrides CollisionShape::testPlane
+		float testPlane(const Plane& p) const
+		{
+			return PlaneTests::test(p, *this);
+		}
+
+		/// Test a CollisionShape
+		template<typename T>
+		float testShape(const T& x) const
+		{
+			return PlaneTests::test(*this, x);
+		}
 
 	private:
 		/// @name Data

+ 231 - 0
anki/collision/PlaneTests.cpp

@@ -0,0 +1,231 @@
+#include "anki/collision/PlaneTests.h"
+#include "anki/collision/Collision.h"
+
+
+namespace anki {
+
+
+//==============================================================================
+float PlaneTests::test(const Plane& p, const CollisionShape& cs)
+{
+	float t;
+	switch(cs.getCollisionShapeType())
+	{
+		case CollisionShape::CST_LINE_SEG:
+			t = test(p, static_cast<const LineSegment&>(cs));
+			break;
+		case CollisionShape::CST_RAY:
+			t = test(p, static_cast<const Ray&>(cs));
+			break;
+		case CollisionShape::CST_PLANE:
+			t = test(p, static_cast<const Plane&>(cs));
+			break;
+		case CollisionShape::CST_SPHERE:
+			t = test(p, static_cast<const Sphere&>(cs));
+			break;
+		case CollisionShape::CST_AABB:
+			t = test(p, static_cast<const Aabb&>(cs));
+			break;
+		case CollisionShape::CST_OBB:
+			t = test(p, static_cast<const Obb&>(cs));
+			break;
+		case CollisionShape::CST_PERSPECTIVE_CAMERA_FRUSTRUM:
+			t = test(p, static_cast<const PerspectiveCameraShape&>(cs));
+			break;
+		default:
+			ASSERT(0 && "Forgot something");
+	}
+	return t;
+}
+
+
+//==============================================================================
+float PlaneTests::test(const Plane& p, const LineSegment& ls)
+{
+	const Vec3& p0 = ls.getOrigin();
+	Vec3 p1 = ls.getOrigin() + ls.getDirection();
+
+	float dist0 = p.test(p0);
+	float dist1 = p.test(p1);
+
+	if(dist0 > 0.0)
+	{
+		if(dist1 > 0.0)
+		{
+			return std::min(dist0, dist1);
+		}
+		else
+		{
+			return 0.0;
+		}
+	}
+	else
+	{
+		if(dist1 < 0.0)
+		{
+			return std::max(dist0, dist1);
+		}
+		else
+		{
+			return 0.0;
+		}
+	}
+}
+
+
+//==============================================================================
+float PlaneTests::test(const Plane& p, const Obb& obb)
+{
+	Vec3 xNormal = obb.getRotation().getTransposed() * p.getNormal();
+
+	// maximum extent in direction of plane normal
+	float r = fabs(obb.getExtend().x() * xNormal.x()) +
+		fabs(obb.getExtend().y() * xNormal.y()) +
+		fabs(obb.getExtend().z() * xNormal.z());
+	// signed distance between box center and plane
+	float d = p.test(obb.getCenter());
+
+	// return signed distance
+	if(fabs(d) < r)
+	{
+		return 0.0;
+	}
+	else if(d < 0.0)
+	{
+		return d + r;
+	}
+	else
+	{
+		return d - r;
+	}
+}
+
+
+//==============================================================================
+float PlaneTests::test(const Plane& p, const PerspectiveCameraShape& pcs)
+{
+	float o = 0.0;
+
+	for(uint i = 0; i < 4; i++)
+	{
+		LineSegment ls(pcs.getEye(), pcs.getDirections()[i]);
+		float t = test(p, ls);
+
+		if(t == 0)
+		{
+			return 0.0;
+		}
+		else if(t < 0.0)
+		{
+			o = std::max(o, t);
+		}
+		else
+		{
+			o = std::min(o, t);
+		}
+	}
+
+	return o;
+}
+
+
+//==============================================================================
+float PlaneTests::test(const Plane& /*p*/, const Plane& /*p1*/)
+{
+	ASSERT(0 && "Ambiguous call");
+	return 0.0;
+}
+
+
+//==============================================================================
+float PlaneTests::test(const Plane& p, const Ray& r)
+{
+	float dist = p.test(r.getOrigin());
+	float cos_ = p.getNormal().dot(r.getDirection());
+
+	if(cos_ > 0.0) // the ray points to the same half-space as the plane
+	{
+		if(dist < 0.0) // the ray's origin is behind the plane
+		{
+			return 0.0;
+		}
+		else
+		{
+			return dist;
+		}
+	}
+	else
+	{
+		if(dist > 0.0)
+		{
+			return 0.0;
+		}
+		else
+		{
+			return dist;
+		}
+	}
+}
+
+
+//==============================================================================
+float PlaneTests::test(const Plane& p, const Sphere& s)
+{
+	float dist = p.test(s.getCenter());
+
+	if(dist > s.getRadius())
+	{
+		return dist - s.getRadius();
+	}
+	else if(-dist > s.getRadius())
+	{
+		return dist + s.getRadius();
+	}
+	else
+	{
+		return 0.0;
+	}
+}
+
+
+//==============================================================================
+float PlaneTests::test(const Plane& p, const Aabb& aabb)
+{
+	Vec3 diagMin, diagMax;
+	// set min/max values for x,y,z direction
+	for(int i = 0; i < 3; i++)
+	{
+		if(p.getNormal()[i] >= 0.0)
+		{
+			diagMin[i] = aabb.getMin()[i];
+			diagMax[i] = aabb.getMax()[i];
+		}
+		else
+		{
+			diagMin[i] = aabb.getMax()[i];
+			diagMax[i] = aabb.getMin()[i];
+		}
+	}
+
+	// minimum on positive side of plane, box on positive side
+	float test = p.test(diagMin);
+	if(test > 0.0)
+	{
+		return test;
+	}
+
+	test = p.test(diagMax);
+	// min on non-positive side, max on non-negative side, intersection
+	if(test >= 0.0)
+	{
+		return 0.0;
+	}
+	// max on negative side, box on negative side
+	else
+	{
+		return test;
+	}
+}
+
+
+} // end namespace

+ 39 - 0
anki/collision/PlaneTests.h

@@ -0,0 +1,39 @@
+#ifndef ANKI_COLLISION_PLANE_TESTS_H
+#define ANKI_COLLISION_PLANE_TESTS_H
+
+#include "anki/collision/Forward.h"
+
+
+namespace anki {
+
+
+/// @addtogroup Collision
+/// @{
+///
+/// Contains methods for testing the position between a collision shape and a
+/// plane.
+///
+/// If the collision shape intersects with the plane then the method returns
+/// 0.0, else it returns the distance. If the distance is < 0.0 then the
+/// collision shape lies behind the plane and if > 0.0 then in front of it
+class PlaneTests
+{
+	public:
+		/// Generic method. It doesn't use visitor pattern for speed reasons
+		static float test(const Plane& p, const CollisionShape& cs);
+
+		static float test(const Plane& p, const LineSegment& ls);
+		static float test(const Plane& p, const Obb& obb);
+		static float test(const Plane& p, const PerspectiveCameraShape& pcs);
+		static float test(const Plane& p, const Plane& p1);
+		static float test(const Plane& p, const Ray& r);
+		static float test(const Plane& p, const Sphere& s);
+		static float test(const Plane& p, const Aabb& aabb);
+};
+/// @}
+
+
+} // end namespace
+
+
+#endif

+ 0 - 33
anki/collision/Ray.cpp

@@ -17,37 +17,4 @@ Ray Ray::getTransformed(const Transform& transform) const
 }
 
 
-//==============================================================================
-// testPlane                                                                   =
-//==============================================================================
-float Ray::testPlane(const Plane& plane) const
-{
-	float dist = plane.test(origin);
-	float cos_ = plane.getNormal().dot(dir);
-
-	if(cos_ > 0.0) // the ray points to the same half-space as the plane
-	{
-		if(dist < 0.0) // the ray's origin is behind the plane
-		{
-			return 0.0;
-		}
-		else
-		{
-			return dist;
-		}
-	}
-	else
-	{
-		if(dist > 0.0)
-		{
-			return 0.0;
-		}
-		else
-		{
-			return dist;
-		}
-	}
-}
-
-
 } // end namespace

+ 12 - 5
anki/collision/Ray.h

@@ -59,17 +59,24 @@ class Ray: public CollisionShape
 		}
 		/// @}
 
-		/// @copydoc CollisionShape::accept
-		void accept(Visitor& v)
+		/// Implements CollisionShape::accept
+		void accept(MutableVisitor& v)
+		{
+			v.visit(*this);
+		}
+		/// Implements CollisionShape::accept
+		void accept(ConstVisitor& v)
 		{
 			v.visit(*this);
 		}
 
 		Ray getTransformed(const Transform& transform) const;
 
-		/// Implements CollisionShape::testPlane
-		/// @see CollisionShape::testPlane
-		float testPlane(const Plane& plane) const;
+		/// Overrides CollisionShape::testPlane
+		float testPlane(const Plane& p) const
+		{
+			return PlaneTests::test(p, *this);
+		}
 
 	private:
 		Vec3 origin;

+ 0 - 22
anki/collision/Sphere.cpp

@@ -74,26 +74,4 @@ Sphere Sphere::getCompoundShape(const Sphere& b) const
 }
 
 
-//==============================================================================
-// testPlane                                                                   =
-//==============================================================================
-float Sphere::testPlane(const Plane& plane) const
-{
-	float dist = plane.test(center);
-
-	if(dist > radius)
-	{
-		return dist - radius;
-	}
-	else if(-dist > radius)
-	{
-		return dist + radius;
-	}
-	else
-	{
-		return 0.0;
-	}
-}
-
-
 } // end namespace

+ 12 - 4
anki/collision/Sphere.h

@@ -59,8 +59,13 @@ class Sphere: public CollisionShape
 		}
 		/// @}
 
-		/// @copydoc CollisionShape::accept
-		void accept(Visitor& v)
+		/// Implements CollisionShape::accept
+		void accept(MutableVisitor& v)
+		{
+			v.visit(*this);
+		}
+		/// Implements CollisionShape::accept
+		void accept(ConstVisitor& v)
 		{
 			v.visit(*this);
 		}
@@ -71,8 +76,11 @@ class Sphere: public CollisionShape
 		/// drawing in the docs dir for more info about the algorithm
 		Sphere getCompoundShape(const Sphere& b) const;
 
-		/// @see CollisionShape::testPlane
-		float testPlane(const Plane& plane) const;
+		/// Overrides CollisionShape::testPlane
+		float testPlane(const Plane& p) const
+		{
+			return PlaneTests::test(p, *this);
+		}
 
 		/// Calculate from a set of points
 		template<typename Container>