]> git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/md3model/md5.cpp
reformat code! now the code is only ugly on the *inside*
[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) do { if (!(expression)) { globalErrorStream() << "md5 parse failed: " #expression "\n"; return false; } } while (0)
33
34 bool MD5_parseToken(Tokeniser &tokeniser, const char *string)
35 {
36     const char *token = tokeniser.getToken();
37     MD5_RETURN_FALSE_IF_FAIL(token != 0);
38     return string_equal(token, string);
39 }
40
41 bool MD5_parseFloat(Tokeniser &tokeniser, float &f)
42 {
43     const char *token = tokeniser.getToken();
44     MD5_RETURN_FALSE_IF_FAIL(token != 0);
45     return string_parse_float(token, f);
46 }
47
48 bool MD5_parseString(Tokeniser &tokeniser, const char *&s)
49 {
50     const char *token = tokeniser.getToken();
51     MD5_RETURN_FALSE_IF_FAIL(token != 0);
52     s = token;
53     return true;
54 }
55
56 bool MD5_parseInteger(Tokeniser &tokeniser, int &i)
57 {
58     const char *token = tokeniser.getToken();
59     MD5_RETURN_FALSE_IF_FAIL(token != 0);
60     return string_parse_int(token, i);
61 }
62
63 bool MD5_parseSize(Tokeniser &tokeniser, std::size_t &i)
64 {
65     const char *token = tokeniser.getToken();
66     MD5_RETURN_FALSE_IF_FAIL(token != 0);
67     return string_parse_size(token, i);
68 }
69
70 bool MD5_parseVector3(Tokeniser &tokeniser, Vector3 &v)
71 {
72     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "("));
73     MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.x()));
74     MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.y()));
75     MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.z()));
76     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")"));
77     return true;
78 }
79
80 template<typename Element>
81 inline Element float_squared(const Element &f)
82 {
83     return f * f;
84 }
85
86 class MD5Joint {
87 public:
88     int parent;
89     Vector3 position;
90     Vector4 rotation;
91 };
92
93 typedef Array<MD5Joint> MD5Joints;
94
95 class MD5Vert {
96 public:
97     std::size_t index;
98     float u;
99     float v;
100     std::size_t weight_index;
101     std::size_t weight_count;
102 };
103
104 typedef Array<MD5Vert> MD5Verts;
105
106 class MD5Tri {
107 public:
108     std::size_t index;
109     std::size_t a;
110     std::size_t b;
111     std::size_t c;
112 };
113
114 typedef Array<MD5Tri> MD5Tris;
115
116 class MD5Weight {
117 public:
118     std::size_t index;
119     std::size_t joint;
120     float t;
121     Vector3 v;
122 };
123
124 typedef Array<MD5Weight> MD5Weights;
125
126 typedef float MD5Component;
127 typedef Array<MD5Component> MD5Components;
128
129 class MD5Frame {
130 public:
131     MD5Components m_components;
132 };
133
134 typedef Array<MD5Weight> MD5Weights;
135
136 bool MD5_parseVersion(Tokeniser &tokeniser)
137 {
138     {
139         const char *versionKey = tokeniser.getToken();
140         if (versionKey == 0 || !string_equal(versionKey, "MD5Version")) {
141             globalErrorStream() << "not a valid md5 file\n";
142             return false;
143         }
144     }
145     {
146         const char *versionValue = tokeniser.getToken();
147         if (versionValue == 0 || !string_equal(versionValue, "10")) {
148             globalErrorStream() << "only md5 version 10 supported\n";
149             return false;
150         }
151     }
152
153     return true;
154 }
155
156 bool MD5Anim_parse(Tokeniser &tokeniser)
157 {
158     MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser));
159     tokeniser.nextLine();
160
161     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline"));
162     const char *commandline;
163     MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline));
164     tokeniser.nextLine();
165
166     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numFrames"));
167     std::size_t numFrames;
168     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numFrames));
169     tokeniser.nextLine();
170
171     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints"));
172     std::size_t numJoints;
173     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints));
174     tokeniser.nextLine();
175
176     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frameRate"));
177     std::size_t frameRate;
178     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, frameRate));
179     tokeniser.nextLine();
180
181     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numAnimatedComponents"));
182     std::size_t numAnimatedComponents;
183     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numAnimatedComponents));
184     tokeniser.nextLine();
185
186     // parse heirarchy
187     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "hierarchy"));
188     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
189     tokeniser.nextLine();
190
191     for (std::size_t i = 0; i < numJoints; ++i) {
192         const char *name;
193         MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, name));
194         int parent;
195         MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, parent));
196         std::size_t flags;
197         MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, flags));
198         std::size_t index;
199         MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, index));
200         tokeniser.nextLine();
201     }
202
203     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
204     tokeniser.nextLine();
205
206     // parse bounds
207     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "bounds"));
208     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
209     tokeniser.nextLine();
210
211     for (std::size_t i = 0; i < numFrames; ++i) {
212         Vector3 mins;
213         MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, mins));
214         Vector3 maxs;
215         MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, maxs));
216         tokeniser.nextLine();
217     }
218
219     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
220     tokeniser.nextLine();
221
222     // parse baseframe
223     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "baseframe"));
224     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
225     tokeniser.nextLine();
226
227     for (std::size_t i = 0; i < numJoints; ++i) {
228         Vector3 position;
229         MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, position));
230         Vector3 rotation;
231         MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, rotation));
232         tokeniser.nextLine();
233     }
234
235     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
236     tokeniser.nextLine();
237
238     // parse frames
239     for (std::size_t i = 0; i < numFrames; ++i) {
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             float component;
246             MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, component));
247             tokeniser.nextLine();
248         }
249
250         MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
251         tokeniser.nextLine();
252     }
253
254     return true;
255 }
256
257 bool MD5Model_parse(Model &model, Tokeniser &tokeniser)
258 {
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         const char *jointName;
285         MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, jointName));
286         MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, (*i).parent));
287         MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*i).position));
288         MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, vector4_to_vector3((*i).rotation)));
289         (*i).rotation.w() = -static_cast<float>( sqrt(1.0f - (float_squared((*i).rotation.x()) +
290                                                               float_squared((*i).rotation.y()) +
291                                                               float_squared((*i).rotation.z()))));
292         tokeniser.nextLine();
293     }
294
295     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
296     tokeniser.nextLine();
297
298     for (std::size_t i = 0; i < numMeshes; ++i) {
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             MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "vert"));
320             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
321             MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - verts.begin()));
322             MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "("));
323             MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).u));
324             MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).v));
325             MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")"));
326             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_index));
327             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_count));
328             tokeniser.nextLine();
329         }
330
331         MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numtris"));
332         std::size_t numTris;
333         MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numTris));
334         tokeniser.nextLine();
335
336         MD5Tris tris(numTris);
337
338         for (MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j) {
339             MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "tri"));
340             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
341             MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - tris.begin()));
342             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).a));
343             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).b));
344             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).c));
345             tokeniser.nextLine();
346         }
347
348         MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numweights"));
349         std::size_t numWeights;
350         MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numWeights));
351         tokeniser.nextLine();
352
353         MD5Weights weights(numWeights);
354
355         for (MD5Weights::iterator j = weights.begin(); j != weights.end(); ++j) {
356             MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "weight"));
357             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
358             MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - weights.begin()));
359             MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).joint));
360             MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).t));
361             MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*j).v));
362             tokeniser.nextLine();
363         }
364
365         MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
366         tokeniser.nextLine();
367
368         for (MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j) {
369             MD5Vert &vert = (*j);
370
371             Vector3 skinned(0, 0, 0);
372             for (std::size_t k = 0; k != vert.weight_count; ++k) {
373                 MD5Weight &weight = weights[vert.weight_index + k];
374                 MD5Joint &joint = joints[weight.joint];
375
376                 skinned += (quaternion_transformed_point(joint.rotation, weight.v) + joint.position) * weight.t;
377             }
378
379             surface.vertices().push_back(
380                     ArbitraryMeshVertex(vertex3f_for_vector3(skinned), Normal3f(0, 0, 0), TexCoord2f(vert.u, vert.v)));
381         }
382
383         for (MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j) {
384             MD5Tri &tri = (*j);
385             surface.indices().insert(RenderIndex(tri.a));
386             surface.indices().insert(RenderIndex(tri.b));
387             surface.indices().insert(RenderIndex(tri.c));
388         }
389
390         for (Surface::indices_t::iterator j = surface.indices().begin(); j != surface.indices().end(); j += 3) {
391             ArbitraryMeshVertex &a = surface.vertices()[*(j + 0)];
392             ArbitraryMeshVertex &b = surface.vertices()[*(j + 1)];
393             ArbitraryMeshVertex &c = surface.vertices()[*(j + 2)];
394             Vector3 weightedNormal(
395                     vector3_cross(
396                             reinterpret_cast<const Vector3 &>( c.vertex ) -
397                             reinterpret_cast<const Vector3 &>( a.vertex ),
398                             reinterpret_cast<const Vector3 &>( b.vertex ) -
399                             reinterpret_cast<const Vector3 &>( a.vertex )
400                     )
401             );
402             reinterpret_cast<Vector3 &>( a.normal ) += weightedNormal;
403             reinterpret_cast<Vector3 &>( b.normal ) += weightedNormal;
404             reinterpret_cast<Vector3 &>( c.normal ) += weightedNormal;
405         }
406
407         for (Surface::vertices_t::iterator j = surface.vertices().begin(); j != surface.vertices().end(); ++j) {
408             vector3_normalise(reinterpret_cast<Vector3 &>((*j).normal ));
409         }
410
411         surface.updateAABB();
412     }
413
414     model.updateAABB();
415
416     return true;
417 }
418
419 void MD5Model_construct(Model &model, TextInputStream &inputStream)
420 {
421     Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(inputStream);
422     MD5Model_parse(model, tokeniser);
423     tokeniser.release();
424 }
425
426 scene::Node &MD5Model_new(TextInputStream &inputStream)
427 {
428     ModelNode *modelNode = new ModelNode();
429     MD5Model_construct(modelNode->model(), inputStream);
430     return modelNode->node();
431 }
432
433 scene::Node &loadMD5Model(ArchiveFile &file)
434 {
435     BinaryToTextInputStream<InputStream> inputStream(file.getInputStream());
436     return MD5Model_new(inputStream);
437 }