source: trunk/src/formats/nmd_loader.cc @ 291

Last change on this file since 291 was 291, checked in by epyon, 11 years ago
  • assimp_loader now uses standard mesh_loader structures
  • assimp_loader now supports multiple animation tracks
  • mesh_loader now supports multiple mesh_nodes data sets
File size: 4.9 KB
Line 
1// Copyright (C) 2014 ChaosForge / Kornel Kisielewicz
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6
7#include "nv/formats/nmd_loader.hh"
8#include "nv/io/std_stream.hh"
9#include "nv/string.hh"
10
11using namespace nv;
12
13bool nv::nmd_loader::load( stream& source )
14{
15        // TODO: proper error handling
16        reset();
17        nmd_header root_header;
18        source.read( &root_header, sizeof( root_header ), 1 );
19        for ( uint32 i = 0; i < root_header.elements; ++i )
20        {
21                nmd_element_header element_header;
22                source.read( &element_header, sizeof( element_header ), 1 );
23                switch ( element_header.type )
24                {
25                case nmd_type::MESH           : load_mesh( source, element_header ); break;
26                case nmd_type::ANIMATION      : load_animation( source, element_header ); break;
27                case nmd_type::STRING_TABLE   : load_strings( source ); break;
28                default: NV_ASSERT( false, "UNKNOWN NMD ELEMENT!" ); break;
29                }
30        }
31        return true;
32}
33
34bool nv::nmd_loader::load_mesh( stream& source, const nmd_element_header& e )
35{
36        mesh_data* mesh = new mesh_data();
37        for ( uint32 s = 0; s < e.children; ++s )
38        {
39                nmd_element_header element_header;
40                source.read( &element_header, sizeof( element_header ), 1 );
41                NV_ASSERT( element_header.type == nmd_type::STREAM, "STREAM expected!" );
42
43                nmd_stream_header stream_header;
44                source.read( &stream_header, sizeof( stream_header ), 1 );
45                mesh_raw_channel* channel = mesh_raw_channel::create( stream_header.format, stream_header.count );
46                source.read( channel->data, stream_header.format.size, stream_header.count );
47                mesh->add_channel( channel );
48        }
49        m_mesh_names.push_back( e.name );
50        m_meshes.push_back( mesh );
51        return true;
52}
53
54mesh_data* nv::nmd_loader::release_mesh_data( size_t index )
55{
56        mesh_data* result = m_meshes[ index ];
57        if ( m_strings ) result->set_name( m_strings->get( m_mesh_names[ index ] ) );
58        m_meshes[ index ] = nullptr;
59        return result;
60}
61
62mesh_data_pack* nv::nmd_loader::release_mesh_data_pack()
63{
64        uint32 size = m_meshes.size();
65        mesh_data* meshes = new mesh_data[ size ];
66        for ( uint32 i = 0; i < size; ++i )
67        {
68                m_meshes[i]->move_to( meshes[i] );
69                delete m_meshes[i];
70        }
71        m_meshes.clear();
72        return new mesh_data_pack( size, meshes, release_mesh_nodes_data() );
73}
74
75void nv::nmd_loader::reset()
76{
77        for ( auto mesh : m_meshes ) if ( mesh ) delete mesh;
78        if ( m_strings )   delete m_strings;
79        if ( m_node_data ) delete m_node_data;
80        m_meshes.clear();
81        m_mesh_names.clear();
82        m_node_names.clear();
83
84        m_node_data  = nullptr;
85        m_node_array = nullptr;
86        m_strings    = nullptr;
87}
88
89nv::nmd_loader::~nmd_loader()
90{
91        reset();
92}
93
94bool nv::nmd_loader::load_strings( stream& source )
95{
96        NV_ASSERT( m_strings == nullptr, "MULTIPLE STRING ENTRIES!" );
97        m_strings = new string_table( &source );
98        return true;
99}
100
101bool nv::nmd_loader::load_animation( stream& source, const nmd_element_header& e )
102{
103        NV_ASSERT( m_node_data == nullptr, "MULTIPLE NODE ENTRIES!" );
104        nmd_animation_header animation_header;
105        source.read( &animation_header, sizeof( animation_header ), 1 );
106        m_node_array = new mesh_node_data[ e.children ];
107        for ( uint32 i = 0; i < e.children; ++i )
108        {
109                nmd_element_header element_header;
110                source.read( &element_header, sizeof( element_header ), 1 );
111                NV_ASSERT( element_header.type == nmd_type::NODE, "NODE expected!" );
112                m_node_names.push_back( element_header.name );
113                uint16 ch_count = element_header.children;
114
115                nmd_node_header node_header;
116                source.read( &node_header, sizeof( node_header ), 1 );
117                m_node_array[i].parent_id     = node_header.parent_id;
118                m_node_array[i].transform     = node_header.transform;
119                m_node_array[i].data          = nullptr;
120                if ( ch_count > 0 )
121                {
122                        key_data* kdata = new key_data;
123                        m_node_array[i].data = kdata;
124                        for ( uint32 c = 0; c < ch_count; ++c )
125                        {
126                                source.read( &element_header, sizeof( element_header ), 1 );
127                                NV_ASSERT( element_header.type == nmd_type::KEY_CHANNEL, "CHANNEL expected!" );
128                                nv::nmd_key_channel_header cheader;
129                                source.read( &cheader, sizeof( cheader ), 1 );
130                                key_raw_channel* channel = key_raw_channel::create( cheader.format, cheader.count );
131                                source.read( channel->data, channel->desc.size, channel->count );
132                                kdata->add_channel( channel );
133                        }
134                }
135        }
136        m_node_data = new mesh_nodes_data( "animation", e.children, m_node_array, animation_header.frame_rate, animation_header.duration, animation_header.flat );
137        return true;
138}
139
140mesh_nodes_data* nv::nmd_loader::release_mesh_nodes_data( size_t )
141{
142        if ( m_node_data )
143        {
144                if ( m_strings )
145                {
146                        for ( uint32 i = 0; i < m_node_data->get_count(); ++i )
147                        {
148                                m_node_array[i].name = m_strings->get( m_node_names[i] );
149                        }
150                }
151                mesh_nodes_data* result = m_node_data;
152                m_node_data = nullptr;
153                m_node_array = nullptr;
154                return result;
155        }
156        return nullptr;
157}
158
Note: See TracBrowser for help on using the repository browser.