Index: trunk/nv/stl/type_erasure.hh
===================================================================
--- trunk/nv/stl/type_erasure.hh	(revision 458)
+++ trunk/nv/stl/type_erasure.hh	(revision 458)
@@ -0,0 +1,203 @@
+// Copyright (C) 2015-2015 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 type_erasure.hh
+ * @author Kornel Kisielewicz epyon@chaosforge.org
+ * @brief type erasure
+ */
+
+
+#ifndef NV_STL_TYPE_ERASURE_HH
+#define NV_STL_TYPE_ERASURE_HH
+
+#include <nv/common.hh>
+#include <nv/stl/iterator.hh>
+
+namespace nv
+{
+
+	template < typename T >
+	class raw_data_iterator : public iterator< block_access_iterator_tag, T, ptrdiff_t, T*, T& >
+	{
+	public:
+		typedef block_access_iterator_tag iterator_category;
+		typedef T                         value_type;
+		typedef ptrdiff_t                 difference_type;
+		typedef T*                        pointer;
+		typedef T&                        reference;
+
+		raw_data_iterator( void* data, uint32 stride = 0, uint32 offset = 0 )
+		{
+			m_current = static_cast<uint8*>( data ) + offset;
+			m_stride = stride;
+		}
+
+		inline reference operator*() const { return *reinterpret_cast<pointer>( m_current ); }
+		inline pointer operator->() const { return reinterpret_cast<pointer>( m_current ); }
+
+		inline raw_data_iterator& operator++() { m_current += stride; return *this; }
+		inline raw_data_iterator operator++( int ) { raw_data_iterator ri( *this ); m_current += stride; return ri; }
+		inline raw_data_iterator& operator--() { m_current -= stride; return *this; }
+		inline raw_data_iterator operator--( int ) { raw_data_iterator ri( *this ); m_current -= stride; return ri; }
+
+		inline raw_data_iterator operator+( difference_type n ) const { return raw_data_iterator( m_current + n * m_stride, m_stride ); }
+		inline raw_data_iterator& operator+=( difference_type n ) { m_current += n * m_stride; return *this; }
+		inline raw_data_iterator operator-( difference_type n ) const { return raw_data_iterator( m_current - n * m_stride, m_stride ); }
+		inline raw_data_iterator& operator-=( difference_type n ) { m_current -= n * m_stride; return *this; }
+		constexpr reference operator[]( difference_type n ) const { return *reinterpret_cast<pointer>( m_current + n * m_stride ); }
+
+		const uint8* raw_data() const { return m_current; }
+		uint32 stride() const { return m_stride; }
+	protected:
+		uint8* m_current;
+		uint32 m_stride;
+	};
+
+
+	template < typename T >
+	class const_raw_data_iterator : public iterator< block_access_iterator_tag, T, ptrdiff_t, const T*, const T& >
+	{
+	public:
+		typedef block_access_iterator_tag iterator_category;
+		typedef T                         value_type;
+		typedef ptrdiff_t                 difference_type;
+		typedef const T*                  pointer;
+		typedef const T&                  reference;
+
+		constexpr const_raw_data_iterator( const raw_data_iterator< T >& it )
+		{
+			m_current = it.raw_data();
+			m_stride  = it.stride();
+		}
+
+		constexpr const_raw_data_iterator( void* data, uint32 stride = 0, uint32 offset = 0 )
+		{
+			m_current = static_cast<const uint8*>( data ) + offset;
+			m_stride  = stride;
+		}
+		constexpr reference operator*() const { return *reinterpret_cast<pointer>( m_current ); }
+		constexpr pointer operator->() const { return reinterpret_cast<pointer>( m_current ); }
+
+		constexpr const_raw_data_iterator& operator++() { m_current += stride; return *this; }
+		constexpr const_raw_data_iterator operator++( int ) { const_raw_data_iterator ri( *this ); m_current += stride; return ri; }
+		constexpr const_raw_data_iterator& operator--() { m_current -= stride; return *this; }
+		constexpr const_raw_data_iterator operator--( int ) { const_raw_data_iterator ri( *this ); m_current -= stride; return ri; }
+
+		constexpr const_raw_data_iterator operator+( difference_type n ) const { return const_raw_data_iterator( m_current + n * m_stride, m_stride ); }
+		constexpr const_raw_data_iterator& operator+=( difference_type n ) { m_current += n * m_stride; return *this; }
+		constexpr const_raw_data_iterator operator-( difference_type n ) const { return const_raw_data_iterator( m_current - n * m_stride, m_stride ); }
+		constexpr const_raw_data_iterator& operator-=( difference_type n ) { m_current -= n * m_stride; return *this; }
+		constexpr reference operator[]( difference_type n ) const { return *reinterpret_cast<pointer>( m_current + n * m_stride ); }
+
+		const uint8* raw_data() const { return m_current; }
+		uint32 stride() const { return m_stride; }
+	protected:
+		const uint8* m_current;
+		uint32 m_stride;
+	};
+
+	template < typename T >
+	constexpr bool operator==( const raw_data_iterator< T >& lhs, const raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() == rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator!=( const raw_data_iterator< T >& lhs, const raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() != rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator<( const raw_data_iterator< T >& lhs, const raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() < rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator>( const raw_data_iterator< T >& lhs, const raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() > rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator<=( const raw_data_iterator< T >& lhs, const raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() <= rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator>=( const raw_data_iterator< T >& lhs, const raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() >= rhs.raw_data();
+	}
+	template < typename T >
+	constexpr typename raw_data_iterator< T >::difference_type operator-( const raw_data_iterator< T >& lhs, const raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return ( lhs.raw_data() - rhs.raw_data() ) / lhs->m_stride;
+	}
+	template < typename T >
+	constexpr raw_data_iterator< T > operator+( typename raw_data_iterator< T >::difference_type n, const raw_data_iterator< T >& iter )
+	{
+		return raw_data_iterator< T >( iter.raw_data() + iter.stride() * n, iter.stride() );
+	}
+
+	template < typename T >
+	constexpr bool operator==( const const_raw_data_iterator< T >& lhs, const const_raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() == rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator!=( const const_raw_data_iterator< T >& lhs, const const_raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() != rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator<( const const_raw_data_iterator< T >& lhs, const const_raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() < rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator>( const const_raw_data_iterator< T >& lhs, const const_raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() > rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator<=( const const_raw_data_iterator< T >& lhs, const const_raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() <= rhs.raw_data();
+	}
+	template < typename T >
+	constexpr bool operator>=( const const_raw_data_iterator< T >& lhs, const const_raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return lhs.raw_data() >= rhs.raw_data();
+	}
+	template < typename T >
+	constexpr typename const_raw_data_iterator< T >::difference_type operator-( const const_raw_data_iterator< T >& lhs, const const_raw_data_iterator< T >& rhs )
+	{
+		NV_ASSERT( lhs.stride() == rhs.stride(), "stride failure!" );
+		return ( lhs.raw_data() - rhs.raw_data() ) / lhs->m_stride;
+	}
+	template < typename T >
+	constexpr const_raw_data_iterator< T > operator+( typename const_raw_data_iterator< T >::difference_type n, const const_raw_data_iterator< T >& iter )
+	{
+		return const_raw_data_iterator< T >( iter.raw_data() + iter.stride() * n, iter.stride() );
+	}
+}
+
+#endif // NV_STL_TYPE_ERASURE_HH
+
+
+
Index: trunk/src/gfx/mesh_creator.cc
===================================================================
--- trunk/src/gfx/mesh_creator.cc	(revision 457)
+++ trunk/src/gfx/mesh_creator.cc	(revision 458)
@@ -215,4 +215,5 @@
 	raw_data_channel g_channel  = data_channel_creator::create< vertex_g >( m_pos_channel->size() );
 	vec4* tangents              = &( data_channel_access< vertex_g >( &g_channel ).data()[0].tangent );
+	fill_n( tangents, m_pos_channel->size(), vec4() );
 	vec3* tangents2             = new vec3[ m_pos_channel->size() ];
 	uint32 tri_count = m_idx_channel ? m_idx_channel->size() / 3 : m_tex_channel->size() / 3;
@@ -246,7 +247,7 @@
 		}
 
-		const vec2& w1 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti0 + m_tex_offset );
-		const vec2& w2 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti1 + m_tex_offset );
-		const vec2& w3 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti2 + m_tex_offset );
+		vec2 w1 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti0 + m_tex_offset );
+		vec2 w2 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti1 + m_tex_offset );
+		vec2 w3 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti2 + m_tex_offset );
 		vec2 st1 = w3 - w1;
 		vec2 st2 = w2 - w1;
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 457)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 458)
@@ -235,8 +235,11 @@
 
 nv::skeletal_mesh_gpu::skeletal_mesh_gpu( context* a_context, const data_channel_set* a_mesh, const mesh_nodes_data* a_bone_data )
-	: skeletal_mesh( a_context ), m_bone_data( a_bone_data ), m_transform( nullptr )
-{
-	m_va          = a_context->create_vertex_array( a_mesh, nv::STATIC_DRAW );
-	m_index_count = a_mesh->get_channel_size( slot::INDEX );
+	: skeletal_mesh( a_context ), m_bone_data( a_bone_data ), m_index_count( 0 ), m_transform( nullptr )
+{
+	if ( a_mesh )
+	{
+		m_va = a_context->create_vertex_array( a_mesh, nv::STATIC_DRAW );
+		m_index_count = a_mesh->get_channel_size( slot::INDEX );
+	}
 	if ( m_bone_data )
 	{
@@ -264,4 +267,5 @@
 {
 	if ( node_id == 0 ) return transform();
+	if ( node_id == uint32(-1) ) return transform( m_transform[0] );
 	return transform( m_transform[ node_id ] );
 }
