changeset 646:07b1cf8e92b5

* Major improvements to fife_math.h and added corresponding Python bindings. Users now have access to FIFE's internal math functions. These functions are recommended to be used by all clients if required. Note: this may cause some problems with certain compilers. I hope this wont have to be reverted. TODO: remove the static constant globals somehow. * Adopted the new math functions for all subsystems * Improvements to DeviceCaps. It now detects all possible screen modes. * User can now select 0 for their bpp and it will attempt to initialize SDL with the current screen bpp.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Wed, 13 Oct 2010 20:24:48 +0000
parents 291ba2946c73
children f2b3512d0e60
files engine/core/controller/engine.cpp engine/core/model/metamodel/grids/hexgrid.cpp engine/core/util/math/angles.h engine/core/util/math/fife_math.h engine/core/util/math/math.i engine/core/util/math/matrix.h engine/core/util/structures/point.h engine/core/video/devicecaps.cpp engine/core/video/devicecaps.h engine/core/view/camera.cpp
diffstat 10 files changed, 323 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/engine/core/controller/engine.cpp	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/controller/engine.cpp	Wed Oct 13 20:24:48 2010 +0000
@@ -210,7 +210,7 @@
 		m_screenMode = m_devcaps.getNearestScreenMode(
 			m_settings.getScreenWidth(),
 			m_settings.getScreenHeight(),
-			(bpp ? bpp : 32) , //if it's 0 we use 32 bit as a default
+			bpp,
 			rbackend,
 			m_settings.isFullScreen());
 
@@ -309,11 +309,11 @@
 
 		TTF_Quit();
 		SDL_Quit();
-		
+
 #ifdef USE_COCOA
 		objc_msgSend(m_autoreleasePool, sel_registerName("release"));
 #endif
-		
+
 		FL_LOG(_log, "================== Engine destructed ==================");
 		m_destroyed = true;
 		//delete m_logmanager;
--- a/engine/core/model/metamodel/grids/hexgrid.cpp	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/model/metamodel/grids/hexgrid.cpp	Wed Oct 13 20:24:48 2010 +0000
@@ -38,8 +38,8 @@
 
 	static const double HEX_WIDTH = 1;
 	static const double HEX_TO_EDGE = HEX_WIDTH / 2;
-	static const double HEX_TO_CORNER = 0.5 / cos(DBL_PI / 6);
-	static const double HEX_EDGE_HALF = HEX_TO_CORNER * sin(DBL_PI / 6);
+	static const double HEX_TO_CORNER = 0.5 / Mathd::Cos(Mathd::pi() / 6);
+	static const double HEX_EDGE_HALF = HEX_TO_CORNER * Mathd::Sin(Mathd::pi() / 6);
 	static const double VERTICAL_MULTIP = sqrt(HEX_WIDTH*HEX_WIDTH - HEX_TO_EDGE*HEX_TO_EDGE);
 	static const double VERTICAL_MULTIP_INV = 1 / VERTICAL_MULTIP;
 
--- a/engine/core/util/math/angles.h	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/util/math/angles.h	Wed Oct 13 20:24:48 2010 +0000
@@ -52,7 +52,7 @@
 		double dy = (c2.y - c1.y);
 		double dx = (c2.x - c1.x);
 
-		int angle = static_cast<int>(atan2(-dy,dx)*(180.0/DBL_PI));
+		int angle = static_cast<int>(Mathd::ATan2(-dy,dx)*(180.0/Mathd::pi()));
 
 		return angle;
 	}
--- a/engine/core/util/math/fife_math.h	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/util/math/fife_math.h	Wed Oct 13 20:24:48 2010 +0000
@@ -23,7 +23,9 @@
 #define FIFE_UTIL_FIFE_MATH_H
 
 // Standard C++ library includes
+#include <cassert>
 #include <cmath>
+#include <limits>
 
 // Platform specific includes
 
