source: trunk/src/formats/md3_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: 15.3 KB
Line 
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/md3_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://www.icculus.org/~phaethon/q3/formats/md3format.html#Surface
16
17// assuming low-endian
18#define MD3_MAX_FRAMES    1024
19#define MD3_MAX_TAGS      16
20#define MD3_MAX_SURFACES  32
21#define MD3_MAX_SHADERS   256
22#define MD3_MAX_VERTS     4096
23#define MD3_MAX_TRIANGLES 8192
24#define MD3_XYZ_SCALE     (1.0f/64.0f)
25
26struct md3_vec3_t
27{
28        float xyz[3];
29};
30
31struct md3_header_t
32{
33        char   ident[4]; // IDP3
34        sint32 version;  // 15
35        uint8  name[64]; // path name
36        sint32 flags;
37        sint32 num_frames;     // Number of Frame objects, with a maximum of MD3_MAX_FRAMES. Current value of MD3_MAX_FRAMES is 1024.
38        sint32 num_tags;       // Number of Tag objects, with a maximum of MD3_MAX_TAGS. Current value of MD3_MAX_TAGS is 16.
39        sint32 num_surfaces;   // Number of Surface objects, with a maximum of MD3_MAX_SURFACES. Current value of MD3_MAX_SURFACES is 32.
40        sint32 num_skins;      // Number of Skin objects. I should note that I have not seen an MD3 using this particular field for anything; this appears to be an artifact from the Quake 2 MD2 format. Surface objects have their own Shader field.
41        sint32 ofs_frames;     // Relative offset from start of MD3 object where Frame objects start. The Frame objects are written sequentially, that is, when you read one Frame object, you do not need to seek() for the next object.
42        sint32 ofs_tags;       // Relative offset from start of MD3 where Tag objects start. Similarly written sequentially.
43        sint32 ofs_surfaces;   // Relative offset from start of MD3 where Surface objects start. Again, written sequentially.
44        sint32 ofs_eof;        // Relative offset from start of MD3 to the end of the MD3 object. Note there is no offset for Skin objects.
45};
46
47struct md3_frame_t
48{
49        md3_vec3_t min_bounds;
50        md3_vec3_t max_bounds;
51        md3_vec3_t local_origin;
52        float      radius;
53        uint8      name[16];
54};
55
56struct md3_tag_t
57{
58        uint8      name[64];
59        md3_vec3_t origin;
60        md3_vec3_t axis[3];
61};
62
63struct md3_surface_header_t
64{
65        char   ident[4]; // IDP3
66        uint8  name[64]; // path name
67        sint32 flags;
68        sint32 num_frames;
69        sint32 num_shaders;
70        sint32 num_verts;
71        sint32 num_triangles;
72        sint32 ofs_triangles;
73        sint32 ofs_shaders;
74        sint32 ofs_st;
75        sint32 ofs_xyznormal;
76        sint32 ofs_end;
77};
78
79struct md3_shader_t
80{
81        uint8  name[64];
82        sint32 shader_index;
83};
84
85struct md3_triangle_t
86{
87        sint32 indexes[3];
88};
89
90struct md3_texcoord_t
91{
92        float  st[2];
93};
94
95struct md3_vertex_t
96{
97        sint16 x;
98        sint16 y;
99        sint16 z;
100        uint16 normal;
101};
102
103struct md3_surface_t
104{
105        md3_surface_header_t header;
106        md3_shader_t*        shaders;
107        md3_triangle_t*      triangles;
108        md3_texcoord_t*      st;
109        md3_vertex_t*        vertices;
110};
111
112struct md3_t
113{
114        md3_header_t   header;
115        md3_frame_t*   frames;
116        md3_tag_t*     tags;
117        md3_surface_t* surfaces;
118        // extra information (not in md3 file)
119        sint32         vertices_per_frame;
120};
121
122static bool check_md3_magic( char* magic )
123{
124        return magic[0] == 'I' && magic[1] == 'D' && magic[2] == 'P' && magic[3] == '3';
125}
126
127static void free_md3_surface( md3_surface_t * surface )
128{
129        delete[] surface->shaders;
130        delete[] surface->triangles;
131        delete[] surface->st;
132        delete[] surface->vertices;
133}
134
135static void free_md3( md3_t * md3 )
136{
137        sint32 count = md3->header.num_surfaces;
138        for ( sint32 i = 0; i < count; ++i )
139        {
140                free_md3_surface( &md3->surfaces[i] );
141        }
142        delete[] md3->frames;
143        delete[] md3->tags;
144        delete[] md3->surfaces;
145}
146
147static bool read_surface( md3_surface_t * surface, nv::stream& source )
148{
149        sint32 pos = static_cast< sint32 >( source.tell() );
150        source.read( &surface->header, sizeof(md3_surface_header_t), 1 );
151
152        if ( !check_md3_magic( surface->header.ident ) )          return false;
153        if ( surface->header.num_frames    >  MD3_MAX_FRAMES )    return false;
154        if ( surface->header.num_shaders   >  MD3_MAX_SHADERS )   return false;
155        if ( surface->header.num_verts     >  MD3_MAX_VERTS )     return false;
156        if ( surface->header.num_triangles >  MD3_MAX_TRIANGLES ) return false;
157
158        surface->shaders   = new md3_shader_t  [ surface->header.num_shaders ];
159        surface->vertices  = new md3_vertex_t  [ surface->header.num_verts * surface->header.num_frames ];
160        surface->st        = new md3_texcoord_t[ surface->header.num_verts ];
161        surface->triangles = new md3_triangle_t[ surface->header.num_triangles ];
162
163        source.seek( pos + surface->header.ofs_shaders, origin::SET );
164        source.read( surface->shaders, sizeof( md3_shader_t ), static_cast<size_t>( surface->header.num_shaders ) );
165
166        source.seek( pos + surface->header.ofs_triangles, origin::SET );
167        source.read( surface->triangles, sizeof( md3_triangle_t ), static_cast<size_t>( surface->header.num_triangles ) );
168
169        source.seek( pos + surface->header.ofs_st, origin::SET );
170        source.read( surface->st, sizeof( md3_texcoord_t ), static_cast<size_t>( surface->header.num_verts ) );
171
172        source.seek( pos + surface->header.ofs_xyznormal, origin::SET );
173        source.read( surface->vertices, sizeof( md3_vertex_t ), static_cast<size_t>( surface->header.num_verts * surface->header.num_frames ) );
174
175        if ( source.tell() != static_cast<std::size_t>( pos + surface->header.ofs_end ) ) return false;
176
177        return true;
178}
179
180static bool read_md3( md3_t * md3, nv::stream& source )
181{
182        md3->frames   = nullptr;
183        md3->tags     = nullptr;
184        md3->surfaces = nullptr;
185
186        source.read( &md3->header, sizeof(md3_header_t), 1 );
187
188        if ( !check_md3_magic( md3->header.ident ) )        return false;
189        if ( md3->header.num_frames   >  MD3_MAX_FRAMES )   return false;
190        if ( md3->header.num_tags     >  MD3_MAX_TAGS )     return false;
191        if ( md3->header.num_surfaces >  MD3_MAX_SURFACES )
192        {
193                // to always have a safe free
194                md3->header.num_surfaces = 0;
195                return false;
196        }
197
198        md3->frames   = new md3_frame_t  [ md3->header.num_frames ];
199        md3->tags     = new md3_tag_t    [ md3->header.num_tags * md3->header.num_frames ];
200        md3->surfaces = new md3_surface_t[ md3->header.num_surfaces ];
201        std::memset( md3->surfaces, 0, static_cast< size_t >( md3->header.num_surfaces ) * sizeof(md3_surface_t) );
202
203        source.seek( md3->header.ofs_frames, origin::SET );
204        source.read( md3->frames, sizeof( md3_frame_t ), static_cast<size_t>( md3->header.num_frames ) );
205
206        source.seek( md3->header.ofs_tags, origin::SET );
207        source.read( md3->tags, sizeof( md3_tag_t ), static_cast<size_t>( md3->header.num_tags * md3->header.num_frames ) );
208
209        source.seek( md3->header.ofs_surfaces, origin::SET );
210        md3->vertices_per_frame = 0;
211
212        for ( sint32 i = 0; i < md3->header.num_surfaces; ++i )
213        {
214                if ( !read_surface( md3->surfaces + i, source ) ) return false;
215                if ( md3->header.num_frames != md3->surfaces[i].header.num_frames ) return false;
216                md3->vertices_per_frame += md3->surfaces[i].header.num_verts;
217        }
218        return true;
219}
220
221static inline vec3 md3_vec3( const md3_vec3_t& v )
222{
223//      return vec3( v.xyz[0], v.xyz[1], v.xyz[2] );
224        return vec3( v.xyz[0], v.xyz[2], v.xyz[1] );
225}
226
227static inline vec2 md3_texcoord( const md3_texcoord_t& v )
228{
229        return vec2( v.st[0], v.st[1] );
230}
231
232static vec3 s_normal_cache[256*256];
233static bool s_normal_ready = false;
234
235md3_loader::md3_loader()
236        : m_md3( nullptr ), m_size( 0 )
237{
238        if ( !s_normal_ready )
239        {
240                float pi      = glm::pi<float>();
241                float convert = (2 * pi) / 255.0f;
242                int n = 0;
243                for ( int lat = 0; lat < 256; ++lat )
244                {
245                        float flat    = lat * convert;
246                        float sin_lat = glm::sin( flat );
247                        float cos_lat = glm::cos( flat );
248                        for ( int lng = 0; lng < 256; ++lng, ++n )
249                        {
250                                float flng    = lng * convert;
251                                float sin_lng = glm::sin( flng );
252                                float cos_lng = glm::cos( flng );
253                                s_normal_cache[n].x = cos_lat * sin_lng;
254//                              s_normal_cache[n].y = sin_lat * sin_lng;
255//                              s_normal_cache[n].z = cos_lng;
256                                s_normal_cache[n].z = sin_lat * sin_lng;
257                                s_normal_cache[n].y = cos_lng;
258                        }
259                }
260
261                s_normal_ready = true;
262        }
263}
264
265
266nv::md3_loader::~md3_loader()
267{
268        if (m_md3 != nullptr)
269        {
270                free_md3( (md3_t*)(m_md3) );
271                delete (md3_t*)m_md3;
272        }
273}
274
275bool nv::md3_loader::load( stream& source )
276{
277        m_tags.clear();
278        m_size = 0;
279
280        m_md3 = (void*)(new md3_t);
281        if ( !read_md3( (md3_t*)m_md3, source ) )
282        {
283                return false;
284        }
285        return true;
286}
287
288/*
289mesh* nv::md3_loader::release_mesh()
290{
291        return get_frame( 0 );
292}
293
294mesh* nv::md3_loader::get_frame( sint32 frame )
295{
296        mesh* m = new mesh();
297        md3_t* md3 = (md3_t*)m_md3;
298
299        NV_LOG( LOG_INFO, "Tags:" );
300        for ( sint32 i = 0; i < md3->header.num_tags; ++i )
301        {
302                const md3_tag_t& rtag = md3->tags[i + md3->header.num_tags * frame];
303
304                md3_tag& tag   = m_tags[ (char*)(rtag.name) ];
305                tag.name       = (char*)(rtag.name);
306                vec4 axisx     = vec4( md3_vec3( rtag.axis[0] ), 0.0 );
307                vec4 axisz     = vec4( md3_vec3( rtag.axis[1] ), 0.0 );
308                vec4 axisy     = vec4( md3_vec3( rtag.axis[2] ), 0.0 );
309                vec4 origin    = vec4( md3_vec3( rtag.origin ),  1.0 );
310                tag.transform  = glm::mat4( axisx, axisy, axisz, origin );
311                NV_LOG( LOG_INFO, "Tag " << tag.name << " found" );
312        }
313
314        vertex_attribute< vec3 >* position = m->add_attribute<vec3>("nv_position");
315        vertex_attribute< vec3 >* normal   = m->add_attribute<vec3>("nv_normal");
316        vertex_attribute< vec2 >* texcoord = m->add_attribute<vec2>("nv_texcoord");
317        vertex_attribute< uint32 >* indices  = m->add_indices<uint32>();
318
319        load_positions( position->get(), frame );
320        load_normals( normal->get(), frame );
321
322        load_texcoords( texcoord->get() );
323        load_indicies( indices->get() );
324
325        m_size = indices->get().size();
326        return m;
327}
328*/
329
330void nv::md3_loader::load_tags( std::vector<transform>& t, const std::string& tag )
331{
332        md3_t* md3 = (md3_t*)m_md3;
333        t.clear();
334        for ( sint32 f = 0; f < md3->header.num_frames; ++f )
335        {
336                for ( sint32 i = 0; i < md3->header.num_tags; ++i )
337                {
338                        const md3_tag_t& rtag = md3->tags[i + md3->header.num_tags * f];
339                        std::string rname((char*)(rtag.name));
340                        if (rname == tag)
341                        {
342                                vec3 axisx  ( md3_vec3( rtag.axis[0] ) );
343                                vec3 axisz  ( md3_vec3( rtag.axis[1] ) );
344                                vec3 axisy  ( md3_vec3( rtag.axis[2] ) );
345                                vec3 origin ( md3_vec3( rtag.origin )  );
346                                t.emplace_back( origin, quat( mat3( axisx, axisy, axisz ) ) );
347                        }
348                }
349
350        }
351}
352
353mesh_data_old* nv::md3_loader::release_mesh_data()
354{
355        mesh_data_creator m;
356
357        load_positions( m.get_positions() );
358        load_normals( m.get_normals() );
359        load_texcoords( m.get_texcoords() );
360        load_indicies( m.get_indices() );
361       
362        std::vector< std::string > names;
363        load_tag_names( names );
364
365        for ( auto& name : names )
366        {
367                load_tags( m.get_tag_map()[ name ], name );
368        }
369
370        return m.release();
371}
372
373mesh_data_old* nv::md3_loader::get_frame( sint32 frame )
374{
375        mesh_data_creator m;
376
377        load_positions( m.get_positions(), frame );
378        load_normals( m.get_normals(), frame );
379        load_texcoords( m.get_texcoords() );
380        load_indicies( m.get_indices() );
381
382        std::vector< std::string > names;
383        load_tag_names( names );
384
385        for ( auto& name : names )
386        {
387                load_tags( m.get_tag_map()[ name ], name );
388        }
389        return m.release();
390}
391
392size_t md3_loader::get_max_frames() const
393{
394        return static_cast< size_t >( ((md3_t*)m_md3)->header.num_frames );
395}
396
397void md3_loader::load_tag_names( std::vector< std::string >& tags )
398{
399        tags.clear();
400        md3_t* md3 = (md3_t*)m_md3;
401        for ( sint32 i = 0; i < md3->header.num_tags; ++i )
402        {
403                const md3_tag_t& rtag = md3->tags[i + md3->header.num_tags];
404                tags.push_back( (char*)(rtag.name) );
405        }
406}
407
408transform md3_loader::get_tag( sint32 frame, const std::string& name ) const
409{
410        md3_t* md3 = (md3_t*)m_md3;
411        for ( sint32 i = 0; i < md3->header.num_tags; ++i )
412        {
413                const md3_tag_t& rtag = md3->tags[i + md3->header.num_tags * frame];
414                std::string rname((char*)(rtag.name));
415                if (rname == name)
416                {
417                        vec3 axisx ( md3_vec3( rtag.axis[0] ) );
418                        vec3 axisz ( md3_vec3( rtag.axis[1] ) );
419                        vec3 axisy ( md3_vec3( rtag.axis[2] ) );
420                        vec3 origin( md3_vec3( rtag.origin ) );
421                        return transform( origin, quat( mat3( axisx, axisy, axisz ) ) );
422                }
423        }
424        return transform();
425}
426
427const md3_tag* md3_loader::get_tag( const std::string& name ) const
428{
429        auto it = m_tags.find( name );
430        if ( it == m_tags.end() ) return nullptr;
431        return &(it->second);
432}
433
434void md3_loader::load_positions( std::vector<vec3>& p, sint32 frame /*=-1*/ )
435{
436        md3_t* md3 = (md3_t*)m_md3;
437        sint32 num_surfaces = md3->header.num_surfaces;
438        p.clear();
439        sint32 current_frame = ( frame == -1 ? 0 : frame );
440        sint32 frame_count   = ( frame == -1 ? md3->header.num_frames : 1 );
441
442        p.reserve( static_cast< size_t >( md3->vertices_per_frame * frame_count ) );
443
444        while ( frame_count > 0 )
445        {
446                for ( sint32 i = 0; i < num_surfaces; ++i )
447                {
448                        md3_surface_t& surface = md3->surfaces[i];
449                        sint32         vcount  = surface.header.num_verts;
450                        sint32         offset  = vcount * current_frame;
451                        sint32         limit   = vcount + offset;
452                        for (sint32 j = offset; j < limit; ++j )
453                        {
454                                md3_vertex_t& v = surface.vertices[j];
455                                p.push_back( vec3( v.x * MD3_XYZ_SCALE, v.z * MD3_XYZ_SCALE, v.y * MD3_XYZ_SCALE ) );
456                        }
457                }
458                ++current_frame;
459                --frame_count;
460        }
461}
462
463void md3_loader::load_normals( std::vector<vec3>& n, sint32 frame /*=-1*/ )
464{
465        md3_t* md3 = (md3_t*)m_md3;
466        sint32 num_surfaces = md3->header.num_surfaces;
467        n.clear();
468        sint32 current_frame = ( frame == -1 ? 0 : frame );
469        sint32 frame_count   = ( frame == -1 ? md3->header.num_frames : 1 );
470
471        n.reserve( static_cast< size_t >( md3->vertices_per_frame * frame_count ) );
472
473        while ( frame_count > 0 )
474        {
475                for ( sint32 i = 0; i < num_surfaces; ++i )
476                {
477                        md3_surface_t& surface = md3->surfaces[i];
478                        sint32         vcount  = surface.header.num_verts;
479                        sint32         offset  = vcount * current_frame;
480                        sint32         limit   = vcount + offset;
481                        for (sint32 j = offset; j < limit; ++j )
482                        {
483                                n.push_back( s_normal_cache[ surface.vertices[j].normal ] );
484                        }
485                }
486                ++current_frame;
487                --frame_count;
488        }
489}
490
491void md3_loader::load_texcoords( std::vector<vec2>& t )
492{
493        md3_t* md3 = (md3_t*)m_md3;
494        sint32 num_surfaces = md3->header.num_surfaces;
495        t.clear();
496        for ( sint32 i = 0; i < num_surfaces; ++i )
497        {
498                const md3_surface_t& surface = md3->surfaces[i];
499                const uint32         vcount  = static_cast< uint32 >( surface.header.num_verts );
500                t.reserve( t.size() + vcount );
501                for (uint32 j = 0; j < vcount; ++j )
502                {
503                        t.push_back( md3_texcoord( surface.st[j] ) );
504                }
505        }
506}
507
508void md3_loader::load_indicies( std::vector<uint32>& idx )
509{
510        md3_t* md3 = (md3_t*)m_md3;
511        sint32 num_surfaces = md3->header.num_surfaces;
512        idx.clear();
513        sint32 index_base = 0;
514        for ( sint32 i = 0; i < num_surfaces; ++i )
515        {
516                const md3_surface_t& surface = md3->surfaces[i];
517                const size_t         tcount  = static_cast< size_t >( surface.header.num_triangles );
518
519                idx.reserve( idx.size() + tcount * 3 );
520                for (size_t j = 0; j < tcount; ++j )
521                {
522                        const md3_triangle_t& t = surface.triangles[j];
523                        idx.push_back( static_cast< uint32 >( index_base + t.indexes[0] ) );
524                        idx.push_back( static_cast< uint32 >( index_base + t.indexes[1] ) );
525                        idx.push_back( static_cast< uint32 >( index_base + t.indexes[2] ) );
526                }
527
528                index_base += surface.header.num_verts;
529        }
530
531}
532
Note: See TracBrowser for help on using the repository browser.