Index: trunk/nv/common.hh
===================================================================
--- trunk/nv/common.hh	(revision 236)
+++ trunk/nv/common.hh	(revision 237)
@@ -101,6 +101,8 @@
 
 #if NV_COMPILER == NV_MSVC 
-#pragma warning(disable: 4201)
-#undef _SCL_SECURE_NO_WARNINGS // to prevent redefinig
+#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
+#pragma warning( disable : 4510 ) // default constructor could not be generated
+#pragma warning( disable : 4610 ) // object 'class' can never be instantiated - user-defined constructor required
+#undef _SCL_SECURE_NO_WARNINGS // to prevent redefining
 #define _SCL_SECURE_NO_WARNINGS
 #endif
@@ -170,4 +172,6 @@
 	typedef uint64 uid;
 
+	struct empty_type {};
+
 } // namespace nv
 
Index: trunk/nv/gfx/debug_draw.hh
===================================================================
--- trunk/nv/gfx/debug_draw.hh	(revision 237)
+++ trunk/nv/gfx/debug_draw.hh	(revision 237)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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_DEBUG_DRAW_HH
+#define NV_DEBUG_DRAW_HH
+
+#include <nv/common.hh>
+#include <nv/math.hh>
+#include <nv/interface/program.hh>
+#include <nv/interface/context.hh>
+
+namespace nv
+{
+	struct debug_vtx
+	{
+		vec3 position;
+		vec3 color;
+
+		debug_vtx( const vec3& v, const vec3& c )
+			: position(v), color( c ) {}
+	};
+
+	class debug_data
+	{
+	public:
+		debug_data( device* a_device );
+		void update();
+		void reset();
+		program*      get_program()      { return m_program; }
+		vertex_array* get_vertex_array() { return m_va; }
+		uint32        get_count()        { return m_data.size(); }
+
+		void push_line( const vec3& a, const vec3& b, const vec3& color );
+		void push_aabox( const vec3& a, const vec3& b, const vec3& color );
+		~debug_data();
+	private:
+		device*                  m_device;
+		program*                 m_program;
+		vertex_array*            m_va;
+		std::vector< debug_vtx > m_data;
+	};
+
+}
+
+#endif // NV_DEBUG_DRAW_HH
Index: trunk/nv/interface/device.hh
===================================================================
--- trunk/nv/interface/device.hh	(revision 236)
+++ trunk/nv/interface/device.hh	(revision 237)
@@ -55,4 +55,61 @@
 			return result;
 		}
+
+		template < typename VTX, slot SLOT >
+		void add_vertex_buffer_impl( vertex_array*, vertex_buffer*, const std::false_type& )
+		{
+		}
+
+		template < typename VTX, slot SLOT >
+		void add_vertex_buffer_impl( vertex_array* va, vertex_buffer* vb, const std::true_type& )
+		{
+			typedef vertex_slot_info< VTX, SLOT > vinfo;
+			typedef datatype_traits< typename vinfo::value_type > dt_traits;
+			va->add_vertex_buffer( SLOT, vb, type_to_enum< dt_traits::base_type >::type, dt_traits::size, vinfo::offset, sizeof( VTX ), false );
+		}
+
+		template < typename VTX, slot SLOT >
+		void add_vertex_buffer( vertex_array* va, vertex_buffer* vb )
+		{
+			add_vertex_buffer_impl< VTX, SLOT >( va, vb, std::integral_constant< bool, vertex_has_slot< VTX, SLOT >::value >() );
+		}
+
+
+		template < typename VTX >
+		vertex_array* create_vertex_array( const VTX* v, size_t count, buffer_hint hint )
+		{
+			vertex_array*  va = create_vertex_array();
+			vertex_buffer* vb = create_vertex_buffer( hint, count * sizeof( VTX ), v );
+			add_vertex_buffer< VTX, slot::POSITION >  ( va, vb );
+			add_vertex_buffer< VTX, slot::TEXCOORD >  ( va, vb );
+			add_vertex_buffer< VTX, slot::NORMAL   >  ( va, vb );
+			add_vertex_buffer< VTX, slot::TANGENT >   ( va, vb );
+			add_vertex_buffer< VTX, slot::BONEINDEX > ( va, vb );
+			add_vertex_buffer< VTX, slot::BONEWEIGHT >( va, vb );
+			add_vertex_buffer< VTX, slot::COLOR >     ( va, vb );
+			return va;
+		}
+
+		template < typename VTX >
+		vertex_array* create_vertex_array( const std::vector< VTX >& data, buffer_hint hint )
+		{
+			return create_vertex_array( data.data(), data.size(), hint );
+		}
+
+		template < typename VTX, typename IDX >
+		vertex_array* create_vertex_array( const VTX* v, size_t vcount, const IDX* i, size_t icount, buffer_hint hint )
+		{
+			vertex_array* va = create_vertex_array( v, vcount, hint );
+			index_buffer* ib = create_index_buffer( hint, icount * sizeof( IDX ), i );
+			va->set_index_buffer( ib, type_to_enum< IDX >::type, true );
+			return va;
+		}
+
+		template < typename VTX, typename IDX >
+		vertex_array* create_vertex_array( const std::vector< VTX >& data, const std::vector< IDX >& idata, buffer_hint hint )
+		{
+			return create_vertex_array( data.data(), data.size(), idata.data(), idata.size(), hint );
+		}
+
 		virtual ~device() {}
 	};
