Index: /trunk/nv/lua/lua_glm.hh
===================================================================
--- /trunk/nv/lua/lua_glm.hh	(revision 53)
+++ /trunk/nv/lua/lua_glm.hh	(revision 53)
@@ -0,0 +1,40 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+#ifndef NV_LUA_GLM_HH
+#define NV_LUA_GLM_HH
+
+#include <nv/common.hh>
+#include <nv/lib/lua.hh>
+#include <glm/glm.hpp>
+
+void nlua_register_glm( lua_State* L );
+
+template< typename T >
+bool nlua_is_vec( lua_State* L, int index )
+{
+	return luaL_testudata( L, index, nv::get_type_name<T>() ) != 0;
+}
+
+template< typename T >
+T nlua_to_vec( lua_State* L, int index )
+{
+	return *(T*)luaL_checkudata( L, index, nv::get_type_name<T>() );
+}
+
+template< typename T >
+T* nlua_to_pvec( lua_State* L, int index )
+{
+	return (T*)luaL_checkudata( L, index, nv::get_type_name<T>() );
+}
+
+template< typename T >
+void nlua_push_vec( lua_State* L, const T& v )
+{
+	new (lua_newuserdata(L, sizeof(T))) T(v);
+	luaL_setmetatable( L, nv::get_type_name<T>() );
+}
+
+#endif // NV_LUA_GLM_HH
Index: /trunk/nv/types.hh
===================================================================
--- /trunk/nv/types.hh	(revision 52)
+++ /trunk/nv/types.hh	(revision 53)
@@ -109,4 +109,16 @@
 	template <> inline const char* get_type_name<f64> () { return "f64"; }
 
+	template <> inline const char* get_type_name< vec2 > () { return "vec2"; }
+	template <> inline const char* get_type_name< vec3 > () { return "vec3"; }
+	template <> inline const char* get_type_name< vec4 > () { return "vec4"; }
+
+	template <> inline const char* get_type_name< ivec2 > () { return "ivec2"; }
+	template <> inline const char* get_type_name< ivec3 > () { return "ivec3"; }
+	template <> inline const char* get_type_name< ivec4 > () { return "ivec4"; }
+
+	template <> inline const char* get_type_name< mat2 > () { return "mat2"; }
+	template <> inline const char* get_type_name< mat3 > () { return "mat3"; }
+	template <> inline const char* get_type_name< mat4 > () { return "mat4"; }
+
 	template <> inline const char* get_type_name<bool> () { return "bool"; }
 
