source: trunk/src/gfx/skeleton_instance.cc @ 482

Last change on this file since 482 was 482, checked in by epyon, 10 years ago
  • skeletal animation updated
File size: 5.3 KB
RevLine 
[475]1// Copyright (C) 2011-2015 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
6
7#include "nv/gfx/skeleton_instance.hh"
8
[480]9#include "nv/core/profiler.hh"
10
[482]11void nv::skeleton_binding::prepare( const mesh_nodes_data* node_data, const data_node_list& bone_data )
[475]12{
[481]13        if ( m_indices.empty() )
[475]14        {
[477]15                // TODO: either fixed size struct or static allocator
16                hash_store< shash64, uint16 > bone_names;
[481]17                m_indices.resize( node_data->size() );
[475]18
[482]19                for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
20                        bone_names[bone_data[bi].name] = bi;
21
[477]22                for ( uint32 n = 0; n < node_data->size(); ++n )
[475]23                {
[477]24                        sint16 bone_id = -1;
[482]25                        auto bi = bone_names.find( node_data->get_info( n ).name );
[477]26                        if ( bi != bone_names.end() )
27                        {
28                                bone_id = sint16( bi->second );
29                        }
30                        m_indices[n] = bone_id;
31
[475]32                }
[482]33                m_bone_count = bone_data.size();
[475]34        }
35
[477]36        if ( m_key.size() == 0 )
[475]37        {
[477]38                for ( uint32 n = 0; n < node_data->size(); ++n )
39                        if ( ( *node_data )[n]->size() > 0 )
40                        {
41                                m_key = ( *node_data )[n]->get_interpolation_key();
42                                break;
43                        }
[475]44        }
45}
46
[481]47void nv::skeleton_instance::assign( const skeleton_transforms& skeleton, const bone_transforms& bones )
[475]48{
[481]49        if ( bones.size() != m_matrix.size() )
50                m_matrix.resize( bones.size() );
51        const transform* transforms = skeleton.transforms();
52        for ( uint32 n = 0; n < skeleton.size(); ++n )
[482]53        {
[481]54                m_matrix[n] = transforms[n].extract() * bones.m_offsets[n];
[482]55        }
[475]56}
57
[481]58void nv::skeleton_instance::assign( const bone_transforms& bones )
[475]59{
[481]60        if ( bones.size() != m_matrix.size() )
61                m_matrix.resize( bones.size() );
62}
63
[482]64void nv::skeleton_transforms::animate_local( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame )
[481]65{
[482]66        if ( m_transforms.size() != binding.skeleton_size() )
67                m_transforms.resize( binding.skeleton_size() );
68        for ( uint32 n = 0; n < node_data->size(); ++n )
69        {
70                const data_channel_set* node = ( *node_data )[n];
71                sint16 bone_id = binding.m_indices[n];
72                if ( bone_id >= 0 )
73                {
74                        if ( node->size() > 0 )
75                                m_transforms[bone_id] = raw_channel_interpolator( node, binding.m_key ).get< transform >( frame );
76                        int confirm_that_not_needed;
77//                      else
78//                              m_transforms[bone_id] = transform( node->get_transform() );
79                }
80        }
81}
82
83void nv::skeleton_transforms::blend_local( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, float blend )
84{
85        if ( m_transforms.size() != binding.skeleton_size() )
86                m_transforms.resize( binding.skeleton_size() );
87        for ( uint32 n = 0; n < node_data->size(); ++n )
88        {
89                const data_channel_set* node = ( *node_data )[n];
90                sint16 bone_id = binding.m_indices[n];
91                if ( bone_id >= 0 )
92                {
93                       
94                        transform tr = node->size() > 0 ? raw_channel_interpolator( node, binding.m_key ).get< transform >( frame ) : transform( /*node->get_transform()*/ ); int confirm_that_not_needed;
95                        m_transforms[bone_id] = nv::interpolate( m_transforms[bone_id], tr, blend );
96                }
97        }
98}
99
100void nv::skeleton_transforms::delocalize_rec( const data_node_tree& node_data, const skeleton_binding& binding, uint32 id, const transform& parent )
101{
102        sint16 bone_id = binding.m_indices[id];
103        transform global_mat = parent;
104        if ( bone_id >= 0 )
105        {
106                global_mat *= m_transforms[bone_id];
107                m_transforms[bone_id] = global_mat;
108        }
109        for ( auto child : node_data.children( id ) )
110        {
111                delocalize_rec( node_data, binding, child, global_mat );
112        }
113}
114
115void nv::skeleton_transforms::animate_rec( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, uint32 id, const transform& parent, bool local )
116{
[477]117        const data_channel_set* node = ( *node_data )[id];
[482]118        transform node_mat;
[475]119
120        if ( node->size() > 0 )
[482]121                node_mat = raw_channel_interpolator( node, binding.m_key ).get< transform >( frame );
122        int confirm_that_not_needed;
123        //      else
124//              node_mat = transform( node->get_transform() );
125        sint16 bone_id = binding.m_indices[id];
126        transform global_mat = parent * node_mat;
127        if ( bone_id >= 0 )
[475]128        {
[482]129                m_transforms[bone_id] = local ? node_mat : global_mat;
130        }
131        for ( auto child : node_data->children( id ) )
132        {
133                animate_rec( node_data, binding, frame, child, global_mat, local );
134        }
135}
136
137void nv::skeleton_transforms::blend_rec( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, uint32 id, const transform& parent, bool local, float blend )
138{
139        const data_channel_set* node = ( *node_data )[id];
140        int confirm_that_not_needed;
141        transform node_mat/*( node->get_transform() )*/;
142
143        if ( node->size() > 0 )
144        {
[477]145                raw_channel_interpolator interpolator( node, binding.m_key );
[480]146                node_mat = interpolator.get< transform >( frame );
[475]147        }
[481]148        sint16 bone_id = binding.m_indices[id];
[480]149        transform global_mat = parent * node_mat;
[475]150        if ( bone_id >= 0 )
151        {
[482]152                m_transforms[bone_id] = nv::interpolate( m_transforms[bone_id], local ? node_mat : global_mat, blend );
[475]153        }
[477]154        for ( auto child : node_data->children( id ) )
[475]155        {
[482]156                blend_rec( node_data, binding, frame, child, global_mat, local, blend );
[475]157        }
158}
[477]159
[482]160
161void nv::bone_transforms::prepare( const data_node_list& bone_data )
[477]162{
[481]163        if ( m_offsets.empty() )
164        {
[482]165                m_offsets.resize( bone_data.size() );
[481]166
[482]167                for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
168                        m_offsets[bi] = bone_data[bi].transform;
[481]169        }
[477]170}
Note: See TracBrowser for help on using the repository browser.