remove RSA's md4.c, replace by DP's
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / jointed.c
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
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 <assert.h>
23 #include <math.h>
24 #include "token.h"
25 #include "joints.h"
26 #include "angles.h"
27 #include "inout.h"
28
29 char *SKEL_ROOT_NAMES[] =
30 {
31         "RAVEN_SPINE"
32 };
33
34 char *SKEL_NAMES[] =
35 {
36         "RAVEN_WAIST1",
37         "RAVEN_WAIST2",
38         "RAVEN_NECK"
39 };
40
41 int NAME_OFFSETS[] =
42 {
43         0
44 };
45
46 int numJointsForSkeleton[] = 
47 {
48         NUM_JOINTS_RAVEN,
49         NUM_JOINTS_BOX
50 };
51
52 float g_scaling[3];
53 float g_rotation[3];
54 float g_translation[3];
55
56 //==========================================================================
57 //
58 // LoadHRCClustered
59 //
60 //==========================================================================
61
62 static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)
63 {
64         int i, j;
65
66         TK_OpenSource(fileName);
67         TK_FetchRequire(TK_HRCH);
68         TK_FetchRequire(TK_COLON);
69         TK_FetchRequire(TK_SOFTIMAGE);
70
71         TK_Beyond(TK_CLUSTERS);
72
73         while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)
74         {
75                 TK_Require(TK_STRING);
76
77                 for( i = 0; i < numJointsForSkeleton[skelType]; ++i)
78                 {
79                         if(stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
80                         {
81                                 i = -i + numJointsForSkeleton[skelType] - 1;
82
83                                 TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
84
85                                 num_verts[i+1] = tk_IntNumber;
86
87                                 clusterList[i] = (int *) SafeMalloc(num_verts[i+1]*sizeof(int), "LoadHRCClustered");
88                                 assert(clusterList[i]);
89                                 // currently this function is only called by LoadTriangleListClustered, which in turn is only
90                                 // called by Cmd_Base in qdata.  This is where the only call to free for this memory is being made.
91
92                                 TK_Beyond(TK_LBRACE);
93
94                                 for(j = 0; j < num_verts[i+1]; ++j)
95                                 {
96                                         TK_Require(TK_INTNUMBER);
97                                         clusterList[i][j] = tk_IntNumber;
98                                         TK_Fetch();
99                                 }
100
101                                 break;
102                         }
103                 }
104         }
105
106         num_verts[0] = numJointsForSkeleton[skelType];
107 }
108
109 static void LoadHRCGlobals(char *fileName)
110 {
111         int i;
112
113         TK_OpenSource(fileName);
114         TK_FetchRequire(TK_HRCH);
115         TK_FetchRequire(TK_COLON);
116         TK_FetchRequire(TK_SOFTIMAGE);
117         TK_Beyond(TK_MODEL);
118
119         TK_Beyond(TK_SCALING);
120         for(i = 0; i < 3; i++)
121         {
122                 TK_Require(TK_FLOATNUMBER);
123                 g_scaling[i] = tk_FloatNumber;
124                 TK_Fetch();
125         }
126
127         TK_Beyond(TK_ROTATION);
128         for(i = 0; i < 3; i++)
129         {
130                 TK_Require(TK_FLOATNUMBER);
131                 g_rotation[i] = tk_FloatNumber;
132                 TK_Fetch();
133         }
134
135         TK_Beyond(TK_TRANSLATION);
136         for(i = 0; i < 3; i++)
137         {
138                 TK_Require(TK_FLOATNUMBER);
139                 g_translation[i] = tk_FloatNumber;
140                 TK_Fetch();
141         }
142 }
143
144 static void ParseVec3(vec3_t in)
145 {
146         TK_Require(TK_FLOATNUMBER);
147         in[1] = tk_FloatNumber;
148         TK_FetchRequire(TK_FLOATNUMBER);
149         in[2] = tk_FloatNumber;
150         TK_FetchRequire(TK_FLOATNUMBER);
151         in[0] = tk_FloatNumber;
152 }
153
154 static void ParseRotation3(vec3_t in)
155 {
156         TK_Require(TK_FLOATNUMBER);
157         in[1] = -tk_FloatNumber;
158         TK_FetchRequire(TK_FLOATNUMBER);
159         in[2] = tk_FloatNumber;
160         TK_FetchRequire(TK_FLOATNUMBER);
161         in[0] = tk_FloatNumber;
162 }
163
164 static void ParseTranslation3(vec3_t in)
165 {
166         TK_Require(TK_FLOATNUMBER);
167         in[1] = tk_FloatNumber;
168         TK_FetchRequire(TK_FLOATNUMBER);
169         in[2] = tk_FloatNumber;
170         TK_FetchRequire(TK_FLOATNUMBER);
171         in[0] = tk_FloatNumber;
172 }
173
174 static void LoadHRCJointList(char *fileName, QDataJoint_t *jointList, int skelType)
175 {
176 #define MAX_STACK 64
177         int i, j;
178         vec3_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
179         int curCorrespondingJoint[MAX_STACK];
180         int currentStack = 0, stackSize;
181         int baseJoint;
182         float cx, sx, cy, sy, cz, sz;
183         float rx, ry, rz;
184         float x2, y2, z2;
185
186
187         TK_OpenSource(fileName);
188         TK_FetchRequire(TK_HRCH);
189         TK_FetchRequire(TK_COLON);
190         TK_FetchRequire(TK_SOFTIMAGE);
191
192         TK_Beyond(TK_MODEL);
193         TK_Beyond(TK_MODEL);
194
195 /*      while(1)
196         {
197                 TK_Beyond(TK_MODEL);
198                 TK_BeyondRequire(TK_NAME, TK_STRING);
199
200                 if(_stricmp(tk_String, SKEL_ROOT_NAMES[skelType]) == 0)
201                         break;
202         }*/
203
204         TK_Beyond(TK_SCALING);
205
206         ParseVec3(curScale[currentStack]);
207
208         TK_Beyond(TK_ROTATION);
209
210         ParseRotation3(curRotation[currentStack]);
211
212         TK_Beyond(TK_TRANSLATION);
213
214         ParseVec3(curTranslation[currentStack]);
215
216         // account for global model translation
217         curTranslation[currentStack][1] += g_translation[0];
218         curTranslation[currentStack][2] += g_translation[1];
219         curTranslation[currentStack][0] += g_translation[2];
220
221         ++currentStack;
222
223         for(i = 0; i < NUM_JOINTS_RAVEN; ++i)
224         {
225                 while(1)
226                 {
227                         TK_Beyond(TK_MODEL);
228
229 //                      TK_BeyondRequire(TK_NAME, TK_STRING);
230
231 //                      if(_stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
232                                 break;
233
234                         TK_Beyond(TK_SCALING);
235
236                         ParseVec3(curScale[currentStack]);
237
238                         TK_Beyond(TK_ROTATION);
239
240                         ParseRotation3(curRotation[currentStack]);
241
242                         TK_Beyond(TK_TRANSLATION);
243
244                         ParseVec3(curTranslation[currentStack]);
245
246                         curCorrespondingJoint[currentStack] = -1;
247
248                         ++currentStack;
249                 }
250
251                 TK_Beyond(TK_SCALING);
252
253                 ParseVec3(curScale[currentStack]);
254
255                 TK_Beyond(TK_ROTATION);
256
257                 ParseRotation3(curRotation[currentStack]);
258
259                 jointList[i].rotation[1] = curRotation[currentStack][1];
260                 jointList[i].rotation[2] = curRotation[currentStack][2];
261                 jointList[i].rotation[0] = curRotation[currentStack][0];
262
263                 TK_Beyond(TK_TRANSLATION);
264
265                 ParseVec3(curTranslation[currentStack]);
266
267                 jointList[i].placement.origin[1] = curTranslation[currentStack][1];
268                 jointList[i].placement.origin[2] = curTranslation[currentStack][2];
269                 jointList[i].placement.origin[0] = curTranslation[currentStack][0];
270
271                 jointList[i].placement.direction[1] = 7.5;
272                 jointList[i].placement.direction[2] = 0.0;
273                 jointList[i].placement.direction[0] = 0.0;
274
275                 jointList[i].placement.up[1] = 0.0;
276                 jointList[i].placement.up[2] = 7.5;
277                 jointList[i].placement.up[0] = 0.0;
278
279                 curCorrespondingJoint[currentStack] = i;
280
281                 ++currentStack;
282         }
283
284         stackSize = currentStack;
285
286         for(i = 0; i < NUM_JOINTS_RAVEN; ++i)
287         {
288                 rx = jointList[i].rotation[0]*ANGLE_TO_RAD;
289                 ry = jointList[i].rotation[1]*ANGLE_TO_RAD;
290                 rz = jointList[i].rotation[2]*ANGLE_TO_RAD;
291
292                 cx = cos(rx);
293                 sx = sin(rx);
294
295                 cy = cos(ry);
296                 sy = sin(ry);
297
298                 cz = cos(rz);
299                 sz = sin(rz);
300
301                 // y-axis rotation for direction
302                 x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;
303                 z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;
304                 jointList[i].placement.direction[0] = x2;
305                 jointList[i].placement.direction[2] = z2;
306
307                 // y-axis rotation for up
308                 x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;
309                 z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;
310                 jointList[i].placement.up[0] = x2;
311                 jointList[i].placement.up[2] = z2;
312
313                 // z-axis rotation for direction
314                 x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;
315                 y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;
316                 jointList[i].placement.direction[0] = x2;
317                 jointList[i].placement.direction[1] = y2;
318
319                 // z-axis rotation for up
320                 x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;
321                 y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;
322                 jointList[i].placement.up[0] = x2;
323                 jointList[i].placement.up[1] = y2;
324
325                 // x-axis rotation for direction vector
326                 y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;
327                 z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;
328                 jointList[i].placement.direction[1] = y2;
329                 jointList[i].placement.direction[2] = z2;
330
331                 // x-axis rotation for up vector
332                 y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;
333                 z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;
334                 jointList[i].placement.up[1] = y2;
335                 jointList[i].placement.up[2] = z2;
336
337                 // translate to position in model
338                 jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
339                 jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
340                 jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
341
342                 // translate to position in model
343                 jointList[i].placement.up[0] += jointList[i].placement.origin[0];
344                 jointList[i].placement.up[1] += jointList[i].placement.origin[1];
345                 jointList[i].placement.up[2] += jointList[i].placement.origin[2];
346         }
347
348         baseJoint = NUM_JOINTS_RAVEN;
349
350         for(i = stackSize/*NUM_JOINTS_RAVEN*/ - 1; i > 0; --i)
351         {
352
353                 rx = curRotation[i-1][0]*ANGLE_TO_RAD;
354                 ry = curRotation[i-1][1]*ANGLE_TO_RAD;
355                 rz = curRotation[i-1][2]*ANGLE_TO_RAD;
356
357                 cx = cos(rx);
358                 sx = sin(rx);
359
360                 cy = cos(ry);
361                 sy = sin(ry);
362
363                 cz = cos(rz);
364                 sz = sin(rz);
365
366                 for(j = i-1; j < stackSize-1; ++j)
367                 {
368                         // y-axis rotation for origin
369                         x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;
370                         z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;
371                         jointList[j].placement.origin[0] = x2;
372                         jointList[j].placement.origin[2] = z2;
373
374                         // y-axis rotation for direction
375                         x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;
376                         z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;
377                         jointList[j].placement.direction[0] = x2;
378                         jointList[j].placement.direction[2] = z2;
379
380                         // y-axis rotation for up
381                         x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;
382                         z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;
383                         jointList[j].placement.up[0] = x2;
384                         jointList[j].placement.up[2] = z2;
385
386                         // z-axis rotation for origin
387                         x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;
388                         y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;
389                         jointList[j].placement.origin[0] = x2;
390                         jointList[j].placement.origin[1] = y2;
391
392                         // z-axis rotation for direction
393                         x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;
394                         y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;
395                         jointList[j].placement.direction[0] = x2;
396                         jointList[j].placement.direction[1] = y2;
397
398                         // z-axis rotation for up
399                         x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;
400                         y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;
401                         jointList[j].placement.up[0] = x2;
402                         jointList[j].placement.up[1] = y2;
403
404                         // x-axis rotation for origin
405                         y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;
406                         z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;
407                         jointList[j].placement.origin[1] = y2;
408                         jointList[j].placement.origin[2] = z2;
409
410                         // x-axis rotation for direction vector
411                         y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;
412                         z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;
413                         jointList[j].placement.direction[1] = y2;
414                         jointList[j].placement.direction[2] = z2;
415
416                         // x-axis rotation for up vector
417                         y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;
418                         z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;
419                         jointList[j].placement.up[1] = y2;
420                         jointList[j].placement.up[2] = z2;
421
422                         if(curCorrespondingJoint[j+1] != -1)
423                         {
424                                 // translate origin
425                                 jointList[j].placement.origin[0] += curTranslation[i-1][0];
426                                 jointList[j].placement.origin[1] += curTranslation[i-1][1];
427                                 jointList[j].placement.origin[2] += curTranslation[i-1][2];
428
429                                 // translate back to local coord
430                                 jointList[j].placement.direction[0] += curTranslation[i-1][0];
431                                 jointList[j].placement.direction[1] += curTranslation[i-1][1];
432                                 jointList[j].placement.direction[2] += curTranslation[i-1][2];
433
434                                 // translate back to local coord
435                                 jointList[j].placement.up[0] += curTranslation[i-1][0];
436                                 jointList[j].placement.up[1] += curTranslation[i-1][1];
437                                 jointList[j].placement.up[2] += curTranslation[i-1][2];
438                         }
439                 }
440         }
441 }
442
443 void LoadGlobals(char *fileName)
444 {
445         FILE *file1;
446     int dot = '.';
447         char *dotstart;
448         char    InputFileName[256];
449
450         dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
451
452         if (!dotstart)
453         {
454                 strcpy(InputFileName, fileName);
455                 strcat(InputFileName, ".hrc");
456                 if((file1 = fopen(InputFileName, "rb")) != NULL)
457                 {
458                         fclose(file1);
459
460                         LoadHRCGlobals(InputFileName);
461
462                         printf(" - assuming .HRC\n");
463                         return;
464                 }
465
466                 Error("\n Could not open file '%s':\n"
467                         "No HRC match.\n", fileName);
468         }
469         else
470         {
471                 if((file1 = fopen(fileName, "rb")) != NULL)
472                 {
473                         printf("\n");
474                         fclose(file1);
475                         if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
476                         {
477                                 LoadHRCGlobals(fileName);
478                                 return;
479                         }
480                 }
481
482                 Error("Could not open file '%s':\n",fileName);
483         }
484 }
485
486 void LoadClusters(char *fileName, int **clusterList, int *num_verts, int skelType)
487 {
488         FILE *file1;
489     int dot = '.';
490         char *dotstart;
491         char    InputFileName[256];
492
493         dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
494
495         if (!dotstart)
496         {
497                 strcpy(InputFileName, fileName);
498                 strcat(InputFileName, ".hrc");
499                 if((file1 = fopen(InputFileName, "rb")) != NULL)
500                 {
501                         fclose(file1);
502
503                         LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);
504
505                         printf(" - assuming .HRC\n");
506                         return;
507                 }
508
509                 Error("\n Could not open file '%s':\n"
510                         "No HRC match.\n", fileName);
511         }
512         else
513         {
514                 if((file1 = fopen(fileName, "rb")) != NULL)
515                 {
516                         printf("\n");
517                         fclose(file1);
518                         if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
519                         {
520                                 LoadHRCClustered(fileName, clusterList, num_verts, skelType);
521                                 return;
522                         }
523                 }
524
525                 Error("Could not open file '%s':\n",fileName);
526         }
527 }
528
529 void LoadJointList(char *fileName, QDataJoint_t *jointList, int skelType)
530 {
531         FILE *file1;
532     int dot = '.';
533         char *dotstart;
534         char    InputFileName[256];
535
536         dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
537
538         if (!dotstart)
539         {
540                 strcpy(InputFileName, fileName);
541                 strcat(InputFileName, ".hrc");
542                 if((file1 = fopen(InputFileName, "rb")) != NULL)
543                 {
544                         fclose(file1);
545
546                         LoadHRCJointList(InputFileName, jointList, skelType);
547
548                         printf(" - assuming .HRC\n");
549                         return;
550                 }
551
552                 Error("\n Could not open file '%s':\n"
553                         "No HRC.\n", fileName);
554         }
555         else
556         {
557                 if((file1 = fopen(fileName, "rb")) != NULL)
558                 {
559                         printf("\n");
560                         fclose(file1);
561                         if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
562                         {
563                                 LoadHRCJointList(fileName, jointList, skelType);
564
565                                 return;
566                         }
567                 }
568
569                 Error("Could not open file '%s':\n",fileName);
570         }
571 }
572