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

Last change on this file since 485 was 485, checked in by epyon, 9 years ago
  • massive update (need to start doing atomics again) :/
File size: 11.4 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::assign( const skeleton_binding& other )
12{
13        m_indices.assign( other.m_indices );
14        m_key        = other.m_key;
15        m_bone_count = other.m_bone_count;
16}
17
18void nv::skeleton_binding::prepare( const mesh_nodes_data* node_data, const data_node_list& bone_data )
19{
20        if ( m_indices.empty() )
21        {
22                // TODO: either fixed size struct or static allocator
23                hash_store< shash64, uint16 > bone_names;
24                m_indices.resize( node_data->size() );
25
26                for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
27                        bone_names[bone_data[bi].name] = bi;
28
29                for ( uint32 n = 0; n < node_data->size(); ++n )
30                {
31                        sint16 bone_id = -1;
32                        auto bi = bone_names.find( node_data->get_info( n ).name );
33                        if ( bi != bone_names.end() )
34                        {
35                                bone_id = sint16( bi->second );
36                        }
37                        m_indices[n] = bone_id;
38
39                }
40                m_bone_count = bone_data.size();
41        }
42
43        if ( m_key.size() == 0 )
44        {
45                for ( uint32 n = 0; n < node_data->size(); ++n )
46                        if ( ( *node_data )[n]->size() > 0 )
47                        {
48                                m_key = ( *node_data )[n]->get_interpolation_key();
49                                break;
50                        }
51        }
52}
53
54void nv::skeleton_binding::prepare( const data_node_list& pose_data, const data_node_list& bone_data )
55{
56        if ( m_indices.empty() )
57        {
58                // TODO: either fixed size struct or static allocator
59                hash_store< shash64, uint16 > bone_names;
60                m_indices.resize( pose_data.size() );
61
62                for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
63                        bone_names[bone_data[bi].name] = bi;
64
65                for ( uint32 n = 0; n < pose_data.size(); ++n )
66                {
67                        sint16 bone_id = -1;
68                        auto bi = bone_names.find( pose_data[ n ].name );
69                        if ( bi != bone_names.end() )
70                        {
71                                bone_id = sint16( bi->second );
72                        }
73                        m_indices[n] = bone_id;
74
75                }
76                m_bone_count = bone_data.size();
77        }
78}
79
80
81void nv::skeleton_instance::assign( const skeleton_transforms& skeleton, const skeleton_binding& binding, const bone_transforms& bones )
82{
83        if ( bones.size() != m_matrix.size() )
84                m_matrix.resize( bones.size() );
85        const transform* transforms = skeleton.xforms();
86        for ( uint32 n = 0; n < skeleton.size(); ++n )
87        {
88                sint16 bone_id = binding.m_indices[n];
89                if ( bone_id >= 0 )
90                {
91                        int too_complex;
92                        transform tr( bones.m_offsets[bone_id] );
93                        tr.set_orientation( normalize( tr.get_orientation() ) );
94                        m_matrix[bone_id] = ( transforms[n] * tr ).extract();
95                }
96        }
97}
98
99
100void nv::skeleton_instance::assign( const skeleton_transforms& skeleton, const bone_transforms& bones )
101{
102        if ( bones.size() != m_matrix.size() )
103                m_matrix.resize( bones.size() );
104        const transform* transforms = skeleton.xforms();
105        for ( uint32 n = 0; n < skeleton.size(); ++n )
106        {
107                transform tr( bones.m_offsets[n] );
108                tr.set_orientation( normalize( tr.get_orientation() ) );
109                m_matrix[n] = ( transforms[n] * tr ).extract();
110        //      m_matrix[n] = transforms[n].extract() * bones.m_offsets[n];
111        }
112}
113
114void nv::skeleton_instance::assign( const bone_transforms& bones )
115{
116        if ( bones.size() != m_matrix.size() )
117                m_matrix.resize( bones.size() );
118}
119
120void nv::skeleton_transforms::assign( const data_node_list* node_data )
121{
122        NV_ASSERT( node_data, "!!!" );
123        if ( m_transforms.size() != node_data->size() )
124                m_transforms.resize( node_data->size() );
125        for ( uint32 n = 0; n < node_data->size(); ++n )
126        {
127                const data_node_info& info = (*node_data)[ n ];
128                m_transforms[n] = transform( info.transform );
129        }
130}
131
132void nv::skeleton_transforms::interpolate_linear( const skeleton_transforms& a, const skeleton_transforms& b, float t )
133{
134        NV_ASSERT( a.size() == b.size(), "!!!" );
135        if ( m_transforms.size() != a.size() )
136                m_transforms.resize( a.size() );
137        for ( uint32 n = 0; n < a.size(); ++n )
138        {
139                m_transforms[n] = transform(
140                        math::mix( a.m_transforms[n].get_position(), b.m_transforms[n].get_position(), t ),
141                        math::lerp( a.m_transforms[n].get_orientation(), b.m_transforms[n].get_orientation(), t )
142                        );
143        }
144
145//      if ( m_transforms.size() > 0 )
146//              m_transforms[0] = nv::interpolate( a.m_transforms[0], b.m_transforms[0], t, interpolation::SPHERICAL );
147}
148
149void nv::skeleton_transforms::interpolate_nlerp( const skeleton_transforms& a, const skeleton_transforms& b, float t )
150{
151        NV_ASSERT( a.size() == b.size(), "!!!" );
152        if ( m_transforms.size() != a.size() )
153                m_transforms.resize( a.size() );
154
155        for ( uint32 n = 0; n < a.size(); ++n )
156        {
157                m_transforms[n] = transform(
158                        math::mix( a.m_transforms[n].get_position(), b.m_transforms[n].get_position(), t ),
159                        math::nlerp( a.m_transforms[n].get_orientation(), b.m_transforms[n].get_orientation(), t )
160                        );
161        }
162}
163
164
165void nv::skeleton_transforms::interpolate_slerp( const skeleton_transforms& a, const skeleton_transforms& b, float t )
166{
167        NV_ASSERT( a.size() == b.size(), "!!!" );
168        if ( m_transforms.size() != a.size() )
169                m_transforms.resize( a.size() );
170        for ( uint32 n = 0; n < a.size(); ++n )
171        {
172                m_transforms[n] = nv::interpolate( a.m_transforms[n], b.m_transforms[n], t, interpolation::SPHERICAL );
173        }
174}
175
176void nv::skeleton_transforms::blend_slerp( const skeleton_transforms& a, const skeleton_transforms& b, float t, float blend )
177{
178        NV_ASSERT( a.size() == b.size(), "!!!" );
179        if ( m_transforms.size() != a.size() )
180                m_transforms.resize( a.size() );
181        for ( uint32 n = 0; n < a.size(); ++n )
182        {
183                transform tr    = nv::interpolate( a.m_transforms[n], b.m_transforms[n], t, interpolation::SPHERICAL );
184                m_transforms[n] = nv::interpolate( m_transforms[n], tr, blend, interpolation::SPHERICAL );
185        }
186}
187
188
189
190void nv::skeleton_transforms::interpolate4( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t )
191{
192        NV_ASSERT( s1.size() == s2.size(), "!!!" );
193        NV_ASSERT( v1.size() == v2.size(), "!!!" );
194        NV_ASSERT( s1.size() == v1.size(), "!!!" );
195        if ( m_transforms.size() != s1.size() )
196                m_transforms.resize( s1.size() );
197        float interp_squared = t*t;
198        float interp_cubed = interp_squared*t;
199        float weights[4];
200        weights[0] = 0.5f * ( -interp_cubed + 2.0f * interp_squared - t );
201        weights[1] = 0.5f * ( 3.0f * interp_cubed - 5.0f * interp_squared + 2.0f );
202        weights[2] = 0.5f * ( -3.0f * interp_cubed + 4.0f * interp_squared + t );
203        weights[3] = 0.5f * ( interp_cubed - interp_squared );
204
205        for ( uint32 n = 0; n < s1.size(); ++n )
206        {
207                quat qs1 = s1.m_transforms[n].get_orientation();
208                quat qs2 = s2.m_transforms[n].get_orientation();
209                quat qv1 = v1.m_transforms[n].get_orientation();
210                quat qv2 = v2.m_transforms[n].get_orientation();
211
212                float a = dot( qv1, qv2 ) > 0.0f ? 1.0f : -1.0f;
213
214                quat qr = weights[0] * qs1
215                                + weights[1] * (a * qv1 )
216                                + weights[2] * qv2
217                                + weights[3] * qs2;
218
219                qr = normalize( qr );
220
221                m_transforms[n] = transform(
222                        weights[0] * s1.m_transforms[n].get_position() +
223                        weights[1] * v1.m_transforms[n].get_position() +
224                        weights[2] * v2.m_transforms[n].get_position() +
225                        weights[3] * s2.m_transforms[n].get_position(),
226                        qr
227                );
228        }
229}
230
231
232void nv::skeleton_transforms::interpolate_squad( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t )
233{
234        NV_ASSERT( s1.size() == s2.size(), "!!!" );
235        NV_ASSERT( v1.size() == v2.size(), "!!!" );
236        NV_ASSERT( s1.size() == v1.size(), "!!!" );
237        if ( m_transforms.size() != s1.size() )
238                m_transforms.resize( s1.size() );
239
240        for ( uint32 n = 0; n < s1.size(); ++n )
241        {
242                nv::quat ss1 = s1.m_transforms[n].get_orientation();
243                nv::quat ss2 = s2.m_transforms[n].get_orientation();
244                nv::quat sv1 = v1.m_transforms[n].get_orientation();
245                nv::quat sv2 = v2.m_transforms[n].get_orientation();
246
247                nv::quat q = normalize( nv::math::squad(
248                        sv1, sv2,
249                        nv::math::intermediate( ss1, sv1, sv2 ),
250                        nv::math::intermediate( sv1, sv2, ss2 ),
251                        t ) );
252
253                m_transforms[n] = transform(
254                        mix( v1.m_transforms[n].get_position(), v2.m_transforms[n].get_position(), t ),
255                        q
256                        );
257        }
258       
259}
260
261void nv::skeleton_transforms::assign( const skeleton_transforms& other )
262{
263        m_transforms.assign( other.m_transforms );
264}
265
266// void nv::skeleton_transforms::blend_local( const mesh_nodes_data* node_data, float frame, float blend )
267// {
268//      if ( m_transforms.size() != node_data->size() )
269//              m_transforms.resize( node_data->size() );
270//      for ( uint32 n = 0; n < node_data->size(); ++n )
271//      {
272//              const data_channel_set* node = ( *node_data )[n];
273//              int inefficient_store_key;
274//
275//              transform tr = node->size() > 0 ? raw_channel_interpolator( node ).get< transform >( frame ) : transform( /*node->get_transform()*/ ); int confirm_that_not_needed;
276//              m_transforms[n] = nv::interpolate( m_transforms[n], tr, blend, interpolation::SPHERICAL );
277//      }
278// }
279//
280// void nv::skeleton_transforms::animate_local( const mesh_nodes_data* node_data, float frame )
281// {
282//      if ( m_transforms.size() != node_data->size() )
283//              m_transforms.resize( node_data->size() );
284//      for ( uint32 n = 0; n < node_data->size(); ++n )
285//      {
286//              const data_channel_set* node = ( *node_data )[n];
287//              if ( node->size() > 0 )
288//              {
289//                      int inefficient_store_key;
290//                      m_transforms[n] = raw_channel_interpolator( node ).get< transform >( frame );
291//              }
292//      }
293// }
294
295void nv::skeleton_transforms::delocalize_rec( const data_node_tree& node_data, uint32 id, const transform& parent )
296{
297        transform global_mat = parent;
298        global_mat *= m_transforms[id];
299        m_transforms[id] = global_mat;
300        for ( auto child : node_data.children( id ) )
301        {
302                delocalize_rec( node_data, child, global_mat );
303        }
304}
305
306// void nv::skeleton_transforms::blend_rec( const mesh_nodes_data* node_data, float frame, uint32 id, const transform& parent, bool local, float blend )
307// {
308//      const data_channel_set* node = ( *node_data )[id];
309//      int confirm_that_not_needed;
310//      transform node_mat/*( node->get_transform() )*/;
311//
312//      if ( node->size() > 0 )
313//      {
314//              int inefficient_store_key;
315//
316//              raw_channel_interpolator interpolator( node );
317//              node_mat = interpolator.get< transform >( frame );
318//      }
319//      transform global_mat = parent * node_mat;
320//      m_transforms[id] = nv::interpolate( m_transforms[id], local ? node_mat : global_mat, blend, interpolation::SPHERICAL );
321//      for ( auto child : node_data->children( id ) )
322//      {
323//              blend_rec( node_data, frame, child, global_mat, local, blend );
324//      }
325//
326// }
327//
328// void nv::skeleton_transforms::animate_rec( const mesh_nodes_data* node_data, float frame, uint32 id, const transform& parent, bool local )
329// {
330//      const data_channel_set* node = ( *node_data )[id];
331//      transform node_mat;
332//      int inefficient_store_key;
333//
334//      if ( node->size() > 0 )
335//              node_mat = raw_channel_interpolator( node ).get< transform >( frame );
336//      int confirm_that_not_needed;
337//      //      else
338//      //              node_mat = transform( node->get_transform() );
339//      transform global_mat = parent * node_mat;
340//      m_transforms[id] = local ? node_mat : global_mat;
341//      for ( auto child : node_data->children( id ) )
342//      {
343//              animate_rec( node_data, frame, child, global_mat, local );
344//      }
345//
346// }
347
348void nv::bone_transforms::prepare( const data_node_list& bone_data )
349{
350        m_offsets.resize( bone_data.size() );
351
352        for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
353                m_offsets[bi] = bone_data[bi].transform;
354}
Note: See TracBrowser for help on using the repository browser.