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

Last change on this file since 480 was 480, checked in by epyon, 10 years ago
  • cleanup of legacy code
  • resource updates
File size: 3.2 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 mesh_nodes_data* bone_data )
12{
13        if ( !m_offsets || !m_indices )
14        {
15                // TODO: either fixed size struct or static allocator
16                hash_store< shash64, uint16 > bone_names;
17                m_offsets = new mat4[bone_data->size()];
18                m_indices = new sint16[node_data->size()];
19
20                for ( nv::uint16 bi = 0; bi < bone_data->size(); ++bi )
21                {
22                        const data_channel_set* bone = ( *bone_data )[bi];
23                        bone_names[bone->get_name()] = bi;
24                        m_offsets[bi] = bone->get_transform();
25                }
26
27                for ( uint32 n = 0; n < node_data->size(); ++n )
28                {
29                        const data_channel_set* node = ( *node_data )[n];
30                        sint16 bone_id = -1;
31
32                        auto bi = bone_names.find( node->get_name() );
33                        if ( bi != bone_names.end() )
34                        {
35                                bone_id = sint16( bi->second );
36                        }
37                        m_indices[n] = bone_id;
38
39                }
40        }
41
42        if ( m_key.size() == 0 )
43        {
44                for ( uint32 n = 0; n < node_data->size(); ++n )
45                        if ( ( *node_data )[n]->size() > 0 )
46                        {
47                                m_key = ( *node_data )[n]->get_interpolation_key();
48                                break;
49                        }
50        }
51
52}
53
54void nv::skeleton_instance::animate( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame )
55{
56        if ( m_transform.size() > 0 )
57        {
58                if ( node_data->is_flat() )
59                {
60                        animate_flat( node_data, binding, frame );
61                }
62                else
63                {
64                        for ( uint32 n = 0; n < node_data->size(); ++n )
65                                if ( ( *node_data )[n]->get_parent_id() == -1 )
66                                        animate_rec( node_data, binding, frame, n, transform() );
67                }
68        }
69}
70
71void nv::skeleton_instance::animate_rec( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, uint32 id, const transform& parent )
72{
73        // TODO: fix transforms, which are now embedded,
74        //       see note in assimp_loader.cc:load_node
75        const data_channel_set* node = ( *node_data )[id];
76        transform node_mat( node->get_transform() );
77
78        if ( node->size() > 0 )
79        {
80                raw_channel_interpolator interpolator( node, binding.m_key );
81                node_mat = interpolator.get< transform >( frame );
82        }
83
84        transform global_mat = parent * node_mat;
85
86        sint16 bone_id = binding.m_indices[id];
87        if ( bone_id >= 0 )
88        {
89                m_transform[bone_id] = global_mat.extract() * binding.m_offsets[bone_id];
90        }
91
92        for ( auto child : node_data->children( id ) )
93        {
94                animate_rec( node_data, binding, frame, child, global_mat );
95        }
96}
97
98void nv::skeleton_instance::animate_flat( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame )
99{
100        for ( uint32 n = 0; n < node_data->size(); ++n )
101                if ( binding.m_indices[n] >= 0 )
102                {
103                        const data_channel_set* node = ( *node_data )[n];
104                        nv::mat4 node_mat( node->get_transform() );
105
106                        if ( node->size() > 0 )
107                        {
108                                raw_channel_interpolator interpolator( node, binding.m_key );
109                                node_mat = interpolator.get< mat4 >( frame );
110                        }
111
112                        sint16 bone_id = binding.m_indices[n];
113                        m_transform[bone_id] = node_mat * binding.m_offsets[bone_id];
114                }
115}
Note: See TracBrowser for help on using the repository browser.