Index: trunk/nv/engine/model_manager.hh
===================================================================
--- trunk/nv/engine/model_manager.hh	(revision 507)
+++ trunk/nv/engine/model_manager.hh	(revision 507)
@@ -0,0 +1,135 @@
+// Copyright (C) 2016-2016 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 model_manager.hh
+* @author Kornel Kisielewicz
+* @brief model_manager
+*/
+
+#ifndef NV_ENGINE_MODEL_MANAGER_HH
+#define NV_ENGINE_MODEL_MANAGER_HH
+
+#include <nv/common.hh>
+#include <nv/core/resource.hh>
+#include <nv/core/random.hh>
+#include <nv/interface/mesh_data.hh>
+#include <nv/engine/material_manager.hh>
+#include <nv/engine/mesh_manager.hh>
+#include <nv/engine/animation.hh>
+#include <nv/engine/resource_system.hh>
+
+#define MNODE 1
+
+namespace nv
+{
+
+	struct model_node
+	{
+		resource< data_channel_set > mesh;
+		resource< material >         material;
+		transform                    local;
+		sint16                       attach_id;
+		float                        chance;
+		bool                         random_rotate_y;
+		bool                         force;
+		vector< model_node* >        children;
+
+		model_node() : attach_id( 0 ), chance( 1.0f ), random_rotate_y( false ), force( false ) {}
+
+		~model_node()
+		{
+			for ( auto c : children ) delete c;
+		}
+	};
+
+	struct model : model_node
+	{
+		resource< animator_data >      animator;
+		resource< animator_bind_data > bind_data;
+		transform                      root;
+		shash64                        attach;
+ 	};
+
+	struct flat_model_element
+	{
+		resource< data_channel_set > mesh;
+		resource< material >         material;
+		sint16                       attach_id;
+		sint16                       parent_id;
+		transform					 local;
+	};
+
+	struct flat_model
+	{
+		flat_model_element             elements[8];
+		uint32                         count;
+		shash64                        attach;
+		transform					   local;
+	};
+
+	NV_RTTI_DECLARE_NAME( model, "model" )
+
+	class model_manager : public lua_resource_manager< model >
+	{
+	public:
+		model_manager( resource_manager* rm, animator_bind_manager* binds, mesh_data_manager* mesh_datas )
+			: m_rm( rm )
+			, m_animator_binds( binds )
+			, m_mesh_datas( mesh_datas )
+		{
+		}
+		virtual string_view get_storage_name() const { return "models"; }
+		virtual string_view get_resource_name() const { return "model"; }
+		static flat_model flatten( const model* m, random_base& rng )
+		{
+			flat_model result;
+			if ( !m ) return result;
+			result.attach = m->attach;
+			result.local = m->root;
+			result.count = 0;
+			flatten( result, m, rng, transform(), -1 );
+			return result;
+		}
+	protected:
+		static void flatten( flat_model& result, const model_node* m, random_base& rng, const transform& ptr, sint32 parent_id )
+		{
+			if ( m->chance < 1.0f )
+				if ( rng.frand() > m->chance )
+					return;
+			transform tr = ptr * m->local;
+			if ( m->random_rotate_y )
+				tr = tr * transform( math::angle_axis( nv::math::pi<float>() * 2.0f * rng.frand(), vec3( 0.0f, 1.0f, 0.0f ) ) );
+
+			if ( m->mesh || m->force )
+			{
+				uint32 id = result.count++;
+				flat_model_element& re = result.elements[id];
+				re.mesh = m->mesh;
+				re.material = m->material;
+				re.local = tr;
+				re.parent_id = parent_id;
+				re.attach_id = m->attach_id;
+				parent_id = id;
+			}
+			for ( auto c : m->children )
+			{
+				flatten( result, c, rng, tr, parent_id );
+			}
+		}
+
+	protected:
+		virtual bool load_resource( lua::table_guard& table, shash64 id );
+		void read_model_node( lua::table_guard& table, model_node* node, resource< mesh_data > def_data );
+	private:
+		resource_manager*      m_rm;
+		animator_bind_manager* m_animator_binds;
+		mesh_data_manager*     m_mesh_datas;
+	};
+
+}
+
+#endif // NV_ENGINE_MODEL_MANAGER_HH
Index: trunk/nv/engine/renderer.hh
===================================================================
--- trunk/nv/engine/renderer.hh	(revision 507)
+++ trunk/nv/engine/renderer.hh	(revision 507)
@@ -0,0 +1,40 @@
+// Copyright (C) 2016-2016 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 image_manager.hh
+* @author Kornel Kisielewicz
+* @brief image_manager
+*/
+
+#ifndef NV_ENGINE_RENDERER_HH
+#define NV_ENGINE_RENDERER_HH
+
+#include <nv/common.hh>
+#include <nv/core/resource.hh>
+#include <nv/interface/device.hh>
+#include <nv/interface/context.hh>
+
+namespace nv
+{
+	struct render_pass
+	{
+		render_state rstate;
+		clear_state  cstate;
+		framebuffer  fbuffer;
+		output_slot  output[8];
+		uint32       output_count;
+
+	};
+
+	class renderer
+	{
+
+	};
+
+}
+
+#endif // NV_ENGINE_RENDERER_HH
Index: trunk/nv/lua/lua_gfx.hh
===================================================================
--- trunk/nv/lua/lua_gfx.hh	(revision 507)
+++ trunk/nv/lua/lua_gfx.hh	(revision 507)
@@ -0,0 +1,67 @@
+// Copyright (C) 2016-2016 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 lua_gfx.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+*/
+
+#ifndef NV_LUA_GFX_HH
+#define NV_LUA_GFX_HH
+
+#include <nv/common.hh>
+#include <nv/interface/device.hh>
+#include <nv/interface/context.hh>
+#include <nv/lua/lua_state.hh>
+#include <nv/lua/lua_math.hh>
+
+namespace nv
+{
+	namespace lua
+	{
+		void register_gfx( lua_State* L );
+
+		template<>
+		struct pass_traits< color_mask > : metatable_pass_traits< color_mask >
+		{
+			static const char* metatable() { return "color_mask"; }
+		};
+
+		template<>
+		struct pass_traits< scissor_test > : metatable_pass_traits< scissor_test >
+		{
+			static const char* metatable() { return "scissor_test"; }
+		};
+
+		template<>
+		struct pass_traits< clear_state > : metatable_pass_traits< clear_state >
+		{
+			static const char* metatable() { return "clear_state"; }
+		};
+
+		namespace detail
+		{
+			inline bool is_color_mask( lua_State* L, int index ) { return is_userdata( L, index, pass_traits<color_mask>::metatable() ); }
+			inline color_mask to_color_mask( lua_State* L, int index ) { return pass_traits<color_mask>::to( L, index ); }
+			inline color_mask* to_pcolor_mask( lua_State* L, int index ) { return to_userdata<color_mask>( L, index ); }
+			inline void push_color_mask( lua_State* L, const color_mask& v ) { pass_traits<color_mask>::push( L, v ); }
+
+			inline bool is_scissor_test( lua_State* L, int index ) { return is_userdata( L, index, pass_traits<scissor_test>::metatable() ); }
+			inline scissor_test to_scissor_test( lua_State* L, int index ) { return pass_traits<scissor_test>::to( L, index ); }
+			inline scissor_test* to_pscissor_test( lua_State* L, int index ) { return to_userdata<scissor_test>( L, index ); }
+			inline void push_scissor_test( lua_State* L, const scissor_test& v ) { pass_traits<scissor_test>::push( L, v ); }
+
+			inline bool is_clear_state( lua_State* L, int index ) { return is_userdata( L, index, pass_traits<clear_state>::metatable() ); }
+			inline clear_state to_clear_state( lua_State* L, int index ) { return pass_traits<clear_state>::to( L, index ); }
+			inline clear_state* to_pclear_state( lua_State* L, int index ) { return to_userdata<clear_state>( L, index ); }
+			inline void push_clear_state( lua_State* L, const clear_state& v ) { pass_traits<clear_state>::push( L, v ); }
+		}
+
+
+	}
+}
+
+#endif // NV_LUA_MAP_TILE_HH
Index: trunk/src/engine/model_manager.cc
===================================================================
--- trunk/src/engine/model_manager.cc	(revision 507)
+++ trunk/src/engine/model_manager.cc	(revision 507)
@@ -0,0 +1,94 @@
+// Copyright (C) 2016-2016 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/engine/model_manager.hh"
+
+#include "nv/lua/lua_math.hh"
+
+using namespace nv;
+
+bool nv::model_manager::load_resource( lua::table_guard& table, shash64 id )
+{
+	model* gm = new model;
+	gm->attach = table.get_string_hash_64( "attach" );
+	gm->root = transform( table.get<vec3>( "position", vec3() ) );
+
+	resource< mesh_data > def_data;
+	if ( table.is_string( "path" ) )
+		def_data = m_rm->get< mesh_data >( table.get_string128( "path" ) );
+
+	if ( table.has_field( "animator" ) )
+	{
+		gm->animator = m_rm->get< animator_data >( table.get_string( "animator" ) );
+		pose_data_set* poses = gm->animator.lock()->poses;
+		if ( !def_data || !def_data.lock()->node_data )
+			gm->bind_data = m_animator_binds->add( id, new animator_bind_data( poses->get_tree(), poses->get_tree() ) );
+		else
+			gm->bind_data = m_animator_binds->add( id, new animator_bind_data( poses->get_tree(), *def_data.lock()->node_data ) );
+	}
+
+	if ( table.is_table( "model" ) )
+	{
+		lua::table_guard model_table( table, "model" );
+		read_model_node( model_table, gm, def_data );
+	}
+
+	add( id, gm );
+	return true;
+}
+
+
+
+void nv::model_manager::read_model_node( lua::table_guard& table, model_node* node, resource< mesh_data > def_data )
+{
+	resource< data_channel_set > cmesh;
+	resource< material >         cmaterial;
+	sint16 attach_id = -1;
+
+	if ( table.is_string( "material" ) )
+		cmaterial = m_rm->get< material >( table.get_string128( "material" ) );
+
+	if ( table.has_field( "path" ) )
+	{
+		nv::string128 cpath( table.get_string128( "path" ) );
+		nv::data_node_info info;
+		cmesh = m_mesh_datas->get_path( cpath, def_data, &info );
+		attach_id = info.parent_id;
+	}
+
+	if ( table.has_field( "attach" ) )
+	{
+		if ( table.is_number( "attach" ) )
+		{
+			attach_id = table.get_integer( "attach", -1 );
+			//				parent_id = 0;
+		}
+		else if ( auto m = def_data.lock() )
+		{
+			auto it = m->node_names.find( table.get_string_hash_64( "attach" ) );
+			if ( it != m->node_names.end() )
+				attach_id = it->second + 1;
+			int error; int hack;
+		}
+	}
+
+	node->force = table.get_boolean( "force", false );
+	node->chance = table.get_float( "chance", 1.0f );
+	node->random_rotate_y = table.get_boolean( "random_rotate", false );
+
+	node->mesh = cmesh;
+	node->attach_id = attach_id;
+	node->material = cmaterial;
+
+	for ( uint32 i = 1; i <= table.get_size(); ++i )
+	{
+		lua::table_guard child_table( table, i );
+		model_node* child = new model_node;
+		node->children.push_back( child );
+		read_model_node( child_table, child, def_data );
+	}
+}
+
Index: trunk/src/engine/renderer.cc
===================================================================
--- trunk/src/engine/renderer.cc	(revision 507)
+++ trunk/src/engine/renderer.cc	(revision 507)
@@ -0,0 +1,7 @@
+// Copyright (C) 2016-2016 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/engine/renderer.hh"
Index: trunk/src/lua/lua_gfx.cc
===================================================================
--- trunk/src/lua/lua_gfx.cc	(revision 507)
+++ trunk/src/lua/lua_gfx.cc	(revision 507)
@@ -0,0 +1,182 @@
+// Copyright (C) 2016-2016 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_gfx.hh"
+
+#include "nv/base/capi.hh"
+#include "nv/lua/lua_raw.hh"
+#include "nv/lua/lua_templates.hh"
+
+using nv::lua::detail::is_color_mask;
+using nv::lua::detail::to_color_mask;
+using nv::lua::detail::to_pcolor_mask;
+using nv::lua::detail::push_color_mask;
+
+using nv::lua::detail::is_scissor_test;
+using nv::lua::detail::to_scissor_test;
+using nv::lua::detail::to_pscissor_test;
+using nv::lua::detail::push_scissor_test;
+
+using nv::lua::detail::is_clear_state;
+using nv::lua::detail::to_clear_state;
+using nv::lua::detail::to_pclear_state;
+using nv::lua::detail::push_clear_state;
+
+static int nlua_color_mask_tostring( lua_State * L )
+{
+	nv::color_mask* m = to_pcolor_mask( L, 1 );
+	lua_pushfstring( L, "color_mask(%s%s%s%s)",
+		m->red ? "R" : "-",
+		m->red ? "G" : "-",
+		m->red ? "B" : "-",
+		m->red ? "A" : "-"
+	);
+	return 1;
+}
+
+static int nlua_color_mask_index( lua_State * L )
+{
+	nv::color_mask* m = to_pcolor_mask( L, 1 );
+	size_t len = 0;
+	const char * key = lua_tolstring( L, 2, &len );
+	if ( len > 0 )
+	{
+		char k = key[0];
+		if ( k == 'r' && ( len == 1 || nv::nvstrcmp( key, "red" ) == 0 ) )
+		{
+			lua_pushboolean( L, m->red ); return 1;
+		}
+		if ( k == 'g' && ( len == 1 || nv::nvstrcmp( key, "green" ) == 0 ) )
+		{
+			lua_pushboolean( L, m->green ); return 1;
+		}
+		if ( k == 'b' && ( len == 1 || nv::nvstrcmp( key, "blue" ) == 0 ) )
+		{
+			lua_pushboolean( L, m->blue ); return 1;
+		}
+		if ( k == 'a' && ( len == 1 || nv::nvstrcmp( key, "alpha" ) == 0 ) )
+		{
+			lua_pushboolean( L, m->alpha ); return 1;
+		}
+	}
+
+	luaL_getmetafield( L, 1, "__functions" );
+	lua_pushvalue( L, 2 );
+	lua_rawget( L, -2 );
+	return 1;
+}
+
+static int nlua_color_mask_newindex( lua_State * L )
+{
+	nv::color_mask* m = to_pcolor_mask( L, 1 );
+	size_t len = 0;
+	const char * key = lua_tolstring( L, 2, &len );
+	if ( len > 0 )
+	{
+		char k = key[0];
+		if ( k == 'r' && ( len == 1 || nv::nvstrcmp( key, "red" ) == 0 ) )
+		{
+			m->red   = lua_toboolean( L, 3 ) != 0; return 0;
+		}
+		if ( k == 'g' && ( len == 1 || nv::nvstrcmp( key, "green" ) == 0 ) )
+		{
+			m->green = lua_toboolean( L, 3 ) != 0; return 0;
+		}
+		if ( k == 'b' && ( len == 1 || nv::nvstrcmp( key, "blue" ) == 0 ) )
+		{
+			m->blue  = lua_toboolean( L, 3 ) != 0; return 0;
+		}
+		if ( k == 'a' && ( len == 1 || nv::nvstrcmp( key, "alpha" ) == 0 ) )
+		{
+			m->alpha = lua_toboolean( L, 3 ) != 0; return 0;
+		}
+	}
+	luaL_error( L, "color_mask : unknown index - %s", lua_tostring( L, 2 ) );
+	return 0;
+}
+
+static int luaopen_color_mask( lua_State * L )
+{
+	struct constructor
+	{
+		static inline nv::color_mask construct( lua_State* L, int index )
+		{
+			int args = lua_gettop( L ) - index;
+			bool r = args >= 0 ? lua_toboolean( L, index + 0 ) != 0 : true;
+			bool g = args >= 1 ? lua_toboolean( L, index + 1 ) != 0 : true;
+			bool b = args >= 2 ? lua_toboolean( L, index + 2 ) != 0 : true;
+			bool a = args >= 3 ? lua_toboolean( L, index + 3 ) != 0 : true;
+			return nv::color_mask( r, g, b, a );
+		}
+	};
+
+	NV_LUA_STACK_ASSERT( L, 1 );
+	static const struct luaL_Reg nlua_color_mask_sf[] = {
+		{ "new",            nv::lua::detail::new_impl<nv::color_mask, constructor> },
+		{ NULL, NULL }
+	};
+
+	static const struct luaL_Reg nlua_color_mask_f[] = {
+		{ "clone",          nv::lua::detail::clone_impl<nv::color_mask> },
+		{ "tostring",       nlua_color_mask_tostring },
+		{ NULL, NULL }
+	};
+
+	static const struct luaL_Reg nlua_color_mask_sm[] = {
+		{ "__call",          nv::lua::detail::call_impl<nv::color_mask, constructor> },
+		{ NULL, NULL }
+	};
+
+	static const struct luaL_Reg nlua_color_mask_m[] = {
+		{ "__eq",       nv::lua::detail::eq_impl<nv::color_mask> },
+		{ "__index",    nlua_color_mask_index },
+		{ "__newindex", nlua_color_mask_newindex },
+		{ "__tostring", nlua_color_mask_tostring },
+		{ NULL, NULL }
+	};
+
+	luaL_newmetatable( L, nv::lua::pass_traits<nv::color_mask>::metatable() );
+	nlua_register( L, nlua_color_mask_m, -1 );
+	lua_createtable( L, 0, 0 );
+	nlua_register( L, nlua_color_mask_f, -1 );
+	lua_setfield( L, -2, "__functions" );
+	lua_pop( L, 1 );
+
+	lua_createtable( L, 0, 0 );
+	nlua_register( L, nlua_color_mask_sf, -1 );
+	lua_createtable( L, 0, 0 );
+	nlua_register( L, nlua_color_mask_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;
+}
+
+static int luaopen_scissor_test( lua_State * L )
+{
+	NV_LUA_STACK_ASSERT( L, 1 );
+	return 1;
+}
+
+static int luaopen_clear_state( lua_State * L )
+{
+	NV_LUA_STACK_ASSERT( L, 1 );
+	return 1;
+}
+
+
+void nv::lua::register_gfx( lua_State* L )
+{
+	int stack = lua_gettop( L );
+	nlua_requiref( L, "color_mask", luaopen_color_mask, 1 );
+	nlua_requiref( L, "scissor_test", luaopen_scissor_test, 1 );
+	nlua_requiref( L, "clear_state", luaopen_clear_state, 1 );
+	lua_settop( L, stack );
+}
