浏览代码

Same as before

Panagiotis Christopoulos Charitos 14 年之前
父节点
当前提交
15f74cce79
共有 2 个文件被更改,包括 215 次插入121 次删除
  1. 87 69
      anki/collision/Frustum.cpp
  2. 128 52
      anki/collision/Frustum.h

+ 87 - 69
anki/collision/Frustum.cpp

@@ -6,78 +6,83 @@
 namespace anki {
 
 
+//==============================================================================
+// Frustum                                                                     =
+//==============================================================================
+
 //==============================================================================
 Frustum& Frustum::operator=(const Frustum& b)
 {
-	type = b.type;
 	planes = b.planes;
-
-	eye = b.eye;
-	dirs = b.dirs;
-
-	obb = b.obb;
+	zNear = b.zNear;
+	zFar = b.zFar;
 	return *this;
 }
 
 
 //==============================================================================
-float Frustum::testPlane(const Plane& p) const
+bool Frustum::insideFrustum(const CollisionShape& b) const
 {
-	if(type == FT_ORTHOGRAPHIC)
-	{
-		return obb.testPlane(p);
-	}
-	else
+	BOOST_FOREACH(const Plane& plane, planes)
 	{
-		float o = 0.0;
-
-		BOOST_FOREACH(const Vec3& dir, dirs)
+		if(b.testPlane(plane) < 0.0)
 		{
-			LineSegment ls(eye, dir);
-			float t = ls.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 false;
 		}
-
-		return o;
 	}
+
+	return true;
 }
 
 
 //==============================================================================
-Frustum Frustum::getTransformed(const Transform& trf) const
+void Frustum::transform(const Transform& trf)
 {
-	Frustum o;
-
 	// Planes
 	for(uint i = 0; i < planes.size(); ++i)
 	{
-		o.planes[i] = planes[i].getTransformed(trf);
+		planes[i].transform(trf);
 	}
+}
 
-	// Other
-	if(type == FT_ORTHOGRAPHIC)
-	{
-		o.obb = obb.getTransformed(trf);
-	}
-	else
+
+//==============================================================================
+// PerspectiveFrustum                                                          =
+//==============================================================================
+
+//==============================================================================
+PerspectiveFrustum& PerspectiveFrustum::operator=(const PerspectiveFrustum& b)
+{
+	Frustum::operator=(*this);
+	eye = b.eye;
+	dirs = b.dirs;
+	fovX = b.fovX;
+	fovY = b.fovY;
+	return *this;
+}
+
+
+//==============================================================================
+float PerspectiveFrustum::testPlane(const Plane& p) const
+{
+	float o = 0.0;
+
+	BOOST_FOREACH(const Vec3& dir, dirs)
 	{
-		o.eye = eye.getTransformed(trf);
+		LineSegment ls(eye, dir);
+		float t = ls.testPlane(p);
 
-		for(uint i = 0; i < dirs.size(); i++)
+		if(t == 0)
+		{
+			return 0.0;
+		}
+		else if(t < 0.0)
+		{
+			o = std::max(o, t);
+		}
+		else
 		{
-			o.dirs[i] = trf.getRotation() * dirs[i];
+			o = std::min(o, t);
 		}
 	}
 
@@ -86,11 +91,45 @@ Frustum Frustum::getTransformed(const Transform& trf) const
 
 
 //==============================================================================
-void Frustum::setPerspective(float fovX, float fovY,
-	float zNear, float zFar, const Transform& trf)
+void PerspectiveFrustum::transform(const Transform& trf)
 {
-	type = FT_PERSPECTIVE;
+	Frustum::transform(trf);
 
+	eye.transform(trf);
+
+	for(uint i = 0; i < dirs.size(); i++)
+	{
+		dirs[i] = trf.getRotation() * dirs[i];
+	}
+}
+
+
+//==============================================================================
+void PerspectiveFrustum::recalculate()
+{
+	// Planes
+	//
+	float c, s; // cos & sine
+
+	Math::sinCos(Math::PI + fovX / 2, s, c);
+	// right
+	planes[FP_RIGHT] = Plane(Vec3(c, 0.0, s), 0.0);
+	// left
+	planes[FP_LEFT] = Plane(Vec3(-c, 0.0, s), 0.0);
+
+	Math::sinCos((3 * Math::PI - fovY) * 0.5, s, c);
+	// top
+	planes[FP_TOP] = Plane(Vec3(0.0, s, c), 0.0);
+	// bottom
+	planes[FP_BOTTOM] = Plane(Vec3(0.0, -s, c), 0.0);
+
+	// near
+	planes[FP_NEAR] = Plane(Vec3(0.0, 0.0, -1.0), zNear);
+	// far
+	planes[FP_FAR] = Plane(Vec3(0.0, 0.0, 1.0), -zFar);
+
+	// Rest
+	//
 	eye = Vec3(0.0, 0.0, -zNear);
 
 	float x = zFar / tan((Math::PI - fovX) / 2.0);
@@ -101,27 +140,6 @@ void Frustum::setPerspective(float fovX, float fovY,
 	dirs[1] = Vec3(-x, y, z - zNear); // top left
 	dirs[2] = Vec3(-x, -y, z - zNear); // bottom left
 	dirs[3] = Vec3(x, -y, z - zNear); // bottom right
-
-	eye.transform(trf);
-	BOOST_FOREACH(Vec3& dir, dirs)
-	{
-		dir = trf.getRotation() * dir;
-	}
-}
-
-
-//==============================================================================
-bool Frustum::insideFrustum(const CollisionShape& b) const
-{
-	BOOST_FOREACH(const Plane& plane, planes)
-	{
-		if(b.testPlane(plane) < 0.0)
-		{
-			return false;
-		}
-	}
-
-	return true;
 }
 
 

+ 128 - 52
anki/collision/Frustum.h

@@ -40,90 +40,166 @@ public:
 		FP_COUNT
 	};
 
-	/// @name Constructors
-	/// @{
-	Frustum()
-		: CollisionShape(CST_FRUSTUM), type(FT_ORTHOGRAPHIC)
+	Frustum(FrustumType type_)
+		: CollisionShape(CST_FRUSTUM), type(type_)
 	{}
 
-	Frustum(const Frustum& b)
-		: CollisionShape(CST_FRUSTUM)
+	/// Copy
+	Frustum& operator=(const Frustum& b);
+
+	/// Implements CollisionShape::transform
+	void transform(const Transform& trf);
+
+	/// Implements CollisionShape::accept
+	void accept(MutableVisitor& v)
 	{
-		*this = b;
+		v.visit(*this);
 	}
+	/// Implements CollisionShape::accept
+	void accept(ConstVisitor& v) const
+	{
+		v.visit(*this);
+	}
+
+	/// Check if a collision shape is inside the frustum
+	bool insideFrustum(const CollisionShape& b) const;
+
+protected:
+	boost::array<Plane, FP_COUNT> planes;
+	float zNear, zFar;
 
-	Frustum(float fovX, float fovY, float zNear,
-		float zFar, const Transform& trf)
-		: CollisionShape(CST_FRUSTUM)
+	/// Called when a viewing variable changes. It recalculates the planes and
+	/// the other variables
+	virtual void recalculate() = 0;
+
+private:
+	FrustumType type;
+};
+
+
+/// XXX
+class PerspectiveFrustum: public Frustum
+{
+public:
+	PerspectiveFrustum()
+		: Frustum(FT_PERSPECTIVE)
+	{}
+
+	/// @name Accessors
+	/// @{
+	float getFovX() const
+	{
+		return fovX;
+	}
+	void setFovX(float ang)
+	{
+		fovX = ang;
+		recalculate();
+	}
+
+	float getFovY() const
+	{
+		return fovY;
+	}
+	void setFovY(float ang)
 	{
-		setPerspective(fovX, fovY, zNear, zFar, trf);
+		fovY = ang;
+		recalculate();
 	}
 
-	Frustum(float left, float right, float near,
-		float far, float top, float buttom, const Transform& trf)
-		: CollisionShape(CST_FRUSTUM)
+	void setAll(float fovX_, float fovY_, float zNear_, float zFar_)
 	{
-		setOrthographic(left, right, near, far, top, buttom, trf);
+		fovX = fovX_;
+		fovY = fovY_,
+		zNear = zNear_;
+		zFar = zFar_;
+		recalculate();
 	}
 	/// @}
 
 	/// Copy
-	Frustum& operator=(const Frustum& b);
+	PerspectiveFrustum& operator=(const PerspectiveFrustum& b);
 
 	/// Implements CollisionShape::testPlane
 	float testPlane(const Plane& p) const;
 
-	/// Implements CollisionShape::transform
-	void transform(const Transform& trf)
-	{
-		*this = getTransformed(trf);
-	}
+	/// Re-implements Frustum::transform
+	void transform(const Transform& trf);
 
-	Frustum getTransformed(const Transform& trf) const;
+private:
+	Vec3 eye; ///< The eye point
+	boost::array<Vec3, 4> dirs; ///< Directions
+	float fovX;
+	float fovY;
 
-	/// Implements CollisionShape::accept
-	void accept(MutableVisitor& v)
+	/// Implements CollisionShape::recalculate
+	void recalculate();
+};
+
+
+/// XXX
+class OrthographicFrustum: public Frustum
+{
+public:
+
+	/// @name Accessors
+	/// @{
+	float getLeft() const
 	{
-		v.visit(*this);
+		return left;
 	}
-	/// Implements CollisionShape::accept
-	void accept(ConstVisitor& v) const
+	void setLeft(float f)
 	{
-		v.visit(*this);
+		left = f;
+		recalculate();
 	}
 
-	/// Set all for perspective camera
-	void setPerspective(float fovX, float fovY, float zNear,
-		float zFar, const Transform& trf);
-
-	/// Set all for orthographic camera
-	void setOrthographic(float left, float right, float near,
-		float far, float top, float buttom, const Transform& trf)
+	float getRight() const
 	{
-		type = FT_ORTHOGRAPHIC;
-		/// XXX
+		return right;
+	}
+	void setRight(float f)
+	{
+		right = f;
+		recalculate();
 	}
 
-	/// Check if a collision shape is inside the frustum
-	bool insideFrustum(const CollisionShape& b) const;
-
-private:
-	FrustumType type;
+	float getTop() const
+	{
+		return top;
+	}
+	void setTop(float f)
+	{
+		top = f;
+		recalculate();
+	}
 
-	boost::array<Plane, FP_COUNT> planes;
+	float getBottom() const
+	{
+		return bottom;
+	}
+	void setBottom(float f)
+	{
+		bottom = f;
+		recalculate();
+	}
 
-	/// @name Including shape for perspective cameras
-	/// @{
-	Vec3 eye; ///< The eye point
-	boost::array<Vec3, 4> dirs; ///< Directions
-	float fovX, fovY, zNear, zFar;
+	void setAll(float left_, float right_, float zNear_,
+		float zFar_, float top_, float bottom_)
+	{
+		left = left_;
+		right = right_;
+		zNear = zNear_;
+		zFar = zFar_;
+		top = top_;
+		bottom = bottom_;
+		recalculate();
+	}
 	/// @}
 
-	/// @name Including shape for orthographic cameras
-	/// @{
+private:
 	Obb obb;
-	float left, right, near, far, top, bottom;
-	/// @}
+	float left, right, top, bottom;
 };
 /// @}