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

Last change on this file since 484 was 484, checked in by epyon, 10 years ago
  • resource manager updates
  • nv-image added
  • missing stl memory added
  • several other missing files
File size: 10.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        {
[484]54                transform tr( bones.m_offsets[n] );
55                tr.set_orientation( normalize( tr.get_orientation() ) );
56                m_matrix[n] = ( transforms[n] * tr ).extract();
57        //      m_matrix[n] = transforms[n].extract() * bones.m_offsets[n];
[482]58        }
[475]59}
60
[481]61void nv::skeleton_instance::assign( const bone_transforms& bones )
[475]62{
[481]63        if ( bones.size() != m_matrix.size() )
64                m_matrix.resize( bones.size() );
65}
66
[483]67void nv::skeleton_transforms::assign( const data_node_list* node_data )
68{
69        NV_ASSERT( node_data, "!!!" );
70        if ( m_transforms.size() != node_data->size() )
71                m_transforms.resize( node_data->size() );
72        for ( uint32 n = 0; n < node_data->size(); ++n )
73        {
74                const data_node_info& info = (*node_data)[ n ];
75                m_transforms[n] = transform( info.transform );
76        }
77}
78
[484]79void nv::skeleton_transforms::interpolate_linear( const skeleton_transforms& a, const skeleton_transforms& b, float t )
[483]80{
81        NV_ASSERT( a.size() == b.size(), "!!!" );
82        if ( m_transforms.size() != a.size() )
83                m_transforms.resize( a.size() );
84        for ( uint32 n = 0; n < a.size(); ++n )
85        {
[484]86                m_transforms[n] = transform(
87                        math::mix( a.m_transforms[n].get_position(), b.m_transforms[n].get_position(), t ),
88                        math::lerp( a.m_transforms[n].get_orientation(), b.m_transforms[n].get_orientation(), t )
89                        );
90        }
91
92        if ( m_transforms.size() > 0 )
93                m_transforms[0] = nv::interpolate( a.m_transforms[0], b.m_transforms[0], t );
94}
95
96void nv::skeleton_transforms::interpolate_nlerp( const skeleton_transforms& a, const skeleton_transforms& b, float t )
97{
98        NV_ASSERT( a.size() == b.size(), "!!!" );
99        if ( m_transforms.size() != a.size() )
100                m_transforms.resize( a.size() );
101
102        for ( uint32 n = 0; n < a.size(); ++n )
103        {
104                m_transforms[n] = transform(
105                        math::mix( a.m_transforms[n].get_position(), b.m_transforms[n].get_position(), t ),
106                        math::nlerp( a.m_transforms[n].get_orientation(), b.m_transforms[n].get_orientation(), t )
107                        );
108        }
109
110        if ( m_transforms.size() > 0 )
111                m_transforms[0] = nv::interpolate( a.m_transforms[0], b.m_transforms[0], t );
112}
113
114
115void nv::skeleton_transforms::interpolate_slerp( const skeleton_transforms& a, const skeleton_transforms& b, float t )
116{
117        NV_ASSERT( a.size() == b.size(), "!!!" );
118        if ( m_transforms.size() != a.size() )
119                m_transforms.resize( a.size() );
120        for ( uint32 n = 0; n < a.size(); ++n )
121        {
[483]122                m_transforms[n] = nv::interpolate( a.m_transforms[n], b.m_transforms[n], t );
123        }
124}
125
[484]126void nv::skeleton_transforms::interpolate4( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t )
127{
128        NV_ASSERT( s1.size() == s2.size(), "!!!" );
129        NV_ASSERT( v1.size() == v2.size(), "!!!" );
130        NV_ASSERT( s1.size() == v1.size(), "!!!" );
131        if ( m_transforms.size() != s1.size() )
132                m_transforms.resize( s1.size() );
133        float interp_squared = t*t;
134        float interp_cubed = interp_squared*t;
135        float weights[4];
136        weights[0] = 0.5f * ( -interp_cubed + 2.0f * interp_squared - t );
137        weights[1] = 0.5f * ( 3.0f * interp_cubed - 5.0f * interp_squared + 2.0f );
138        weights[2] = 0.5f * ( -3.0f * interp_cubed + 4.0f * interp_squared + t );
139        weights[3] = 0.5f * ( interp_cubed - interp_squared );
140
141        for ( uint32 n = 0; n < s1.size(); ++n )
142        {
143                quat qs1 = s1.m_transforms[n].get_orientation();
144                quat qs2 = s2.m_transforms[n].get_orientation();
145                quat qv1 = v1.m_transforms[n].get_orientation();
146                quat qv2 = v2.m_transforms[n].get_orientation();
147
148                float a = dot( qv1, qv2 ) > 0.0f ? 1.0f : -1.0f;
149
150                quat qr = weights[0] * qs1
151                                + weights[1] * (a * qv1 )
152                                + weights[2] * qv2
153                                + weights[3] * qs2;
154
155                qr = normalize( qr );
156
157                if ( n == 0 )
158                        qr = nv::math::slerp( v1.m_transforms[n].get_orientation(), v2.m_transforms[n].get_orientation(), t );
159
160                m_transforms[n] = transform(
161                        weights[0] * s1.m_transforms[n].get_position() +
162                        weights[1] * v1.m_transforms[n].get_position() +
163                        weights[2] * v2.m_transforms[n].get_position() +
164                        weights[3] * s2.m_transforms[n].get_position(),
165                        qr
166                );
167        }
168}
169
170
171void nv::skeleton_transforms::interpolate_squad( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t )
172{
173        NV_ASSERT( s1.size() == s2.size(), "!!!" );
174        NV_ASSERT( v1.size() == v2.size(), "!!!" );
175        NV_ASSERT( s1.size() == v1.size(), "!!!" );
176        if ( m_transforms.size() != s1.size() )
177                m_transforms.resize( s1.size() );
178
179        for ( uint32 n = 0; n < s1.size(); ++n )
180        {
181                nv::quat ss1 = s1.m_transforms[n].get_orientation();
182                nv::quat ss2 = s2.m_transforms[n].get_orientation();
183                nv::quat q = normalize( nv::math::squad(
184                        v1.m_transforms[n].get_orientation(),
185                        v2.m_transforms[n].get_orientation(),
186                        nv::math::intermediate( ss1, v1.m_transforms[n].get_orientation(), v2.m_transforms[n].get_orientation() ),
187                        nv::math::intermediate( v1.m_transforms[n].get_orientation(), v2.m_transforms[n].get_orientation(), ss2 ),
188                        t ) );
189                if ( n == 0 ) q = nv::math::slerp(
190                        v1.m_transforms[n].get_orientation(),
191                        v2.m_transforms[n].get_orientation(), t );
192
193                m_transforms[n] = transform(
194                        mix( v1.m_transforms[n].get_position(), v2.m_transforms[n].get_position(), t ),
195                        q
196                        );
197        }
198
199}
200
[483]201void nv::skeleton_transforms::assign( const skeleton_transforms& other )
202{
203        m_transforms.assign( other.m_transforms );
204}
205
[482]206void nv::skeleton_transforms::animate_local( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame )
[481]207{
[482]208        if ( m_transforms.size() != binding.skeleton_size() )
209                m_transforms.resize( binding.skeleton_size() );
210        for ( uint32 n = 0; n < node_data->size(); ++n )
211        {
212                const data_channel_set* node = ( *node_data )[n];
213                sint16 bone_id = binding.m_indices[n];
214                if ( bone_id >= 0 )
215                {
216                        if ( node->size() > 0 )
[484]217                        {
[482]218                                m_transforms[bone_id] = raw_channel_interpolator( node, binding.m_key ).get< transform >( frame );
[484]219                        }
[482]220                        int confirm_that_not_needed;
221//                      else
222//                              m_transforms[bone_id] = transform( node->get_transform() );
223                }
224        }
225}
226
227void nv::skeleton_transforms::blend_local( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, float blend )
228{
229        if ( m_transforms.size() != binding.skeleton_size() )
230                m_transforms.resize( binding.skeleton_size() );
231        for ( uint32 n = 0; n < node_data->size(); ++n )
232        {
233                const data_channel_set* node = ( *node_data )[n];
234                sint16 bone_id = binding.m_indices[n];
235                if ( bone_id >= 0 )
236                {
237                       
238                        transform tr = node->size() > 0 ? raw_channel_interpolator( node, binding.m_key ).get< transform >( frame ) : transform( /*node->get_transform()*/ ); int confirm_that_not_needed;
239                        m_transforms[bone_id] = nv::interpolate( m_transforms[bone_id], tr, blend );
240                }
241        }
242}
243
244void nv::skeleton_transforms::delocalize_rec( const data_node_tree& node_data, const skeleton_binding& binding, uint32 id, const transform& parent )
245{
246        sint16 bone_id = binding.m_indices[id];
247        transform global_mat = parent;
248        if ( bone_id >= 0 )
249        {
250                global_mat *= m_transforms[bone_id];
251                m_transforms[bone_id] = global_mat;
252        }
253        for ( auto child : node_data.children( id ) )
254        {
255                delocalize_rec( node_data, binding, child, global_mat );
256        }
257}
258
259void nv::skeleton_transforms::animate_rec( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, uint32 id, const transform& parent, bool local )
260{
[477]261        const data_channel_set* node = ( *node_data )[id];
[482]262        transform node_mat;
[475]263
264        if ( node->size() > 0 )
[482]265                node_mat = raw_channel_interpolator( node, binding.m_key ).get< transform >( frame );
266        int confirm_that_not_needed;
267        //      else
268//              node_mat = transform( node->get_transform() );
269        sint16 bone_id = binding.m_indices[id];
270        transform global_mat = parent * node_mat;
271        if ( bone_id >= 0 )
[475]272        {
[482]273                m_transforms[bone_id] = local ? node_mat : global_mat;
274        }
275        for ( auto child : node_data->children( id ) )
276        {
277                animate_rec( node_data, binding, frame, child, global_mat, local );
278        }
279}
280
281void 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 )
282{
283        const data_channel_set* node = ( *node_data )[id];
284        int confirm_that_not_needed;
285        transform node_mat/*( node->get_transform() )*/;
286
287        if ( node->size() > 0 )
288        {
[477]289                raw_channel_interpolator interpolator( node, binding.m_key );
[480]290                node_mat = interpolator.get< transform >( frame );
[475]291        }
[481]292        sint16 bone_id = binding.m_indices[id];
[480]293        transform global_mat = parent * node_mat;
[475]294        if ( bone_id >= 0 )
295        {
[482]296                m_transforms[bone_id] = nv::interpolate( m_transforms[bone_id], local ? node_mat : global_mat, blend );
[475]297        }
[477]298        for ( auto child : node_data->children( id ) )
[475]299        {
[482]300                blend_rec( node_data, binding, frame, child, global_mat, local, blend );
[475]301        }
302}
[477]303
[482]304
305void nv::bone_transforms::prepare( const data_node_list& bone_data )
[477]306{
[484]307        m_offsets.resize( bone_data.size() );
[481]308
[484]309        for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
310                m_offsets[bi] = bone_data[bi].transform;
[477]311}
Note: See TracBrowser for help on using the repository browser.