source: trunk/src/formats/md2_loader.cc @ 236

Last change on this file since 236 was 236, checked in by epyon, 11 years ago
  • mass renames to prepare for new mesh_data
File size: 10.8 KB
RevLine 
[189]1// Copyright (C) 2012-2013 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/md2_loader.hh"
8
9#include <glm/gtc/constants.hpp>
10#include "nv/logging.hh"
11#include <cstring>
12
13using namespace nv;
14
15// based on http://tfc.duke.free.fr/coding/md2-specs-en.html
16
17// assuming low-endian
18#define MD2_MAX_FRAMES    512
19#define MD2_MAX_SKINS     32
20#define MD2_MAX_VERTS     2048
21#define MD2_MAX_TRIANGLES 4096
22#define MD2_MAX_TEXCOORDS 2048
23#define MD2_NORMAL_COUNT  162
24
25typedef float md2_vec3_t[3];
26
27static const md2_vec3_t md2_normal_table[MD2_NORMAL_COUNT] = {
28#include "src/formats/md2_normals.inc"
29};
30
31struct md2_header_t
32{
33        char magic[4];
34        int version;
35
36        int skinwidth;
37        int skinheight;
38
39        int framesize;
40
41        int num_skins;
42        int num_vertices;
43        int num_st;
44        int num_tris;
45        int num_glcmds;
46        int num_frames;
47
48        int offset_skins;
49        int offset_st;
50        int offset_tris;
51        int offset_frames;
52        int offset_glcmds;
53        int offset_end;
54};
55
56struct md2_skin_t
57{
58        char name[64];
59};
60
61struct md2_texcoord_t
62{
63        short s;
64        short t;
65};
66
67struct md2_triangle_t
68{
69        unsigned short vertex[3];
70        unsigned short st[3];
71};
72
73struct md2_vertex_t
74{
[198]75        uint8 v[3];
76        uint8 n;
[189]77};
78
79struct md2_frame_t
80{
81        md2_vec3_t scale;
82        md2_vec3_t translate;
83        char name[16];
84        md2_vertex_t *vertices;
85};
86
87struct md2_glcmd_t
88{
89        float s;
90        float t;
91        int index;
92};
93
94struct md2_t
95{
96        md2_header_t    header;
97        md2_skin_t*     skins;
98        md2_texcoord_t* texcoords;
99        md2_triangle_t* triangles;
100        md2_frame_t*    frames;
101        int*            glcmds;
102};
103
104static bool check_md2_magic( char* magic )
105{
106        return magic[0] == 'I' && magic[1] == 'D' && magic[2] == 'P' && magic[3] == '2';
107}
108
109static void free_md2_frame( md2_frame_t* frame )
110{
111        delete[] frame->vertices;
112}
113
114static void free_md2( md2_t* md2 )
115{
116        delete[] md2->skins;
117        delete[] md2->texcoords;
118        delete[] md2->triangles;
119        delete[] md2->glcmds;
120        for ( int i = 0; i < md2->header.num_frames; ++i )
121        {
122                free_md2_frame( &(md2->frames[i]) );
123        }
124        delete[] md2->frames;
125}
126
[198]127static bool read_md2_frame( md2_frame_t* frame, unsigned vcount, nv::stream& source )
[189]128{
129        frame->vertices = new md2_vertex_t[ vcount ];
130        source.read( frame->scale,     sizeof(md2_vec3_t), 1 );
131        source.read( frame->translate, sizeof(md2_vec3_t), 1 );
132        source.read( frame->name,      sizeof(char), 16 );
133        source.read( frame->vertices,  sizeof(md2_vertex_t), vcount );
134        return true;
135}
136
137static bool read_md2( md2_t* md2, nv::stream& source )
138{
139        md2->frames     = nullptr;
140        md2->skins      = nullptr;
141        md2->texcoords  = nullptr;
142        md2->triangles  = nullptr;
143        md2->glcmds     = nullptr;
144
145        source.read( &(md2->header), sizeof(md2_header_t), 1 );
146
147        if ( !check_md2_magic( md2->header.magic )       ||
148                md2->header.num_skins    > MD2_MAX_SKINS     ||
149                md2->header.num_vertices > MD2_MAX_VERTS     ||
150                md2->header.num_st       > MD2_MAX_TEXCOORDS ||
151                md2->header.num_tris     > MD2_MAX_TRIANGLES ||
152                md2->header.num_frames   > MD2_MAX_FRAMES )
153        {
154                return false;
155        }
156
157        NV_LOG( LOG_INFO, "num_skins    = " << md2->header.num_skins );
158        NV_LOG( LOG_INFO, "num_vertices = " << md2->header.num_vertices );
159        NV_LOG( LOG_INFO, "num_st       = " << md2->header.num_st );
160        NV_LOG( LOG_INFO, "num_tris     = " << md2->header.num_tris );
161        NV_LOG( LOG_INFO, "num_frames   = " << md2->header.num_frames );
162
163
164        md2->skins      = new md2_skin_t    [ md2->header.num_skins ];
165        md2->texcoords  = new md2_texcoord_t[ md2->header.num_st ];
166        md2->triangles  = new md2_triangle_t[ md2->header.num_tris ];
167        md2->glcmds     = new int           [ md2->header.num_glcmds ];
168       
169        source.seek( md2->header.offset_skins, origin::SET );
[198]170        source.read( md2->skins, sizeof(md2_skin_t), static_cast<size_t>( md2->header.num_skins ) );
[189]171
172        source.seek( md2->header.offset_st, origin::SET );
[198]173        source.read( md2->texcoords, sizeof(md2_texcoord_t), static_cast<size_t>( md2->header.num_st ) );
[189]174
175        source.seek( md2->header.offset_tris, origin::SET );
[198]176        source.read( md2->triangles, sizeof(md2_triangle_t), static_cast<size_t>( md2->header.num_tris ) );
[189]177
178        source.seek( md2->header.offset_glcmds, origin::SET);
[198]179        source.read( md2->glcmds, sizeof(int), static_cast<size_t>( md2->header.num_glcmds ) );
[189]180
181        md2->frames    = new md2_frame_t   [ md2->header.num_frames ];
182        source.seek( md2->header.offset_frames, origin::SET );
183        for ( int i = 0; i < md2->header.num_frames; ++i )
184        {
[198]185                if (!read_md2_frame( &(md2->frames[i]), static_cast<unsigned>( md2->header.num_vertices ), source ) ) return false;
[189]186        }
187
188        return true;
189}
190
191static inline vec3 md2_vec3( const md2_vec3_t& v )
192{
193        //      return vec3( v[0], v[1], v[2] );
194        return vec3( v[0], v[2], v[1] );
195}
196
[198]197static inline vec3 md2_normal( uint8 normal )
[189]198{
199        return md2_vec3( md2_normal_table[normal] );
200}
201
202static vec3 s_md2_normal_cache[MD2_NORMAL_COUNT];
203static bool s_md2_normal_ready = false;
204
205md2_loader::md2_loader() : m_md2( nullptr ), m_size( 0 )
206{
207        if ( !s_md2_normal_ready )
208        {
209                for ( int i = 0; i < MD2_NORMAL_COUNT; ++i )
210                {
211                        s_md2_normal_cache[i].x = md2_normal_table[i][0];
212//                      s_md2_normal_cache[i].y = md2_normal_table[i][1];
213//                      s_md2_normal_cache[i].z = md2_normal_table[i][2];
214                        s_md2_normal_cache[i].y = md2_normal_table[i][2];
215                        s_md2_normal_cache[i].z = md2_normal_table[i][1];
216                }
217        }
218}
219
220
221md2_loader::~md2_loader()
222{
223        if (m_md2 != nullptr)
224        {
225                free_md2( (md2_t*)(m_md2) );
226                delete (md2_t*)m_md2;
227        }
228}
229
230bool md2_loader::load( stream& source )
231{
232        m_size = 0;
233        m_md2 = (void*)(new md2_t);
234        if ( !read_md2( (md2_t*)m_md2, source ) )
235        {
236                return false;
237        }
238        reindex();
239        m_size = m_new_indexes.size();
240        return true;
241}
242
[236]243mesh_data_old* nv::md2_loader::release_mesh_data()
[224]244{
245        mesh_data_creator m;
246
247        load_positions( m.get_positions() );
248        load_normals( m.get_normals() );
249        load_texcoords( m.get_texcoords() );
250        load_indicies( m.get_indices() );
251
252        m_size = m.get_indices().size();
253        return m.release();
254}
255
[236]256mesh_data_old* nv::md2_loader::get_frame( sint32 frame )
[224]257{
258        mesh_data_creator m;
259
260        load_positions( m.get_positions(), frame );
261        load_normals( m.get_normals(), frame );
262        load_texcoords( m.get_texcoords() );
263        load_indicies( m.get_indices() );
264
265        m_size = m.get_indices().size();
266        return m.release();
267}
268
269
270/*
[189]271mesh* nv::md2_loader::release_mesh()
272{
273        return get_frame( 0 );
274}
275
276mesh* nv::md2_loader::get_frame( sint32 frame )
277{
278        md2_t* md2 = (md2_t*)m_md2;
279        if ( md2 == nullptr || frame >= md2->header.num_frames ) return nullptr;
280        mesh* m = new mesh();
281
282        vertex_attribute< vec3 >*   position = m->add_attribute<vec3>("nv_position");
283        vertex_attribute< vec3 >*   normal   = m->add_attribute<vec3>("nv_normal");
284        vertex_attribute< vec2 >*   texcoord = m->add_attribute<vec2>("nv_texcoord");
[224]285        vertex_attribute< uint32 >* indices  = m->add_indices<uint32>();
[189]286
287        load_positions( position->get(), frame );
288        load_normals( normal->get(), frame );
289
290        load_texcoords( texcoord->get() );
291        load_indicies( indices->get() );
292
293        m_size = indices->get().size();
294        return m;
295}
[224]296*/
[189]297
[198]298size_t md2_loader::get_max_frames() const
[189]299{
[198]300        return static_cast< size_t >( ((md2_t*)m_md2)->header.num_frames );
[189]301}
302
303void md2_loader::load_positions( std::vector<vec3>& p, sint32 frame /*=-1*/ )
304{
305        md2_t* md2 = (md2_t*)m_md2;
[198]306        size_t num_frames = static_cast< size_t >( md2->header.num_frames );
307        size_t num_verts  =     m_new_vindexes.size();
[189]308        p.clear();
[198]309        size_t current_frame = ( frame == -1 ? 0 : static_cast< size_t >( frame ) );
310        size_t frame_count   = ( frame == -1 ? num_frames : 1 );
[189]311
312        p.reserve( num_verts * frame_count );
313
314        while ( frame_count > 0 )
315        {
[198]316                const md2_frame_t& cframe = md2->frames[current_frame];
317                NV_LOG( LOG_INFO, "FrameID = " << cframe.name );
[189]318
[198]319                vec3 scale     = md2_vec3( cframe.scale );
320                vec3 translate = md2_vec3( cframe.translate );
[189]321
[198]322                for (size_t i = 0; i < num_verts; ++i )
[189]323                {
[198]324                        const md2_vertex_t& v = cframe.vertices[ m_new_vindexes[ i ] ];
[189]325                        p.push_back( vec3( v.v[0], v.v[2], v.v[1] ) * scale + translate );
326                }
327                ++current_frame;
328                --frame_count;
329        }
330}
331
332void md2_loader::load_normals( std::vector<vec3>& n, sint32 frame /*=-1*/ )
333{
334        md2_t* md2 = (md2_t*)m_md2;
[198]335        size_t num_frames = static_cast< size_t >( md2->header.num_frames );
336        size_t num_verts  =     m_new_vindexes.size();
[189]337        n.clear();
[198]338        size_t current_frame = ( frame == -1 ? 0 : static_cast< size_t>( frame ) );
339        size_t frame_count   = ( frame == -1 ? num_frames : 1 );
[189]340
341        n.reserve( num_verts * frame_count );
342
343        while ( frame_count > 0 )
344        {
[198]345                const md2_frame_t& cframe = md2->frames[current_frame];
[189]346
[198]347                for (size_t i = 0; i < num_verts; ++i )
[189]348                {
[198]349                        const md2_vertex_t& v = cframe.vertices[ m_new_vindexes[ i ] ];
[189]350                        n.push_back( s_md2_normal_cache[ v.n ] );
351                }
352                ++current_frame;
353                --frame_count;
354        }
355}
356
357void md2_loader::load_texcoords( std::vector<vec2>& t )
358{
359        md2_t* md2 = (md2_t*)m_md2;
[198]360        size_t num_verts  = m_new_vindexes.size();
[189]361
362        t.clear();
363        t.reserve( num_verts );
364
365        vec2 scale( 1.0f / (float) md2->header.skinwidth, 1.0f / (float) md2->header.skinheight );
366
[198]367        for (size_t i = 0; i < num_verts; ++i )
[189]368        {
369                const md2_texcoord_t& st = md2->texcoords[ m_new_tindexes[ i ] ];
370                t.push_back( scale * vec2( st.s, st.t ) );
371        }
372
373}
374
[224]375void md2_loader::load_indicies( std::vector<uint32>& idx )
[189]376{
377        idx.assign( m_new_indexes.begin(), m_new_indexes.end() );
378}
379
380void nv::md2_loader::reindex()
381{
382        md2_t* md2 = (md2_t*)m_md2;
[198]383        uint32 num_indexes = static_cast< uint32 >( md2->header.num_tris * 3 );
[189]384
385        uint32 stats_reuse      = 0;
386        uint32 stats_collision  = 0;
387
[204]388        std::vector< sint32 > index_translation( static_cast< uint32 >( md2->header.num_vertices ), -1 );
[189]389
390        m_new_indexes.clear();
391        m_new_indexes.reserve( num_indexes );
392        m_new_vindexes.reserve( num_indexes );
393        m_new_tindexes.reserve( num_indexes );
394
395        uint16 index_count = 0;
396
397        for ( int i = 0; i < md2->header.num_tris; ++i )
398        {
399                const md2_triangle_t& t = md2->triangles[i];
400                for ( int j = 0; j < 3; ++j )
401                {
[198]402                        uint16 index  = t.vertex[j];
403                        uint16 tindex = t.st[j];
[189]404
405                        if ( index_translation[ index ] != -1 )
406                        {
[198]407                                uint16 prev = static_cast< uint16 >( index_translation[ index ] );
[189]408                                if ( m_new_tindexes[ prev ] == tindex )
409                                {
410                                        m_new_indexes.push_back( prev );
411                                        stats_reuse++;
412                                        continue;
413                                }
414                        }
415                       
416                        m_new_vindexes.push_back( index );
417                        m_new_tindexes.push_back( tindex );
418                        m_new_indexes.push_back( index_count );
419                        if ( index_translation[ index ] == -1 )
420                        {
421                                index_translation[ index ] = index_count;
422                        }
423                        else
424                        {
425                                stats_collision++;
426                        }
427                        index_count++;
428                }
429        }
430
431        NV_LOG( LOG_INFO, "New vertex count = " << m_new_vindexes.size() );
432        NV_LOG( LOG_INFO, "Collisions       = " << stats_collision );
433        NV_LOG( LOG_INFO, "Reuse count      = " << stats_reuse );
434}
Note: See TracBrowser for help on using the repository browser.