source: trunk/src/formats/md3_loader.cc @ 148

Last change on this file since 148 was 148, checked in by epyon, 12 years ago
  • md3 loader - work in progress
File size: 12.7 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 <glm/gtx/string_cast.hpp>
11#include "nv/logging.hh"
12#include <cstring>
13
14using namespace nv;
15
16// based on http://www.icculus.org/~phaethon/q3/formats/md3format.html#Surface
17
18// assuming low-endian
19#define MD3_MAGIC         "IDP3"
20#define MD3_MAX_FRAMES    1024
21#define MD3_MAX_TAGS      16
22#define MD3_MAX_SURFACES  32
23#define MD3_MAX_SHADERS   256
24#define MD3_MAX_VERTS     4096
25#define MD3_MAX_TRIANGLES 8192
26#define MD3_XYZ_SCALE     (1.0f/64.0f)
27
28struct md3_vec3_t
29{
30        float xyz[3];
31};
32
33struct md3_header_t
34{
35        char   ident[4]; // IDP3
36        sint32 version;  // 15
37        uint8  name[64]; // path name
38        sint32 flags;
39        sint32 num_frames;     // Number of Frame objects, with a maximum of MD3_MAX_FRAMES. Current value of MD3_MAX_FRAMES is 1024.
40        sint32 num_tags;       // Number of Tag objects, with a maximum of MD3_MAX_TAGS. Current value of MD3_MAX_TAGS is 16.
41        sint32 num_surfaces;   // Number of Surface objects, with a maximum of MD3_MAX_SURFACES. Current value of MD3_MAX_SURFACES is 32.
42        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.
43        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.
44        sint32 ofs_tags;       // Relative offset from start of MD3 where Tag objects start. Similarly written sequentially.
45        sint32 ofs_surfaces;   // Relative offset from start of MD3 where Surface objects start. Again, written sequentially.
46        sint32 ofs_eof;        // Relative offset from start of MD3 to the end of the MD3 object. Note there is no offset for Skin objects.
47};
48
49struct md3_frame_t
50{
51        md3_vec3_t min_bounds;
52        md3_vec3_t max_bounds;
53        md3_vec3_t local_origin;
54        float      radius;
55        uint8      name[16];
56};
57
58struct md3_tag_t
59{
60        uint8      name[64];
61        md3_vec3_t origin;
62        md3_vec3_t axis[3];
63};
64
65struct md3_surface_header_t
66{
67        char   ident[4]; // IDP3
68        uint8  name[64]; // path name
69        sint32 flags;
70        sint32 num_frames;
71        sint32 num_shaders;
72        sint32 num_verts;
73        sint32 num_triangles;
74        sint32 ofs_triangles;
75        sint32 ofs_shaders;
76        sint32 ofs_st;
77        sint32 ofs_xyznormal;
78        sint32 ofs_end;
79};
80
81struct md3_shader_t
82{
83        uint8  name[64];
84        sint32 shader_index;
85};
86
87struct md3_triangle_t
88{
89        sint32 indexes[3];
90};
91
92struct md3_texcoord_t
93{
94        float  st[2];
95};
96
97struct md3_vertex_t
98{
99        sint16 x;
100        sint16 y;
101        sint16 z;
102        sint16 normal;
103};
104
105struct md3_surface_t
106{
107        md3_surface_header_t header;
108        md3_shader_t*        shaders;
109        md3_triangle_t*      triangles;
110        md3_texcoord_t*      st;
111        md3_vertex_t*        vertices;
112};
113
114struct md3_t
115{
116        md3_header_t   header;
117        md3_frame_t*   frames;
118        md3_tag_t*     tags;
119        md3_surface_t* surfaces;
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 = 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 ), surface->header.num_shaders );
165
166        source.seek( pos + surface->header.ofs_triangles, origin::SET );
167        source.read( surface->triangles, sizeof( md3_triangle_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 ), surface->header.num_verts );
171
172        source.seek( pos + surface->header.ofs_xyznormal, origin::SET );
173        source.read( surface->vertices, sizeof( md3_vertex_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, 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 ), md3->header.num_frames );
205
206        source.seek( md3->header.ofs_tags, origin::SET );
207        source.read( md3->tags, sizeof( md3_tag_t ), md3->header.num_tags * md3->header.num_frames );
208
209        source.seek( md3->header.ofs_surfaces, origin::SET );
210
211        for ( sint32 i = 0; i < md3->header.num_surfaces; ++i )
212        {
213                if ( !read_surface( md3->surfaces + i, source ) ) return false;
214                if ( md3->header.num_frames != md3->surfaces[i].header.num_frames ) return false;
215        }
216        return true;
217}
218
219static inline vec3 md3_vec3( const md3_vec3_t& v )
220{
221//      return vec3( v.xyz[0], v.xyz[1], v.xyz[2] );
222        return vec3( v.xyz[0], v.xyz[2], v.xyz[1] );
223}
224
225static inline vec2 md3_texcoord( const md3_texcoord_t& v )
226{
227        return vec2( v.st[0], v.st[1] );
228}
229
230static inline vec3 md3_vec3( const md3_vertex_t& v )
231{
232//      return vec3( v.x * MD3_XYZ_SCALE, v.y * MD3_XYZ_SCALE, v.z * MD3_XYZ_SCALE );
233        return vec3( v.x * MD3_XYZ_SCALE, v.z * MD3_XYZ_SCALE, v.y * MD3_XYZ_SCALE );
234}
235
236static inline vec3 md3_normal( const md3_vertex_t& v )
237{
238        float pi  = glm::pi<float>();
239        float lat = (((v.normal >> 8) & 255) * (2 * pi)) / 255.0f;
240        float lng = ((v.normal & 255) * (2 * pi)) / 255.0f;
241        return vec3(
242                glm::cos( lat ) * glm::sin( lng ),
243//              glm::sin( lat ) * glm::sin( lng ),
244//              glm::cos( lng )
245                glm::cos( lng ),
246                glm::sin( lat ) * glm::sin( lng )
247        );
248}
249
250
251md3_loader::md3_loader()
252        : m_md3( nullptr ), m_size( 0 )
253{
254       
255}
256
257
258nv::md3_loader::~md3_loader()
259{
260        if (m_md3 != nullptr)
261        {
262                free_md3( (md3_t*)(m_md3) );
263                delete (md3_t*)m_md3;
264        }
265}
266
267bool nv::md3_loader::load( stream& source )
268{
269        m_tags.clear();
270        m_size = 0;
271
272        m_md3 = (void*)(new md3_t);
273        if ( !read_md3( (md3_t*)m_md3, source ) )
274        {
275                return false;
276        }
277        return true;
278}
279
280mesh* nv::md3_loader::release_mesh()
281{
282        return get_frame( 0 );
283}
284
285mesh* nv::md3_loader::get_frame( sint32 frame )
286{
287        mesh* m = new mesh();
288        md3_t* md3 = (md3_t*)m_md3;
289
290        NV_LOG( LOG_INFO, "Tags:" );
291        for ( sint32 i = 0; i < md3->header.num_tags; ++i )
292        {
293                const md3_tag_t& rtag = md3->tags[i + md3->header.num_tags * frame];
294
295                md3_tag& tag   = m_tags[ (char*)(rtag.name) ];
296                tag.name       = (char*)(rtag.name);
297                vec4 axisx     = vec4( md3_vec3( rtag.axis[0] ), 0.0 );
298                vec4 axisz     = vec4( md3_vec3( rtag.axis[1] ), 0.0 );
299                vec4 axisy     = vec4( md3_vec3( rtag.axis[2] ), 0.0 );
300                vec4 origin    = vec4( md3_vec3( rtag.origin ),  1.0 );
301                tag.transform  = glm::mat4( axisx, axisy, axisz, origin );
302                NV_LOG( LOG_INFO, "Tag " << tag.name << " found" );
303        }
304
305        vertex_attribute< vec3 >* position = m->add_attribute<vec3>("position");
306        vertex_attribute< vec3 >* normal   = m->add_attribute<vec3>("normal");
307        vertex_attribute< vec2 >* texcoord = m->add_attribute<vec2>("texcoord");
308        vertex_attribute< uint16 >* indices  = m->add_indices<uint16>();
309
310        load_positions( position->get(), frame );
311        load_normals( normal->get(), frame );
312
313        load_texcoords( texcoord->get() );
314        load_indicies( indices->get() );
315
316        m_size = indices->get().size();
317        return m;
318}
319
320mat4 md3_loader::get_tag( sint32 frame, const std::string& name ) const
321{
322        md3_t* md3 = (md3_t*)m_md3;
323        for ( sint32 i = 0; i < md3->header.num_tags; ++i )
324        {
325                const md3_tag_t& rtag = md3->tags[i + md3->header.num_tags * frame];
326                std::string rname((char*)(rtag.name));
327                if (rname == name)
328                {
329                        vec4 axisx     = vec4( md3_vec3( rtag.axis[0] ), 0.0 );
330                        vec4 axisz     = vec4( md3_vec3( rtag.axis[1] ), 0.0 );
331                        vec4 axisy     = vec4( md3_vec3( rtag.axis[2] ), 0.0 );
332                        vec4 origin    = vec4( md3_vec3( rtag.origin ),  1.0 );
333                        return glm::mat4( axisx, axisy, axisz, origin );
334                }
335        }
336        return glm::mat4();
337}
338
339const md3_tag* md3_loader::get_tag( const std::string& name ) const
340{
341        auto it = m_tags.find( name );
342        if ( it == m_tags.end() ) return nullptr;
343        return &(it->second);
344}
345
346void md3_loader::load_positions( std::vector<vec3>& p, sint32 frame /*=-1*/ )
347{
348        md3_t* md3 = (md3_t*)m_md3;
349        sint32 num_surfaces = md3->header.num_surfaces;
350        p.clear();
351        sint32 current_frame = ( frame == -1 ? 0 : frame );
352        sint32 frame_count   = ( frame == -1 ? md3->header.num_frames : 1 );
353
354        while ( frame_count > 0 )
355        {
356                for ( sint32 i = 0; i < num_surfaces; ++i )
357                {
358                        md3_surface_t& surface = md3->surfaces[i];
359                        sint32         vcount  = surface.header.num_verts;
360                        sint32         offset  = vcount * current_frame;
361                        p.reserve( p.size() + vcount );
362                        for (sint32 j = 0; j < vcount; ++j )
363                        {
364                                p.push_back( md3_vec3( surface.vertices[j + offset] ) );
365                        }
366                }
367                ++current_frame;
368                --frame_count;
369        }
370}
371
372void md3_loader::load_normals( std::vector<vec3>& n, sint32 frame /*=-1*/ )
373{
374        md3_t* md3 = (md3_t*)m_md3;
375        sint32 num_surfaces = md3->header.num_surfaces;
376        n.clear();
377        sint32 current_frame = ( frame == -1 ? 0 : frame );
378        sint32 frame_count   = ( frame == -1 ? md3->header.num_frames : 1 );
379
380        while ( frame_count > 0 )
381        {
382                for ( sint32 i = 0; i < num_surfaces; ++i )
383                {
384                        md3_surface_t& surface = md3->surfaces[i];
385                        sint32         vcount  = surface.header.num_verts;
386                        sint32         offset  = vcount * current_frame;
387                        n.reserve( n.size() + vcount );
388                        for (sint32 j = 0; j < vcount; ++j )
389                        {
390                                n.push_back( md3_normal( surface.vertices[j + offset] ) );
391                        }
392                }
393                ++current_frame;
394                --frame_count;
395        }
396}
397
398void md3_loader::load_texcoords( std::vector<vec2>& t )
399{
400        md3_t* md3 = (md3_t*)m_md3;
401        sint32 num_surfaces = md3->header.num_surfaces;
402        t.clear();
403        for ( sint32 i = 0; i < num_surfaces; ++i )
404        {
405                const md3_surface_t& surface = md3->surfaces[i];
406                const sint32         vcount  = surface.header.num_verts;
407                t.reserve( t.size() + vcount );
408                for (sint32 j = 0; j < vcount; ++j )
409                {
410                        t.push_back( md3_texcoord( surface.st[j] ) );
411                }
412        }
413}
414
415void md3_loader::load_indicies( std::vector<uint16>& idx )
416{
417        md3_t* md3 = (md3_t*)m_md3;
418        sint32 num_surfaces = md3->header.num_surfaces;
419        idx.clear();
420        sint32 index_base = 0;
421        for ( sint32 i = 0; i < num_surfaces; ++i )
422        {
423                const md3_surface_t& surface = md3->surfaces[i];
424                const sint32         tcount  = surface.header.num_triangles;
425
426                idx.reserve( idx.size() + tcount * 3 );
427                for (sint32 j = 0; j < tcount; ++j )
428                {
429                        const md3_triangle_t& t = surface.triangles[j];
430                        idx.push_back( static_cast< uint16 >( index_base + t.indexes[0] ) );
431                        idx.push_back( static_cast< uint16 >( index_base + t.indexes[1] ) );
432                        idx.push_back( static_cast< uint16 >( index_base + t.indexes[2] ) );
433                }
434
435                index_base += surface.header.num_verts;
436        }
437
438}
Note: See TracBrowser for help on using the repository browser.