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
Line 
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
9#include "nv/core/profiler.hh"
10
11void nv::skeleton_binding::prepare( const mesh_nodes_data* node_data, const data_node_list& bone_data )
12{
13        if ( m_indices.empty() )
14        {
15                // TODO: either fixed size struct or static allocator
16                hash_store< shash64, uint16 > bone_names;
17                m_indices.resize( node_data->size() );
18
19                for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
20                        bone_names[bone_data[bi].name] = bi;
21
22                for ( uint32 n = 0; n < node_data->size(); ++n )
23                {
24                        sint16 bone_id = -1;
25                        auto bi = bone_names.find( node_data->get_info( n ).name );
26                        if ( bi != bone_names.end() )
27                        {
28                                bone_id = sint16( bi->second );
29                        }
30                        m_indices[n] = bone_id;
31
32                }
33                m_bone_count = bone_data.size();
34        }
35
36        if ( m_key.size() == 0 )
37        {
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                        }
44        }
45}
46
47void nv::skeleton_instance::assign( const skeleton_transforms& skeleton, const bone_transforms& bones )
48{
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 )
53        {
54                m_matrix[n] = transforms[n].extract() * bones.m_offsets[n];
55        }
56}
57
58void nv::skeleton_instance::assign( const bone_transforms& bones )
59{
60        if ( bones.size() != m_matrix.size() )
61                m_matrix.resize( bones.size() );
62}
63
64void nv::skeleton_transforms::animate_local( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame )
65{
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{
117        const data_channel_set* node = ( *node_data )[id];
118        transform node_mat;
119
120        if ( node->size() > 0 )
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 )
128        {
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        {
145                raw_channel_interpolator interpolator( node, binding.m_key );
146                node_mat = interpolator.get< transform >( frame );
147        }
148        sint16 bone_id = binding.m_indices[id];
149        transform global_mat = parent * node_mat;
150        if ( bone_id >= 0 )
151        {
152                m_transforms[bone_id] = nv::interpolate( m_transforms[bone_id], local ? node_mat : global_mat, blend );
153        }
154        for ( auto child : node_data->children( id ) )
155        {
156                blend_rec( node_data, binding, frame, child, global_mat, local, blend );
157        }
158}
159
160
161void nv::bone_transforms::prepare( const data_node_list& bone_data )
162{
163        if ( m_offsets.empty() )
164        {
165                m_offsets.resize( bone_data.size() );
166
167                for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
168                        m_offsets[bi] = bone_data[bi].transform;
169        }
170}
Note: See TracBrowser for help on using the repository browser.