]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/md3model/md5.cpp
Merge remote-tracking branch 'illwieckz/lokipaths'
[xonotic/netradiant.git] / plugins / md3model / md5.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "md5.h"
23
24 #include "iscriplib.h"
25 #include "imodel.h"
26
27 #include "archivelib.h"
28 #include "stringio.h"
29
30 #include "model.h"
31
32 #define MD5_RETURN_FALSE_IF_FAIL( expression ) if ( !( expression ) ) { globalErrorStream() << "md5 parse failed: " # expression "\n"; return false; } else
33
34 bool MD5_parseToken( Tokeniser& tokeniser, const char* string ){
35         const char* token = tokeniser.getToken();
36         MD5_RETURN_FALSE_IF_FAIL( token != 0 );
37         return string_equal( token, string );
38 }
39
40 bool MD5_parseFloat( Tokeniser& tokeniser, float& f ){
41         const char* token = tokeniser.getToken();
42         MD5_RETURN_FALSE_IF_FAIL( token != 0 );
43         return string_parse_float( token, f );
44 }
45
46 bool MD5_parseString( Tokeniser& tokeniser, const char*& s ){
47         const char* token = tokeniser.getToken();
48         MD5_RETURN_FALSE_IF_FAIL( token != 0 );
49         s = token;
50         return true;
51 }
52
53 bool MD5_parseInteger( Tokeniser& tokeniser, int& i ){
54         const char* token = tokeniser.getToken();
55         MD5_RETURN_FALSE_IF_FAIL( token != 0 );
56         return string_parse_int( token, i );
57 }
58
59 bool MD5_parseSize( Tokeniser& tokeniser, std::size_t& i ){
60         const char* token = tokeniser.getToken();
61         MD5_RETURN_FALSE_IF_FAIL( token != 0 );
62         return string_parse_size( token, i );
63 }
64
65 bool MD5_parseVector3( Tokeniser& tokeniser, Vector3& v ){
66         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "(" ) );
67         MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.x() ) );
68         MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.y() ) );
69         MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.z() ) );
70         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, ")" ) );
71         return true;
72 }
73
74 template<typename Element>
75 inline Element float_squared( const Element& f ){
76         return f * f;
77 }
78
79 class MD5Joint
80 {
81 public:
82 int parent;
83 Vector3 position;
84 Vector4 rotation;
85 };
86
87 typedef Array<MD5Joint> MD5Joints;
88
89 class MD5Vert
90 {
91 public:
92 std::size_t index;
93 float u;
94 float v;
95 std::size_t weight_index;
96 std::size_t weight_count;
97 };
98
99 typedef Array<MD5Vert> MD5Verts;
100
101 class MD5Tri
102 {
103 public:
104 std::size_t index;
105 std::size_t a;
106 std::size_t b;
107 std::size_t c;
108 };
109
110 typedef Array<MD5Tri> MD5Tris;
111
112 class MD5Weight
113 {
114 public:
115 std::size_t index;
116 std::size_t joint;
117 float t;
118 Vector3 v;
119 };
120
121 typedef Array<MD5Weight> MD5Weights;
122
123 typedef float MD5Component;
124 typedef Array<MD5Component> MD5Components;
125
126 class MD5Frame
127 {
128 public:
129 MD5Components m_components;
130 };
131
132 typedef Array<MD5Weight> MD5Weights;
133
134 bool MD5_parseVersion( Tokeniser& tokeniser ){
135         {
136                 const char* versionKey = tokeniser.getToken();
137                 if ( versionKey == 0 || !string_equal( versionKey, "MD5Version" ) ) {
138                         globalErrorStream() << "not a valid md5 file\n";
139                         return false;
140                 }
141         }
142         {
143                 const char* versionValue = tokeniser.getToken();
144                 if ( versionValue == 0 || !string_equal( versionValue, "10" ) ) {
145                         globalErrorStream() << "only md5 version 10 supported\n";
146                         return false;
147                 }
148         }
149
150         return true;
151 }
152
153 bool MD5Anim_parse( Tokeniser& tokeniser ){
154         MD5_RETURN_FALSE_IF_FAIL( MD5_parseVersion( tokeniser ) );
155         tokeniser.nextLine();
156
157         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "commandline" ) );
158         const char* commandline;
159         MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, commandline ) );
160         tokeniser.nextLine();
161
162         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numFrames" ) );
163         std::size_t numFrames;
164         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numFrames ) );
165         tokeniser.nextLine();
166
167         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numJoints" ) );
168         std::size_t numJoints;
169         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numJoints ) );
170         tokeniser.nextLine();
171
172         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "frameRate" ) );
173         std::size_t frameRate;
174         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, frameRate ) );
175         tokeniser.nextLine();
176
177         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numAnimatedComponents" ) );
178         std::size_t numAnimatedComponents;
179         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numAnimatedComponents ) );
180         tokeniser.nextLine();
181
182         // parse heirarchy
183         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "hierarchy" ) );
184         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) );
185         tokeniser.nextLine();
186
187         for ( std::size_t i = 0; i < numJoints; ++i )
188         {
189                 const char* name;
190                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, name ) );
191                 int parent;
192                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseInteger( tokeniser, parent ) );
193                 std::size_t flags;
194                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, flags ) );
195                 std::size_t index;
196                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, index ) );
197                 tokeniser.nextLine();
198         }
199
200         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) );
201         tokeniser.nextLine();
202
203         // parse bounds
204         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "bounds" ) );
205         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) );
206         tokeniser.nextLine();
207
208         for ( std::size_t i = 0; i < numFrames; ++i )
209         {
210                 Vector3 mins;
211                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, mins ) );
212                 Vector3 maxs;
213                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, maxs ) );
214                 tokeniser.nextLine();
215         }
216
217         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) );
218         tokeniser.nextLine();
219
220         // parse baseframe
221         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "baseframe" ) );
222         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) );
223         tokeniser.nextLine();
224
225         for ( std::size_t i = 0; i < numJoints; ++i )
226         {
227                 Vector3 position;
228                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, position ) );
229                 Vector3 rotation;
230                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, rotation ) );
231                 tokeniser.nextLine();
232         }
233
234         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) );
235         tokeniser.nextLine();
236
237         // parse frames
238         for ( std::size_t i = 0; i < numFrames; ++i )
239         {
240                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "frame" ) );
241                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) );
242                 tokeniser.nextLine();
243
244                 for ( std::size_t i = 0; i < numAnimatedComponents; ++i )
245                 {
246                         float component;
247                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, component ) );
248                         tokeniser.nextLine();
249                 }
250
251                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) );
252                 tokeniser.nextLine();
253         }
254
255         return true;
256 }
257
258 bool MD5Model_parse( Model& model, Tokeniser& tokeniser ){
259         MD5_RETURN_FALSE_IF_FAIL( MD5_parseVersion( tokeniser ) );
260         tokeniser.nextLine();
261
262         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "commandline" ) );
263         const char* commandline;
264         MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, commandline ) );
265         tokeniser.nextLine();
266
267         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numJoints" ) );
268         std::size_t numJoints;
269         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numJoints ) );
270         tokeniser.nextLine();
271
272         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numMeshes" ) );
273         std::size_t numMeshes;
274         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numMeshes ) );
275         tokeniser.nextLine();
276
277         MD5Joints joints( numJoints );
278
279         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "joints" ) );
280         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) );
281         tokeniser.nextLine();
282
283         for ( MD5Joints::iterator i = joints.begin(); i != joints.end(); ++i )
284         {
285                 const char* jointName;
286                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, jointName ) );
287                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseInteger( tokeniser, ( *i ).parent ) );
288                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, ( *i ).position ) );
289                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, vector4_to_vector3( ( *i ).rotation ) ) );
290                 ( *i ).rotation.w() = -static_cast<float>( sqrt( 1.0f - ( float_squared( ( *i ).rotation.x() ) + float_squared( ( *i ).rotation.y() ) + float_squared( ( *i ).rotation.z() ) ) ) );
291                 tokeniser.nextLine();
292         }
293
294         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) );
295         tokeniser.nextLine();
296
297         for ( std::size_t i = 0; i < numMeshes; ++i )
298         {
299                 Surface& surface = model.newSurface();
300
301                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "mesh" ) );
302                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) );
303                 tokeniser.nextLine();
304
305                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "shader" ) );
306                 const char* shader;
307                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, shader ) );
308                 surface.setShader( shader );
309                 tokeniser.nextLine();
310
311                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numverts" ) );
312                 std::size_t numVerts;
313                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numVerts ) );
314                 tokeniser.nextLine();
315
316                 MD5Verts verts( numVerts );
317
318                 for ( MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j )
319                 {
320                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "vert" ) );
321                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) );
322                         MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - verts.begin() ) );
323                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "(" ) );
324                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).u ) );
325                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).v ) );
326                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, ")" ) );
327                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).weight_index ) );
328                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).weight_count ) );
329                         tokeniser.nextLine();
330                 }
331
332                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numtris" ) );
333                 std::size_t numTris;
334                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numTris ) );
335                 tokeniser.nextLine();
336
337                 MD5Tris tris( numTris );
338
339                 for ( MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j )
340                 {
341                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "tri" ) );
342                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) );
343                         MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - tris.begin() ) );
344                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).a ) );
345                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).b ) );
346                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).c ) );
347                         tokeniser.nextLine();
348                 }
349
350                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numweights" ) );
351                 std::size_t numWeights;
352                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numWeights ) );
353                 tokeniser.nextLine();
354
355                 MD5Weights weights( numWeights );
356
357                 for ( MD5Weights::iterator j = weights.begin(); j != weights.end(); ++j )
358                 {
359                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "weight" ) );
360                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) );
361                         MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - weights.begin() ) );
362                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).joint ) );
363                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).t ) );
364                         MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, ( *j ).v ) );
365                         tokeniser.nextLine();
366                 }
367
368                 MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) );
369                 tokeniser.nextLine();
370
371                 for ( MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j )
372                 {
373                         MD5Vert& vert = ( *j );
374
375                         Vector3 skinned( 0, 0, 0 );
376                         for ( std::size_t k = 0; k != vert.weight_count; ++k )
377                         {
378                                 MD5Weight& weight = weights[vert.weight_index + k];
379                                 MD5Joint& joint = joints[weight.joint];
380
381                                 skinned += ( quaternion_transformed_point( joint.rotation, weight.v ) + joint.position ) * weight.t;
382                         }
383
384                         surface.vertices().push_back( ArbitraryMeshVertex( vertex3f_for_vector3( skinned ), Normal3f( 0, 0, 0 ), TexCoord2f( vert.u, vert.v ) ) );
385                 }
386
387                 for ( MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j )
388                 {
389                         MD5Tri& tri = ( *j );
390                         surface.indices().insert( RenderIndex( tri.a ) );
391                         surface.indices().insert( RenderIndex( tri.b ) );
392                         surface.indices().insert( RenderIndex( tri.c ) );
393                 }
394
395                 for ( Surface::indices_t::iterator j = surface.indices().begin(); j != surface.indices().end(); j += 3 )
396                 {
397                         ArbitraryMeshVertex& a = surface.vertices()[*( j + 0 )];
398                         ArbitraryMeshVertex& b = surface.vertices()[*( j + 1 )];
399                         ArbitraryMeshVertex& c = surface.vertices()[*( j + 2 )];
400                         Vector3 weightedNormal(
401                                 vector3_cross(
402                                         reinterpret_cast<const Vector3&>( c.vertex ) - reinterpret_cast<const Vector3&>( a.vertex ),
403                                         reinterpret_cast<const Vector3&>( b.vertex ) - reinterpret_cast<const Vector3&>( a.vertex )
404                                         )
405                                 );
406                         reinterpret_cast<Vector3&>( a.normal ) += weightedNormal;
407                         reinterpret_cast<Vector3&>( b.normal ) += weightedNormal;
408                         reinterpret_cast<Vector3&>( c.normal ) += weightedNormal;
409                 }
410
411                 for ( Surface::vertices_t::iterator j = surface.vertices().begin(); j != surface.vertices().end(); ++j )
412                 {
413                         vector3_normalise( reinterpret_cast<Vector3&>( ( *j ).normal ) );
414                 }
415
416                 surface.updateAABB();
417         }
418
419         model.updateAABB();
420
421         return true;
422 }
423
424 void MD5Model_construct( Model& model, TextInputStream& inputStream ){
425         Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser( inputStream );
426         MD5Model_parse( model, tokeniser );
427         tokeniser.release();
428 }
429
430 scene::Node& MD5Model_new( TextInputStream& inputStream ){
431         ModelNode* modelNode = new ModelNode();
432         MD5Model_construct( modelNode->model(), inputStream );
433         return modelNode->node();
434 }
435
436 scene::Node& loadMD5Model( ArchiveFile& file ){
437         BinaryToTextInputStream<InputStream> inputStream( file.getInputStream() );
438         return MD5Model_new( inputStream );
439 }