Index: trunk/nv/lua/lua_area.hh
===================================================================
--- trunk/nv/lua/lua_area.hh	(revision 451)
+++ trunk/nv/lua/lua_area.hh	(revision 452)
@@ -10,5 +10,5 @@
 #include <nv/common.hh>
 #include <nv/core/position.hh>
-#include <nv/lua/lua_glm.hh>
+#include <nv/lua/lua_math.hh>
 #include <nv/lua/lua_state.hh>
 #include <nv/lua/lua_values.hh>
Index: trunk/nv/lua/lua_glm.hh
===================================================================
--- trunk/nv/lua/lua_glm.hh	(revision 451)
+++ 	(revision )
@@ -1,66 +1,0 @@
-// Copyright (C) 2012-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.
-
-#ifndef NV_LUA_GLM_HH
-#define NV_LUA_GLM_HH
-
-#include <nv/common.hh>
-#include <nv/stl/math.hh>
-#include <nv/lua/lua_values.hh>
-
-namespace nv
-{
-	namespace lua
-	{
-		void register_glm( lua_State* L );
-
-		template<> struct pass_traits< vec2 >  : metatable_pass_traits< vec2 >  { static const char* metatable() { return "vec2"; } };
-		template<> struct pass_traits< vec3 >  : metatable_pass_traits< vec3 >  { static const char* metatable() { return "vec3"; } };
-		template<> struct pass_traits< vec4 >  : metatable_pass_traits< vec4 >  { static const char* metatable() { return "vec4"; } };
-		template<> struct pass_traits< ivec2 > : metatable_pass_traits< ivec2 > { static const char* metatable() { return "ivec2"; } };
-		template<> struct pass_traits< ivec3 > : metatable_pass_traits< ivec3 > { static const char* metatable() { return "ivec2"; } };
-		template<> struct pass_traits< ivec4 > : metatable_pass_traits< ivec4 > { static const char* metatable() { return "ivec2"; } };
-
-		namespace detail
-		{
-			template< typename T >
-			bool is_vec( lua_State* L, int index )
-			{
-				return is_userdata( L, index, pass_traits<T>::metatable() );
-			}
-
-			template< typename T >
-			T to_vec( lua_State* L, int index )
-			{
-				return pass_traits<T>::to( L, index );
-			}
-
-			template< typename T >
-			T to_vec( lua_State* L, int index, const T& def )
-			{
-				return pass_traits<T>::to( L, index, def );
-			}
-
-			template< typename T >
-			T* to_pvec( lua_State* L, int index )
-			{
-				return to_userdata<T>( L, index );
-			}
-
-			template< typename T >
-			void push_vec( lua_State* L, const T& v )
-			{
-				pass_traits<T>::push( L, v );
-			}
-
-		}
-
-	}
-
-}
-
-
-#endif // NV_LUA_GLM_HH
Index: trunk/nv/lua/lua_math.hh
===================================================================
--- trunk/nv/lua/lua_math.hh	(revision 452)
+++ trunk/nv/lua/lua_math.hh	(revision 452)
@@ -0,0 +1,66 @@
+// Copyright (C) 2012-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.
+
+#ifndef NV_LUA_MATH_HH
+#define NV_LUA_MATH_HH
+
+#include <nv/common.hh>
+#include <nv/stl/math.hh>
+#include <nv/lua/lua_values.hh>
+
+namespace nv
+{
+	namespace lua
+	{
+		void register_math( lua_State* L );
+
+		template<> struct pass_traits< vec2 >  : metatable_pass_traits< vec2 >  { static const char* metatable() { return "vec2"; } };
+		template<> struct pass_traits< vec3 >  : metatable_pass_traits< vec3 >  { static const char* metatable() { return "vec3"; } };
+		template<> struct pass_traits< vec4 >  : metatable_pass_traits< vec4 >  { static const char* metatable() { return "vec4"; } };
+		template<> struct pass_traits< ivec2 > : metatable_pass_traits< ivec2 > { static const char* metatable() { return "ivec2"; } };
+		template<> struct pass_traits< ivec3 > : metatable_pass_traits< ivec3 > { static const char* metatable() { return "ivec2"; } };
+		template<> struct pass_traits< ivec4 > : metatable_pass_traits< ivec4 > { static const char* metatable() { return "ivec2"; } };
+
+		namespace detail
+		{
+			template< typename T >
+			bool is_vec( lua_State* L, int index )
+			{
+				return is_userdata( L, index, pass_traits<T>::metatable() );
+			}
+
+			template< typename T >
+			T to_vec( lua_State* L, int index )
+			{
+				return pass_traits<T>::to( L, index );
+			}
+
+			template< typename T >
+			T to_vec( lua_State* L, int index, const T& def )
+			{
+				return pass_traits<T>::to( L, index, def );
+			}
+
+			template< typename T >
+			T* to_pvec( lua_State* L, int index )
+			{
+				return to_userdata<T>( L, index );
+			}
+
+			template< typename T >
+			void push_vec( lua_State* L, const T& v )
+			{
+				pass_traits<T>::push( L, v );
+			}
+
+		}
+
+	}
+
+}
+
+
+#endif // NV_LUA_MATH_HH
Index: trunk/src/engine/particle_engine.cc
===================================================================
--- trunk/src/engine/particle_engine.cc	(revision 451)
+++ trunk/src/engine/particle_engine.cc	(revision 452)
@@ -10,5 +10,5 @@
 #include <nv/core/random.hh>
 #include <nv/stl/utility.hh>
