Index: trunk/src/formats/md2_loader.cc
===================================================================
--- trunk/src/formats/md2_loader.cc	(revision 223)
+++ trunk/src/formats/md2_loader.cc	(revision 224)
@@ -241,4 +241,32 @@
 }
 
+mesh_data* nv::md2_loader::release_mesh_data()
+{
+	mesh_data_creator m;
+
+	load_positions( m.get_positions() );
+	load_normals( m.get_normals() );
+	load_texcoords( m.get_texcoords() );
+	load_indicies( m.get_indices() );
+
+	m_size = m.get_indices().size();
+	return m.release();
+}
+
+mesh_data* nv::md2_loader::get_frame( sint32 frame )
+{
+	mesh_data_creator m;
+
+	load_positions( m.get_positions(), frame );
+	load_normals( m.get_normals(), frame );
+	load_texcoords( m.get_texcoords() );
+	load_indicies( m.get_indices() );
+
+	m_size = m.get_indices().size();
+	return m.release();
+}
+
+
+/*
 mesh* nv::md2_loader::release_mesh()
 {
@@ -255,5 +283,5 @@
 	vertex_attribute< vec3 >*   normal   = m->add_attribute<vec3>("nv_normal");
 	vertex_attribute< vec2 >*   texcoord = m->add_attribute<vec2>("nv_texcoord");
-	vertex_attribute< uint16 >* indices  = m->add_indices<uint16>();
+	vertex_attribute< uint32 >* indices  = m->add_indices<uint32>();
 
 	load_positions( position->get(), frame );
@@ -266,4 +294,5 @@
 	return m;
 }
+*/
 
 size_t md2_loader::get_max_frames() const
@@ -344,5 +373,5 @@
 }
 
-void md2_loader::load_indicies( std::vector<uint16>& idx )
+void md2_loader::load_indicies( std::vector<uint32>& idx )
 {
 	idx.assign( m_new_indexes.begin(), m_new_indexes.end() );
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 223)
+++ trunk/src/formats/md3_loader.cc	(revision 224)
@@ -286,4 +286,5 @@
 }
 
+/*
 mesh* nv::md3_loader::release_mesh()
 {
@@ -314,5 +315,5 @@
 	vertex_attribute< vec3 >* normal   = m->add_attribute<vec3>("nv_normal");
 	vertex_attribute< vec2 >* texcoord = m->add_attribute<vec2>("nv_texcoord");
-	vertex_attribute< uint16 >* indices  = m->add_indices<uint16>();
+	vertex_attribute< uint32 >* indices  = m->add_indices<uint32>();
 
 	load_positions( position->get(), frame );
@@ -325,4 +326,5 @@
 	return m;
 }
+*/
 
 void nv::md3_loader::load_tags( std::vector<mat4>& t, const std::string& tag )
@@ -349,4 +351,43 @@
 }
 
+mesh_data* nv::md3_loader::release_mesh_data()
+{
+	mesh_data_creator m;
+
+	load_positions( m.get_positions() );
+	load_normals( m.get_normals() );
+	load_texcoords( m.get_texcoords() );
+	load_indicies( m.get_indices() );
+	
+	std::vector< std::string > names;
+	load_tag_names( names );
+
+	for ( auto& name : names )
+	{
+		load_tags( m.get_tag_map()[ name ], name );
+	}
+
+	return m.release();
+}
+
+mesh_data* nv::md3_loader::get_frame( sint32 frame )
+{
+	mesh_data_creator m;
+
+	load_positions( m.get_positions(), frame );
+	load_normals( m.get_normals(), frame );
+	load_texcoords( m.get_texcoords() );
+	load_indicies( m.get_indices() );
+
+	std::vector< std::string > names;
+	load_tag_names( names );
+
+	for ( auto& name : names )
+	{
+		load_tags( m.get_tag_map()[ name ], name );
+	}
+	return m.release();
+}
+
 size_t md3_loader::get_max_frames() const
 {
@@ -465,5 +506,5 @@
 }
 
