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
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
[477]9void nv::skeleton_binding::prepare( const mesh_nodes_data* node_data, const mesh_nodes_data* bone_data )
[475]10{
[477]11        if ( !m_offsets || !m_indices )
[475]12        {
[477]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()];
[475]17
[477]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                }
[475]24
[477]25                for ( uint32 n = 0; n < node_data->size(); ++n )
[475]26                {
[477]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
[475]37                }
38        }
39
[477]40        if ( m_key.size() == 0 )
[475]41        {
[477]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                        }
[475]48        }
[477]49
[475]50}
51
[477]52void nv::skeleton_instance::animate( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame )
[475]53{
[477]54        if ( m_transform.size() > 0 )
55        {
56                if ( node_data->is_flat() )
[475]57                {
[477]58                        animate_flat( node_data, binding, frame );
[475]59                }
[477]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        }
[475]67}
68
[477]69void nv::skeleton_instance::animate_rec( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, uint32 id, const mat4& parent )
[475]70{
71        // TODO: fix transforms, which are now embedded,
72        //       see note in assimp_loader.cc:load_node
[477]73        const data_channel_set* node = ( *node_data )[id];
[475]74        mat4 node_mat( node->get_transform() );
75
76        if ( node->size() > 0 )
77        {
[477]78                raw_channel_interpolator interpolator( node, binding.m_key );
[475]79                node_mat = interpolator.get< mat4 >( frame );
80        }
81
82        mat4 global_mat = parent * node_mat;
83
[477]84        sint16 bone_id = binding.m_indices[id];
[475]85        if ( bone_id >= 0 )
86        {
[477]87                m_transform[bone_id] = global_mat * binding.m_offsets[bone_id];
[475]88        }
89
[477]90        for ( auto child : node_data->children( id ) )
[475]91        {
[477]92                animate_rec( node_data, binding, frame, child, global_mat );
[475]93        }
94}
[477]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.