Index: trunk/nv/interface/program.hh
===================================================================
--- trunk/nv/interface/program.hh	(revision 236)
+++ trunk/nv/interface/program.hh	(revision 237)
@@ -15,4 +15,5 @@
 #include <unordered_map>
 #include <nv/interface/uniform.hh>
+#include <nv/interface/vertex.hh>
 #include <nv/logging.hh>
 #include <nv/exception.hh>
@@ -24,15 +25,4 @@
 {
 	class camera;
-
-	enum slot
-	{
-		POSITION   = 0,
-		TEXCOORD   = 1,
-		NORMAL     = 2,
-		TANGENT    = 3,
-		BONEINDEX  = 4,
-		BONEWEIGHT = 5,
-		COLOR      = 6,
-	};
 
 	enum texture_slot
Index: trunk/nv/interface/vertex.hh
===================================================================
--- trunk/nv/interface/vertex.hh	(revision 237)
+++ trunk/nv/interface/vertex.hh	(revision 237)
@@ -0,0 +1,283 @@
+// Copyright (C) 2014 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
+
+// WARNING: this file is explicitly designed to fuck with your brain
+
+#ifndef NV_VERTEX_HH
+#define NV_VERTEX_HH
+
+#include <nv/common.hh>
+#include <nv/math.hh>
+
+namespace nv
+{
+
+	enum slot
+	{
+		POSITION       = 0,
+		TEXCOORD       = 1,
+		NORMAL         = 2,
+		TANGENT        = 3,
+		BONEINDEX      = 4,
+		BONEWEIGHT     = 5,
+		COLOR          = 6,
+
+		SLOT_MAX       = 6,
+		SLOT_MAX_STORE = 8,
+	};
+
+// 	struct vertex_descriptor
+// 	{
+// 		static const datatype position_etype   = NONE;
+// 		static const datatype normal_etype     = NONE;
+// 		static const datatype texcoord_etype   = NONE;
+// 		static const datatype tangent_etype    = NONE;
+// 		static const datatype boneindex_etype  = NONE;
+// 		static const datatype boneweight_etype = NONE;
+// 		static const datatype color_etype      = NONE;
+// 	};
+// 
+// 	template < typename VD >
+// 	struct vertex_type 
+// 		: public VD
+// 
+// 	{
+// 		typedef typename enum_to_type< VD::position_etype >::type    position_type;
+// 		typedef typename enum_to_type< VD::normal_etype >::type      normal_type;
+// 		typedef typename enum_to_type< VD::texcoord_etype >::type    texcoord_type;
+// 		typedef typename enum_to_type< VD::tangent_etype >::type     tangent_type;
+// 		typedef typename enum_to_type< VD::boneindex_etype >::type   boneindex_type;
+// 		typedef typename enum_to_type< VD::boneweight_etype >::type  boneweight_type;
+// 		typedef typename enum_to_type< VD::color_etype >::type       color_type;
+// 	};
+
+	namespace detail
+	{
+
+		template < typename VT, slot SLOT >
+		struct vertex_has_slot_impl
+		{
+			static bool const value = false;
+		};
+
+		template < typename VT >
+		struct vertex_has_slot_impl< VT, POSITION >
+		{
+		private:
+			struct fallback { int position; };
+			struct derived : VT, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::position>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;;
+		};
+
+		template < typename VT >
+		struct vertex_has_slot_impl< VT, NORMAL >
+		{
+		private:
+			struct fallback { int normal; };
+			struct derived : VT, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::normal>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;
+		};
+
+		template < typename VT >
+		struct vertex_has_slot_impl< VT, TEXCOORD >
+		{
+		private:
+			struct fallback { int texcoord; };
+			struct derived : VT, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::texcoord>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;
+		};
+
+		template < typename VT >
+		struct vertex_has_slot_impl< VT, TANGENT >
+		{
+		private:
+			struct fallback { int tangent; };
+			struct derived : VT, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::tangent>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;
+		};
+
+		template < typename VT >
+		struct vertex_has_slot_impl< VT, BONEINDEX >
+		{
+		private:
+			struct fallback { int boneindex; };
+			struct derived : VT, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::boneindex>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;
+		};
+
+		template < typename VT >
+		struct vertex_has_slot_impl< VT, BONEWEIGHT >
+		{
+		private:
+			struct fallback { int boneweight; };
+			struct derived : VT, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::boneweight>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;
+		};
+
+		template < typename VT >
+		struct vertex_has_slot_impl< VT, COLOR >
+		{
+		private:
+			struct fallback { int color; };
+			struct derived : VT, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::color>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;
+		};
+
+		template < typename VT, slot SLOT, bool HAS_SLOT >
+		struct vertex_slot_info_impl
+		{
+		};
+
+		template < typename VT, slot SLOT >
+		struct vertex_slot_info_impl < VT, SLOT, false >
+		{
+			typedef empty_type value_type;
+			static const datatype etype  = datatype::NONE;
+			static const int      offset = 0;
+		};
+
+		template < typename VT >
+		struct vertex_slot_info_impl< VT, POSITION, true >
+		{
+			typedef decltype( VT::position ) value_type;
+			static const datatype etype  = type_to_enum< decltype( VT::position ) >::type;
+			static const int      offset = offsetof( VT, position );
+		};
+
+		template < typename VT >
+		struct vertex_slot_info_impl< VT, TEXCOORD, true >
+		{
+			typedef decltype( VT::texcoord ) value_type;
+			static const datatype etype  = type_to_enum< decltype( VT::texcoord ) >::type;
+			static const int      offset = offsetof( VT, texcoord );
+		};
+
+		template < typename VT >
+		struct vertex_slot_info_impl< VT, NORMAL, true >
+		{
+			typedef decltype( VT::normal ) value_type;
+			static const datatype etype  = type_to_enum< decltype( VT::normal ) >::type;
+			static const int      offset = offsetof( VT, normal );
+		};
+
+		template < typename VT >
+		struct vertex_slot_info_impl< VT, TANGENT, true >
+		{
+			typedef decltype( VT::tangent ) value_type;
+			static const datatype etype  = type_to_enum< decltype( VT::tangent ) >::type;
+			static const int      offset = offsetof( VT, tangent );
+		};
+
+		template < typename VT >
+		struct vertex_slot_info_impl< VT, BONEINDEX, true >
+		{
+			typedef decltype( VT::boneindex ) value_type;
+			static const datatype etype  = type_to_enum< decltype( VT::boneindex ) >::type;
+			static const int      offset = offsetof( VT, boneindex );
+		};
+
+		template < typename VT >
+		struct vertex_slot_info_impl< VT, BONEWEIGHT, true >
+		{
+			typedef decltype( VT::boneweight ) value_type;
+			static const datatype etype  = type_to_enum< decltype( VT::boneweight ) >::type;
+			static const int      offset = offsetof( VT, boneweight );
+		};
+
+		template < typename VT >
+		struct vertex_slot_info_impl< VT, COLOR, true >
+		{
+			typedef decltype( VT::color ) value_type;
+			static const datatype etype  = type_to_enum< decltype( VT::color ) >::type;
+			static const int      offset = offsetof( VT, color );
+		};
+	
+	}
+
+	template < typename VT, slot SLOT >
+	struct vertex_has_slot : public detail::vertex_has_slot_impl< VT, SLOT >
+	{
+	};
+
+
+	template < typename VT, slot SLOT >
+	struct vertex_slot_info : public detail::vertex_slot_info_impl< VT, SLOT, detail::vertex_has_slot_impl< VT, SLOT >::value >
+	{
+	};
+
+	struct vertex_descriptor_slot
+	{
+		datatype etype;
+		uint32   offset;
+		slot     vslot;
+	};
+
+	struct vertex_descriptor
+	{
+		vertex_descriptor_slot slots[ SLOT_MAX_STORE ];
+		uint32                 count;
+		uint32                 size;
+
+		template < typename VTX >
+		void initialize()
+		{
+			count = 0;
+			initialize_slot< VTX, slot::POSITION >();
+			initialize_slot< VTX, slot::TEXCOORD >();
+			initialize_slot< VTX, slot::NORMAL >();
+			initialize_slot< VTX, slot::TANGENT >();
+			initialize_slot< VTX, slot::BONEINDEX >();
+			initialize_slot< VTX, slot::BONEWEIGHT >();
+			initialize_slot< VTX, slot::COLOR >();
+			size = sizeof( VTX );
+		}
+	private:
+		template < typename VTX, slot SLOT >
+		void initialize_slot()
+		{
+			typedef vertex_slot_info< VTX, SLOT > slot_info;
+			slots[ count ].etype  = slot_info::etype;
+			if ( slots[ count ].etype != datatype::NONE )
+			{
+				slots[ count ].vslot  = SLOT;
+				slots[ count ].offset = slot_info::offset;
+				count++
+			}
+		}
+
+	};
+
+}
+
+#endif // NV_VERTEX_HH
Index: trunk/nv/math.hh
===================================================================
--- trunk/nv/math.hh	(revision 236)
+++ trunk/nv/math.hh	(revision 237)
@@ -83,4 +83,5 @@
 	enum datatype
 	{
+		NONE,
 		INT,
 		BYTE,
@@ -107,4 +108,5 @@
 	template < datatype EnumType > struct enum_to_type {};
 
+	template <> struct enum_to_type< NONE >  { typedef void type; };
 	template <> struct enum_to_type< INT >   { typedef int type; };
 	template <> struct enum_to_type< UINT >  { typedef unsigned int type; };
@@ -160,4 +162,22 @@
 	template <> struct type_to_enum< mat4 > { static const datatype type = FLOAT_MATRIX_4; };
 
+	template < typename T >
+	struct sizeof_type 
+	{
+		static const int result = sizeof( T );
+	};
+
+	template <>
+	struct sizeof_type< void >
+	{
+		static const int result = 0;
+	};
+
+	template < datatype T >
+	struct sizeof_enum_type 
+	{
+		static const int result = sizeof_type< typename enum_to_type<T>::type >::result;
+	};
+
 
 } // namespace nv
Index: trunk/src/gfx/debug_draw.cc
===================================================================
--- trunk/src/gfx/debug_draw.cc	(revision 237)
+++ trunk/src/gfx/debug_draw.cc	(revision 237)
@@ -0,0 +1,79 @@
+// Copyright (C) 2014 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/gfx/debug_draw.hh"
+
+#include "nv/interface/device.hh"
+
+static const char *nv_debug_draw_vertex_shader =
+	"#version 120\n"
+	"attribute vec3 nv_position;\n"
+	"attribute vec3 nv_color;\n"
+	"varying vec3 v_color;\n"
+	"uniform mat4 nv_m_mvp;\n"
+	"void main(void)\n"
+	"{\n"
+	"	gl_Position = nv_m_mvp * vec4 (nv_position, 1.0);\n"
+	"	v_color     = nv_color;\n"
+	"}\n";
+static const char *nv_debug_draw_fragment_shader =
+	"#version 120\n"
+	"varying vec3 v_color;\n"
+	"void main(void)\n"
+	"{\n"
+	"	gl_FragColor = vec4( v_color, 1.0 );\n"
+	"}\n";
+
+nv::debug_data::debug_data( device* a_device )
+	: m_device( a_device ), m_program( nullptr ), m_va( nullptr )
+{
+	m_program = m_device->create_program( nv_debug_draw_vertex_shader, nv_debug_draw_fragment_shader );
+}
+
+void nv::debug_data::update()
+{
+	delete m_va;
+	m_va = m_device->create_vertex_array( m_data, nv::STATIC_DRAW );
+}
+
+void nv::debug_data::reset()
+{
+	m_data.clear();
+}
+
+void nv::debug_data::push_line( const vec3& a, const vec3& b, const vec3& color )
+{
+	m_data.emplace_back( a, color );
+	m_data.emplace_back( b, color );
+}
+
+void nv::debug_data::push_aabox( const vec3& a, const vec3& b, const vec3& color )
+{
+	vec3 corners[8] =
+	{
+		vec3( a.x, a.y, a.z ), vec3( b.x, a.y, a.z ), vec3( b.x, a.y, b.z ), vec3( a.x, a.y, b.z ),
+		vec3( a.x, b.y, a.z ), vec3( b.x, b.y, a.z ), vec3( b.x, b.y, b.z ), vec3( a.x, b.y, b.z ),
+	};
+
+	push_line( corners[0], corners[1], color );
+	push_line( corners[1], corners[2], color );
+	push_line( corners[2], corners[3], color );
+	push_line( corners[3], corners[0], color );
+	push_line( corners[0], corners[4], color );
+	push_line( corners[1], corners[5], color );
+	push_line( corners[2], corners[6], color );
+	push_line( corners[3], corners[7], color );
+	push_line( corners[4], corners[5], color );
+	push_line( corners[5], corners[6], color );
+	push_line( corners[6], corners[7], color );
+	push_line( corners[7], corners[4], color );
+}
+
+nv::debug_data::~debug_data()
+{
+	delete m_va;
+	delete m_program;
+}
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 236)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 237)
@@ -58,7 +58,8 @@
 	// Technically this is not needed, because the va is just a fake class, 
 	// but if it's real it will be needed?
