Index: /trunk/nv/core/arcball.hh
===================================================================
--- /trunk/nv/core/arcball.hh	(revision 453)
+++ /trunk/nv/core/arcball.hh	(revision 454)
@@ -50,6 +50,6 @@
 			vec3 vb = get_arcball_vector( nposition );
 
-			m_angle = math::acos( glm::min( 1.0f, math::dot( va, vb ) ) );
-			m_axis  = glm::cross( va, vb );
+			m_angle = math::acos( math::min( 1.0f, math::dot( va, vb ) ) );
+			m_axis  = math::cross( va, vb );
 			m_last  = nposition;
 		}
@@ -65,5 +65,5 @@
 				p.z = sqrt( 1.0f - sq );
 			else
-				p = glm::normalize( p );
+				p = math::normalize( p );
 			return p;
 		}
Index: /trunk/nv/core/position.hh
===================================================================
--- /trunk/nv/core/position.hh	(revision 453)
+++ /trunk/nv/core/position.hh	(revision 454)
@@ -279,7 +279,7 @@
 		{
 			if (r.contains(*this)) return false;
-			ul = glm::max( ul, r.ul );
-			lr = glm::min( lr, r.lr );
-			ul = glm::min( ul, lr );
+			ul = math::max( ul, r.ul );
+			lr = math::min( lr, r.lr );
+			ul = math::min( ul, lr );
 			return true;
 		}
@@ -294,6 +294,6 @@
 		{
 			if ( r.get_width() < get_width() || r.get_height() < get_height() ) return false;
-			( *this ) += glm::min( r.ul - ul, position() );
-			( *this ) -= glm::min( lr - r.lr, position() );
+			( *this ) += math::min( r.ul - ul, position() );
+			( *this ) -= math::min( lr - r.lr, position() );
 			return true;
 		}
@@ -315,6 +315,6 @@
 		void include_point( position p )
 		{
-			lr = glm::max( lr, p );
-			ul = glm::min( ul, p );
+			lr = math::max( lr, p );
+			ul = math::min( ul, p );
 		}
 
Index: /trunk/nv/core/transform.hh
===================================================================
--- /trunk/nv/core/transform.hh	(revision 453)
+++ /trunk/nv/core/transform.hh	(revision 454)
@@ -26,6 +26,6 @@
 		void set_orientation( const quat& a_orientation ) { m_orientation = a_orientation; }
  		void set_orientation( float radians, const vec3& axis )
- 		{ // use math::radians if degrees!
- 			m_orientation = glm::angleAxis( radians, axis );
+ 		{
+ 			m_orientation = math::angle_axis( radians, axis );
  		}
 
@@ -36,5 +36,5 @@
 		void move( const vec3& heading, float distance )
 		{
-			m_position += glm::normalize( heading ) * distance;
+			m_position += math::normalize( heading ) * distance;
 		}
 		void translate( const vec3& absolute )
@@ -42,9 +42,9 @@
 			m_position += absolute;
 		}
-// 		void rotate( const vec3& axis, f32 angle )
-// 		{ // use math::radians if degrees!
-// 			quat temp( angle, axis );
-// 			m_orientation = temp * m_orientation;
-// 		}
+ 		void rotate( const vec3& axis, f32 angle )
+ 		{
+ 			quat temp( angle, axis );
+ 			m_orientation = temp * m_orientation;
+ 		}
 		void set( const mat4& from )
 		{
@@ -54,5 +54,5 @@
 		mat4 extract() const
 		{
-			mat4 result = mat4_cast( m_orientation );
+			mat4 result = math::mat4_cast( m_orientation );
 			result[3] = vec4( m_position, 1.0f );
 			return result;
@@ -60,7 +60,7 @@
 		transform inverse() const
 		{
-			quat new_orient( glm::inverse( m_orientation ) );
+			quat new_orient( math::inverse( m_orientation ) );
 			// TODO: simplify
-			return transform( -mat3_cast(new_orient) * m_position, new_orient );
+			return transform( -math::mat3_cast(new_orient) * m_position, new_orient );
 		}
 
@@ -99,6 +99,6 @@
 	{
 		return transform( 
-			glm::mix  ( a.get_position(), b.get_position(), value ), 
-			glm::slerp( a.get_orientation(), b.get_orientation(), value )
+			math::mix  ( a.get_position(), b.get_position(), value ), 
+			math::slerp( a.get_orientation(), b.get_orientation(), value )
 		);
 	}
Index: /trunk/nv/gfx/animation.hh
===================================================================
--- /trunk/nv/gfx/animation.hh	(revision 453)
+++ /trunk/nv/gfx/animation.hh	(revision 454)
@@ -108,5 +108,5 @@
 				float time1 = fdata[index1 * static_cast<int>( keyfsize )];
 				float delta = time1 - time0;
-				factor = glm::clamp( ( time - time0 ) / delta, 0.0f, 1.0f );
+				factor = math::clamp( ( time - time0 ) / delta, 0.0f, 1.0f );
 			}
 			else
@@ -117,7 +117,7 @@
 					return keyfresult;
 				}
-				index0 = glm::clamp<int>( int( time ), 0, int( channel.size() ) - 2 );
+				index0 = math::clamp( int( time ), 0, int( channel.size() ) - 2 );
 				index1 = index0 + 1;
-				factor = glm::clamp<float>( time - index0, 0.0f, 1.0f );
+				factor = math::clamp( time - index0, 0.0f, 1.0f );
 			}
 			uint32 ret = 0;
@@ -167,6 +167,6 @@
 // 				return;
 // 			}
-// 			size_t index = glm::clamp<size_t>( size_t( frame ), 0, count - 2 );
-// 			float factor = glm::clamp<float> ( frame - index, 0.0f, 1.0f );
+// 			size_t index = math::clamp( size_t( frame ), 0, count - 2 );
+// 			float factor = math::clamp( frame - index, 0.0f, 1.0f );
 // 			interpolate_key( result, keys[index], keys[index+1], factor );
 // 		}
@@ -208,5 +208,5 @@
 // 			NV_ASSERT( index >= 0, "animation time fail!");
 // 			float delta  = keys[index + 1].time - keys[index].time;
-// 			float factor = glm::clamp( (time - keys[index].time) / delta, 0.0f, 1.0f );
+// 			float factor = math::clamp( (time - keys[index].time) / delta, 0.0f, 1.0f );
 // 			interpolate_key( result, keys[index], keys[index+1], factor );
 // 		}
Index: /trunk/nv/interface/camera.hh
===================================================================
--- /trunk/nv/interface/camera.hh	(revision 453)
+++ /trunk/nv/interface/camera.hh	(revision 454)
@@ -28,5 +28,5 @@
 			m_view      = math::look_at( eye, focus, up );
 			m_position  = eye;
-			m_direction = glm::normalize( focus - eye );
+			m_direction = math::normalize( focus - eye );
 		}
 
@@ -79,7 +79,7 @@
 		mat4 get_mvp()        const { return m_camera.get_projection() * get_modelview(); }
 
-		mat4 get_view_inv()   const { return glm::inverse( get_view() ); }
-		mat4 get_model_inv()  const { return glm::inverse( get_model() ); }
-		mat3 get_normal()     const { return glm::transpose(glm::inverse( mat3( get_modelview() ) ) ); }
+		mat4 get_view_inv()   const { return math::inverse( get_view() ); }
+		mat4 get_model_inv()  const { return math::inverse( get_model() ); }
+		mat3 get_normal()     const { return math::transpose( math::inverse( mat3( get_modelview() ) ) ); }
 	protected:
 		mat4   m_model;
Index: /trunk/nv/interface/interpolation_template.hh
===================================================================
--- /trunk/nv/interface/interpolation_template.hh	(revision 453)
+++ /trunk/nv/interface/interpolation_template.hh	(revision 454)
@@ -87,14 +87,14 @@
 
 		template < typename KEY >
