// Copyright (C) 2011-2017 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/gfx/skeleton_instance.hh" #include "nv/core/profiler.hh" #include "nv/interface/interpolate.hh" void nv::skeleton_binding::assign( const skeleton_binding& other ) { m_indices.assign( other.m_indices ); m_key = other.m_key; m_bone_count = other.m_bone_count; } void nv::skeleton_binding::prepare( const mesh_nodes_data* node_data, const data_node_list& bone_data ) { if ( m_indices.empty() ) { // TODO: either fixed size struct or static allocator hash_store< shash64, uint16 > bone_names; m_indices.resize( node_data->size() ); for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi ) bone_names[bone_data[bi].name] = bi; for ( uint32 n = 0; n < node_data->size(); ++n ) { sint16 bone_id = -1; auto bi = bone_names.find( node_data->get_info( n ).name ); if ( bi != bone_names.end() ) { bone_id = sint16( bi->second ); } m_indices[n] = bone_id; } m_bone_count = bone_data.size(); } if ( m_key.size() == 0 ) { for ( uint32 n = 0; n < node_data->size(); ++n ) if ( ( *node_data )[n]->size() > 0 ) { m_key = ( *node_data )[n]->get_interpolation_key(); break; } } } void nv::skeleton_binding::prepare( const data_node_list& pose_data, const data_node_list& bone_data ) { if ( m_indices.empty() ) { // TODO: either fixed size struct or static allocator hash_store< shash64, uint16 > bone_names; m_indices.resize( pose_data.size() ); for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi ) bone_names[bone_data[bi].name] = bi; for ( uint32 n = 0; n < pose_data.size(); ++n ) { sint16 bone_id = -1; auto bi = bone_names.find( pose_data[ n ].name ); if ( bi != bone_names.end() ) { bone_id = sint16( bi->second ); } m_indices[n] = bone_id; } m_bone_count = bone_data.size(); } } void nv::skeleton_transforms::assign( const data_node_list* node_data ) { NV_ASSERT( node_data, "!!!" ); if ( m_transforms.size() != node_data->size() ) m_transforms.resize( node_data->size() ); for ( uint32 n = 0; n < node_data->size(); ++n ) { m_transforms[n] = transform( ( *node_data )[n].transform ); } } void nv::skeleton_transforms::assign( const skeleton_transforms& other, const array_view< bool >& mask ) { if ( m_transforms.size() != other.size() ) m_transforms.resize( other.size() ); if ( mask.size() == 0 ) m_transforms.assign( other.m_transforms ); else for ( uint32 i = 0; i < other.size(); ++i ) if ( mask[i] ) m_transforms[i] = other.m_transforms[i]; } void nv::skeleton_transforms::interpolate( const skeleton_transforms& a, const skeleton_transforms& b, float t, interpolation i ) { if ( m_transforms.size() != a.size() ) m_transforms.resize( a.size() ); ::nv::interpolate( m_transforms, t, i, a.m_transforms, b.m_transforms ); } void nv::skeleton_transforms::interpolate( const skeleton_transforms& a, const skeleton_transforms& b, float t, interpolation i, const array_view< bool >& mask ) { if ( m_transforms.size() != a.size() ) m_transforms.resize( a.size() ); if ( mask.size() > 0 ) ::nv::interpolate( m_transforms, t, i, mask, a.m_transforms, b.m_transforms ); else ::nv::interpolate( m_transforms, t, i, a.m_transforms, b.m_transforms ); } void nv::skeleton_transforms::interpolate( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t, interpolation i ) { if ( m_transforms.size() != s1.size() ) m_transforms.resize( s1.size() ); ::nv::interpolate( m_transforms, t, i, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms ); } void nv::skeleton_transforms::interpolate( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t, interpolation i, const array_view< bool >& mask ) { if ( m_transforms.size() != s1.size() ) m_transforms.resize( s1.size() ); if ( mask.size() > 0 ) ::nv::interpolate( m_transforms, t, i, mask, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms ); else ::nv::interpolate( m_transforms, t, i, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms ); } void nv::skeleton_transforms::blend( const skeleton_transforms& a, const skeleton_transforms& b, float t, interpolation i, float blend, interpolation bi ) { NV_ASSERT( a.size() == b.size(), "!!!" ); if ( m_transforms.size() != a.size() ) m_transforms.resize( a.size() ); ::nv::interpolate( m_transforms, t, i, blend, bi, a.m_transforms, b.m_transforms ); } void nv::skeleton_transforms::blend( const skeleton_transforms& a, const skeleton_transforms& b, float t, interpolation i, float blend, interpolation bi, const array_view< bool >& mask ) { NV_ASSERT( a.size() == b.size(), "!!!" ); if ( m_transforms.size() != a.size() ) m_transforms.resize( a.size() ); if ( mask.size() > 0 ) ::nv::interpolate( m_transforms, t, i, blend, bi, mask, a.m_transforms, b.m_transforms ); else ::nv::interpolate( m_transforms, t, i, blend, bi, a.m_transforms, b.m_transforms ); } void nv::skeleton_transforms::blend( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t, interpolation i, float blend, interpolation bi ) { if ( m_transforms.size() != s1.size() ) m_transforms.resize( s1.size() ); ::nv::interpolate( m_transforms, t, i, blend, bi, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms ); } void nv::skeleton_transforms::blend( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t, interpolation i, float blend, interpolation bi, const array_view< bool >& mask ) { if ( m_transforms.size() != s1.size() ) m_transforms.resize( s1.size() ); if ( mask.size() > 0 ) ::nv::interpolate( m_transforms, t, i, blend, bi, mask, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms ); else ::nv::interpolate( m_transforms, t, i, blend, bi, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms ); } void nv::skeleton_transforms::assign( const skeleton_transforms& other ) { m_transforms.assign( other.m_transforms ); } void nv::skeleton_transforms::delocalize_rec( const data_node_tree& node_data, uint32 id, const transform& parent ) { transform global_mat = parent; global_mat *= m_transforms[id]; m_transforms[id] = global_mat; for ( auto child : node_data.children( id ) ) { delocalize_rec( node_data, child, global_mat ); } } void nv::skeleton_transforms::delocalize_rec( const data_node_tree& node_data, uint32 id, const transform& parent, const array_view< bool >& mask ) { transform global_mat = parent; bool b = mask[id]; if ( !b ) global_mat = m_transforms[id]; else { global_mat *= m_transforms[id]; m_transforms[id] = global_mat; } for ( auto child : node_data.children( id ) ) { delocalize_rec( node_data, child, global_mat, mask ); } }