-	m_va->update_vertex_buffer( nv::slot::POSITION, m_vb_position, false );
-	m_va->update_vertex_buffer( nv::slot::NORMAL,   m_vb_normal,   false );
-	m_va->update_vertex_buffer( nv::slot::TANGENT,  m_vb_tangent,  false );
+// 	m_va->update_vertex_buffer( nv::slot::POSITION, m_vb_position, false );
+// 	m_va->update_vertex_buffer( nv::slot::NORMAL,   m_vb_normal,   false );
+// 	m_va->update_vertex_buffer( nv::slot::TANGENT,  m_vb_tangent,  false );
+	// TODO: answer is - probably not
 }
 
Index: trunk/src/gl/gl_enum.cc
===================================================================
--- trunk/src/gl/gl_enum.cc	(revision 236)
+++ trunk/src/gl/gl_enum.cc	(revision 237)
@@ -246,4 +246,22 @@
 	case GL_INT_VEC3       : return INT_VECTOR_3;
 	case GL_INT_VEC4       : return INT_VECTOR_4;
+// TODO: separate types?
+	case GL_SAMPLER_1D         : return INT;
+	case GL_SAMPLER_2D         : return INT;
+	case GL_SAMPLER_3D         : return INT;
+	case GL_SAMPLER_CUBE       : return INT;
+	case GL_SAMPLER_1D_SHADOW  : return INT;	
+	case GL_SAMPLER_2D_SHADOW  : return INT;
+// TODO: implement?
+//	case GL_BOOL	
+//	case GL_BOOL_VEC2
+//	case GL_BOOL_VEC3
+//	case GL_BOOL_VEC4
+//	case GL_FLOAT_MAT2x3	
+//	case GL_FLOAT_MAT2x4	
+//	case GL_FLOAT_MAT3x2	
+//	case GL_FLOAT_MAT3x4	
+//	case GL_FLOAT_MAT4x2	
+//	case GL_FLOAT_MAT4x3	
 	default : return datatype(0); // TODO: throw!
 	}