-void md3_loader::load_indicies( std::vector<uint16>& idx )
+void md3_loader::load_indicies( std::vector<uint32>& idx )
 {
 	md3_t* md3 = (md3_t*)m_md3;
@@ -480,7 +521,7 @@
 		{
 			const md3_triangle_t& t = surface.triangles[j];
-			idx.push_back( static_cast< uint16 >( index_base + t.indexes[0] ) );
-			idx.push_back( static_cast< uint16 >( index_base + t.indexes[1] ) );
-			idx.push_back( static_cast< uint16 >( index_base + t.indexes[2] ) );
+			idx.push_back( static_cast< uint32 >( index_base + t.indexes[0] ) );
+			idx.push_back( static_cast< uint32 >( index_base + t.indexes[1] ) );
+			idx.push_back( static_cast< uint32 >( index_base + t.indexes[2] ) );
 		}
 
@@ -490,24 +531,2 @@
 }
 
-keyframed_mesh_data::keyframed_mesh_data( keyframed_loader* loader )
-{
-	loader->load_positions( m_positions );
-	loader->load_normals( m_normals );
-	loader->load_texcoords( m_texcoords );
-	loader->load_indicies( m_indices );
-
-	std::vector< std::string > names;
-
-	md3_loader* md3loader = dynamic_cast< md3_loader* >( loader );
-	if ( md3loader != nullptr )
-	{
-		md3loader->load_tag_names( names );
-		for ( auto& name : names )
-		{
-			md3loader->load_tags( m_tags[ name ], name );
-		}
-	}
-
-	m_frames = loader->get_max_frames();
-}
-
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 223)
+++ trunk/src/formats/md5_loader.cc	(revision 224)
@@ -90,5 +90,5 @@
 		{
 			// TODO : efficiency dammit
-			md5_mesh mesh;
+			md5_mesh* mesh = new md5_mesh;
 			int num_verts, num_tris, num_weights;
 
@@ -99,6 +99,6 @@
 				if ( command == "shader" )
 				{
-					sstream >> mesh.shader;
-					remove_quotes( mesh.shader );
+					sstream >> mesh->shader;
+					remove_quotes( mesh->shader );
 					// texturePath.replace_extension( ".tga" );
 					next_line( sstream );
@@ -120,6 +120,6 @@
 						next_line( sstream );
 
-						mesh.verts.push_back(vert);
-						mesh.texcoord_buffer.push_back( vert.texcoord );
+						mesh->verts.push_back(vert);
+						mesh->texcoord_buffer.push_back( vert.texcoord );
 					}  
 				}
@@ -136,8 +136,8 @@
 						next_line( sstream );
 
-						mesh.tris.push_back( tri );
-						mesh.index_buffer.push_back( (uint32)tri.indices[0] );
-						mesh.index_buffer.push_back( (uint32)tri.indices[1] );
-						mesh.index_buffer.push_back( (uint32)tri.indices[2] );
+						mesh->tris.push_back( tri );
+						mesh->index_buffer.push_back( (uint32)tri.indices[0] );
+						mesh->index_buffer.push_back( (uint32)tri.indices[1] );
+						mesh->index_buffer.push_back( (uint32)tri.indices[2] );
 					}              
 				}
@@ -156,5 +156,5 @@
 						discard( sstream, ")" );
 						next_line( sstream );
-						mesh.weights.push_back(weight);
+						mesh->weights.push_back(weight);
 					}
 				}
@@ -180,12 +180,12 @@
 }
 
