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 |
|
---|
13 | using 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 |
|
---|
26 | struct md3_vec3_t
|
---|
27 | {
|
---|
28 | float xyz[3];
|
---|
29 | };
|
---|
30 |
|
---|
31 | struct 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 |
|
---|
47 | struct 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 |
|
---|
56 | struct md3_tag_t
|
---|
57 | {
|
---|
58 | uint8 name[64];
|
---|
59 | md3_vec3_t origin;
|
---|
60 | md3_vec3_t axis[3];
|
---|
61 | };
|
---|
62 |
|
---|
63 | struct 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 |
|
---|
79 | struct md3_shader_t
|
---|
80 | {
|
---|
81 | uint8 name[64];
|
---|
82 | sint32 shader_index;
|
---|
83 | };
|
---|
84 |
|
---|
85 | struct md3_triangle_t
|
---|
86 | {
|
---|
87 | sint32 indexes[3];
|
---|
88 | };
|
---|
89 |
|
---|
90 | struct md3_texcoord_t
|
---|
91 | {
|
---|
92 | float st[2];
|
---|
93 | };
|
---|
94 |
|
---|
95 | struct md3_vertex_t
|
---|
96 | {
|
---|
97 | sint16 x;
|
---|
98 | sint16 y;
|
---|
99 | sint16 z;
|
---|
100 | uint16 normal;
|
---|
101 | };
|
---|
102 |
|
---|
103 | struct 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 |
|
---|
112 | struct 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 |
|
---|
122 | static bool check_md3_magic( char* magic )
|
---|
123 | {
|
---|
124 | return magic[0] == 'I' && magic[1] == 'D' && magic[2] == 'P' && magic[3] == '3';
|
---|
125 | }
|
---|
126 |
|
---|
127 | static 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 |
|
---|
135 | static 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 |
|
---|
147 | static 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 |
|
---|
180 | static 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 |
|
---|
221 | static 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 |
|
---|
227 | static inline vec2 md3_texcoord( const md3_texcoord_t& v )
|
---|
228 | {
|
---|
229 | return vec2( v.st[0], v.st[1] );
|
---|
230 | }
|
---|
231 |
|
---|
232 | static vec3 s_normal_cache[256*256];
|
---|
233 | static bool s_normal_ready = false;
|
---|
234 |
|
---|
235 | md3_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 |
|
---|
266 | nv::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 |
|
---|
275 | bool 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 | /*
|
---|
289 | mesh* nv::md3_loader::release_mesh()
|
---|
290 | {
|
---|
291 | return get_frame( 0 );
|
---|
292 | }
|
---|
293 |
|
---|
294 | mesh* 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 |
|
---|
330 | void nv::md3_loader::load_tags( std::vector<mat4>& 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 | vec4 axisx = vec4( md3_vec3( rtag.axis[0] ), 0.0 );
|
---|
343 | vec4 axisz = vec4( md3_vec3( rtag.axis[1] ), 0.0 );
|
---|
344 | vec4 axisy = vec4( md3_vec3( rtag.axis[2] ), 0.0 );
|
---|
345 | vec4 origin = vec4( md3_vec3( rtag.origin ), 1.0 );
|
---|
346 | t.emplace_back( axisx, axisy, axisz, origin );
|
---|
347 | }
|
---|
348 | }
|
---|
349 |
|
---|
350 | }
|
---|
351 | }
|
---|
352 |
|
---|
353 | mesh_data* 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 |
|
---|
373 | mesh_data* 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 |
|
---|
392 | size_t md3_loader::get_max_frames() const
|
---|
393 | {
|
---|
394 | return static_cast< size_t >( ((md3_t*)m_md3)->header.num_frames );
|
---|
395 | }
|
---|
396 |
|
---|
397 | void 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 |
|
---|
408 | mat4 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 | vec4 axisx = vec4( md3_vec3( rtag.axis[0] ), 0.0 );
|
---|
418 | vec4 axisz = vec4( md3_vec3( rtag.axis[1] ), 0.0 );
|
---|
419 | vec4 axisy = vec4( md3_vec3( rtag.axis[2] ), 0.0 );
|
---|
420 | vec4 origin = vec4( md3_vec3( rtag.origin ), 1.0 );
|
---|
421 | return glm::mat4( axisx, axisy, axisz, origin );
|
---|
422 | }
|
---|
423 | }
|
---|
424 | return glm::mat4();
|
---|
425 | }
|
---|
426 |
|
---|
427 | const 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 |
|
---|
434 | void 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 |
|
---|
463 | void 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 |
|
---|
491 | void 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 |
|
---|
508 | void 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 |
|
---|