Index: trunk/src/gl/gl_program.cc
===================================================================
--- trunk/src/gl/gl_program.cc	(revision 236)
+++ trunk/src/gl/gl_program.cc	(revision 237)
@@ -197,5 +197,7 @@
 		}
 
-		m_uniform_map[ name ] = create_uniform( utype, name, uni_loc, uni_len );
+		uniform_base* u = create_uniform( utype, name, uni_loc, uni_len );
+		NV_ASSERT( u, "Unknown uniform type!" );
+		m_uniform_map[ name ] = u;
 	}
 
Index: trunk/tests/objload_test/objload_test.cc
===================================================================
--- trunk/tests/objload_test/objload_test.cc	(revision 236)
+++ trunk/tests/objload_test/objload_test.cc	(revision 237)
@@ -32,5 +32,5 @@
 	nv::vertex_array* m_va;
 	nv::program*      m_program;
-	nv::mesh_data*    m_mesh;
+	nv::mesh_data_old* m_mesh;
 	nv::uint32        m_count;
 };
@@ -39,5 +39,5 @@
 {
 	m_device = new nv::gl_device();
-	m_window = m_device->create_window( 800, 600 );
+	m_window = m_device->create_window( 800, 600, false );
 	nv::sampler sampler( nv::sampler::LINEAR, nv::sampler::REPEAT );
 	