Index: /trunk/src/lua/lua_glm.cc
===================================================================
--- /trunk/src/lua/lua_glm.cc	(revision 53)
+++ /trunk/src/lua/lua_glm.cc	(revision 53)
@@ -0,0 +1,344 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#include "nv/lua/lua_glm.hh"
+#include "nv/types.hh"
+#include "nv/string.hh"
+#include <new>
+
+static size_t nlua_swizzel_lookup[256];
+
+inline bool nlua_is_swizzel( const char* str, size_t 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 construct( lua_State* L, int index ) {
+		return T();
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< 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 construct( lua_State* L, int index ) {
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+			return nlua_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 construct( lua_State* L, int index ) {
+		typedef glm::detail::tvec2<T::value_type> vec2;
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+		{
+			if ( nlua_is_vec<T>( L, index ) )
+				return nlua_to_vec<T>( L, index );
+			else
+				return T( nlua_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 ), nlua_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 construct( lua_State* L, int index ) {
+		typedef glm::detail::tvec2<T::value_type> vec2;
+		typedef glm::detail::tvec3<T::value_type> vec3;
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+		{
+			if ( nlua_is_vec<T>( L, index ) )
+				return nlua_to_vec<T>( L, index );
+			else
+			{
+				if ( nlua_is_vec<vec3>( L, index ) )
+					return T( nlua_to_vec<vec3>( L, index ), lua_tonumber( L, index + 1 ) );
+				else
+				{
+					if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
+						return T( nlua_to_vec<vec2>( L, index ), nlua_to_vec<vec2>( L, index + 1 ) );
+					else
+						return T( nlua_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 ( nlua_is_vec<vec3>( L, index+1 ) )
+					return T( lua_tonumber( L, index ), nlua_to_vec<vec3>( L, index+1 ) );
+				else
+					return T( lua_tonumber( L, index ), nlua_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 ), nlua_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 )
+{
+	nlua_push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( T::value_type )>::construct( L, 1 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_call( lua_State* L )
+{
+	nlua_push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( T::value_type )>::construct( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+static int nlua_vec_unm( lua_State* L )
+{
+	nlua_push_vec<T>( L, -nlua_to_vec<T>( L, 1 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_add( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		nlua_push_vec<T>( L, (T::value_type)(lua_tonumber( L, 1 )) + nlua_to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + (T::value_type)(lua_tonumber( L, 2 )) );
+		else
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_sub( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		nlua_push_vec<T>( L, (T::value_type)(lua_tonumber( L, 1 )) - nlua_to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - (T::value_type)(lua_tonumber( L, 2 )) );
+		else
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_mul( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		nlua_push_vec<T>( L, (T::value_type)(lua_tonumber( L, 1 )) * nlua_to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * (T::value_type)(lua_tonumber( L, 2 )) );
+		else
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_div( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		nlua_push_vec<T>( L, (T::value_type)(lua_tonumber( L, 1 )) / nlua_to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / (T::value_type)(lua_tonumber( L, 2 )) );
+		else
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_eq( lua_State* L )
+{
+	lua_pushboolean( L, nlua_to_vec<T>( L, 1 ) == nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_get( lua_State* L )
+{
+	T v = nlua_to_vec<T>( L, 1 );
+	for ( size_t 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 = nlua_to_pvec<T>( L, 1 );
+	size_t len  = 0;
+	size_t vlen = v->length();
+	const char * key = lua_tolstring( L, 2, &len );
+	size_t 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 : nlua_push_vec( L, glm::detail::tvec2<T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]] ) ); return 1;
+		case 3 : nlua_push_vec( L, glm::detail::tvec3<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 : nlua_push_vec( L, glm::detail::tvec4<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;
+		}
+	}
+
+	lua_getglobal( L, nv::get_type_name<T>() );
+	lua_pushvalue( L, -2 );
+	lua_rawget( L, -2 );
+
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_newindex( lua_State* L )
+{
+	typedef glm::detail::tvec2<T::value_type> vec2;
+	typedef glm::detail::tvec3<T::value_type> vec3;
+	typedef glm::detail::tvec4<T::value_type> vec4;
+
+	T* v = nlua_to_pvec<T>( L, 1 );
+	size_t len  = 0;
+	size_t vlen = v->length();
+	const char * key = lua_tolstring( L, 2, &len );
+	size_t idx = 255;
+	if( len == 1 )
+	{
+		idx = nlua_swizzel_lookup[ key[ 0 ] ];
+		if ( idx < vlen )
+		{
+			(*v)[idx] = (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 = nlua_to_vec<vec2>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v2[i]; } return 0;
+		case 3 : { vec3 v3 = nlua_to_vec<vec3>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v3[i]; } return 0;
+		case 4 : { vec4 v4 = nlua_to_vec<vec4>(L,3); for (size_t i = 0; i<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 = nlua_to_vec<T>( L, 1 );
+	std::string s = "(";
+	for ( size_t i = 0; i < v.length(); ++i )
+	{
+		if (i > 0) s += ",";
+		s += nv::to_string(v[i]);
+	}
+	s+=")";
+	lua_pushstring( L, s.c_str() );
+	return 1;
+}
+
+template< typename T >
+int luaopen_vec( lua_State * L )
+{
+	static const struct luaL_Reg nlua_vec_f [] = {
+		{ "new",            nlua_vec_new<T> },
+		{ "get",            nlua_vec_get<T> },
+		{NULL, NULL}
+	};
+
+	static const struct luaL_Reg nlua_vec_fm [] = {
+		{ "__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::get_type_name<T>() );
+	luaL_setfuncs( L, nlua_vec_m, 0 );
+	lua_pop(L,1);
+	luaL_newlib(L, nlua_vec_f);
+	lua_newtable( L );
+	luaL_setfuncs( L, nlua_vec_fm, 0 );
+	lua_setmetatable( L, -2 );
+	return 1;
+}
+
+void nlua_register_glm( lua_State* L )
+{ 
+	for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255;
+	nlua_swizzel_lookup['x'] = 0;
+	nlua_swizzel_lookup['r'] = 0;
+	nlua_swizzel_lookup['s'] = 0;
+	nlua_swizzel_lookup['0'] = 0;
+	nlua_swizzel_lookup['y'] = 1;
+	nlua_swizzel_lookup['g'] = 1;
+	nlua_swizzel_lookup['t'] = 0;
+	nlua_swizzel_lookup['1'] = 1;
+	nlua_swizzel_lookup['z'] = 2;
+	nlua_swizzel_lookup['b'] = 2;
+	nlua_swizzel_lookup['u'] = 0;
+	nlua_swizzel_lookup['2'] = 2;
+	nlua_swizzel_lookup['w'] = 3;
+	nlua_swizzel_lookup['a'] = 3;
+	nlua_swizzel_lookup['v'] = 0;
+	nlua_swizzel_lookup['3'] = 3;
+	luaL_requiref(L, "ivec2", luaopen_vec<glm::ivec2>, 1);
+	luaL_requiref(L, "ivec3", luaopen_vec<glm::ivec3>, 1);
+	luaL_requiref(L, "ivec4", luaopen_vec<glm::ivec4>, 1);
+	luaL_requiref(L, "vec2", luaopen_vec<glm::vec2>, 1);
+	luaL_requiref(L, "vec3", luaopen_vec<glm::vec3>, 1);
+	luaL_requiref(L, "vec4", luaopen_vec<glm::vec4>, 1);
+}
+
Index: /trunk/tests/lualib_test/lualib_test.cc
===================================================================
--- /trunk/tests/lualib_test/lualib_test.cc	(revision 52)
+++ /trunk/tests/lualib_test/lualib_test.cc	(revision 53)
@@ -1,4 +1,5 @@
 #include <nv/lib/lua.hh>
 #include <nv/lua/lua_raw.hh>
+#include <nv/lua/lua_glm.hh>
 #include <nv/logger.hh>
 #include <string>
@@ -24,4 +25,6 @@
 		{ NULL, NULL}
 	};
+
+	nlua_register_glm( lua_state );
 
 	const luaL_Reg *lib = lualibs;
