]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/md3model/md5.cpp
Merge commit '48410b113dd2036e69dbf723a39ec9af02fc9b12'
[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 {
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 {
88 public:
89   int parent;
90   Vector3 position;
91   Vector4 rotation;
92 };
93
94 typedef Array<MD5Joint> MD5Joints;
95
96 class MD5Vert
97 {
98 public:
99   std::size_t index;
100   float u;
101   float v;
102   std::size_t weight_index;
103   std::size_t weight_count;
104 };
105
106 typedef Array<MD5Vert> MD5Verts;
107
108 class MD5Tri
109 {
110 public:
111   std::size_t index;
112   std::size_t a;
113   std::size_t b;
114   std::size_t c;
115 };
116
117 typedef Array<MD5Tri> MD5Tris;
118
119 class MD5Weight
120 {
121 public:
122   std::size_t index;
123   std::size_t joint;
124   float t;
125   Vector3 v;
126 };
127
128 typedef Array<MD5Weight> MD5Weights;
129
130 typedef float MD5Component;
131 typedef Array<MD5Component> MD5Components;
132
133 class MD5Frame
134 {
135 public:
136   MD5Components m_components;
137 };
138
139 typedef Array<MD5Weight> MD5Weights;
140
141 bool MD5_parseVersion(Tokeniser& tokeniser)
142 {
143   {
144     const char* versionKey = tokeniser.getToken();
145     if(versionKey == 0 || !string_equal(versionKey, "MD5Version"))
146     {
147       globalErrorStream() << "not a valid md5 file\n";
148       return false;
149     }
150   }
151   {
152     const char* versionValue = tokeniser.getToken();
153     if(versionValue == 0 || !string_equal(versionValue, "10"))
154     {
155       globalErrorStream() << "only md5 version 10 supported\n";
156       return false;
157     }
158   }
159
160   return true;
161 }
162
163 bool MD5Anim_parse(Tokeniser& tokeniser)
164 {
165   MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser));
166   tokeniser.nextLine();
167
168   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline"));
169   const char* commandline;
170   MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline));
171   tokeniser.nextLine();
172
173   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numFrames"));
174   std::size_t numFrames;
175   MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numFrames));
176   tokeniser.nextLine();
177
178   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints"));
179   std::size_t numJoints;
180   MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints));
181   tokeniser.nextLine();
182
183   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frameRate"));
184   std::size_t frameRate;
185   MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, frameRate));
186   tokeniser.nextLine();
187
188   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numAnimatedComponents"));
189   std::size_t numAnimatedComponents;
190   MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numAnimatedComponents));
191   tokeniser.nextLine();
192
193   // parse heirarchy
194   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "hierarchy"));
195   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
196   tokeniser.nextLine();
197
198   for(std::size_t i = 0; i < numJoints; ++i)
199   {
200     const char* name;
201     MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, name));
202     int parent;
203     MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, parent));
204     std::size_t flags;
205     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, flags));
206     std::size_t index;
207     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, index));
208     tokeniser.nextLine();
209   }
210
211   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
212   tokeniser.nextLine();
213
214   // parse bounds
215   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "bounds"));
216   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
217   tokeniser.nextLine();
218
219   for(std::size_t i = 0; i < numFrames; ++i)
220   {
221     Vector3 mins;
222     MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, mins));
223     Vector3 maxs;
224     MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, maxs));
225     tokeniser.nextLine();
226   }
227
228   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
229   tokeniser.nextLine();
230
231   // parse baseframe
232   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "baseframe"));
233   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
234   tokeniser.nextLine();
235
236   for(std::size_t i = 0; i < numJoints; ++i)
237   {
238     Vector3 position;
239     MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, position));
240     Vector3 rotation;
241     MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, rotation));
242     tokeniser.nextLine();
243   }
244
245   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
246   tokeniser.nextLine();
247
248   // parse frames
249   for(std::size_t i = 0; i < numFrames; ++i)
250   {
251     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frame"));
252     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
253     tokeniser.nextLine();
254
255     for(std::size_t i = 0; i < numAnimatedComponents; ++i)
256     {
257       float component;
258       MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, component));
259       tokeniser.nextLine();
260     }
261
262     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
263     tokeniser.nextLine();
264   }
265
266   return true;
267 }
268
269 bool MD5Model_parse(Model& model, Tokeniser& tokeniser)
270 {
271   MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser));
272   tokeniser.nextLine();
273
274   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline"));
275   const char* commandline;
276   MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline));
277   tokeniser.nextLine();
278
279   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints"));
280   std::size_t numJoints;
281   MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints));
282   tokeniser.nextLine();
283
284   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numMeshes"));
285   std::size_t numMeshes;
286   MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numMeshes));
287   tokeniser.nextLine();
288
289   MD5Joints joints(numJoints);
290
291   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "joints"));
292   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
293   tokeniser.nextLine();
294
295   for(MD5Joints::iterator i = joints.begin(); i != joints.end(); ++i)
296   {
297     const char* jointName;
298     MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, jointName));
299     MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, (*i).parent));
300     MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*i).position));
301     MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, vector4_to_vector3((*i).rotation)));
302     (*i).rotation.w() = -static_cast<float>(sqrt(1.0f - (float_squared((*i).rotation.x()) + float_squared((*i).rotation.y()) + float_squared((*i).rotation.z()))));
303     tokeniser.nextLine();
304   }
305
306   MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
307   tokeniser.nextLine();
308
309   for(std::size_t i = 0; i < numMeshes; ++i)
310   {
311     Surface& surface = model.newSurface();
312
313     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "mesh"));
314     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
315     tokeniser.nextLine();
316
317     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "shader"));
318     const char* shader;
319     MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, shader));
320     surface.setShader(shader);
321     tokeniser.nextLine();
322  
323     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numverts"));
324     std::size_t numVerts;
325     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numVerts));
326     tokeniser.nextLine();
327
328     MD5Verts verts(numVerts);
329
330     for(MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j)
331     {
332       MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "vert"));
333       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
334       MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - verts.begin()));
335       MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "("));
336       MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).u));
337       MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).v));
338       MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")"));
339       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_index));
340       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_count));
341       tokeniser.nextLine();
342     }
343
344     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numtris"));
345     std::size_t numTris;
346     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numTris));
347     tokeniser.nextLine();
348
349     MD5Tris tris(numTris);
350
351     for(MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j)
352     {
353       MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "tri"));
354       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
355       MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - tris.begin()));
356       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).a));
357       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).b));
358       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).c));
359       tokeniser.nextLine();
360     }
361
362     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numweights"));
363     std::size_t numWeights;
364     MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numWeights));
365     tokeniser.nextLine();
366
367     MD5Weights weights(numWeights);
368
369     for(MD5Weights::iterator j = weights.begin(); j != weights.end(); ++j)
370     {
371       MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "weight"));
372       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
373       MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - weights.begin()));
374       MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).joint));
375       MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).t));
376       MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*j).v));
377       tokeniser.nextLine();
378     }
379
380     MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
381     tokeniser.nextLine();
382
383     for(MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j)
384     {
385       MD5Vert& vert = (*j);
386
387       Vector3 skinned(0, 0, 0);
388       for(std::size_t k = 0; k != vert.weight_count; ++k)
389       {
390         MD5Weight& weight = weights[vert.weight_index + k];
391         MD5Joint& joint = joints[weight.joint];
392
393         skinned += (quaternion_transformed_point(joint.rotation, weight.v) + joint.position) * weight.t;
394       }
395       
396       surface.vertices().push_back(ArbitraryMeshVertex(vertex3f_for_vector3(skinned), Normal3f(0, 0, 0), TexCoord2f(vert.u, vert.v)));
397     }
398
399     for(MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j)
400     {
401       MD5Tri& tri = (*j);
402       surface.indices().insert(RenderIndex(tri.a));
403       surface.indices().insert(RenderIndex(tri.b));
404       surface.indices().insert(RenderIndex(tri.c));
405     }
406
407     for(Surface::indices_t::iterator j = surface.indices().begin(); j != surface.indices().end(); j += 3)
408     {
409                         ArbitraryMeshVertex& a = surface.vertices()[*(j + 0)];
410                         ArbitraryMeshVertex& b = surface.vertices()[*(j + 1)];
411                         ArbitraryMeshVertex& c = surface.vertices()[*(j + 2)];
412                         Vector3 weightedNormal(
413         vector3_cross(
414           reinterpret_cast<const Vector3&>(c.vertex) - reinterpret_cast<const Vector3&>(a.vertex),
415           reinterpret_cast<const Vector3&>(b.vertex) - reinterpret_cast<const Vector3&>(a.vertex)
416         )
417       );
418       reinterpret_cast<Vector3&>(a.normal) += weightedNormal;
419       reinterpret_cast<Vector3&>(b.normal) += weightedNormal;
420       reinterpret_cast<Vector3&>(c.normal) += weightedNormal;
421     }
422
423     for(Surface::vertices_t::iterator j = surface.vertices().begin(); j != surface.vertices().end(); ++j)
424     {
425       vector3_normalise(reinterpret_cast<Vector3&>((*j).normal));
426     }
427
428     surface.updateAABB();
429   }
430
431   model.updateAABB();
432
433   return true;
434 }
435
436 void MD5Model_construct(Model& model, TextInputStream& inputStream)
437 {
438   Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(inputStream);
439   MD5Model_parse(model, tokeniser);
440   tokeniser.release();
441 }
442
443 scene::Node& MD5Model_new(TextInputStream& inputStream)
444 {
445   ModelNode* modelNode = new ModelNode();
446   MD5Model_construct(modelNode->model(), inputStream);
447   return modelNode->node();
448 }
449
450 scene::Node& loadMD5Model(ArchiveFile& file)
451 {
452   BinaryToTextInputStream<InputStream> inputStream(file.getInputStream());
453   return MD5Model_new(inputStream);
454 }