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

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