@@ -48,6 +50,8 @@
 
 namespace FIFE {
 
+	static const float FLT_STD_EPSILON = std::numeric_limits<float>::epsilon();
+	static const float FLT_STD_MAX = std::numeric_limits<float>::max();
 	static const float FLT_ZERO_TOLERANCE = 1e-06f;
 	static const float FLT_PI = 4.0f*std::atan(1.0f);
 	static const float FLT_TWO_PI = 2.0f*FLT_PI;
@@ -61,19 +65,224 @@
 	static const float FLT_INV_LOG_2 = 1.0f/std::log(2.0f);
 	static const float FLT_INV_LOG_10 = 1.0f/std::log(10.0f);
 
+	static const double DBL_STD_EPSILON = std::numeric_limits<double>::epsilon();
+	static const double DBL_STD_MAX = std::numeric_limits<double>::max();
 	static const double DBL_ZERO_TOLERANCE = 1e-08;
-	static const double DBL_PI = 4.0*std::atan(1.0f);
+	static const double DBL_PI = 4.0*std::atan(1.0);
 	static const double DBL_TWO_PI = 2.0*DBL_PI;
 	static const double DBL_HALF_PI = 0.5*DBL_PI;
 	static const double DBL_INVERSE_PI = 1.0/DBL_PI;
 	static const double DBL_INVERSE_TWO_PI = 1.0/DBL_TWO_PI;
 	static const double DBL_DEG_TO_RAD = DBL_PI/180.0;
-	static const double DBL_RAD_TO_DEG = 180.0/DBL_PI;
-	static const double DBL_LOG_2 = std::log(2.0f);
-	static const double DBL_LOG_10 = std::log(10.0f);
-	static const double DBL_INV_LOG_2 = 1.0/std::log(2.0f);
-	static const double DBL_INV_LOG_10 = 1.0/std::log(10.0f);
+	static const double DBL_RAD_TO_DEG = 180.0f/DBL_PI;
+	static const double DBL_LOG_2 = std::log(2.0);
+	static const double DBL_LOG_10 = std::log(10.0);
+	static const double DBL_INV_LOG_2 = 1.0/std::log(2.0);
+	static const double DBL_INV_LOG_10 = 1.0/std::log(10.0);
+
+	template <class numT>
+	struct float_traits { };
+
+	template <>
+	struct float_traits<float> {
+		typedef float float_type;
+		static inline float_type epsilon() { return FLT_STD_EPSILON; }
+		static inline float_type zeroTolerance() { return FLT_ZERO_TOLERANCE; }
+		static inline float_type max() { return FLT_STD_MAX; }
+		static inline float_type pi() { return FLT_PI; }
+		static inline float_type twoPi() { return FLT_TWO_PI; }
+		static inline float_type halfPi() { return FLT_HALF_PI; }
+		static inline float_type inversePi() { return FLT_INVERSE_PI; }
+		static inline float_type inverseTwoPi() { return FLT_INVERSE_TWO_PI; }
+		static inline float_type degToRad() { return FLT_DEG_TO_RAD; }
+		static inline float_type radToDeg() { return FLT_RAD_TO_DEG; }
+		static inline float_type log2() { return FLT_LOG_2; }
+		static inline float_type log10() { return FLT_LOG_10; }
+		static inline float_type invLog2() { return FLT_INV_LOG_2; }
+		static inline float_type invLog10() { return FLT_INV_LOG_10; }
+	};
+
+	template <>
+	struct float_traits<double> {
+		typedef double float_type;
+		static inline float_type epsilon() { return DBL_STD_EPSILON; }
+		static inline float_type zeroTolerance() { return DBL_ZERO_TOLERANCE; }
+		static inline float_type max() { return DBL_STD_MAX; }
+		static inline float_type pi() { return DBL_PI; }
+		static inline float_type twoPi() { return DBL_TWO_PI; }
+		static inline float_type halfPi() { return DBL_HALF_PI; }
+		static inline float_type inversePi() { return DBL_INVERSE_PI; }
+		static inline float_type inverseTwoPi() { return DBL_INVERSE_TWO_PI; }
+		static inline float_type degToRad() { return DBL_DEG_TO_RAD; }
+		static inline float_type radToDeg() { return DBL_RAD_TO_DEG; }
+		static inline float_type log2() { return DBL_LOG_2; }
+		static inline float_type log10() { return DBL_LOG_10; }
+		static inline float_type invLog2() { return DBL_INV_LOG_2; }
+		static inline float_type invLog10() { return DBL_INV_LOG_10; }
+	};
+
+	template <typename T>
+	class Math {
+	public:
+		typedef T num_type;
+		typedef float_traits<num_type> traits_type;
+
+		static inline num_type epsilon() { return traits_type::epsilon(); }
+		static inline num_type zeroTolerance() { return traits_type::zeroTolerance(); }
+		static inline num_type max() { return traits_type::max(); }
+		static inline num_type pi() { return traits_type::pi(); }
+		static inline num_type twoPi() { return traits_type::twoPi(); }
+		static inline num_type halfPi() { return traits_type::halfPi(); }
+		static inline num_type inversePi() { return traits_type::inversePi(); }
+		static inline num_type inverseTwoPi() { return traits_type::inverseTwoPi(); }
+		static inline num_type degToRad() { return traits_type::degToRad(); }
+		static inline num_type radToDeg() { return traits_type::radToDeg(); }
+		static inline num_type log2() { return traits_type::log2(); }
+		static inline num_type log10() { return traits_type::log10(); }
+		static inline num_type invLog2() { return traits_type::invLog2(); }
+		static inline num_type invLog10() { return traits_type::invLog10(); }
+
+		static T ACos(T _val);
+		static T ASin(T _val);
+		static T ATan(T _val);
+		static T ATan2(T _x, T _y);
+		static T Ceil(T _val);
+		static T Cos(T _val);
+		static T Exp(T _val);
+		static T FAbs(T _val);
+		static T Floor(T _val);
+		static T FMod (T _x, T _y);
+		static T InvSqrt(T _val);
+		static T Log(T _val);
+		static T Log2(T _val);
+		static T Log10(T _val);
+		static T Pow(T _base, T _exponent);
+		static T Sin(T _val);
+		static T Sqr(T _val);
+		static T Sqrt(T _val);
+		static T Tan(T _val);
+	};
+
+	typedef Math<float> Mathf;
+	typedef Math<double> Mathd;
 
+	template<typename T>
+	inline T Math<T>::ACos(T _val) {
+		if (-static_cast<T>(1) < _val) {
+			if (_val < static_cast<T>(1)) {
+				return static_cast<T>(std::acos(_val));
+			}
+			else {
+				return static_cast<T>(0);
+			}
+		}
+		else {
+			return pi();
+		}
+	}
+
+	template <class T>
+	inline T Math<T>::ASin(T _val) {
+		if (-static_cast<T>(1) < _val) {
+			if (_val < static_cast<T>(1)) {
+				return static_cast<T>(std::asin(_val));
+			}
+			else {
+				return halfPi();
+			}
+		}
+		else {
+			return -halfPi();
+		}
+	}
+
+	template <class T>
+	inline T Math<T>::ATan(T _val) {
+		return static_cast<T>(std::atan(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::ATan2(T _x, T _y) {
+		return static_cast<T>(std::atan2(_x, _y));
+	}
+
+	template <class T>
+	inline T Math<T>::Ceil(T _val) {
+		return static_cast<T>(std::ceil(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::Cos(T _val) {
+		return static_cast<T>(std::cos(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::Exp(T _val){
+		return static_cast<T>(std::exp(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::FAbs(T _val) {
+		return static_cast<T>(std::fabs(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::Floor(T _val) {
+		return static_cast<T>(std::floor(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::FMod(T _x, T _y) {
+		return static_cast<T>(std::fmod(_x, _y));
+	}
+
+	template <class T>
+	inline T Math<T>::InvSqrt(T _val) {
+		return static_cast<T>(1/std::sqrt(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::Log(T _val) {
+		return static_cast<T>(std::log(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::Log2(T _val) {
+		return invLog2() * static_cast<T>(std::log(_val));
+	}
+	template <class T>
+	inline T Math<T>::Log10(T _val) {
+
+		return invLog10() * static_cast<T>(std::log(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::Pow(T _base, T _exponent) {
+		return static_cast<T>(std::pow(_base, _exponent));
+	}
+
+	template <class T>
+	inline T Math<T>::Sin(T _val) {
+		return static_cast<T>(std::sin(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::Sqr(T _val) {
+		return _val*_val;
+	}
+
+	template <class T>
+	inline T Math<T>::Sqrt(T _val) {
+		return static_cast<T>(std::sqrt(_val));
+	}
+
+	template <class T>
+	inline T Math<T>::Tan(T _val) {
+		return static_cast<T>(std::tan(_val));
+	}
+
+	/** Returns the next higher power of 2 based on the passed argument
+	 */
 	inline unsigned nextPow2(unsigned x)
 	{
 		--x;
--- a/engine/core/util/math/math.i	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/util/math/math.i	Wed Oct 13 20:24:48 2010 +0000
@@ -26,30 +26,55 @@
 
 namespace FIFE {
 
-	static const float FLT_ZERO_TOLERANCE;
-	static const float FLT_PI;
-	static const float FLT_TWO_PI;
-	static const float FLT_HALF_PI;
-	static const float FLT_INVERSE_PI;
-	static const float FLT_INVERSE_TWO_PI;
-	static const float FLT_DEG_TO_RAD;
-	static const float FLT_RAD_TO_DEG;
-	static const float FLT_LOG_2;
-	static const float FLT_LOG_10;
-	static const float FLT_INV_LOG_2;
-	static const float FLT_INV_LOG_10;
+	template <class numT>
+	struct float_traits { };
+
+	template <typename T>
+	class Math {
+	public:
+		typedef T num_type;
+		typedef float_traits<num_type> traits_type;
+
+		static inline num_type epsilon();
+		static inline num_type zeroTolerance();
+		static inline num_type max();
+		static inline num_type pi();
+		static inline num_type twoPi();
+		static inline num_type halfPi();
+		static inline num_type inversePi();
+		static inline num_type inverseTwoPi();
+		static inline num_type degToRad();
+		static inline num_type radToDeg();
+		static inline num_type log2();
+		static inline num_type log10();
+		static inline num_type invLog2();
+		static inline num_type invLog10();
 
-	static const double DBL_ZERO_TOLERANCE;
-	static const double DBL_PI;
-	static const double DBL_TWO_PI;
-	static const double DBL_HALF_PI;
-	static const double DBL_INVERSE_PI;
-	static const double DBL_INVERSE_TWO_PI;
-	static const double DBL_DEG_TO_RAD;
-	static const double DBL_RAD_TO_DEG;
-	static const double DBL_LOG_2;
-	static const double DBL_LOG_10;
-	static const double DBL_INV_LOG_2;
-	static const double DBL_INV_LOG_10;
+		static T ACos(T _val);
+		static T ASin(T _val);
+		static T ATan(T _val);
+		static T ATan2(T _x, T _y);
+		static T Ceil(T _val);
+		static T Cos(T _val);
+		static T Exp(T _val);
+		static T FAbs(T _val);
+		static T Floor(T _val);
+		static T FMod (T _x, T _y);
+		static T InvSqrt(T _val);
+		static T Log(T _val);
+		static T Log2(T _val);
+		static T Log10(T _val);
+		static T Pow(T _base, T _exponent);
+		static T Sin(T _val);
+		static T Sqr(T _val);
+		static T Sqrt(T _val);
+		static T Tan(T _val);
+	};
+
+	typedef Math<float> Mathf;
+	typedef Math<double> Mathd;
+	
+	%template(Mathf) Math<float>;
+	%template(Mathd) Math<double>;
 
 }
--- a/engine/core/util/math/matrix.h	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/util/math/matrix.h	Wed Oct 13 20:24:48 2010 +0000
@@ -118,8 +118,8 @@
 					y/=mag;
 					z/=mag;
 				}
-				T c = cos(angle*DBL_PI/180);
-				T s = sin(angle*DBL_PI/180);
+				T c = Math<T>::Cos(angle*Math<T>::pi()/180);
+				T s = Math<T>::Sin(angle*Math<T>::pi()/180);
 				m0 = x*x*(1-c)+c;
 				m1 = y*x*(1-c)+z*s;
 				m2 = z*x*(1-c)-y*s;
--- a/engine/core/util/structures/point.h	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/util/structures/point.h	Wed Oct 13 20:24:48 2010 +0000
@@ -131,7 +131,7 @@
 			T invLength = 1.0/length();
 
 			//TODO: get rid of this static cast
-			if (invLength > static_cast<T>(DBL_ZERO_TOLERANCE)) {
+			if (invLength > static_cast<T>(Mathd::zeroTolerance())) {
 				x = x * invLength;
 				y = y * invLength;
 			}
@@ -145,9 +145,9 @@
 		 */
 		void rotate(T angle){
 			//TODO: get rid of this static cast
-			T theta = (angle * static_cast<T>(DBL_PI))/180;
-			T costheta = cos(theta);
-			T sintheta = sin(theta);
+			T theta = (angle * static_cast<T>(Mathd::pi()))/180;
+			T costheta = static_cast<T>(Mathd::Cos(theta));
+			T sintheta = static_cast<T>(Mathd::Sin(theta));
 
 			T nx = x;
 			T ny = y;
@@ -160,9 +160,9 @@
 		 */
 		void rotate(const PointType2D<T>& origin, T angle){
 			//TODO: get rid of this static cast
-			T theta = (angle * static_cast<T>(DBL_PI))/180;
-			T costheta = cos(theta);
-			T sintheta = sin(theta);
+			T theta = (angle * static_cast<T>(Mathd::pi()))/180;
+			T costheta = static_cast<T>(Mathd::Cos(theta));
+			T sintheta = static_cast<T>(Mathd::Sin(theta));
 
 			T nx = x - origin.x;
 			T ny = y - origin.y;
@@ -281,7 +281,7 @@
 			T invLength = 1.0/length();
 
 			//TODO: get rid of this static cast
-			if (invLength > static_cast<T>(DBL_ZERO_TOLERANCE)) {
+			if (invLength > static_cast<T>(Mathd::zeroTolerance())) {
 				x = x * invLength;
 				y = y * invLength;
 				z = z * invLength;
--- a/engine/core/video/devicecaps.cpp	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/video/devicecaps.cpp	Wed Oct 13 20:24:48 2010 +0000
@@ -21,6 +21,7 @@
 
 // Standard C++ library includes
 #include <iostream>
+#include <algorithm>
 
 // 3rd party library includes
 #include <SDL.h>
@@ -51,6 +52,18 @@
 		m_SDLFlags = rhs.getSDLFlags();
 	}
 
+	bool ScreenMode::operator <(const ScreenMode& rhs) const {
+		if (m_bpp < rhs.getBPP() ) {
+			return true;
+		}
+		else if (m_bpp == rhs.getBPP()) {
+			if (m_width < rhs.getWidth() || m_height < rhs.getHeight()) {
+				return true;
+			}
+		}
+		return false;
+	}
+
 	DeviceCaps::DeviceCaps() :
 	    m_driverName("Invalid"),
 		m_hwAvailable(false),
@@ -115,7 +128,7 @@
 		int bufferSize = 256;
 		char buffer[bufferSize];
 
-		int numBPP = 1;
+		int numBPP = 3;
 		int bpps[numBPP];
 
 		//clear in case this is called twice
@@ -145,8 +158,10 @@
 #endif
 		//BITS PER PIXEL
 
-		bpps[0] = 32;
-		
+		bpps[0] = 16;
+		bpps[1] = 24;
+		bpps[2] = 32;
+
 		//COMMON FS RESOLUTIONS
 		int resolutions[15][2] = {
 			{640, 480},
@@ -174,10 +189,9 @@
 					int bpp;
 					if (flags[j] & SDL_FULLSCREEN) {
 						bpp = SDL_VideoModeOK(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]);
-						
+
 						if (bpp > 0) {
-							ScreenMode mode = ScreenMode(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]);
-							m_screenModes.push_back(mode);
+							m_screenModes.push_back(ScreenMode(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]));
 						}
 					}
 					else {  //windowed mode
@@ -185,8 +199,7 @@
 						//we are checking to make sure the bpp is supported here.
 						bpp = SDL_VideoModeOK(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]);
 						if (bpp > 0) {
-							ScreenMode mode = ScreenMode(0,0, bpps[i], flags[j]);
-							m_screenModes.push_back(mode);
+							m_screenModes.push_back(ScreenMode(0,0, bpps[i], flags[j]));
 							break; //insert windowed mode once as all resolutions are supported.
 						}
 					}
@@ -195,6 +208,11 @@
 			}
 		}
 
+		//sort the list to keep the most preferred modes at the top of the selection process
+		//in getNearestScreenMode()
+		std::sort(m_screenModes.begin(), m_screenModes.end());
+		std::reverse(m_screenModes.begin(), m_screenModes.end());
+
 		if(SDL_VideoDriverName(buffer, bufferSize) != NULL) {
 			m_driverName = std::string(buffer);
 		}
@@ -260,6 +278,20 @@
 				break;
 			}
 
+			//current screen bpp selected
+			if (widthCheck && heightCheck && bpp == 0 && fsCheck && rendCheck) {
+				mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags());
+				foundMode = true;
+				break;
+			}
+
+			if (m_screenModes[i].getWidth() == 0 && m_screenModes[i].getHeight() == 0  && bpp == 0 && fsCheck && rendCheck) {
+				mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags());
+				foundMode = true;
+				break;
+			}
+
+
 			widthCheck = false;
 			heightCheck = false;
 			bppCheck = false;
--- a/engine/core/video/devicecaps.h	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/video/devicecaps.h	Wed Oct 13 20:24:48 2010 +0000
@@ -51,6 +51,8 @@
 		 */
 		~ScreenMode() {};
 
+		bool operator <(const ScreenMode& rhs) const;
+
 		/** Returns the width of the screen mode.
 		 * @note If both width and height are 0 it means that ALL modes are available
 		 * for use with the specified flags.  Most likely this is a windowed mode.
--- a/engine/core/view/camera.cpp	Tue Oct 12 18:58:47 2010 +0000
+++ b/engine/core/view/camera.cpp	Wed Oct 13 20:24:48 2010 +0000
@@ -327,7 +327,7 @@
 
 	void Camera::calculateZValue(ScreenPoint& screen_coords) {
 		int dy = -(screen_coords.y - toScreenCoordinates(m_location.getMapCoordinates()).y);
-		screen_coords.z = static_cast<int>(tan(m_tilt * (DBL_PI / 180.0)) * static_cast<double>(dy));
+		screen_coords.z = static_cast<int>(Mathd::Tan(m_tilt * (Mathd::pi() / 180.0)) * static_cast<double>(dy));
 	}
 
 	ExactModelCoordinate Camera::toMapCoordinates(ScreenPoint screen_coords, bool z_calculated) {