-#include <nv/lua/lua_glm.hh>
+#include <nv/lua/lua_math.hh>
 #include <nv/core/logging.hh>
 
Index: trunk/src/lua/lua_glm.cc
===================================================================
--- trunk/src/lua/lua_glm.cc	(revision 451)
+++ 	(revision )
@@ -1,392 +1,0 @@
-// Copyright (C) 2012-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.
-
-#include "nv/lua/lua_glm.hh"
-
-#include "nv/lua/lua_raw.hh"
-#include "nv/core/random.hh"
-#include "nv/stl/type_traits/common.hh"
-
-static int nlua_swizzel_lookup[256];
-
-using nv::lua::detail::is_vec;
-using nv::lua::detail::to_vec;
-using nv::lua::detail::to_pvec;
-using nv::lua::detail::push_vec;
-
-inline bool nlua_is_swizzel( const unsigned char* str, int max )
-{
-	while (*str)
-	{
-		if (nlua_swizzel_lookup[*str] > max) return false;
-		str++;
-	}
-	return true;
-}
-
-template < typename T, size_t k >
-struct nlua_vec_constructor {
-	static inline T unit() { return T(); }
-	static inline T construct( lua_State*, int ) {
-		return T();
-	}
-};
-
-template < typename T > struct nlua_vec_constructor< T, 1 > {
-	static inline T unit() { return T( 1 ); }
-	static inline T construct( lua_State* L, int index ) {
-		return T( lua_tonumber( L, index ) );
-	}
-};
-
-template < typename T > struct nlua_vec_constructor< T, 2 > {
-	static inline T unit() { return T( 1, 1 ); }
-	static inline T construct( lua_State* L, int index ) {
-		if ( lua_type( L, index ) == LUA_TUSERDATA )
-			return to_vec<T>( L, index );
-		else
-			return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ) );
-	}
-};
-
-template < typename T > struct nlua_vec_constructor< T, 3 > {
-	static inline T unit() { return T( 1, 1, 1 ); }
-	static inline T construct( lua_State* L, int index ) {
-		typedef nv::math::tvec2<typename T::value_type> vec2;
-		if ( lua_type( L, index ) == LUA_TUSERDATA )
-		{
-			if ( is_vec<T>( L, index ) )
-				return to_vec<T>( L, index );
-			else
-				return T( to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ) );
-		}
-		else
-		{
-			if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
-				return T( lua_tonumber( L, index ), to_vec<vec2>( L, index+1 ) );
-			else
-				return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
-		}
-	}
-};
-
-template < typename T > struct nlua_vec_constructor< T, 4 > {
-	static inline T unit() { return T( 1, 1, 1, 1 ); }
-	static inline T construct( lua_State* L, int index ) {
-		typedef nv::math::tvec2<typename T::value_type> vec2;
-		typedef nv::math::tvec3<typename T::value_type> vec3;
-		if ( lua_type( L, index ) == LUA_TUSERDATA )
-		{
-			if ( is_vec<T>( L, index ) )
-				return to_vec<T>( L, index );
-			else
-			{
-				if ( is_vec<vec3>( L, index ) )
-					return T( to_vec<vec3>( L, index ), lua_tonumber( L, index + 1 ) );
-				else
-				{
-					if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
-						return T( to_vec<vec2>( L, index ), to_vec<vec2>( L, index + 1 ) );
-					else
-						return T( to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
-				}
-			}
-		}
-		else
-		{
-			if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
-			{
-				if ( is_vec<vec3>( L, index+1 ) )
-					return T( lua_tonumber( L, index ), to_vec<vec3>( L, index+1 ) );
-				else
-					return T( lua_tonumber( L, index ), to_vec<vec2>( L, index+1 ), lua_tonumber( L, index + 2 ) );
-			}
-			else
-			{
-				if ( lua_type( L, index+2 ) == LUA_TUSERDATA )
-					return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), to_vec<vec2>( L, index+2 ) );
-				else
-					return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ), lua_tonumber( L, index + 3 ) );
-			}
-		}
-	}
-};
-
-template< typename T >
-int nlua_vec_new( lua_State* L )
-{
-	push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 1 ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_random( lua_State* L )
-{
-	push_vec<T>( L, nv::random::get().range( to_vec<T>( L, 1 ), to_vec<T>( L, 2 ) ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_clone( lua_State* L )
-{
-	push_vec<T>( L, to_vec<T>( L, 1 ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_call( lua_State* L )
-{
-	push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 2 ) );
-	return 1;
-}
-
-template< typename T >
-static int nlua_vec_unm( lua_State* L )
-{
-	push_vec<T>( L, -to_vec<T>( L, 1 ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_add( lua_State* L )
-{
-	if ( lua_type( L, 1 ) == LUA_TNUMBER )
-		push_vec<T>( L, static_cast<typename T::value_type>(lua_tonumber( L, 1 )) + to_vec<T>( L, 2 ) );
-	else
-		if ( lua_type( L, 2 ) == LUA_TNUMBER )
-			push_vec<T>( L, to_vec<T>( L, 1 ) + static_cast<typename T::value_type>(lua_tonumber( L, 2 )) );
-		else
-			push_vec<T>( L, to_vec<T>( L, 1 ) + to_vec<T>( L, 2 ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_sub( lua_State* L )
-{
-	if ( lua_type( L, 1 ) == LUA_TNUMBER )
-		push_vec<T>( L, static_cast<typename T::value_type>(lua_tonumber( L, 1 )) - to_vec<T>( L, 2 ) );
-	else
-		if ( lua_type( L, 2 ) == LUA_TNUMBER )
-			push_vec<T>( L, to_vec<T>( L, 1 ) - static_cast<typename T::value_type>(lua_tonumber( L, 2 )) );
-		else
-			push_vec<T>( L, to_vec<T>( L, 1 ) - to_vec<T>( L, 2 ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_mul( lua_State* L )
-{
-	if ( lua_type( L, 1 ) == LUA_TNUMBER )
-		push_vec<T>( L, static_cast<typename T::value_type>(lua_tonumber( L, 1 )) * to_vec<T>( L, 2 ) );
-	else
-		if ( lua_type( L, 2 ) == LUA_TNUMBER )
-			push_vec<T>( L, to_vec<T>( L, 1 ) * static_cast<typename T::value_type>(lua_tonumber( L, 2 )) );
-		else
-			push_vec<T>( L, to_vec<T>( L, 1 ) * to_vec<T>( L, 2 ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_div( lua_State* L )
-{
-	if ( lua_type( L, 1 ) == LUA_TNUMBER )
-		push_vec<T>( L, static_cast<typename T::value_type>(lua_tonumber( L, 1 )) / to_vec<T>( L, 2 ) );
-	else
-		if ( lua_type( L, 2 ) == LUA_TNUMBER )
-			push_vec<T>( L, to_vec<T>( L, 1 ) / static_cast<typename T::value_type>(lua_tonumber( L, 2 )) );
-		else
-			push_vec<T>( L, to_vec<T>( L, 1 ) / to_vec<T>( L, 2 ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_eq( lua_State* L )
-{
-	lua_pushboolean( L, to_vec<T>( L, 1 ) == to_vec<T>( L, 2 ) );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_get( lua_State* L )
-{
-	T v = to_vec<T>( L, 1 );
-	for ( int i = 0; i < v.length(); ++i )
-	{
-		lua_pushnumber( L, v[i] );
-	}
-	return v.length();
-}
-
-template< typename T >
-int nlua_vec_index( lua_State* L )
-{
-	T* v = to_pvec<T>( L, 1 );
-	size_t len  = 0;
-	int vlen = v->length();
-	const unsigned char * key = reinterpret_cast<const unsigned char *>( lua_tolstring( L, 2, &len ) );
-	int idx = 255;
-
-	if ( len == 1 )
-	{
-		idx = nlua_swizzel_lookup[ key[ 0 ] ];
-		if ( idx < vlen )
-		{
-			lua_pushnumber( L, (*v)[idx] );
-			return 1;
-		}
-	}
-	else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
-	{
-		switch (len) {
-		case 2 : push_vec( L, nv::math::tvec2<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]] ) ); return 1;
-		case 3 : push_vec( L, nv::math::tvec3<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]] ) ); return 1;
-		case 4 : push_vec( L, nv::math::tvec4<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]], (*v)[nlua_swizzel_lookup[key[3]]] ) ); return 1;
-		default: break;
-		}
-	}
-
-	luaL_getmetafield( L, 1, "__functions" );
-	lua_pushvalue( L, 2 );
-	lua_rawget( L, -2 );
-	return 1;
-}
-
-template< typename T >
-int nlua_vec_newindex( lua_State* L )
-{
-	typedef nv::math::tvec2<typename T::value_type> vec2;
-	typedef nv::math::tvec3<typename T::value_type> vec3;
-	typedef nv::math::tvec4<typename T::value_type> vec4;
-
-	T* v = to_pvec<T>( L, 1 );
-	size_t len  = 0;
-	int vlen = v->length();
-	const unsigned char * key = reinterpret_cast<const unsigned char *>( lua_tolstring( L, 2, &len ) );
-	int idx = 255;
-	if( len == 1 )
-	{
-		idx = nlua_swizzel_lookup[ key[ 0 ] ];
-		if ( idx < vlen )
-		{
-			(*v)[idx] = static_cast<typename T::value_type>( luaL_checknumber( L, 3 ) );
-			return 0;
-		}
-	}
-	else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
-	{
- 		switch (len) {
-		case 2 : { vec2 v2 = to_vec<vec2>(L,3); for ( int i = 0; i<int( len ); ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v2[i]; } return 0;
-		case 3 : { vec3 v3 = to_vec<vec3>(L,3); for ( int i = 0; i<int( len ); ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v3[i]; } return 0;
-		case 4 : { vec4 v4 = to_vec<vec4>(L,3); for ( int i = 0; i<int( len ); ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v4[i]; } return 0;
- 		default: break;
-		}
-	}
-	return 0;
-}
-
-template< typename T >
-static int nlua_vec_tostring( lua_State* L )
-{
-	T v = to_vec<T>( L, 1 );
-	bool fl = nv::is_floating_point<typename T::value_type>::value;
-	switch ( v.length() )
-	{
-	case 1: lua_pushfstring( L, ( fl ? "(%f)"          : "(%d)" ),          v[0] ); break;
-	case 2: lua_pushfstring( L, ( fl ? "(%f,%f)"       : "(%d,%d)" ),       v[0], v[1] ); break;
-	case 3: lua_pushfstring( L, ( fl ? "(%f,%f,%f)"    : "(%d,%d,%d)" ),    v[0], v[1], v[2] ); break;
-	case 4: lua_pushfstring( L, ( fl ? "(%f,%f,%f,%f)" : "(%d,%d,%d,%d)" ), v[0], v[1], v[2], v[3] ); break;
-	default:
-		lua_pushliteral( L, "(vector?)" ); break;
-	}
-	return 1;
-}
-
-template< typename T >
-int luaopen_vec( lua_State * L )
-{
-	static const struct luaL_Reg nlua_vec_sf [] = {
-		{ "new",            nlua_vec_new<T> },
-		{ "random",         nlua_vec_random<T> },
-		{NULL, NULL}
-	};
-
-	static const struct luaL_Reg nlua_vec_f [] = {
-		{ "clone",          nlua_vec_clone<T> },
-		{ "get",            nlua_vec_get<T> },
-		{ "tostring",       nlua_vec_tostring<T> },
-		{NULL, NULL}
-	};
-
-	static const struct luaL_Reg nlua_vec_sm [] = {
-		{ "__call",         nlua_vec_call<T> },
-		{NULL, NULL}
-	};
-
-	static const struct luaL_Reg nlua_vec_m [] = {
-		{ "__add",      nlua_vec_add<T> },
-		{ "__sub",      nlua_vec_sub<T> },
-		{ "__unm",      nlua_vec_unm<T> },
-		{ "__mul",      nlua_vec_mul<T> },
-		{ "__div",      nlua_vec_div<T> },
-		{ "__eq",       nlua_vec_eq<T> },
-		{ "__index",    nlua_vec_index<T> },
-		{ "__newindex", nlua_vec_newindex<T> },
-		{ "__tostring", nlua_vec_tostring<T> },
-		{NULL, NULL}
-	};
-
-	luaL_newmetatable( L, nv::lua::pass_traits<T>::metatable() );
-	nlua_register( L, nlua_vec_m, -1 );
-	lua_createtable( L, 0, 0 );
-	nlua_register( L, nlua_vec_f, -1 );
-	lua_setfield(L, -2, "__functions" );
-	lua_pop( L, 1 );
-
-	lua_createtable( L, 0, 0 );
-	nlua_register( L, nlua_vec_sf, -1 );
-	lua_createtable( L, 0, 0 );
-	nlua_register( L, nlua_vec_sm, -1 );
-	lua_setmetatable( L, -2 );
-
-	nv::lua::detail::push_vec( L, T() );
-	lua_setfield( L, -2, "ZERO" );
-	nv::lua::detail::push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::unit() );
-	lua_setfield( L, -2, "UNIT" );
-	return 1;
-}
-
-void nv::lua::register_glm( lua_State* L )
-{ 
-	for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255;
-	using nv::uchar8;
-	nlua_swizzel_lookup[uchar8( 'x' )] = 0;
-	nlua_swizzel_lookup[uchar8( 'r' )] = 0;
-	nlua_swizzel_lookup[uchar8( 's' )] = 0;
-	nlua_swizzel_lookup[uchar8( '0' )] = 0;
-	nlua_swizzel_lookup[uchar8( 'y' )] = 1;
-	nlua_swizzel_lookup[uchar8( 'g' )] = 1;
-	nlua_swizzel_lookup[uchar8( 't' )] = 0;
-	nlua_swizzel_lookup[uchar8( '1' )] = 1;
-	nlua_swizzel_lookup[uchar8( 'z' )] = 2;
-	nlua_swizzel_lookup[uchar8( 'b' )] = 2;
-	nlua_swizzel_lookup[uchar8( 'u' )] = 0;
-	nlua_swizzel_lookup[uchar8( '2' )] = 2;
-	nlua_swizzel_lookup[uchar8( 'w' )] = 3;
-	nlua_swizzel_lookup[uchar8( 'a' )] = 3;
-	nlua_swizzel_lookup[uchar8( 'v' )] = 0;
-	nlua_swizzel_lookup[uchar8( '3' )] = 3;
-	int stack = lua_gettop( L );
-
-	luaL_requiref(L, "coord", luaopen_vec<nv::ivec2>, 1);
-	luaL_requiref(L, "ivec2", luaopen_vec<nv::ivec2>, 1);
-	luaL_requiref(L, "ivec3", luaopen_vec<nv::ivec3>, 1);
-	luaL_requiref(L, "ivec4", luaopen_vec<nv::ivec4>, 1);
-	luaL_requiref(L, "vec2", luaopen_vec<nv::vec2>, 1);
-	luaL_requiref(L, "vec3", luaopen_vec<nv::vec3>, 1);
-	luaL_requiref(L, "vec4", luaopen_vec<nv::vec4>, 1);
-	lua_settop( L, stack );
-}
-
Index: trunk/src/lua/lua_map_area.cc
===================================================================
--- trunk/src/lua/lua_map_area.cc	(revision 451)
+++ trunk/src/lua/lua_map_area.cc	(revision 452)
@@ -8,5 +8,5 @@
 #include "nv/stl/flags.hh"
 #include "nv/lua/lua_area.hh"
-#include "nv/lua/lua_glm.hh"
+#include "nv/lua/lua_math.hh"
 #include "nv/lua/lua_values.hh"
 #include "nv/lua/lua_raw.hh"
Index: trunk/src/lua/lua_map_tile.cc
===================================================================
--- trunk/src/lua/lua_map_tile.cc	(revision 451)
+++ trunk/src/lua/lua_map_tile.cc	(revision 452)
@@ -13,5 +13,5 @@
 #include "nv/core/random.hh"
 #include "nv/lua/lua_area.hh"
-#include "nv/lua/lua_glm.hh"
+#include "nv/lua/lua_math.hh"
 #include "nv/lua/lua_values.hh"
 #include "nv/lua/lua_raw.hh"
Index: trunk/src/lua/lua_math.cc
===================================================================
--- trunk/src/lua/lua_math.cc	(revision 452)
+++ trunk/src/lua/lua_math.cc	(revision 452)
@@ -0,0 +1,392 @@
+// Copyright (C) 2012-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.
+
+#include "nv/lua/lua_math.hh"
+
+#include "nv/lua/lua_raw.hh"
+#include "nv/core/random.hh"
+#include "nv/stl/type_traits/common.hh"
+
+static int nlua_swizzel_lookup[256];
+
+using nv::lua::detail::is_vec;
+using nv::lua::detail::to_vec;
+using nv::lua::detail::to_pvec;
+using nv::lua::detail::push_vec;
+
+inline bool nlua_is_swizzel( const unsigned char* str, int max )
+{
+	while (*str)
+	{
+		if (nlua_swizzel_lookup[*str] > max) return false;
+		str++;
+	}
+	return true;
+}
+
+template < typename T, size_t k >
+struct nlua_vec_constructor {
+	static inline T unit() { return T(); }
+	static inline T construct( lua_State*, int ) {
+		return T();
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< T, 1 > {
+	static inline T unit() { return T( 1 ); }
+	static inline T construct( lua_State* L, int index ) {
+		return T( lua_tonumber( L, index ) );
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< T, 2 > {
+	static inline T unit() { return T( 1, 1 ); }
+	static inline T construct( lua_State* L, int index ) {
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+			return to_vec<T>( L, index );
+		else
+			return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ) );
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< T, 3 > {
+	static inline T unit() { return T( 1, 1, 1 ); }
+	static inline T construct( lua_State* L, int index ) {
+		typedef nv::math::tvec2<typename T::value_type> vec2;
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+		{
+			if ( is_vec<T>( L, index ) )
+				return to_vec<T>( L, index );
+			else
+				return T( to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ) );
+		}
+		else
+		{
+			if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
+				return T( lua_tonumber( L, index ), to_vec<vec2>( L, index+1 ) );
+			else
+				return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
+		}
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< T, 4 > {
+	static inline T unit() { return T( 1, 1, 1, 1 ); }
+	static inline T construct( lua_State* L, int index ) {
+		typedef nv::math::tvec2<typename T::value_type> vec2;
+		typedef nv::math::tvec3<typename T::value_type> vec3;
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+		{
+			if ( is_vec<T>( L, index ) )
+				return to_vec<T>( L, index );
+			else
+			{
+				if ( is_vec<vec3>( L, index ) )
+					return T( to_vec<vec3>( L, index ), lua_tonumber( L, index + 1 ) );
+				else
+				{
+					if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
+						return T( to_vec<vec2>( L, index ), to_vec<vec2>( L, index + 1 ) );
+					else
+						return T( to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
+				}
+			}
+		}
+		else
+		{
+			if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
+			{
+				if ( is_vec<vec3>( L, index+1 ) )
+					return T( lua_tonumber( L, index ), to_vec<vec3>( L, index+1 ) );
+				else
+					return T( lua_tonumber( L, index ), to_vec<vec2>( L, index+1 ), lua_tonumber( L, index + 2 ) );
+			}
+			else
+			{
+				if ( lua_type( L, index+2 ) == LUA_TUSERDATA )
+					return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), to_vec<vec2>( L, index+2 ) );
+				else
+					return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ), lua_tonumber( L, index + 3 ) );
+			}
+		}
+	}
+};
+
+template< typename T >
+int nlua_vec_new( lua_State* L )
+{
+	push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 1 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_random( lua_State* L )
+{
+	push_vec<T>( L, nv::random::get().range( to_vec<T>( L, 1 ), to_vec<T>( L, 2 ) ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_clone( lua_State* L )
+{
+	push_vec<T>( L, to_vec<T>( L, 1 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_call( lua_State* L )
+{
+	push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+static int nlua_vec_unm( lua_State* L )
+{
+	push_vec<T>( L, -to_vec<T>( L, 1 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_add( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		push_vec<T>( L, static_cast<typename T::value_type>(lua_tonumber( L, 1 )) + to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			push_vec<T>( L, to_vec<T>( L, 1 ) + static_cast<typename T::value_type>(lua_tonumber( L, 2 )) );
+		else
+			push_vec<T>( L, to_vec<T>( L, 1 ) + to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_sub( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		push_vec<T>( L, static_cast<typename T::value_type>(lua_tonumber( L, 1 )) - to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			push_vec<T>( L, to_vec<T>( L, 1 ) - static_cast<typename T::value_type>(lua_tonumber( L, 2 )) );
+		else
+			push_vec<T>( L, to_vec<T>( L, 1 ) - to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_mul( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		push_vec<T>( L, static_cast<typename T::value_type>(lua_tonumber( L, 1 )) * to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			push_vec<T>( L, to_vec<T>( L, 1 ) * static_cast<typename T::value_type>(lua_tonumber( L, 2 )) );
+		else
+			push_vec<T>( L, to_vec<T>( L, 1 ) * to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_div( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		push_vec<T>( L, static_cast<typename T::value_type>(lua_tonumber( L, 1 )) / to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			push_vec<T>( L, to_vec<T>( L, 1 ) / static_cast<typename T::value_type>(lua_tonumber( L, 2 )) );
+		else
+			push_vec<T>( L, to_vec<T>( L, 1 ) / to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_eq( lua_State* L )
+{
+	lua_pushboolean( L, to_vec<T>( L, 1 ) == to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_get( lua_State* L )
+{
+	T v = to_vec<T>( L, 1 );
+	for ( int i = 0; i < v.length(); ++i )
+	{
+		lua_pushnumber( L, v[i] );
+	}
+	return v.length();
+}
+
+template< typename T >
+int nlua_vec_index( lua_State* L )
+{
+	T* v = to_pvec<T>( L, 1 );
+	size_t len  = 0;
+	int vlen = v->length();
+	const unsigned char * key = reinterpret_cast<const unsigned char *>( lua_tolstring( L, 2, &len ) );
+	int idx = 255;
+
+	if ( len == 1 )
+	{
+		idx = nlua_swizzel_lookup[ key[ 0 ] ];
+		if ( idx < vlen )
+		{
+			lua_pushnumber( L, (*v)[idx] );
+			return 1;
+		}
+	}
+	else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
+	{
+		switch (len) {
+		case 2 : push_vec( L, nv::math::tvec2<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]] ) ); return 1;
+		case 3 : push_vec( L, nv::math::tvec3<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]] ) ); return 1;
+		case 4 : push_vec( L, nv::math::tvec4<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]], (*v)[nlua_swizzel_lookup[key[3]]] ) ); return 1;
+		default: break;
+		}
+	}
+
+	luaL_getmetafield( L, 1, "__functions" );
+	lua_pushvalue( L, 2 );
+	lua_rawget( L, -2 );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_newindex( lua_State* L )
+{
+	typedef nv::math::tvec2<typename T::value_type> vec2;
+	typedef nv::math::tvec3<typename T::value_type> vec3;
+	typedef nv::math::tvec4<typename T::value_type> vec4;
+
+	T* v = to_pvec<T>( L, 1 );
+	size_t len  = 0;
+	int vlen = v->length();
+	const unsigned char * key = reinterpret_cast<const unsigned char *>( lua_tolstring( L, 2, &len ) );
+	int idx = 255;
+	if( len == 1 )
+	{
+		idx = nlua_swizzel_lookup[ key[ 0 ] ];
+		if ( idx < vlen )
+		{
+			(*v)[idx] = static_cast<typename T::value_type>( luaL_checknumber( L, 3 ) );
+			return 0;
+		}
+	}
+	else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
+	{
+ 		switch (len) {
+		case 2 : { vec2 v2 = to_vec<vec2>(L,3); for ( int i = 0; i<int( len ); ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v2[i]; } return 0;
+		case 3 : { vec3 v3 = to_vec<vec3>(L,3); for ( int i = 0; i<int( len ); ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v3[i]; } return 0;
+		case 4 : { vec4 v4 = to_vec<vec4>(L,3); for ( int i = 0; i<int( len ); ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v4[i]; } return 0;
+ 		default: break;
+		}
+	}
+	return 0;
+}
+
+template< typename T >
+static int nlua_vec_tostring( lua_State* L )
+{
+	T v = to_vec<T>( L, 1 );
+	bool fl = nv::is_floating_point<typename T::value_type>::value;
+	switch ( v.length() )
+	{
+	case 1: lua_pushfstring( L, ( fl ? "(%f)"          : "(%d)" ),          v[0] ); break;
+	case 2: lua_pushfstring( L, ( fl ? "(%f,%f)"       : "(%d,%d)" ),       v[0], v[1] ); break;
+	case 3: lua_pushfstring( L, ( fl ? "(%f,%f,%f)"    : "(%d,%d,%d)" ),    v[0], v[1], v[2] ); break;
+	case 4: lua_pushfstring( L, ( fl ? "(%f,%f,%f,%f)" : "(%d,%d,%d,%d)" ), v[0], v[1], v[2], v[3] ); break;
+	default:
+		lua_pushliteral( L, "(vector?)" ); break;
+	}
+	return 1;
+}
+
+template< typename T >
+int luaopen_vec( lua_State * L )
+{
+	static const struct luaL_Reg nlua_vec_sf [] = {
+		{ "new",            nlua_vec_new<T> },
+		{ "random",         nlua_vec_random<T> },
+		{NULL, NULL}
+	};
+
+	static const struct luaL_Reg nlua_vec_f [] = {
+		{ "clone",          nlua_vec_clone<T> },
+		{ "get",            nlua_vec_get<T> },
+		{ "tostring",       nlua_vec_tostring<T> },
+		{NULL, NULL}
+	};
+
+	static const struct luaL_Reg nlua_vec_sm [] = {
+		{ "__call",         nlua_vec_call<T> },
+		{NULL, NULL}
+	};
+
+	static const struct luaL_Reg nlua_vec_m [] = {
+		{ "__add",      nlua_vec_add<T> },
+		{ "__sub",      nlua_vec_sub<T> },
+		{ "__unm",      nlua_vec_unm<T> },
+		{ "__mul",      nlua_vec_mul<T> },
+		{ "__div",      nlua_vec_div<T> },
+		{ "__eq",       nlua_vec_eq<T> },
+		{ "__index",    nlua_vec_index<T> },
+		{ "__newindex", nlua_vec_newindex<T> },
+		{ "__tostring", nlua_vec_tostring<T> },
+		{NULL, NULL}
+	};
+
+	luaL_newmetatable( L, nv::lua::pass_traits<T>::metatable() );
+	nlua_register( L, nlua_vec_m, -1 );
+	lua_createtable( L, 0, 0 );
+	nlua_register( L, nlua_vec_f, -1 );
+	lua_setfield(L, -2, "__functions" );
+	lua_pop( L, 1 );
+
+	lua_createtable( L, 0, 0 );
+	nlua_register( L, nlua_vec_sf, -1 );
+	lua_createtable( L, 0, 0 );
+	nlua_register( L, nlua_vec_sm, -1 );
+	lua_setmetatable( L, -2 );
+
+	nv::lua::detail::push_vec( L, T() );
+	lua_setfield( L, -2, "ZERO" );
+	nv::lua::detail::push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::unit() );
+	lua_setfield( L, -2, "UNIT" );
+	return 1;
+}
+
+void nv::lua::register_math( lua_State* L )
+{ 
+	for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255;
+	using nv::uchar8;
+	nlua_swizzel_lookup[uchar8( 'x' )] = 0;
+	nlua_swizzel_lookup[uchar8( 'r' )] = 0;
+	nlua_swizzel_lookup[uchar8( 's' )] = 0;
+	nlua_swizzel_lookup[uchar8( '0' )] = 0;
+	nlua_swizzel_lookup[uchar8( 'y' )] = 1;
+	nlua_swizzel_lookup[uchar8( 'g' )] = 1;
+	nlua_swizzel_lookup[uchar8( 't' )] = 0;
+	nlua_swizzel_lookup[uchar8( '1' )] = 1;
+	nlua_swizzel_lookup[uchar8( 'z' )] = 2;
+	nlua_swizzel_lookup[uchar8( 'b' )] = 2;
+	nlua_swizzel_lookup[uchar8( 'u' )] = 0;
+	nlua_swizzel_lookup[uchar8( '2' )] = 2;
+	nlua_swizzel_lookup[uchar8( 'w' )] = 3;
+	nlua_swizzel_lookup[uchar8( 'a' )] = 3;
+	nlua_swizzel_lookup[uchar8( 'v' )] = 0;
+	nlua_swizzel_lookup[uchar8( '3' )] = 3;
+	int stack = lua_gettop( L );
+
+	luaL_requiref(L, "coord", luaopen_vec<nv::ivec2>, 1);
+	luaL_requiref(L, "ivec2", luaopen_vec<nv::ivec2>, 1);
+	luaL_requiref(L, "ivec3", luaopen_vec<nv::ivec3>, 1);
+	luaL_requiref(L, "ivec4", luaopen_vec<nv::ivec4>, 1);
+	luaL_requiref(L, "vec2", luaopen_vec<nv::vec2>, 1);
+	luaL_requiref(L, "vec3", luaopen_vec<nv::vec3>, 1);
+	luaL_requiref(L, "vec4", luaopen_vec<nv::vec4>, 1);
+	lua_settop( L, stack );
+}
+
