Index: trunk/src/engine/model_manager.cc
===================================================================
--- trunk/src/engine/model_manager.cc	(revision 514)
+++ trunk/src/engine/model_manager.cc	(revision 515)
@@ -58,4 +58,7 @@
 	if ( table.is_string( "material" ) )
 		cmaterial = m_rm->get< material >( table.get_string128( "material" ) );
+
+	if ( table.is_string( "tag" ) )
+		node->tag = table.get_string32( "tag" );
 
 	if ( table.has_field( "path" ) )
Index: trunk/src/engine/particle_engine.cc
===================================================================
--- trunk/src/engine/particle_engine.cc	(revision 514)
+++ trunk/src/engine/particle_engine.cc	(revision 515)
@@ -605,5 +605,5 @@
 }
 
-void nv::particle_engine::update( particle_system system, float dtime )
+void nv::particle_engine::update( particle_system system, transform model, float dtime  )
 {
 	particle_system_info* info = m_systems.get( system );
@@ -621,5 +621,5 @@
 		update_emmiters( info, dtime );
 		destroy_particles( info, dtime );
-		create_particles( info, dtime );
+		create_particles( info, model, dtime );
 		update_particles( info, dtime );
 
@@ -776,5 +776,5 @@
 }
 
-void nv::particle_engine::create_particles( particle_system_info* info, float dtime )
+void nv::particle_engine::create_particles( particle_system_info* info, transform model, float dtime )
 {
 	uint32 ecount = info->data->emmiter_count;
@@ -782,7 +782,5 @@
 
 	random& r = random::get();
-	vec3 source;
-	mat3 orient;
-//	bool local = info->data->local;
+	bool local = model.is_identity();
 // 	if ( !local ) 
 // 	{
@@ -806,7 +804,8 @@
 					edata.emmiter_func( &(info->data->emmiters[i]), &pinfo, 1 );
 					pinfo.position = vec3();
-//					if ( !local ) pinfo.position  = orient * pinfo.position + source;
 					pinfo.position+= edata.position;
-					pinfo.color    = edata.color_min == edata.color_max ? 
+					if ( !local )
+						pinfo.position = pinfo.position * model;
+					pinfo.color    = edata.color_min == edata.color_max ?
 						edata.color_min : r.range( edata.color_min, edata.color_max );
 					pinfo.size     = edata.size_min == edata.size_max ?
@@ -829,5 +828,5 @@
 						float sin_theta = sqrt(1.0f - cos_theta * cos_theta );
 						float phi       = r.frange( 0.0f, 2* math::pi<float>() );
-						pinfo.velocity  = orient * 
+						pinfo.velocity  = model.get_orientation() * 
 							( edata.odir * ( cos(phi) * sin_theta ) +
 							edata.cdir * ( sin(phi)*sin_theta ) +
Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 514)
+++ trunk/src/gl/gl_context.cc	(revision 515)
@@ -964,4 +964,5 @@
 	glTexParameteri( gl_type, GL_TEXTURE_WRAP_S, GLint( nv::sampler_wrap_to_enum( asampler.wrap_s ) ) );
 	glTexParameteri( gl_type, GL_TEXTURE_WRAP_T, GLint( nv::sampler_wrap_to_enum( asampler.wrap_t ) ) );
+	glTexParameteri( gl_type, GL_TEXTURE_WRAP_R, GLint( nv::sampler_wrap_to_enum( asampler.wrap_r ) ) );
 
 	if ( is_depth )
Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 514)
+++ trunk/src/lua/lua_state.cc	(revision 515)
@@ -344,4 +344,23 @@
 }
 
+
+nv::string32 nv::lua::table_guard::get_string32( string_view element, string_view defval /*= string_view() */ )
+{
+	lua_getfield( m_state, -1, element.data() );
+	size_t l = 0;
+	const char* str = nullptr;
+	if ( lua_type( m_state, -1 ) == LUA_TSTRING )
+	{
+		str = lua_tolstring( m_state, -1, &l );
+	}
+	else
+	{
+		l = defval.size();
+		str = defval.data();
+	}
+	string32 result( str, l );
+	lua_pop( m_state, 1 );
+	return result;
+}
 
 char lua::table_guard::get_char( string_view element, char defval /*= "" */ )