-		mat4 extract_matrix_p_impl( const KEY& k ) { return glm::translate(mat4(),k.translation); }
-		template < typename KEY >
-		mat4 extract_matrix_r_impl( const KEY& k ) { return glm::mat4_cast( k.rotation ); }
-		template < typename KEY >
-		mat4 extract_matrix_s_impl( const KEY& k ) { return glm::scale(mat4(),k.scale); }
+		mat4 extract_matrix_p_impl( const KEY& k ) { return math::translate(mat4(),k.translation); }
+		template < typename KEY >
+		mat4 extract_matrix_r_impl( const KEY& k ) { return math::mat4_cast( k.rotation ); }
+		template < typename KEY >
+		mat4 extract_matrix_s_impl( const KEY& k ) { return math::scale(mat4(),k.scale); }
 		template < typename KEY >
 		mat4 extract_matrix_pr_impl( const KEY& k )
 		{
 			// TODO: this is obviously unoptimized
-			mat4 result = glm::mat4_cast( k.rotation );
+			mat4 result = math::mat4_cast( k.rotation );
 			result[3] = vec4( k.translation, 1.0f );
 			return result;
@@ -104,6 +104,6 @@
 		{
 			// TODO: this is obviously unoptimized
-			mat4 result = glm::mat4_cast( k.rotation );
-			return glm::scale(result,k.scale);
+			mat4 result = math::mat4_cast( k.rotation );
+			return math::scale(result,k.scale);
 		}
 		template < typename KEY >
@@ -111,5 +111,5 @@
 		{
 			// TODO: this is obviously unoptimized
-			return glm::scale(glm::translate(mat4(),k.translation),k.scale);
+			return math::scale( math::translate(mat4(),k.translation),k.scale);
 		}
 		template < typename KEY >
@@ -117,5 +117,5 @@
 		{
 			// TODO: this is obviously unoptimized
-			return glm::translate(mat4(),k.translation) * glm::mat4_cast( k.rotation ) * glm::scale(mat4(),k.scale);
+			return math::translate(mat4(),k.translation) * math::mat4_cast( k.rotation ) * math::scale(mat4(),k.scale);
 		}
 
Index: /trunk/nv/lib/assimp.hh
===================================================================
--- /trunk/nv/lib/assimp.hh	(revision 453)
+++ /trunk/nv/lib/assimp.hh	(revision 454)
@@ -68,10 +68,10 @@
 	{
 		const float* p = reinterpret_cast<const float*>( &m );
-		return glm::transpose( make_mat4( p ) );
+		return math::transpose( make_mat4( p ) );
 	}
 
 	inline quat assimp_quat_cast( const aiQuaternion& q )
 	{
-		return nv::quat( q.w, q.x, q.y, q.z );
+		return quat( q.w, q.x, q.y, q.z );
 	}
 
Index: /trunk/nv/stl/math.hh
===================================================================
--- /trunk/nv/stl/math.hh	(revision 453)
+++ /trunk/nv/stl/math.hh	(revision 454)
@@ -10,9 +10,14 @@
 #define NV_STL_MATH_HH
 
-#include <nv/common.hh>
 #include <nv/stl/math/common.hh>
 #include <nv/stl/math/constants.hh>
+#include <nv/stl/math/relational.hh>
+#include <nv/stl/math/epsilon.hh>
 #include <nv/stl/math/geometric.hh>
+#include <nv/stl/math/exponential.hh>
 #include <nv/stl/math/matrix_transform.hh>
+#include <nv/stl/math/angle.hh>
+#include <nv/stl/math/quaternion.hh>
+
 #include <nv/stl/math/cast.hh>
 
@@ -211,5 +216,5 @@
 	T interpolate( const T& lhs, const T& rhs, float f )
 	{
-		return glm::mix( lhs, rhs, f );
+		return math::mix( lhs, rhs, f );
 	}
 
@@ -217,5 +222,5 @@
 	inline quat interpolate( const quat& lhs, const quat& rhs, float f )
 	{
-		return glm::slerp( lhs, rhs, f );
+		return math::slerp( lhs, rhs, f );
 	}
 
@@ -227,5 +232,5 @@
 	{
 		typename math::tvec3<T>::value_type sqr = x.x * x.x + x.y * x.y + x.z * x.z;
-		return ( sqr > 0 ? x * glm::inversesqrt(sqr) : def );
+		return ( sqr > 0 ? x * math::inversesqrt(sqr) : def );
 	}
 
Index: /trunk/nv/stl/math/angle.hh
===================================================================
--- /trunk/nv/stl/math/angle.hh	(revision 454)
+++ /trunk/nv/stl/math/angle.hh	(revision 454)
@@ -0,0 +1,177 @@
+// Copyright (C) 2015-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+/**
+* @file angle.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+* @brief angle related math
+*/
+
+#ifndef NV_STL_MATH_ANGLE_HH
+#define NV_STL_MATH_ANGLE_HH
+
+#include <nv/stl/math/common.hh>
+#include <nv/stl/math/geometric.hh>
+#include <nv/stl/math/matrix_transform.hh>
+
+namespace nv
+{
+	
+	namespace math
+	{
+
+		template < typename T >
+		inline tvec3<T> slerp( const tvec3<T>& a, const tvec3<T>& b, const T& v )
+		{
+			T angle     = acos( dot( a, b ) );
+			T sin_angle = sin( angle );
+			T t1 = sin( ( static_cast<T>( 1 ) - v ) * angle ) / sin_angle;
+			T t2 = sin( v * angle ) / sin_angle;
+			return a * t1 + b * t2;
+		}
+
+		template < typename T >
+		inline tvec2<T> rotate( const tvec2<T>& v, const T& angle )
+		{
+			tvec2<T> result;
+			T cosa( cos( angle ) );
+			T sina( sin( angle ) );
+			result.x = v.x * cosa - v.y * sina;
+			result.y = v.x * sina + v.y * cosa;
+			return result;
+		}
+
+		template < typename T >
+		inline tvec3<T> rotate( const tvec3<T>& v, const T& angle, const tvec3<T>& normal )
+		{
+			return tmat3<T>( rotate( angle, normal ) ) * v;
+		}
+
+		template < typename T >
+		inline tvec4<T> rotate( const tvec4<T>& v, const T& angle, const tvec3<T>& normal )
+		{
+			return math::rotate( angle, normal ) * v;
+		}
+
+		template < typename T >
+		inline tvec3<T> rotate_x( const tvec3<T>& v, const T& angle )
+		{
+			tvec3<T> result( v );
+			T cosa( cos( angle ) );
+			T sina( sin( angle ) );
+
+			result.y = v.y * cosa - v.z * sina;
+			result.z = v.y * sina + v.z * cosa;
+			return result;
+		}
+
+		template < typename T >
+		inline tvec3<T> rotate_y( const tvec3<T>& v, const T& angle )
+		{
+			tvec3<T> result = v;
+			T cosa( cos( angle ) );
+			T sina( sin( angle ) );
+
+			result.x =  v.x * cosa + v.z * sina;
+			result.z = -v.x * sina + v.z * cosa;
+			return result;
+		}
+
+		template < typename T >
+		inline tvec3<T> rotate_z( const tvec3<T>& v, const T& angle )
+		{
+			tvec3<T> result = v;
+			T cosa( cos( angle ) );
+			T sina( sin( angle ) );
+
+			result.x = v.x * cosa - v.y * sina;
+			result.y = v.x * sina + v.y * cosa;
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<T> rotate_x( const tvec4<T>& v, const T& angle )
+		{
+			tvec3<T> result = v;
+			T cosa( cos( angle ) );
+			T sina( sin( angle ) );
+
+			result.y = v.y * cosa - v.z * sina;
+			result.z = v.y * sina + v.z * cosa;
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<T> rotate_y( const tvec4<T>& v, const T& angle )
+		{
+			tvec3<T> result = v;
+			T cosa( cos( angle ) );
+			T sina( sin( angle ) );
+
+			result.x =  v.x * cosa + v.z * sina;
+			result.z = -v.x * sina + v.z * cosa;
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<T> rotate_z( const tvec4<T>& v, const T& angle )
+		{
+			tvec3<T> result = v;
+			T cosa( cos( angle ) );
+			T sina( sin( angle ) );
+
+			result.x = v.x * cosa - v.y * sina;
+			result.y = v.x * sina + v.y * cosa;
+			return result;
+		}
+
+		template < typename T >
+		inline tmat4<T> orientation( const tvec3<T>& normal, const tvec3<T>& up )
+		{
+			if ( all( equal( normal, up ) ) ) return tmat4<T>( T( 1 ) );
+			tvec3<T> raxis = cross( up, normal );
+			T rangle = acos( dot( normal, up ) );
+			return rotate( rangle, raxis );
+		}
+
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T angle(	T a, T y )
+		{
+			return acos( clamp( dot( a, b ), T( -1 ), T( 1 ) ) );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline value_type_t<T> angle( const T& a, const T& b )
+		{
+			return acos( clamp( dot( a, b ), T( -1 ), T( 1 ) ) );
+		}
+
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T oriented_angle( const tvec2<T>& a, const tvec2<T>& b )
+		{
+			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
+			const T result( acos( clamp( dot( a, b ), T( -1 ), T( 1 ) ) ) );
+
+			if ( all( epsilon_equal( y, math::rotate( a, result ), T( 0.0001 ) ) ) )
+				return result;
+			else
+				return -result;
+		}
+
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T oriented_angle( const tvec3<T>& a, const tvec3<T>& b, const tvec3<T>& ref )
+		{
+			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
+
+			const T result( acos( clamp( dot( a, b ), T( -1 ), T( 1 ) ) ) );
+			return mix( result, -result, dot( ref, cross( a, b ) ) < T( 0 ) );
+		}
+
+	}
+
+}
+
+#endif // NV_STL_MATH_ANGLE_HH
Index: /trunk/nv/stl/math/basic.hh
===================================================================
--- /trunk/nv/stl/math/basic.hh	(revision 454)
+++ /trunk/nv/stl/math/basic.hh	(revision 454)
@@ -0,0 +1,283 @@
+// Copyright (C) 2015-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+/**
+* @file basic.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+* @brief basic math ops
+*/
+
+#ifndef NV_STL_MATH_BASIC_HH
+#define NV_STL_MATH_BASIC_HH
+
+#include <nv/stl/math/common.hh>
+#include <nv/stl/math/relational.hh>
+
+namespace nv
+{
+
+	namespace math
+	{
+		namespace detail
+		{
+
+			template <
+				typename T,
+				bool Signed = numeric_limits<T>::is_signed
+			>
+			struct abs_helper;
+
+			template < typename T >
+			struct abs_helper< T, false >
+			{
+				constexpr static T call( T x )
+				{
+					return x;
+				}
+			};
+
+			template < typename T >
+			struct abs_helper< T, true >
+			{
+				constexpr static T call( T x )
+				{
+					return x >= T( 0 ) ? x : -x;
+				}
+			};
+
+			template <
+				typename T,
+				typename Mix = T,
+				bool MixBool = is_same< value_type_t<Mix>, bool >,
+				bool TIsVector = is_vec<T>::value,
+				bool MixIsVector = is_vec<Mix>::value >
+			struct mix_helper
+			{
+				inline static T call( const T& a, const T& b, const Mix& m )
+				{
+					return a + m * ( b - a );
+				}
+			};
+
+			template < typename T, bool IsVector >
+			struct mix_helper < T, bool, true, IsVector, false >
+			{
+				inline static T call( const T& a, const T& b, bool m )
+				{
+					return m ? b : a;
+				}
+			};
+
+			template < typename T, typename U >
+			struct mix_helper < T, U, true, true, true >
+			{
+				inline static T call( const T& a, const T& b, const U& m )
+				{
+					T result( ctor::uninitialize );
+					for ( component_count_t i = 0; i < component_count( a ); ++i )
+						result[i] = m[i] ? b[i] : a[i];
+					return result;
+				}
+			};
+
+			template < typename T, typename U = value_type_t<T>, bool IsFloating = is_floating_point< U >::value, bool IsSigned = is_signed< U >::value >
+			struct sign_helper
+			{
+				inline static T call( const T& a )
+				{
+					return T( less_than( T( 0 ), a ) ) - T( less_than( a, T( 0 ) ) );
+				}
+			};
+
+			template < typename T, typename U >
+			struct sign_helper< T, U, false, false >
+			{
+				inline static T call( const T& a )
+				{
+					return T( greater_than( a, T( 0 ) ) );
+				}
+			};
+
+			template < typename T, typename U >
+			struct sign_helper< T, U, false, true >
+			{
+				inline static T call( const T& a )
+				{
+					typedef typename make_unsigned<T>::type UT;
+					typedef typename make_unsigned<U>::type UU;
+					const U shift( static_cast<U>( sizeof( U ) * 8 - 1 ) );
+					const T y( UT( -a ) >> UU( shift ) );
+					return ( a >> shift ) | y;
+				}
+			};
+
+		}
+
+		template < typename T, typename enable_if< is_arithmetic<T>::value >::type* = nullptr >
+		inline T abs( T x )
+		{
+			return detail::abs_helper< T >::call( x );
+		}
+
+		template <>
+		inline sint32 abs( sint32 x )
+		{
+			const sint32 y = x >> 31;
+			return ( x ^ y ) - y;
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T abs( const T& x )
+		{
+			return detail::unary_functor< T >::call( abs, x );
+		}
+
+		template < typename T, typename enable_if< is_arithmetic<T>::value >::type* = nullptr >
+		inline T sign( T x )
+		{
+			return detail::sign_helper< T, T >::call( x );
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T sign( const T& x )
+		{
+			return detail::sign_helper< T >::call( x );
+		}
+
+		using ::floor;
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T floor( const T& x )
+		{
+			return detail::unary_functor< T >::call( floor, x );
+		}
+
+		using ::trunc;
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T trunc( const T& x )
+		{
+			return detail::unary_functor< T >::call( trunc, x );
+		}
+
+		using ::round;
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T round( const T& x )
+		{
+			return detail::unary_functor< T >::call( round, x );
+		}
+
+		using ::ceil;
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T ceil( const T& x )
+		{
+			return detail::unary_functor< T >::call( ceil, x );
+		}
+
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T fract( T x )
+		{
+			return x - floor( x );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T fract( const T& x )
+		{
+			return x - floor( x );
+		}
+
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T mod( T a, T b )
+		{
+			return a - b * floor( a / b );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T mod( const T& a, const T& b )
+		{
+			return a - b * floor( a / b );
+		}
+
+		template < typename T, typename enable_if< is_arithmetic<T>::value >::type* = nullptr >
+		constexpr T min( T a, T b )
+		{
+			return a < b ? a : b;
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T min( const T& a, value_type_t<T> b )
+		{
+			return detail::binary_scalar_functor< T >::call( min, a, b );
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T min( const T& a, const T& b )
+		{
+			return detail::binary_functor< T >::call( min, a, b );
+		}
+
+		template < typename T, typename enable_if< is_arithmetic<T>::value >::type* = nullptr >
+		constexpr T max( T a, T b )
+		{
+			return a > b ? a : b;
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T max( const T& a, value_type_t<T> b )
+		{
+			return detail::binary_scalar_functor< T >::call( max, a, b );
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T max( const T& a, const T& b )
+		{
+			return detail::binary_functor< T >::call( max, a, b );
+		}
+
+		template < typename T, typename enable_if< is_arithmetic<T>::value >::type* = nullptr >
+		constexpr T clamp( T x, T minv, T maxv )
+		{
+			return ::nv::math::min( ::nv::math::max( x, minv ), maxv );
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T clamp( const T& x, value_type_t<T> minv, value_type_t<T> maxv )
+		{
+			return ::nv::math::min( ::nv::math::max( x, minv ), maxv );
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T clamp( const T& x, const T& minv, const T& maxv )
+		{
+			return ::nv::math::min( ::nv::math::max( x, minv ), maxv );
+		}
+
+		template < typename T >
+		constexpr T mix( T a, T b, bool m )
+		{
+			return m ? b : a;
+		}
+
+		template < typename T, typename enable_if< is_arithmetic<T>::value >::type* = nullptr >
+		constexpr T mix( T a, T b, T m )
+		{
+			return detail::mix_helper< T, T, is_same< T, bool >::value >::call( a, b, m );
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T mix( const T& a, const T& b, value_type_t<T> m )
+		{
+			return detail::mix_helper< T, value_type_t<T>, is_same< value_type_t<T>, bool >::value >::call( a, b, m );
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline T mix( const T& a, const T& b, const T& m )
+		{
+			return detail::mix_helper< T >::call( a, b, m );
+		}
+
+	}
+}
+
+#endif // NV_STL_MATH_BASIC_HH
Index: /trunk/nv/stl/math/common.hh
===================================================================
--- /trunk/nv/stl/math/common.hh	(revision 453)
+++ /trunk/nv/stl/math/common.hh	(revision 454)
@@ -15,6 +15,6 @@
 
 #include <nv/common.hh>
-#include <nv/stl/type_traits/common.hh>
-
+#include <nv/stl/utility/common.hh>
+#include <nv/stl/type_traits.hh>
 #if NV_COMPILER == NV_GNUC
 #pragma GCC system_header
@@ -33,4 +33,14 @@
 	namespace math
 	{
+
+		// TODO: Remove
+		using glm::inverse;
+		using glm::transpose;
+
+		using glm::detail::component_count_t;
+		using glm::detail::component_count;
+
+		using glm::ctor;
+
 		using ::cos;
 		using ::sin;
@@ -39,11 +49,15 @@
 		using ::cosh;
 		using ::sinh;
-		using ::abs;
 		using ::tan;
+
 		using ::sqrt;
 		using ::pow;
+		using ::log2;
+		using ::log;
+		using ::exp;
+
 		using ::floor;
-		using ::ceil;
 		using ::round;
+
 #if 0
 		template < typename T > using tvec2 = ::glm::detail::tvec2<T, glm::precision::highp>;
@@ -61,34 +75,136 @@
 		template < typename T > using tmat3 = ::glm::tmat3x3<T>;
 		template < typename T > using tmat4 = ::glm::tmat4x4<T>;
-		template < typename T > using tquat = ::glm::tquat<T,glm::highp>;
+		template < typename T > using tquat = ::glm::tquat<T, glm::highp>;
 #endif
 
 		typedef glm::quat quat;
-		using glm::ctor;
+
+		template < typename T > struct is_vec : false_type {};
+		template < typename T > struct is_mat : false_type {};
+		template < typename T > struct is_quat : false_type {};
+
+		template < typename T > struct is_fp : is_floating_point< T > {};
+		template < typename T > struct is_fp_vec : false_type {};
+		template < typename T > struct is_fp_mat : false_type {};
+		template < typename T > struct is_fp_quat : false_type {};
+
+		template < typename T > struct is_bool_vec : false_type {};
+
+		template < typename T > struct is_vec < tvec2< T > > : true_type {};
+		template < typename T > struct is_vec < tvec3< T > > : true_type {};
+		template < typename T > struct is_vec < tvec4< T > > : true_type {};
+		template < typename T > struct is_mat < tmat2< T > > : true_type {};
+		template < typename T > struct is_mat < tmat3< T > > : true_type {};
+		template < typename T > struct is_mat < tmat4< T > > : true_type {};
+		template < typename T > struct is_quat< tquat< T > > : true_type {};
+
+		template < typename T > struct is_fp     < tvec2< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp     < tvec3< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp     < tvec4< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp_vec < tvec2< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp_vec < tvec3< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp_vec < tvec4< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp_mat < tmat2< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp_mat < tmat3< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp_mat < tmat4< T > > : is_floating_point< T > {};
+		template < typename T > struct is_fp_quat< tquat< T > > : is_floating_point< T > {};
+
+		template <> struct is_bool_vec < tvec2< bool > > : true_type {};
+		template <> struct is_bool_vec < tvec3< bool > > : true_type {};
+		template <> struct is_bool_vec < tvec4< bool > > : true_type {};
+
+		namespace detail
+		{
+			template < typename Vec, typename R = value_type_t<Vec>, typename T = value_type_t<Vec> >
+			struct unary_functor {};
+
+			template < typename R, typename T >
+			struct unary_functor< tvec2< T >, R, T >
+			{
+				inline static tvec2<R> call( R( *func )( T ), const tvec2<T>& v )
+				{
+					return tvec2<R>( func( v.x ), func( v.y ) );
+				}
+			};
+
+			template < typename R, typename T >
+			struct unary_functor< tvec3< T >, R, T >
+			{
+				inline static tvec3<R> call( R( *func )( T ), const tvec3<T>& v )
+				{
+					return tvec3<R>( func( v.x ), func( v.y ), func( v.z ) );
+				}
+			};
+
+			template < typename R, typename T >
+			struct unary_functor< tvec4< T >, R, T >
+			{
+				inline static tvec4<R> call( R( *Func ) ( T x ), const tvec4<T>& v )
+				{
+					return tvec4<R>( func( v.x ), func( v.y ), func( v.z ), func( v.w ) );
+				}
+			};
+
+			template < typename Vec, typename T = value_type_t<Vec> >
+			struct binary_functor {};
+
+			template < typename T >
+			struct binary_functor< tvec2< T >, T >
+			{
+				inline static tvec2<T> call( T( *func ) ( T, T ), const tvec2<T>& a, const tvec2<T>& b )
+				{
+					return tvec2<T>( func( a.x, b.x ), func( a.y, b.y ) );
+				}
+			};
+
+			template < typename T >
+			struct binary_functor< tvec3< T >, T >
+			{
+				inline static tvec3<T> call( T( *func ) ( T, T ), const tvec3<T>& a, const tvec3<T>& b )
+				{
+					return tvec3<T>( func( a.x, b.x ), func( a.y, b.y ), func( a.z, b.z ) );
+				}
+			};
+
+			template < typename T >
+			struct binary_functor< tvec4< T >, T >
+			{
+				inline static tvec4<T> call( T( *func ) ( T, T ), const tvec4<T>& a, const tvec4<T>& b )
+				{
+					return tvec4<T>( func( a.x, b.x ), func( a.y, b.y ), func( a.z, b.z ), func( a.w, b.w ) );
+				}
+			};
+
+			template < typename Vec, typename T = value_type_t<Vec> >
+			struct binary_scalar_functor {};
+
+			template < typename T >
+			struct binary_scalar_functor< tvec2< T >, T >
+			{
+				inline static tvec2<T> call( T( *func ) ( T, T ), const tvec2<T>& a, T b )
+				{
+					return tvec2<T>( func( a.x, b ), func( a.y, b ) );
+				}
+			};
+
+			template < typename T >
+			struct binary_scalar_functor< tvec3< T >, T >
+			{
+				inline static tvec3<T> call( T( *func ) ( T, T ), const tvec3<T>& a, T b )
+				{
+					return tvec3<T>( func( a.x, b ), func( a.y, b ), func( a.z, b ) );
+				}
+			};
+
+			template < typename T >
+			struct binary_scalar_functor< tvec4< T >, T >
+			{
+				inline static tvec4<T> call( T( *func ) ( T, T ), const tvec4<T>& a, T b )
+				{
+					return tvec4<T>( func( a.x, b ), func( a.y, b ), func( a.z, b ), func( a.w, b ) );
+				}
+			};
+		}
 	}
-
-	template < typename T >
-	struct is_math_vector : false_type {};
-
-	template < typename T >
-	struct is_math_matrix : false_type {};
-
-	template < typename T >
-	struct is_math_quat : false_type {};
-
-	template < typename T >
-	struct is_math_class : bool_constant< 
-		is_math_vector< T >::value || 
-		is_math_matrix< T >::value ||
-		is_math_quat< T >::value
-	> {};
-
-	template < typename T > struct is_math_vector< math::tvec2< T > > : true_type {};
-	template < typename T > struct is_math_vector< math::tvec3< T > > : true_type {};
-	template < typename T > struct is_math_vector< math::tvec4< T > > : true_type {};
-	template < typename T > struct is_math_matrix< math::tmat2< T > > : true_type {};
-	template < typename T > struct is_math_matrix< math::tmat3< T > > : true_type {};
-	template < typename T > struct is_math_matrix< math::tmat4< T > > : true_type {};
-	template < typename T > struct is_math_quat  < math::tquat< T > > : true_type {};
 
 	typedef math::tvec2<sint8> i8vec2;
@@ -118,4 +234,42 @@
 	typedef math::quat quat;
 
+
+
+	template < typename T > 
+	struct make_unsigned< math::tvec2< T > >
+	{
+		typedef math::tvec2< make_unsigned_t< T > > type;
+	};
+
+	template < typename T >
+	struct make_unsigned< math::tvec3< T > >
+	{
+		typedef math::tvec3< make_unsigned_t< T > > type;
+	};
+
+	template < typename T >
+	struct make_unsigned< math::tvec4< T > >
+	{
+		typedef math::tvec4< make_unsigned_t< T > > type;
+	};
+
+	template < typename T >
+	struct make_signed< math::tvec2< T > >
+	{
+		typedef math::tvec2< make_signed_t< T > > type;
+	};
+
+	template < typename T >
+	struct make_signed< math::tvec3< T > >
+	{
+		typedef math::tvec3< make_signed_t< T > > type;
+	};
+
+	template < typename T >
+	struct make_signed< math::tvec4< T > >
+	{
+		typedef math::tvec4< make_signed_t< T > > type;
+	};
+
 }
 
Index: /trunk/nv/stl/math/epsilon.hh
===================================================================
--- /trunk/nv/stl/math/epsilon.hh	(revision 454)
+++ /trunk/nv/stl/math/epsilon.hh	(revision 454)
@@ -0,0 +1,66 @@
+// Copyright (C) 2015-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+/**
+ * @file epsilon.hh
+ * @author Kornel Kisielewicz epyon@chaosforge.org
+ * @brief epsilon math ops
+ */
+
+#ifndef NV_STL_MATH_EPSILON_HH
+#define NV_STL_MATH_EPSILON_HH
+
+#include <nv/stl/math/common.hh>
+#include <nv/stl/math/relational.hh>
+
+namespace nv
+{
+
+	namespace math
+	{
+
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline bool epsilon_equal( T a, T b, T epsilon )
+		{
+			return abs( a - b ) < epsilon;
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t< T > epsilon_equal( const T& a, const T& b, const T& epsilon )
+		{
+			return less_than( abs( a - b ), T( epsilon ) );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t< T > epsilon_equal( const T& a, const T& b, value_type_t<T> epsilon )
+		{
+			return less_than( abs( a - b ), T( epsilon ) );
+		}
+
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline bool epsilon_not_equal( T a, T b, T epsilon )
+		{
+			return abs( a - b ) >= epsilon;
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t< T > epsilon_not_equal( const T& a, const T& b, const T& epsilon )
+		{
+			return greater_than_equal( abs( a - b ), T( epsilon ) );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t< T > epsilon_not_equal( const T& a, const T& b, value_type_t<T> epsilon )
+		{
+			return greater_than_equal( abs( a - b ), T( epsilon ) );
+		}
+
+
+	}
+
+}
+
+#endif // NV_STL_MATH_EPSILON_HH
Index: /trunk/nv/stl/math/exponential.hh
===================================================================
--- /trunk/nv/stl/math/exponential.hh	(revision 454)
+++ /trunk/nv/stl/math/exponential.hh	(revision 454)
@@ -0,0 +1,77 @@
+// Copyright (C) 2015-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+/**
+* @file exponential.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+* @brief exponential math ops
+*/
+
+#ifndef NV_STL_MATH_EXPONENTIAL_HH
+#define NV_STL_MATH_EXPONENTIAL_HH
+
+#include <nv/stl/math/common.hh>
+#include <nv/stl/math/constants.hh>
+
+namespace nv
+{
+
+	namespace math
+	{
+		
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T pow( const T& base, const T& exponent )
+		{
+			return detail::binary_functor<T>::call( pow, base, exponent );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T exp( const T& x )
+		{
+			return detail::unary_functor<T>::call( exp, x );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T log( const T& x )
+		{
+			return detail::unary_functor<T>::call( log, x );
+		}
+
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T exp2( T x )
+		{
+			return exp( ln_two<T>() );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T exp2( const T& x )
+		{
+			return detail::unary_functor<T>::call( exp2, x );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T log2( const T& x )
+		{
+			return detail::unary_functor<T>::call( log2, x );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T sqrt( const T& x )
+		{
+			return detail::unary_functor<T>::call( sqrt, x );
+		}
+
+		template < typename T, typename enable_if< is_fp<T>::value >::type* = nullptr >
+		inline T inversesqrt( const T& x )
+		{
+			return static_cast<T>( 1 ) / sqrt( x );
+		}
+
+	}
+
+}
+
+#endif // NV_STL_MATH_EXPONENTIAL_HH
Index: /trunk/nv/stl/math/geometric.hh
===================================================================
--- /trunk/nv/stl/math/geometric.hh	(revision 453)
+++ /trunk/nv/stl/math/geometric.hh	(revision 454)
@@ -15,4 +15,6 @@
 
 #include <nv/stl/math/common.hh>
+#include <nv/stl/math/basic.hh>
+#include <nv/stl/math/exponential.hh>
 
 namespace nv
@@ -58,35 +60,29 @@
 		}
 
-		template < typename T >
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
 		inline T length( T x )
 		{
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
 			return abs( x );
 		}
 
-		template < typename T, template <typename> class Vec >
-		inline T length( const Vec<T>& v )
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline value_type_t<T> length( const T& v )
 		{
-			static_assert( is_math_vector< Vec<T> >::value, "math::vecX expected!" );
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
 			return sqrt( dot( v, v ) );
 		}
 
-		template <typename T>
-		inline T distance( const T& a, const T& b )
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T distance( T a, T b )
 		{
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
 			return length( b - a );
 		}
 
-		template < typename T, template <typename> class Vec >
-		inline T distance( const Vec<T>& a, const Vec<T>& b )
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline value_type_t<T> distance( const T& a, const T& b )
 		{
-			static_assert( is_math_vector< Vec<T> >::value, "math::vecX expected!" );
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
 			return length( b - a );
 		}
 
-		template < typename T >
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
 		inline T dot( T a, T b )
 		{
@@ -95,52 +91,45 @@
 		}
 
-		template < typename T, template <typename> class Vec >
-		inline T dot( const Vec<T>& a, const Vec<T>& b )
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline value_type_t<T> dot( const T& a, const T& b )
 		{
-			static_assert( is_math_vector< Vec<T> >::value, "math::vecX expected!" );
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
-			return detail::dot_impl< Vec, T >::get( a, b );
+			return detail::dot_impl< T >::get( a, b );
 		}
 
-		template < typename T >
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
 		inline tvec3<T> cross( const tvec3<T>& a, const tvec3<T>& b )
 		{
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
 			return tvec3<T>(
-				a.y * b.z - y.y * b.z,
-				a.z * b.x - y.z * b.x,
-				a.x * b.y - y.x * b.y
+				a.y * b.z - b.y * a.z,
+				a.z * b.x - b.z * a.x,
+				a.x * b.y - b.x * a.y
 			);
 		}
 
-		template < typename T >
-		inline T normalize( const T& x )
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T normalize( T x )
 		{
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
 			return x < T( 0 ) ? T( -1 ) : T( 1 );
 		}
 
-		template < typename T, template <typename> class Vec >
-		inline Vec<T> normalize( const Vec<T>& x )
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T normalize( const T& x )
 		{
-			static_assert( is_math_vector< Vec<T> >::value, "math::vecX expected!" );
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
 			return x * inversesqrt( dot( x, x ) );
 		}
 
-		template < typename T >
-		inline T faceforward( const T& n, const T& i, const T& nref )
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T faceforward( T n, T i, T nref )
 		{
 			return dot( nref, i ) < static_cast<T>( 0 ) ? n : -n;
 		}
 
-		template < typename T, template <typename> class Vec >
-		inline Vec<T> faceforward( const Vec<T>& n, const Vec<T>& i, const Vec<T>& nref )
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T faceforward( const T& n, const T& i, const T& nref )
 		{
-			static_assert( is_math_vector< Vec<T> >::value, "math::vecX expected!" );
-			return dot( nref, i ) < static_cast<T>( 0 ) ? n : -n;
+			return dot( nref, i ) < static_cast<value_type_t<T>>( 0 ) ? n : -n;
 		}
 
-		template < typename T >
+		template < typename T, typename enable_if< is_fp<T>::value >::type* = nullptr >
 		inline T reflect( const T& i, const T& n )
 		{
@@ -148,9 +137,7 @@
 		}
 
-		template < typename T >
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
 		inline T refract( const T& i, const T& n, const T& eta )
 		{
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
-
 			const T dotv( dot( n, i ) );
 			const T k( static_cast<T>( 1 ) - eta * eta * ( static_cast<T>( 1 ) - dotv * dotv ) );
@@ -158,13 +145,12 @@
 		}
 
-		template < typename T, template <typename> class Vec >
-		inline Vec<T> refract( const Vec<T>& i, const Vec<T>& n, T eta )
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline T refract( const T& i, const T& n, value_type_t<T> eta )
 		{
-			static_assert( is_math_vector< Vec<T> >::value, "math::vecX expected!" );
-			static_assert( is_floating_point<T>::value, "Type expected to be floating point!" );
+			typedef value_type_t<T> value_type;
 
-			T const dotv( dot( n, i ) );
-			T const k( static_cast<T>( 1 ) - eta * eta * ( static_cast<T>( 1 ) - dotv * dotv ) );
-			return ( eta * i - ( eta * dotv + sqrt( k ) ) * n ) * static_cast<T>( k >= static_cast<T>( 0 ) );
+			value_type const dotv( dot( n, i ) );
+			value_type const k( static_cast<T>( 1 ) - eta * eta * ( static_cast<value_type>( 1 ) - dotv * dotv ) );
+			return ( eta * i - ( eta * dotv + sqrt( k ) ) * n ) * static_cast<value_type>( k >= static_cast<value_type>( 0 ) );
 		}
 
Index: /trunk/nv/stl/math/matrix_transform.hh
===================================================================
--- /trunk/nv/stl/math/matrix_transform.hh	(revision 453)
+++ /trunk/nv/stl/math/matrix_transform.hh	(revision 454)
@@ -37,5 +37,5 @@
 			T const s = math::sin( a );
 
-			tvec3<T> axis( glm::normalize( v ) );
+			tvec3<T> axis( normalize( v ) );
 			tvec3<T> temp( ( T( 1 ) - c ) * axis );
 
@@ -70,4 +70,22 @@
 			result[3] = m[3];
 			return result;
+		}
+
+		template < typename T >
+		inline tmat4<T> translate( const tvec3<T>& v )
+		{
+			return translate( tmat4<T>( 1.0f ), v );
+		}
+
+		template < typename T >
+		inline tmat4<T> rotate( T angle, const tvec3<T>& v )
+		{
+			return rotate( tmat4<T>( 1.0f ), angle, v );
+		}
+
+		template < typename T >
+		inline tmat4<T> scale( const tvec3<T>& v )
+		{
+			return scale( tmat4<T>( 1.0f ), v );
 		}
 
@@ -183,5 +201,5 @@
 		inline tvec3<T> unproject( const tvec3<T>& win, const tmat4<T>& model, const tmat4<T>& proj, const tvec4<U>& viewport )
 		{
-			tmat4<T> invp = glm::inverse( proj * model );
+			tmat4<T> invp = inverse( proj * model );
 
 			tvec4<T> temp = tvec4<T>( win, T( 1 ) );
@@ -215,7 +233,7 @@
 		inline tmat4<T> look_at( const tvec3<T>& eye, const tvec3<T>& center, const tvec3<T>& up )
 		{
-			const tvec3<T> f( glm::normalize( center - eye ) );
-			const tvec3<T> s( glm::normalize( glm::cross( f, up ) ) );
-			const tvec3<T> u( glm::cross( s, f ) );
+			const tvec3<T> f( normalize( center - eye ) );
+			const tvec3<T> s( normalize( cross( f, up ) ) );
+			const tvec3<T> u( cross( s, f ) );
 
 			tmat4<T> result( 1 );
@@ -229,7 +247,7 @@
 			result[1][2] = -f.y;
 			result[2][2] = -f.z;
-			result[3][0] = -glm::dot( s, eye );
-			result[3][1] = -glm::dot( u, eye );
-			result[3][2] = glm::dot( f, eye );
+			result[3][0] = -dot( s, eye );
+			result[3][1] = -dot( u, eye );
+			result[3][2] = dot( f, eye );
 			return result;
 		}
Index: /trunk/nv/stl/math/quaternion.hh
===================================================================
--- /trunk/nv/stl/math/quaternion.hh	(revision 454)
+++ /trunk/nv/stl/math/quaternion.hh	(revision 454)
@@ -0,0 +1,361 @@
+// Copyright (C) 2015-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+/**
+* @file quaternion.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+* @brief quaternion ops
+*/
+
+#ifndef NV_STL_MATH_QUATERNION_HH
+#define NV_STL_MATH_QUATERNION_HH
+
+#include <nv/stl/math/common.hh>
+#include <nv/stl/math/constants.hh>
+#include <nv/stl/math/geometric.hh>
+#include <nv/stl/math/angle.hh>
+
+namespace nv
+{
+
+	namespace math
+	{
+		namespace detail
+		{
+
+			template < typename T >
+			struct dot_impl< tquat< T > >
+			{
+				inline static T get( const tquat<T>& a, const tquat<T>& b )
+				{
+					tvec4<T> tmp( a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w );
+					return ( tmp.x + tmp.y ) + ( tmp.z + tmp.w );
+				}
+			};
+
+		}
+
+
+		template < typename T >
+		inline tquat<T> conjugate( const tquat<T>& q )
+		{
+			return tquat<T>( q.w, -q.x, -q.y, -q.z );
+		}
+
+		template < typename T >
+		inline tquat<T> inverse( const tquat<T>& q )
+		{
+			return conjugate( q ) / dot( q, q );
+		}
+
+		template < typename T >
+		inline T length( const tquat<T>& q )
+		{
+			return math::sqrt( dot( q, q ) );
+		}
+
+		template < typename T >
+		inline tquat<T> normalize( const tquat<T>& q )
+		{
+			T len = length( q );
+			if ( len <= T( 0 ) ) return tquat<T>( 1, 0, 0, 0 );
+			T rlen = T( 1 ) / len;
+			return tquat<T>( q.w * rlen, q.x * rlen, q.y * rlen, q.z * rlen );
+		}
+
+		template < typename T >
+		inline tquat<T> cross( const tquat<T>& q1, const tquat<T>& q2 )
+		{
+			return tquat<T>(
+				q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z,
+				q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y,
+				q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z,
+				q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x );
+		}
+
+		template < typename T >
+		inline tquat<T> mix( const tquat<T>& a, const tquat<T>& b, T m )
+		{
+			T cos_theta = dot( a, b );
+
+			if ( cos_theta > T( 1 ) - epsilon<T>() )
+			{
+				return tquat<T>(
+					mix( a.w, b.w, m ),
+					mix( a.x, b.x, m ),
+					mix( a.y, b.y, m ),
+					mix( a.z, b.z, m ) );
+			}
+			else
+			{
+				T angle = acos( cos_theta );
+				return ( sin( ( T( 1 ) - m ) * angle ) * a + sin( m * angle ) * b ) / sin( angle );
+			}
+		}
+
+		template < typename T >
+		inline tquat<T> lerp( const tquat<T>& a, const tquat<T>& b, T m )
+		{
+			NV_ASSERT( m >= static_cast<T>( 0 ), "Bad argument to lerp!" );
+			NV_ASSERT( m <= static_cast<T>( 1 ), "Bad argument to lerp!" );
+
+			return a * ( T( 1 ) - m ) + ( b * m );
+		}
+
+		template < typename T >
+		inline tquat<T> slerp( const tquat<T>& x, const tquat<T>& y, T m )
+		{
+			tquat<T> z = y;
+			T cos_theta = dot( x, y );
+			if ( cos_theta < T( 0 ) )
+			{
+				z = -y;
+				cos_theta = -cos_theta;
+			}
+			if ( cos_theta > T( 1 ) - epsilon<T>() )
+			{
+				return tquat<T>(
+					mix( x.w, z.w, m ),
+					mix( x.x, z.x, m ),
+					mix( x.y, z.y, m ),
+					mix( x.z, z.z, m ) );
+			}
+			else
+			{
+				T angle = acos( cos_theta );
+				return ( sin( ( T( 1 ) - m ) * angle ) * x + sin( m * angle ) * z ) / sin( angle );
+			}
+		}
+
+		template < typename T >
+		inline tquat<T> rotate( const tquat<T>& q, T angle, const tvec3<T>& v )
+		{
+			tvec3<T> temp = v;
+			T len = math::length( temp );
+			if ( abs( len - T( 1 ) ) > T( 0.001 ) )
+			{
+				T rlen = static_cast<T>( 1 ) / len;
+				temp.x *= rlen;
+				temp.y *= rlen;
+				temp.z *= rlen;
+			}
+
+			T sina = sin( angle * T( 0.5 ) );
+			return q * tquat<T>( cos( angle * T( 0.5 ) ), temp.x * sina, temp.y * sina, temp.z * sina );
+		}
+
+		template < typename T >
+		inline tvec3<T> euler_angles( const tquat<T>& x )
+		{
+			return tvec3<T>( pitch( x ), yaw( x ), roll( x ) );
+		}
+
+		template < typename T >
+		inline T roll( const tquat<T>& q )
+		{
+			return T( atan( T( 2 ) * ( q.x * q.y + q.w * q.z ), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z ) );
+		}
+
+		template < typename T >
+		inline T pitch( const tquat<T>& q )
+		{
+			return T( atan( T( 2 ) * ( q.y * q.z + q.w * q.x ), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z ) );
+		}
+
+		template < typename T >
+		inline T yaw( const tquat<T>& q )
+		{
+			return asin( T( -2 ) * ( q.x * q.z - q.w * q.y ) );
+		}
+
+		template < typename T >
+		inline tmat3<T> mat3_cast( const tquat<T>& q )
+		{
+			tmat3<T> result( T( 1 ) );
+			T qxx( q.x * q.x );
+			T qyy( q.y * q.y );
+			T qzz( q.z * q.z );
+			T qxz( q.x * q.z );
+			T qxy( q.x * q.y );
+			T qyz( q.y * q.z );
+			T qwx( q.w * q.x );
+			T qwy( q.w * q.y );
+			T qwz( q.w * q.z );
+
+			result[0][0] = 1 - 2 * ( qyy + qzz );
+			result[0][1] = 2 * ( qxy + qwz );
+			result[0][2] = 2 * ( qxz - qwy );
+
+			result[1][0] = 2 * ( qxy - qwz );
+			result[1][1] = 1 - 2 * ( qxx + qzz );
+			result[1][2] = 2 * ( qyz + qwx );
+
+			result[2][0] = 2 * ( qxz + qwy );
+			result[2][1] = 2 * ( qyz - qwx );
+			result[2][2] = 1 - 2 * ( qxx + qyy );
+			return result;
+		}
+
+		template < typename T >
+		inline tmat4<T> mat4_cast( const tquat<T>& q )
+		{
+			return tmat4<T>( mat3_cast( q ) );
+		}
+
+		template < typename T >
+		inline tquat<T> quat_cast( const tmat3<T>& m )
+		{
+			T fx = m[0][0] - m[1][1] - m[2][2];
+			T fy = m[1][1] - m[0][0] - m[2][2];
+			T fz = m[2][2] - m[0][0] - m[1][1];
+			T fw = m[0][0] + m[1][1] + m[2][2];
+
+			int imax = 0;
+			T fmax = fw;
+			if ( fx > fmax )
+			{
+				fmax = fx;
+				imax = 1;
+			}
+			if ( fy > fmax )
+			{
+				fmax = fy;
+				imax = 2;
+			}
+			if ( fz > fmax )
+			{
+				fmax = fz;
+				imax = 3;
+			}
+
+			T vmax = sqrt( fmax + T( 1 ) ) * T( 0.5 );
+			T mult = static_cast<T>( 0.25 ) / vmax;
+
+			tquat<T> result( ctor::uninitialize );
+			switch ( imax )
+			{
+			case 0:
+				result.w = vmax;
+				result.x = ( m[1][2] - m[2][1] ) * mult;
+				result.y = ( m[2][0] - m[0][2] ) * mult;
+				result.z = ( m[0][1] - m[1][0] ) * mult;
+				break;
+			case 1:
+				result.w = ( m[1][2] - m[2][1] ) * mult;
+				result.x = vmax;
+				result.y = ( m[0][1] + m[1][0] ) * mult;
+				result.z = ( m[2][0] + m[0][2] ) * mult;
+				break;
+			case 2:
+				result.w = ( m[2][0] - m[0][2] ) * mult;
+				result.x = ( m[0][1] + m[1][0] ) * mult;
+				result.y = vmax;
+				result.z = ( m[1][2] + m[2][1] ) * mult;
+				break;
+			case 3:
+				result.w = ( m[0][1] - m[1][0] ) * mult;
+				result.x = ( m[2][0] + m[0][2] ) * mult;
+				result.y = ( m[1][2] + m[2][1] ) * mult;
+				result.z = vmax;
+				break;
+
+			default: break;
+			}
+			return result;
+		}
+
+		template < typename T >
+		inline tquat<T> quat_cast( const tmat4<T>& m4 )
+		{
+			return quat_cast( tmat3<T>( m4 ) );
+		}
+
+		template < typename T >
+		inline T angle( const tquat<T>& x )
+		{
+			return acos( x.w ) * T( 2 );
+		}
+
+		template < typename T >
+		inline tvec3<T> axis( const tquat<T>& x )
+		{
+			T tmp1 = static_cast<T>( 1 ) - x.w * x.w;
+			if ( tmp1 <= static_cast<T>( 0 ) ) return tvec3<T>( 0, 0, 1 );
+			T tmp2 = static_cast<T>( 1 ) / sqrt( tmp1 );
+			return tvec3<T>( x.x * tmp2, x.y * tmp2, x.z * tmp2 );
+		}
+
+		template < typename T >
+		inline tquat<T> angle_axis( T angle, const tvec3<T>& v )
+		{
+			tquat<T> result( ctor::uninitialize );
+			T sina = sin( angle * static_cast<T>( 0.5 ) );
+			result.w = ( angle * static_cast<T>( 0.5 ) );
+			result.x = v.x * sina;
+			result.y = v.y * sina;
+			result.z = v.z * sina;
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<bool> less_than( const tquat<T>& lhs, const tquat<T>& rhs )
+		{
+			tvec4<bool> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( x ); ++i )
+				result[i] = rhs[i] < lhs[i];
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<bool> less_than_equal( const tquat<T>& lhs, const tquat<T>& rhs )
+		{
+			tvec4<bool> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( x ); ++i )
+				result[i] = rhs[i] <= lhs[i];
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<bool> greater_than( const tquat<T>& lhs, const tquat<T>& rhs )
+		{
+			tvec4<bool> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( x ); ++i )
+				result[i] = rhs[i] > lhs[i];
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<bool> greater_than_equal( const tquat<T>& lhs, const tquat<T>& rhs )
+		{
+			tvec4<bool, P> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( x ); ++i )
+				result[i] = rhs[i] >= lhs[i];
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<bool> equal( const tquat<T>& lhs, const tquat<T>& rhs )
+		{
+			tvec4<bool, P> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( x ); ++i )
+				result[i] = rhs[i] == lhs[i];
+			return result;
+		}
+
+		template < typename T >
+		inline tvec4<bool> not_equal( const tquat<T>& lhs, const tquat<T>& rhs )
+		{
+			tvec4<bool> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( x ); ++i )
+				result[i] = rhs[i] != lhs[i];
+			return result;
+		}
+
+	}
+
+}
+
+#endif // NV_STL_MATH_QUATERNION_HH
Index: /trunk/nv/stl/math/relational.hh
===================================================================
--- /trunk/nv/stl/math/relational.hh	(revision 454)
+++ /trunk/nv/stl/math/relational.hh	(revision 454)
@@ -0,0 +1,138 @@
+// Copyright (C) 2015-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+/**
+* @file relational.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+* @brief relational math ops
+*/
+
+#ifndef NV_STL_MATH_RELATIONAL_HH
+#define NV_STL_MATH_RELATIONAL_HH
+
+#include <nv/stl/math/common.hh>
+
+namespace nv
+{
+
+	namespace math
+	{
+
+		namespace detail
+		{
+			template < typename T >
+			struct make_bool_vec;
+
+			template < typename T >
+			struct make_bool_vec< tvec2< T > >
+			{
+				typedef tvec2< bool > type;
+			};
+
+			template < typename T >
+			struct make_bool_vec< tvec3< T > >
+			{
+				typedef tvec3< bool > type;
+			};
+
+			template < typename T >
+			struct make_bool_vec< tvec4< T > >
+			{
+				typedef tvec4< bool > type;
+			};
+
+		}
+
+		template < typename T >
+		using bool_vec_t = typename detail::make_bool_vec<T>::type;
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t<T> less_than( const T& lhs, const T& rhs )
+		{
+			bool_vec_t<T> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( lhs ); ++i )
+				result[i] = lhs[i] < rhs[i];
+
+			return result;
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t<T> less_than_equal( const T& lhs, const T& rhs )
+		{
+			bool_vec_t<T> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( lhs ); ++i )
+				result[i] = lhs[i] <= rhs[i];
+			return result;
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t<T> greater_than( const T& lhs, const T& rhs )
+		{
+			bool_vec_t<T> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( lhs ); ++i )
+				result[i] = lhs[i] > rhs[i];
+			return result;
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t<T> greater_than_equal( const T& lhs, const T& rhs )
+		{
+			bool_vec_t<T> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( lhs ); ++i )
+				result[i] = lhs[i] >= rhs[i];
+			return result;
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t<T> equal( const T& lhs, const T& rhs )
+		{
+			bool_vec_t<T> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( lhs ); ++i )
+				result[i] = lhs[i] == rhs[i];
+			return result;
+		}
+
+		template < typename T, typename enable_if< is_vec<T>::value >::type* = nullptr >
+		inline bool_vec_t<T> not_equal( const T& lhs, const T& rhs )
+		{
+			bool_vec_t<T> result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( lhs ); ++i )
+				result[i] = lhs[i] != rhs[i];
+			return result;
+		}
+
+		template < typename T, typename enable_if< is_bool_vec<T>::value >::type* = nullptr >
+		inline bool any( const T& v )
+		{
+			bool result = false;
+			for ( component_count_t i = 0; i < component_count( v ); ++i )
+				result = result || v[i];
+			return result;
+		}
+
+		template < typename T, typename enable_if< is_bool_vec<T>::value >::type* = nullptr >
+		inline bool all( const T& v )
+		{
+			bool result = true;
+			for ( component_count_t i = 0; i < component_count( v ); ++i )
+				result = result && v[i];
+			return result;
+		}
+
+		template < typename T, typename enable_if< is_bool_vec<T>::value >::type* = nullptr >
+		inline T not_( const T& v )
+		{
+			T result( ctor::uninitialize );
+			for ( component_count_t i = 0; i < component_count( v ); ++i )
+				result[i] = !v[i];
+			return result;
+		}
+
+	}
+
+}
+
+#endif // NV_STL_MATH_RELATIONAL_HH
Index: /trunk/nv/stl/type_traits/common.hh
===================================================================
--- /trunk/nv/stl/type_traits/common.hh	(revision 453)
+++ /trunk/nv/stl/type_traits/common.hh	(revision 454)
@@ -227,4 +227,22 @@
 		return detail::addressof_impl<T>::f( detail::addressof_helper<T>( v ), 0 );
 	}
+
+
+	template < typename T >
+	struct extract_value_type
+	{
+		typedef typename T::value_type type;
+	};
+
+	template < typename T >
+	struct extract_size_type
+	{
+		typedef typename T::size_type type;
+	};
+
+	template < typename T >
+	using value_type_t = typename extract_value_type<T>::type;
+	template < typename T >
+	using size_type_t = typename extract_size_type<T>::type;
 
 	namespace detail
Index: /trunk/nv/stl/type_traits/transforms.hh
===================================================================
--- /trunk/nv/stl/type_traits/transforms.hh	(revision 453)
+++ /trunk/nv/stl/type_traits/transforms.hh	(revision 454)
@@ -82,5 +82,5 @@
 			typedef signed_type< remove_cv_t<T> > signed_type_result;
 		public:
-			typedef match_cv< T, typename signed_type_result::type > type;
+			typedef typename match_cv< T, typename signed_type_result::type >::type type;
 		};
 
@@ -107,5 +107,5 @@
 			typedef unsigned_type<remove_cv_t<T>> unsigned_type_result;
 		public:
-			typedef match_cv< T, typename unsigned_type_result::type > type;
+			typedef typename match_cv< T, typename unsigned_type_result::type >::type type;
 		};
 
Index: /trunk/src/core/random.cc
===================================================================
--- /trunk/src/core/random.cc	(revision 453)
+++ /trunk/src/core/random.cc	(revision 454)
@@ -231,5 +231,5 @@
 	vec2 opoint     = ellipse_edge( oradii );
 	vec2 opoint2    = opoint * opoint;
-	vec2 odir       = glm::normalize( opoint );
+	vec2 odir       = math::normalize( opoint );
 	f32 odist2    = opoint2.x + opoint2.y;
 
@@ -251,5 +251,5 @@
 	vec3 opoint     = ellipsoid_edge( oradii );
 	vec3 opoint2    = opoint * opoint;
-	vec3 odir       = glm::normalize( opoint );
+	vec3 odir       = math::normalize( opoint );
 	f32 odist2    = opoint2.x + opoint2.y + opoint2.z;
 
Index: /trunk/src/engine/particle_engine.cc
===================================================================
--- /trunk/src/engine/particle_engine.cc	(revision 453)
+++ /trunk/src/engine/particle_engine.cc	(revision 454)
@@ -231,5 +231,5 @@
 	datap->plane_normal = normalize_safe( datap->plane_normal, vec3(0.0f,1.0f,0.0f) );
 	datap->bounce       = table->get<float>("bounce", 0.0f );
-	datap->distance     = -glm::dot( datap->plane_normal, datap->plane_point ) / math::sqrt(glm::dot( datap->plane_normal, datap->plane_normal ) );
+	datap->distance     = -math::dot( datap->plane_normal, datap->plane_point ) / math::sqrt( math::dot( datap->plane_normal, datap->plane_normal ) );
 	return true;
 }
@@ -242,12 +242,12 @@
 		particle& pt = p[i];
 		vec3 direction  = pt.velocity * factor;
-		if ( glm::dot( datap->plane_normal, pt.position + direction ) + datap->distance <= 0.0f )
+		if ( math::dot( datap->plane_normal, pt.position + direction ) + datap->distance <= 0.0f )
 		{
-			float val = glm::dot( datap->plane_normal, pt.position ) + datap->distance;
+			float val = math::dot( datap->plane_normal, pt.position ) + datap->distance;
 			if ( val > 0.0f )
 			{
-				vec3 part_dir = direction * ( -val / glm::dot( datap->plane_normal, direction ) );
+				vec3 part_dir = direction * ( -val / math::dot( datap->plane_normal, direction ) );
 				pt.position = pt.position + part_dir + ( part_dir - direction ) * datap->bounce;
-				pt.velocity = glm::reflect( pt.velocity, datap->plane_normal ) * datap->bounce;
+				pt.velocity = math::reflect( pt.velocity, datap->plane_normal ) * datap->bounce;
 			}
 		}
@@ -273,5 +273,5 @@
 	for ( uint32 i = 0; i < count; ++i )
 	{
-		p[i].color = glm::clamp( p[i].color + adjustment, 0.0f, 1.0f );
+		p[i].color = math::clamp( p[i].color + adjustment, 0.0f, 1.0f );
 	}
 }
@@ -296,5 +296,5 @@
 	for ( uint32 i = 0; i < count; ++i )
 	{
-		p[i].size = glm::max( p[i].size + adjustment, vec2() );
+		p[i].size = math::max( p[i].size + adjustment, vec2() );
 	}
 }
@@ -347,6 +347,6 @@
 	}
 
-	data.common_up  = glm::normalize( table.get<vec3>("common_up",  vec3(1,0,0) ) );
-	data.common_dir = glm::normalize( table.get<vec3>("common_dir", vec3(0,1,0) ) );
+	data.common_up  = math::normalize( table.get<vec3>("common_up",  vec3(1,0,0) ) );
+	data.common_dir = math::normalize( table.get<vec3>("common_dir", vec3(0,1,0) ) );
 
 	vec2 def_size        = table.get<vec2>("size", vec2(0.1,0.1) );
@@ -409,9 +409,10 @@
 
 				edata.rate         = element.get<float>("rate", 1.0f );
-				edata.dir          = glm::normalize( element.get<vec3>("direction", vec3(0,1,0) ) );
+				edata.dir          = math::normalize( element.get<vec3>("direction", vec3(0,1,0) ) );
 				
 				edata.odir = vec3( 0, 0, 1 );
 				if ( edata.dir != vec3( 0, 1, 0 ) && edata.dir != vec3( 0, -1, 0 ) )
-					edata.odir = glm::normalize( glm::cross( edata.dir, vec3( 0, 1, 0 ) ) );		edata.cdir = glm::cross( edata.dir, edata.odir );
+					edata.odir = math::normalize( math::cross( edata.dir, vec3( 0, 1, 0 ) ) );
+				edata.cdir = math::cross( edata.dir, edata.odir );
 
 				data.emmiter_count++;
@@ -563,5 +564,5 @@
 		m_model_matrix = s.get_model();
 		m_camera_pos   = s.get_camera().get_position();
-		m_inv_view_dir = glm::normalize(-s.get_camera().get_direction());
+		m_inv_view_dir = math::normalize(-s.get_camera().get_direction());
 
 		update_emmiters( info, m_last_update );
@@ -636,29 +637,29 @@
 
 		vec3 view_dir( m_inv_view_dir );
-		if ( accurate_facing ) view_dir = glm::normalize( m_camera_pos - pdata.position );
+		if ( accurate_facing ) view_dir = math::normalize( m_camera_pos - pdata.position );
 
 		switch ( orientation )
 		{
 		case particle_orientation::POINT :
-			right   = glm::normalize( glm::cross( view_dir, vec3( 0, 1, 0 ) ) );
-			rot_mat = mat3( right, glm::cross( right, -view_dir ), -view_dir );
+			right   = math::normalize( math::cross( view_dir, vec3( 0, 1, 0 ) ) );
+			rot_mat = mat3( right, math::cross( right, -view_dir ), -view_dir );
 			break;
 		case particle_orientation::ORIENTED :
 			pdir    = normalize_safe( pdata.velocity, pdir );
-			right   = glm::normalize( glm::cross( pdir, view_dir ) );
-			rot_mat = mat3( right, pdir, glm::cross( pdir, right ) );
+			right   = math::normalize( math::cross( pdir, view_dir ) );
+			rot_mat = mat3( right, pdir, math::cross( pdir, right ) );
 			break;
 		case particle_orientation::ORIENTED_COMMON :
-			right   = glm::normalize( glm::cross( common_dir, view_dir ) );
-			rot_mat = mat3( right, common_dir, glm::cross( common_dir, right ) );
+			right   = math::normalize( math::cross( common_dir, view_dir ) );
+			rot_mat = mat3( right, common_dir, math::cross( common_dir, right ) );
 			break;
 		case particle_orientation::PERPENDICULAR :
 			pdir    = normalize_safe( pdata.velocity, pdir );
-			right   = glm::normalize( glm::cross( common_up, pdir ) );
-			rot_mat = mat3( right, common_up, glm::cross( common_up, right ) );
+			right   = math::normalize( math::cross( common_up, pdir ) );
+			rot_mat = mat3( right, common_up, math::cross( common_up, right ) );
 			break;
 		case particle_orientation::PERPENDICULAR_COMMON :
-			right   = glm::normalize( glm::cross( common_up, common_dir ) );
-			rot_mat = mat3( right, common_up, glm::cross( common_up, right ) );
+			right   = math::normalize( math::cross( common_up, common_dir ) );
+			rot_mat = mat3( right, common_up, math::cross( common_up, right ) );
 			break;
 		}
Index: /trunk/src/formats/assimp_loader.cc
===================================================================
--- /trunk/src/formats/assimp_loader.cc	(revision 453)
+++ /trunk/src/formats/assimp_loader.cc	(revision 454)
@@ -134,11 +134,11 @@
 		{
 			vec3 v = assimp_vec3_cast( mesh->mVertices[i] );
-			vec3 n = glm::normalize( assimp_vec3_cast( mesh->mNormals[i] ) );
-			vec3 t = glm::normalize( assimp_vec3_cast( mesh->mTangents[i] ) );
-			vec3 b = glm::normalize( assimp_vec3_cast( mesh->mBitangents[i] ) );
+			vec3 n = math::normalize( assimp_vec3_cast( mesh->mNormals[i] ) );
+			vec3 t = math::normalize( assimp_vec3_cast( mesh->mTangents[i] ) );
+			vec3 b = math::normalize( assimp_vec3_cast( mesh->mBitangents[i] ) );
 			vec2 s = assimp_st_cast( mesh->mTextureCoords[0][i] );
 
-			vec3 t_i = glm::normalize( t - n * glm::dot( n, t ) );
-			float det = ( glm::dot( glm::cross( n, t ), b ) );
+			vec3 t_i = math::normalize( t - n * math::dot( n, t ) );
+			float det = ( math::dot( math::cross( n, t ), b ) );
 			det = ( det < 0.0f ? -1.0f : 1.0f );
 			nv::vec4 vt( t_i[0], t_i[1], t_i[2], det );
@@ -441,5 +441,5 @@
 // 	{
 // 		vec3 scale_vec0 = assimp_vec3_cast( node->mScalingKeys[0].mValue );
-// 		float scale_value   = glm::length( math::abs( scale_vec0 - vec3(1,1,1) ) );
+// 		float scale_value   = math::length( math::abs( scale_vec0 - vec3(1,1,1) ) );
 // 		if ( node->mNumScalingKeys > 1 || scale_value > 0.001 ) 
 // 		{
Index: /trunk/src/formats/obj_loader.cc
===================================================================
--- /trunk/src/formats/obj_loader.cc	(revision 453)
+++ /trunk/src/formats/obj_loader.cc	(revision 454)
@@ -283,6 +283,6 @@
 			if ( ! (tv.x == 0.0f && tv.y == 0.0f && tv.z == 0.0f) )
 			{
-				m_data[a].tangent    = vec4( glm::normalize(tv - nv * glm::dot( nv, tv )), 0.0f ); 
-				m_data[a].tangent[3] = (glm::dot(glm::cross(nv, tv), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
+				m_data[a].tangent    = vec4( math::normalize(tv - nv * math::dot( nv, tv )), 0.0f );
+				m_data[a].tangent[3] = ( math::dot( math::cross(nv, tv), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
 			}
 		}
Index: /trunk/src/gfx/keyframed_mesh.cc
===================================================================
--- /trunk/src/gfx/keyframed_mesh.cc	(revision 453)
+++ /trunk/src/gfx/keyframed_mesh.cc	(revision 454)
@@ -217,7 +217,7 @@
 		for ( size_t i = 0; i < m_vertex_count; ++i )
 		{
-			vtx[i].position = glm::mix( prev[i].position, next[i].position, m_interpolation );
-			vtx[i].normal   = glm::mix( prev[i].normal,   next[i].normal,   m_interpolation );
-			vtx[i].tangent  = glm::mix( prev[i].tangent,  next[i].tangent,   m_interpolation );
+			vtx[i].position = math::mix( prev[i].position, next[i].position, m_interpolation );
+			vtx[i].normal   = math::mix( prev[i].normal,   next[i].normal,   m_interpolation );
+			vtx[i].tangent  = math::mix( prev[i].tangent,  next[i].tangent,   m_interpolation );
 		}
 	}
@@ -231,6 +231,6 @@
 		for ( size_t i = 0; i < m_vertex_count; ++i )
 		{
-			vtx[i].position = glm::mix( prev[i].position, next[i].position, m_interpolation );
-			vtx[i].normal   = glm::mix( prev[i].normal,   next[i].normal,   m_interpolation );
+			vtx[i].position = math::mix( prev[i].position, next[i].position, m_interpolation );
+			vtx[i].normal   = math::mix( prev[i].normal,   next[i].normal,   m_interpolation );
 		}
 	}
Index: /trunk/src/gfx/mesh_creator.cc
===================================================================
--- /trunk/src/gfx/mesh_creator.cc	(revision 453)
+++ /trunk/src/gfx/mesh_creator.cc	(revision 454)
@@ -95,5 +95,5 @@
 void nv::mesh_nodes_creator::transform( float scale, const mat3& r33 )
 {
-	mat3 ri33 = glm::inverse( r33 );
+	mat3 ri33 = math::inverse( r33 );
 	mat4 pre_transform ( scale * r33 );
 	mat4 post_transform( 1.f/scale * ri33 ); 
@@ -150,5 +150,5 @@
 			{
 				vec3& n = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + n_offset );
-				n = glm::normalize( normal_transform * n );
+				n = math::normalize( normal_transform * n );
 			}
 		if ( t_offset != -1 )
@@ -156,5 +156,5 @@
 			{
 				vec4& t = *reinterpret_cast<vec4*>(raw_data + vtx_size*i + t_offset );
-				t = vec4( glm::normalize( normal_transform * vec3(t) ), t[3] );
+				t = vec4( math::normalize( normal_transform * vec3(t) ), t[3] );
 			}
 	}
@@ -299,5 +299,5 @@
 			vec3 xyz2 = v2 - v1;
 
-			//vec3 normal = glm::cross( xyz1, xyz2 );
+			//vec3 normal = math::cross( xyz1, xyz2 );
 			//
 			//vtcs[ ti0 ].normal += normal;
@@ -323,6 +323,6 @@
 		if ( ! ( t.x == 0.0f && t.y == 0.0f && t.z == 0.0f ) )
 		{
-			tangents[i]    = vec4( glm::normalize(t - n * glm::dot( n, t )), 0.0f ); 
-			tangents[i][3] = (glm::dot(glm::cross(n, t), tangents2[i]) < 0.0f) ? -1.0f : 1.0f;
+			tangents[i]    = vec4( math::normalize(t - n * math::dot( n, t )), 0.0f );
+			tangents[i][3] = ( math::dot( math::cross(n, t), tangents2[i]) < 0.0f) ? -1.0f : 1.0f;
 		}
 	}
Index: /trunk/src/lua/lua_area.cc
===================================================================
--- /trunk/src/lua/lua_area.cc	(revision 453)
+++ /trunk/src/lua/lua_area.cc	(revision 454)
@@ -255,5 +255,5 @@
 	nv::rectangle* a = to_parea( L, 1 );
 	nv::ivec2*     c = to_pcoord( L, 2 );
-	*c = glm::clamp( *c, a->ul, a->lr );
+	*c = nv::math::clamp( *c, a->ul, a->lr );
 	return 0;
 }
@@ -263,5 +263,5 @@
 	nv::rectangle* a = to_parea( L, 1 );
 	nv::ivec2*     c = to_pcoord( L, 2 );
-	push_coord( L, glm::clamp( *c, a->ul, a->lr ) );
+	push_coord( L, nv::math::clamp( *c, a->ul, a->lr ) );
 	return 0;
 }
Index: /trunk/src/lua/lua_values.cc
===================================================================
--- /trunk/src/lua/lua_values.cc	(revision 453)
+++ /trunk/src/lua/lua_values.cc	(revision 454)
@@ -25,5 +25,5 @@
 void* nv::lua::detail::raw_check_userdata( lua_State *L, int index, const char* metatable )
 {
-	return luaL_checkudata( L, index, metatable );
+	return luaL_testudata( L, index, metatable );
 }
 
Index: /trunk/src/rogue/fov_recursive_shadowcasting.cc
===================================================================
--- /trunk/src/rogue/fov_recursive_shadowcasting.cc	(revision 453)
+++ /trunk/src/rogue/fov_recursive_shadowcasting.cc	(revision 454)
@@ -24,6 +24,6 @@
 	{
 		position max_radius = m_size-m_position;
-		max_radius = glm::max(max_radius,m_position);
-		m_radius = static_cast<int>( glm::length( vec2( max_radius ) ) )+1;
+		max_radius = math::max(max_radius,m_position);
+		m_radius = static_cast<int>( math::length( vec2( max_radius ) ) )+1;
 	}
 	m_radius2 = m_radius * m_radius;
Index: /trunk/src/sdl/sdl_audio.cc
===================================================================
--- /trunk/src/sdl/sdl_audio.cc	(revision 453)
+++ /trunk/src/sdl/sdl_audio.cc	(revision 454)
@@ -75,6 +75,6 @@
 			if ( relative != vec3() )
 			{
-				angle = math::degrees( -glm::orientedAngle( m_forward, glm::normalize( relative ), m_up ) );
-				distance = glm::clamp( 20.0f * glm::length( relative ), 0.0f, 255.0f );
+				angle = math::degrees( -math::oriented_angle( m_forward, math::normalize( relative ), m_up ) );
+				distance = math::clamp( 20.0f * math::length( relative ), 0.0f, 255.0f );
 			}
 			if ( angle < 0.0f ) angle += 360.0f;
