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

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