-bool md5_loader::prepare_mesh( md5_mesh& mesh )
-{
-	mesh.position_buffer.clear();
-	mesh.texcoord_buffer.clear();
-
-	for ( uint32 i = 0; i < mesh.verts.size(); ++i )
-	{
-		md5_vertex& vert = mesh.verts[i];
+bool md5_loader::prepare_mesh( md5_mesh* mesh )
+{
+	mesh->position_buffer.clear();
+	mesh->texcoord_buffer.clear();
+
+	for ( uint32 i = 0; i < mesh->verts.size(); ++i )
+	{
+		md5_vertex& vert = mesh->verts[i];
 
 		vert.position = glm::vec3(0);
@@ -195,5 +195,5 @@
 		for ( size_t j = 0; j < vert.weight_count; ++j )
 		{
-			md5_weight& weight = mesh.weights[vert.start_weight + j];
+			md5_weight& weight = mesh->weights[vert.start_weight + j];
 			md5_joint&  joint  = m_joints[weight.joint_id];
 
@@ -203,6 +203,6 @@
 		}
 
-		mesh.position_buffer.push_back(vert.position);
-		mesh.texcoord_buffer.push_back(vert.texcoord);
+		mesh->position_buffer.push_back(vert.position);
+		mesh->texcoord_buffer.push_back(vert.texcoord);
 	}
 
@@ -210,14 +210,14 @@
 }
 
-bool md5_loader::prepare_normals( md5_mesh& mesh )
-{
-	mesh.normal_buffer.clear();
-
-	for ( unsigned int i = 0; i < mesh.tris.size(); ++i )
-	{
-		const md5_triangle& tri = mesh.tris[i];
-		glm::vec3 v1 = mesh.verts[ tri.indices[0] ].position;
-		glm::vec3 v2 = mesh.verts[ tri.indices[1] ].position;
-		glm::vec3 v3 = mesh.verts[ tri.indices[2] ].position;
+bool md5_loader::prepare_normals( md5_mesh* mesh )
+{
+	mesh->normal_buffer.clear();
+
+	for ( unsigned int i = 0; i < mesh->tris.size(); ++i )
+	{
+		const md5_triangle& tri = mesh->tris[i];
+		glm::vec3 v1 = mesh->verts[ tri.indices[0] ].position;
+		glm::vec3 v2 = mesh->verts[ tri.indices[1] ].position;
+		glm::vec3 v3 = mesh->verts[ tri.indices[2] ].position;
 		glm::vec3 xyz1 = v3 - v1;
 		glm::vec3 xyz2 = v2 - v1;
@@ -225,11 +225,11 @@
 		glm::vec3 normal = glm::cross( xyz1, xyz2 );
 
-		mesh.verts[ tri.indices[0] ].normal += normal;
-		mesh.verts[ tri.indices[1] ].normal += normal;
-		mesh.verts[ tri.indices[2] ].normal += normal;
-
-		const vec2& w1 = mesh.verts[ tri.indices[0] ].texcoord;
-		const vec2& w2 = mesh.verts[ tri.indices[1] ].texcoord;
-		const vec2& w3 = mesh.verts[ tri.indices[2] ].texcoord;
+		mesh->verts[ tri.indices[0] ].normal += normal;
+		mesh->verts[ tri.indices[1] ].normal += normal;
+		mesh->verts[ tri.indices[2] ].normal += normal;
+
+		const vec2& w1 = mesh->verts[ tri.indices[0] ].texcoord;
+		const vec2& w2 = mesh->verts[ tri.indices[1] ].texcoord;
+		const vec2& w3 = mesh->verts[ tri.indices[2] ].texcoord;
 
 		vec2 st1 = w3 - w1;
@@ -240,17 +240,17 @@
 		vec3 tangent = (( xyz1 * st2.y ) - ( xyz2 * st1.y )) * coef;
 
-		mesh.verts[ tri.indices[0] ].tangent += tangent;
-		mesh.verts[ tri.indices[1] ].tangent += tangent;
-		mesh.verts[ tri.indices[2] ].tangent += tangent;
-	}
-
-	for ( size_t i = 0; i < mesh.verts.size(); ++i )
-	{
-		md5_vertex& vert = mesh.verts[i];
+		mesh->verts[ tri.indices[0] ].tangent += tangent;
+		mesh->verts[ tri.indices[1] ].tangent += tangent;
+		mesh->verts[ tri.indices[2] ].tangent += tangent;
+	}
+
+	for ( size_t i = 0; i < mesh->verts.size(); ++i )
+	{
+		md5_vertex& vert = mesh->verts[i];
 
 		glm::vec3 normal  = glm::normalize( vert.normal );
 		glm::vec3 tangent = glm::normalize( vert.tangent );
-		mesh.normal_buffer.push_back( normal );
-		mesh.tangent_buffer.push_back( tangent );
+		mesh->normal_buffer.push_back( normal );
+		mesh->tangent_buffer.push_back( tangent );
 
 		vert.normal  = glm::vec3(0);
@@ -259,5 +259,5 @@
 		for ( size_t j = 0; j < vert.weight_count; ++j )
 		{
-			const md5_weight& weight = mesh.weights[vert.start_weight + j];
+			const md5_weight& weight = mesh->weights[vert.start_weight + j];
 			const md5_joint&  joint  = m_joints[weight.joint_id];
 			vert.normal  += ( normal  * joint.orient ) * weight.bias;
@@ -269,4 +269,17 @@
 }
 
+mesh_data* nv::md5_loader::release_submesh_data( uint32 mesh_id )
+{
+	mesh_data_creator m;
+	m.get_positions().assign( m_meshes[mesh_id]->position_buffer.begin(), m_meshes[mesh_id]->position_buffer.begin() );
+	m.get_normals()  .assign( m_meshes[mesh_id]->normal_buffer.begin(),   m_meshes[mesh_id]->normal_buffer.begin() );
+	m.get_tangents() .assign( m_meshes[mesh_id]->tangent_buffer.begin(),  m_meshes[mesh_id]->tangent_buffer.begin() );
+	m.get_texcoords().assign( m_meshes[mesh_id]->texcoord_buffer.begin(), m_meshes[mesh_id]->texcoord_buffer.begin() );
+	m.get_indices()  .assign( m_meshes[mesh_id]->index_buffer.begin(),    m_meshes[mesh_id]->index_buffer.begin() );
+
+	return m.release();
+}
+
+/*
 mesh* md5_loader::release_mesh()
 {
@@ -287,4 +300,5 @@
 	return m;
 }
+*/
 
 md5_animation::md5_animation()
@@ -539,12 +553,12 @@
 }
 
-bool md5_loader::prepare_animated_mesh( md5_mesh& mesh, const md5_animation::md5_frame_skeleton& skel )
-{
-	for ( unsigned int i = 0; i < mesh.verts.size(); ++i )
-	{
-		const md5_vertex& vert = mesh.verts[i];
-		glm::vec3& pos     = mesh.position_buffer[i];
-		glm::vec3& normal  = mesh.normal_buffer[i];
-		glm::vec3& tangent = mesh.tangent_buffer[i];
+bool md5_loader::prepare_animated_mesh( md5_mesh* mesh, const md5_animation::md5_frame_skeleton& skel )
+{
+	for ( unsigned int i = 0; i < mesh->verts.size(); ++i )
+	{
+		const md5_vertex& vert = mesh->verts[i];
+		glm::vec3& pos     = mesh->position_buffer[i];
+		glm::vec3& normal  = mesh->normal_buffer[i];
+		glm::vec3& tangent = mesh->tangent_buffer[i];
 
 		pos     = glm::vec3(0);
@@ -554,5 +568,5 @@
 		for ( size_t j = 0; j < vert.weight_count; ++j )
 		{
-			const md5_weight& weight = mesh.weights[vert.start_weight + j];
+			const md5_weight& weight = mesh->weights[vert.start_weight + j];
 			const md5_animation::md5_skeleton_joint& joint = skel.joints[weight.joint_id];
 
Index: trunk/src/formats/obj_loader.cc
===================================================================
--- trunk/src/formats/obj_loader.cc	(revision 223)
+++ trunk/src/formats/obj_loader.cc	(revision 224)
@@ -119,13 +119,9 @@
 struct mesh_obj_reader : public obj_reader
 {
-	mesh_obj_reader( mesh* m ) : m_position( nullptr ), m_normal( nullptr ), m_tex_coord( nullptr ), m_tangent( nullptr ), m_mesh( m ) {}
+	mesh_obj_reader( mesh_data_creator* m ) : m_mesh( m ) {}
 	virtual std::size_t add_face( uint32* v, uint32* t, uint32* n, size_t count );
 	virtual void calculate_tangents();
 
-	vertex_attribute< vec3 >* m_position;
-	vertex_attribute< vec3 >* m_normal;
-	vertex_attribute< vec2 >* m_tex_coord;
-	vertex_attribute< vec4 >* m_tangent;
-	mesh* m_mesh;
+	mesh_data_creator* m_mesh;
 };
 
@@ -138,22 +134,9 @@
 	}
 
-	if ( m_position == nullptr )
-	{
-		m_position  = m_mesh->add_attribute< vec3 >( "nv_position" );
-	}
-	if ( m_tex_coord == nullptr )
-	{
-		m_tex_coord = m_mesh->add_attribute< vec2 >( "nv_texcoord" );
-	}
-	if ( m_normal == nullptr && ni != nullptr )
-	{
-		m_normal = m_mesh->add_attribute< vec3 >( "nv_normal" );
-	}
-
 	// TODO : support if normals not present;
 
-	std::vector< vec3 >& vp = m_position->get();
-	std::vector< vec2 >& vt = m_tex_coord->get();
-	std::vector< vec3 >& vn = m_normal->get();
+	std::vector< vec3 >& vp = m_mesh->get_positions();
+	std::vector< vec3 >& vn = m_mesh->get_normals();
+	std::vector< vec2 >& vt = m_mesh->get_texcoords();
 
 	std::size_t result = 0;
@@ -174,10 +157,8 @@
 void mesh_obj_reader::calculate_tangents()
 {
-	m_tangent = m_mesh->add_attribute< vec4 >( "nv_tangent" );
-
-	std::vector< vec3 >& vp = m_position->get();
-	std::vector< vec2 >& vt = m_tex_coord->get();
-	std::vector< vec3 >& vn = m_normal->get();
-	std::vector< vec4 >& tg = m_tangent->get();
+	const std::vector< vec3 >& vp = m_mesh->get_positions();
+	const std::vector< vec2 >& vt = m_mesh->get_texcoords();
+	const std::vector< vec3 >& vn = m_mesh->get_normals();
+	std::vector< vec3 >& tg = m_mesh->get_tangents();
 
 	size_t count  = vp.size();
@@ -225,4 +206,5 @@
 		tan1[i3] += sdir;
 
+		// tan2 not needed anymore??
 		tan2[i1] += tdir;
 		tan2[i2] += tdir;
@@ -235,6 +217,6 @@
 		const vec3& t = tan1[a];
 
-		tg[a] = vec4( glm::normalize(t - n * glm::dot( n, t )), 
-		    (glm::dot(glm::cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f );
+		tg[a] = vec3( glm::normalize(t - n * glm::dot( n, t )) ); 
+		//tg[a][3] =    (glm::dot(glm::cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
 	}
 
@@ -258,6 +240,6 @@
 		delete m_mesh;
 	}
-	m_mesh = new mesh();
-	mesh_obj_reader reader( m_mesh );
+	mesh_data_creator creator;
+	mesh_obj_reader reader( &creator );
 	std_stream sstream( &source );
 	reader.read_stream( sstream );
@@ -267,4 +249,5 @@
 		reader.calculate_tangents();
 	}
+	m_mesh = creator.release();
 	return true;
 }
Index: trunk/src/gfx/keyframed_mesh.cc
===================================================================
--- trunk/src/gfx/keyframed_mesh.cc	(revision 223)
+++ trunk/src/gfx/keyframed_mesh.cc	(revision 224)
@@ -15,5 +15,5 @@
 using namespace nv;
 
-keyframed_mesh::keyframed_mesh( context* a_context, keyframed_mesh_data* a_data, program* a_program )
+keyframed_mesh::keyframed_mesh( context* a_context, mesh_data* a_data, program* a_program )
 	: m_context( a_context )
 	, m_data( a_data )
@@ -112,5 +112,5 @@
 }
 
-keyframed_mesh_gpu::keyframed_mesh_gpu( context* a_context, keyframed_mesh_data* a_data, program* a_program )
+keyframed_mesh_gpu::keyframed_mesh_gpu( context* a_context, mesh_data* a_data, program* a_program )
 	: keyframed_mesh( a_context, a_data, a_program )
 	, m_loc_next_position( 0 )
@@ -133,6 +133,6 @@
 	vb = m_context->get_device()->create_vertex_buffer( nv::STATIC_DRAW, m_data->get_vertex_count() * sizeof( nv::vec2 ), (void*)m_data->get_texcoords().data() );
 	m_va->add_vertex_buffer( nv::slot::TEXCOORD, vb, nv::FLOAT, 2 );
-	nv::index_buffer* ib = m_context->get_device()->create_index_buffer( nv::STATIC_DRAW, m_data->get_index_count() * sizeof( nv::uint16 ), (void*)m_data->get_indices().data() );
-	m_va->set_index_buffer( ib, nv::USHORT, true );
+	nv::index_buffer* ib = m_context->get_device()->create_index_buffer( nv::STATIC_DRAW, m_data->get_index_count() * sizeof( nv::uint32 ), (void*)m_data->get_indices().data() );
+	m_va->set_index_buffer( ib, nv::UINT, true );
 }
 
@@ -156,11 +156,11 @@
 
 
-nv::keyframed_mesh_cpu::keyframed_mesh_cpu( context* a_context, keyframed_mesh_data* a_data, program* a_program )
+nv::keyframed_mesh_cpu::keyframed_mesh_cpu( context* a_context, mesh_data* a_data, program* a_program )
 	: keyframed_mesh( a_context, a_data, a_program )
 {
-	m_vb_position = m_context->get_device()->create_vertex_buffer( nv::STATIC_DRAW, m_data->get_vertex_count() * sizeof( nv::vec3 ) * m_data->get_frame_count(), (void*)m_data->get_position_data(0) );
+	m_vb_position = m_context->get_device()->create_vertex_buffer( nv::STATIC_DRAW, m_data->get_vertex_count() * sizeof( nv::vec3 ), (void*)m_data->get_position_frame(0) );
 	m_va->add_vertex_buffer( nv::slot::POSITION, m_vb_position, nv::FLOAT, 3 );
 
-	m_vb_normal   = m_context->get_device()->create_vertex_buffer( nv::STATIC_DRAW, m_data->get_vertex_count() * sizeof( nv::vec3 ) * m_data->get_frame_count(), (void*)m_data->get_normal_data(0) );
+	m_vb_normal   = m_context->get_device()->create_vertex_buffer( nv::STATIC_DRAW, m_data->get_vertex_count() * sizeof( nv::vec3 ), (void*)m_data->get_normal_frame(0) );
 	m_va->add_vertex_buffer( nv::slot::NORMAL, m_vb_normal, nv::FLOAT, 3 );
 
@@ -169,6 +169,6 @@
 	m_va->add_vertex_buffer( nv::slot::TEXCOORD, vb, nv::FLOAT, 2 );
 
-	nv::index_buffer* ib = m_context->get_device()->create_index_buffer( nv::STATIC_DRAW, m_data->get_index_count() * sizeof( nv::uint16 ), (void*)m_data->get_indices().data() );
-	m_va->set_index_buffer( ib, nv::USHORT, true );
+	nv::index_buffer* ib = m_context->get_device()->create_index_buffer( nv::STATIC_DRAW, m_data->get_index_count() * sizeof( nv::uint32 ), (void*)m_data->get_indices().data() );
+	m_va->set_index_buffer( ib, nv::UINT, true );
 
 	m_position.resize( m_data->get_vertex_count() );
@@ -181,8 +181,8 @@
 
 	size_t vtx_count = m_data->get_vertex_count();
-	const vec3* prev_position = m_data->get_position_data( m_last_frame );
-	const vec3* next_position = m_data->get_position_data( m_next_frame );
-	const vec3* prev_normal   = m_data->get_normal_data( m_last_frame );
-	const vec3* next_normal   = m_data->get_normal_data( m_next_frame );
+	const vec3* prev_position = m_data->get_position_frame( m_last_frame );
+	const vec3* next_position = m_data->get_position_frame( m_next_frame );
+	const vec3* prev_normal   = m_data->get_normal_frame( m_last_frame );
+	const vec3* next_normal   = m_data->get_normal_frame( m_next_frame );
 
 	for ( size_t i = 0; i < vtx_count; ++i )
