]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/qd_skeletons.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / qd_skeletons.c
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 #include "qd_skeletons.h"\r
23 #include "skeletons.h"\r
24 #include "qd_fmodel.h"\r
25 #include "angles.h"\r
26 #include "token.h"\r
27 #include "qdata.h"\r
28 #include "reference.h"\r
29 \r
30 #include <assert.h>\r
31 #include <math.h>\r
32 #include <memory.h>\r
33 \r
34 \r
35 // We're assuming no more than 16 reference points, with no more than 32 characters in the name\r
36 char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];\r
37 int      RefPointNum = 0;\r
38 \r
39 Skeletalfmheader_t g_skelModel;\r
40 \r
41 void ClearSkeletalModel()\r
42 {\r
43         g_skelModel.type = SKEL_NULL;\r
44         g_skelModel.clustered = false;\r
45         g_skelModel.references = REF_NULL;\r
46 }\r
47 \r
48 //==========================================================================\r
49 //\r
50 // LoadHRCClustered\r
51 //\r
52 //==========================================================================\r
53 \r
54 // Places the null terminated src string into the dest string less any trailing digits or underscores\r
55 void StripTrailingDigits(char *src, char *dest)\r
56 {\r
57 #ifndef NDEBUG\r
58         int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files\r
59 #endif\r
60         int i = 0;\r
61 \r
62         while(src[i] != '\0')\r
63         {\r
64                 ++i;\r
65 #ifndef NDEBUG\r
66                 assert(i < max);\r
67 #endif\r
68         }\r
69 \r
70         while((src[--i] >= '0' && src[i] <= '9') || src[i] == '_')\r
71         {\r
72 \r
73         }\r
74 \r
75         memcpy(dest, src, ++i);\r
76 \r
77         dest[i] = '\0';\r
78 }\r
79 \r
80 static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)\r
81 {\r
82         extern void HandleHRCModel(triangle_t **triList, int *triangleCount, \r
83                 mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth);\r
84 \r
85         extern mesh_node_t      *pmnodes;\r
86 \r
87         triangle_t *triList;\r
88 //      mesh_node_t *nodesList;\r
89         int num_mesh_nodes = 0, triangleCount = 0;\r
90 \r
91 #if 0\r
92         int i;\r
93         int j, numVerts;\r
94         char stripped[SKELETAL_NAME_MAX];\r
95 \r
96         for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)\r
97         {\r
98                 num_verts[i] = 0;\r
99         }\r
100 \r
101         TK_OpenSource(fileName);\r
102         TK_FetchRequire(TK_HRCH);\r
103         TK_FetchRequire(TK_COLON);\r
104         TK_FetchRequire(TK_SOFTIMAGE);\r
105 \r
106         TK_Beyond(TK_CLUSTERS);\r
107 \r
108         while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)\r
109         {\r
110                 TK_Require(TK_STRING);\r
111 \r
112                 StripTrailingDigits(tk_String, stripped);\r
113 \r
114                 for( i = 0; i < numJointsInSkeleton[skelType]; ++i)\r
115                 {\r
116                         if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)\r
117                         {\r
118                                 i = -i + numJointsInSkeleton[skelType] - 1;\r
119 \r
120                                 TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);\r
121 \r
122                                 numVerts = tk_IntNumber;\r
123 \r
124                                 if(!num_verts[i+1])     // first set of verts for cluster\r
125                                 {\r
126                                         clusterList[i] = SafeMalloc(numVerts*sizeof(int), "LoadHRCClustered");\r
127                                         assert(clusterList[i]);\r
128                                 }\r
129                                 else                            // any later sets of verts need to copy current\r
130                                 {\r
131                                         int *temp;\r
132 \r
133                                         temp = SafeMalloc((num_verts[i+1]+numVerts)*sizeof(int), "LoadHRCClustered");\r
134                                         assert(temp);\r
135 \r
136                                         memcpy(temp + numVerts, clusterList[i], num_verts[i+1]*sizeof(int));\r
137 \r
138                                         free(clusterList[i]);\r
139 \r
140                                         clusterList[i] = temp;\r
141                                 }\r
142 \r
143                                 // currently this function is only called by LoadModelClusters.\r
144                                 // Apparently the matching free has disappeared, \r
145                                 // should probably be free at the end of FMCmd_Base\r
146 \r
147                                 TK_Beyond(TK_LBRACE);\r
148 \r
149                                 for(j = 0; j < numVerts; ++j)\r
150                                 {\r
151                                         TK_Require(TK_INTNUMBER);\r
152                                         clusterList[i][j] = tk_IntNumber;\r
153                                         TK_Fetch();\r
154                                 }\r
155 \r
156                                 num_verts[i+1] += numVerts;\r
157 \r
158                                 break;\r
159                         }\r
160                 }\r
161         }\r
162 \r
163         num_verts[0] = numJointsInSkeleton[skelType];\r
164 #endif\r
165 \r
166 #if 1   // get the index number localized to the root\r
167 //      for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)\r
168 //      {\r
169 //              g_skelModel.num_verts[i] = 0;\r
170 //      }\r
171 \r
172         TK_OpenSource(fileName);\r
173         TK_FetchRequire(TK_HRCH);\r
174         TK_FetchRequire(TK_COLON);\r
175         TK_FetchRequire(TK_SOFTIMAGE);\r
176 \r
177         // prime it\r
178         TK_Beyond(TK_MODEL);\r
179 \r
180         triList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");\r
181         memset(triList,0,MAXTRIANGLES*sizeof(triangle_t));\r
182 //      nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");\r
183         pmnodes = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");\r
184 \r
185         memset(pmnodes, 0, MAX_FM_MESH_NODES * sizeof(mesh_node_t));\r
186 \r
187         // this should eventually use a stripped down version of this\r
188         HandleHRCModel(&triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0);\r
189 \r
190 //      free(nodesList);\r
191         free(triList);\r
192 \r
193         num_verts[0] = numJointsInSkeleton[skelType];\r
194 #endif\r
195 }\r
196 \r
197 void ReadHRCClusterList(mesh_node_t *meshNode, int baseIndex)\r
198 {\r
199         int i, j, numVerts;\r
200         tokenType_t nextToken;\r
201         char stripped[SKELETAL_NAME_MAX];\r
202 \r
203         meshNode->clustered = true;\r
204 \r
205         nextToken = TK_Get(TK_CLUSTER_NAME);\r
206 \r
207         while (nextToken == TK_CLUSTER_NAME)\r
208         {\r
209                 TK_FetchRequire(TK_STRING);\r
210 \r
211                 StripTrailingDigits(tk_String, stripped);\r
212 \r
213                 for( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)\r
214                 {\r
215                         if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type]+i]) == 0)\r
216                         {\r
217                                 i = -i + numJointsInSkeleton[g_skelModel.type] - 1;\r
218 \r
219                                 TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);\r
220 \r
221                                 numVerts = tk_IntNumber;\r
222 \r
223                                 if(!baseIndex)\r
224                                 {\r
225                                         meshNode->clusters[i] = (int *) SafeMalloc(numVerts*sizeof(int), "ReadHRCClusterList");\r
226                                         assert(meshNode->clusters[i]);\r
227                                 }\r
228                                 else\r
229                                 {\r
230                                         int *temp; \r
231 \r
232                                         temp = meshNode->clusters[i];\r
233                                         meshNode->clusters[i] = (int *) SafeMalloc((meshNode->num_verts[i+1]+numVerts)*sizeof(int), "ReadHRCClusterList");\r
234                                         assert(meshNode->clusters[i]);\r
235 \r
236                                         memcpy(meshNode->clusters[i], temp, meshNode->num_verts[i+1]*sizeof(int));\r
237                                         free(temp);\r
238                                 }\r
239 \r
240                                 // currently this function is only called by LoadModelClusters.\r
241                                 // Apparently the matching free has disappeared, \r
242                                 // should probably be free at the end of FMCmd_Base\r
243 \r
244                                 TK_Beyond(TK_LBRACE);\r
245 \r
246                                 for(j = 0; j < numVerts; ++j)\r
247                                 {\r
248                                         TK_Require(TK_INTNUMBER);\r
249                                         meshNode->clusters[i][baseIndex+j] = tk_IntNumber+baseIndex;\r
250                                         TK_Fetch();\r
251                                 }\r
252 \r
253                                 if(baseIndex)\r
254                                 {\r
255                                         meshNode->num_verts[i+1] += numVerts;\r
256                                 }\r
257                                 else\r
258                                 {\r
259                                         meshNode->num_verts[i+1] = numVerts;\r
260                                 }\r
261 \r
262                                 break;\r
263                         }\r
264                 }\r
265 \r
266                 TK_BeyondRequire(TK_CLUSTER_STATE, TK_INTNUMBER);\r
267                 nextToken = TK_Fetch();\r
268         }\r
269 }\r
270 \r
271 static void LoadHRCGlobals(char *fileName)\r
272 {\r
273         int i;\r
274 \r
275         TK_OpenSource(fileName);\r
276         TK_FetchRequire(TK_HRCH);\r
277         TK_FetchRequire(TK_COLON);\r
278         TK_FetchRequire(TK_SOFTIMAGE);\r
279         TK_Beyond(TK_MODEL);\r
280 \r
281         TK_Beyond(TK_SCALING);\r
282         for(i = 0; i < 3; i++)\r
283         {\r
284                 TK_Require(TK_FLOATNUMBER);\r
285                 g_skelModel.scaling[i] = tk_FloatNumber;\r
286                 TK_Fetch();\r
287         }\r
288 \r
289         TK_Beyond(TK_ROTATION);\r
290         for(i = 0; i < 3; i++)\r
291         {\r
292                 TK_Require(TK_FLOATNUMBER);\r
293                 g_skelModel.rotation[i] = tk_FloatNumber;\r
294                 TK_Fetch();\r
295         }\r
296 \r
297         TK_Beyond(TK_TRANSLATION);\r
298         for(i = 0; i < 3; i++)\r
299         {\r
300                 TK_Require(TK_FLOATNUMBER);\r
301                 g_skelModel.translation[i] = tk_FloatNumber;\r
302                 TK_Fetch();\r
303         }\r
304 }\r
305 \r
306 static void ParseVec3(vec3_t in)\r
307 {\r
308         TK_Require(TK_FLOATNUMBER);\r
309         in[1] = tk_FloatNumber;\r
310         TK_FetchRequire(TK_FLOATNUMBER);\r
311         in[2] = tk_FloatNumber;\r
312         TK_FetchRequire(TK_FLOATNUMBER);\r
313         in[0] = tk_FloatNumber;\r
314 }\r
315 \r
316 static void ParseVec3d(vec3d_t in)\r
317 {\r
318         TK_Require(TK_FLOATNUMBER);\r
319         in[1] = tk_FloatNumber;\r
320         TK_FetchRequire(TK_FLOATNUMBER);\r
321         in[2] = tk_FloatNumber;\r
322         TK_FetchRequire(TK_FLOATNUMBER);\r
323         in[0] = tk_FloatNumber;\r
324 }\r
325 \r
326 static void ParseRotation3(vec3_t in)\r
327 {\r
328         TK_Require(TK_FLOATNUMBER);\r
329         in[1] = tk_FloatNumber;\r
330         TK_FetchRequire(TK_FLOATNUMBER);\r
331         in[2] = tk_FloatNumber;\r
332         TK_FetchRequire(TK_FLOATNUMBER);\r
333         in[0] = tk_FloatNumber;\r
334 }\r
335 \r
336 static void ParseRotation3d(vec3d_t in)\r
337 {\r
338         TK_Require(TK_FLOATNUMBER);\r
339         in[1] = tk_FloatNumber;\r
340         TK_FetchRequire(TK_FLOATNUMBER);\r
341         in[2] = tk_FloatNumber;\r
342         TK_FetchRequire(TK_FLOATNUMBER);\r
343         in[0] = tk_FloatNumber;\r
344 }\r
345 \r
346 static void ParseTranslation3(vec3_t in)\r
347 {\r
348         TK_Require(TK_FLOATNUMBER);\r
349         in[1] = tk_FloatNumber;\r
350         TK_FetchRequire(TK_FLOATNUMBER);\r
351         in[2] = tk_FloatNumber;\r
352         TK_FetchRequire(TK_FLOATNUMBER);\r
353         in[0] = tk_FloatNumber;\r
354 }\r
355 \r
356 static void ParseTranslation3d(vec3d_t in)\r
357 {\r
358         TK_Require(TK_FLOATNUMBER);\r
359         in[1] = tk_FloatNumber;\r
360         TK_FetchRequire(TK_FLOATNUMBER);\r
361         in[2] = tk_FloatNumber;\r
362         TK_FetchRequire(TK_FLOATNUMBER);\r
363         in[0] = tk_FloatNumber;\r
364 }\r
365 \r
366 static void LoadHRCJointList(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)\r
367 {\r
368 #define MAX_STACK 64\r
369         int i, j;\r
370         vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];\r
371         int curCorrespondingJoint[MAX_STACK];\r
372         int currentStack = 0, stackSize;\r
373         double cx, sx, cy, sy, cz, sz;\r
374         double rx, ry, rz;\r
375         double x2, y2, z2;\r
376         char stripped[SKELETAL_NAME_MAX];\r
377         Placement_d_t *placement;\r
378 \r
379         TK_OpenSource(fileName);\r
380         TK_FetchRequire(TK_HRCH);\r
381         TK_FetchRequire(TK_COLON);\r
382         TK_FetchRequire(TK_SOFTIMAGE);\r
383 \r
384         TK_Beyond(TK_MODEL);\r
385 \r
386         while(TK_Search(TK_NAME) != TK_EOF)\r
387         {\r
388                 TK_Require(TK_STRING);\r
389 \r
390                 StripTrailingDigits(tk_String, stripped);\r
391 \r
392                 if(stricmp(stripped, skeletonRootNames[skeletonRNameOffsets[skelType]]) == 0)\r
393                 {\r
394                         break;\r
395                 }\r
396         }\r
397 \r
398         if(tk_Token == TK_EOF)\r
399         {\r
400                 Error("Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]]);\r
401                 return;\r
402         }\r
403 \r
404         TK_Beyond(TK_SCALING);\r
405 \r
406         ParseVec3d(curScale[currentStack]);\r
407 \r
408         TK_Beyond(TK_ROTATION);\r
409 \r
410         ParseRotation3d(curRotation[currentStack]);\r
411 \r
412         TK_Beyond(TK_TRANSLATION);\r
413 \r
414         ParseVec3d(curTranslation[currentStack]);\r
415 \r
416         // account for global model translation\r
417         curTranslation[currentStack][1] += g_skelModel.translation[0];\r
418         curTranslation[currentStack][2] += g_skelModel.translation[1];\r
419         curTranslation[currentStack][0] += g_skelModel.translation[2];\r
420 \r
421         curCorrespondingJoint[currentStack] = -1;\r
422 \r
423         ++currentStack;\r
424 \r
425         for(i = 0; i < numJointsInSkeleton[skelType]; ++i)\r
426         {\r
427                 while(1)\r
428                 {\r
429                         TK_Beyond(TK_MODEL);\r
430 \r
431                         TK_BeyondRequire(TK_NAME, TK_STRING);\r
432 \r
433                         StripTrailingDigits(tk_String, stripped);\r
434 \r
435                         if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)\r
436                                 break;\r
437 \r
438                         TK_Beyond(TK_SCALING);\r
439 \r
440                         ParseVec3d(curScale[currentStack]);\r
441 \r
442                         TK_Beyond(TK_ROTATION);\r
443 \r
444                         ParseRotation3d(curRotation[currentStack]);\r
445 \r
446                         TK_Beyond(TK_TRANSLATION);\r
447 \r
448                         ParseVec3d(curTranslation[currentStack]);\r
449 \r
450                         curCorrespondingJoint[currentStack] = -1;\r
451 \r
452                         ++currentStack;\r
453                 }\r
454 \r
455                 TK_Beyond(TK_SCALING);\r
456 \r
457                 ParseVec3d(curScale[currentStack]);\r
458 \r
459                 TK_Beyond(TK_ROTATION);\r
460 \r
461                 ParseRotation3d(curRotation[currentStack]);\r
462 \r
463                 jointList[i].rotation[1] = curRotation[currentStack][1];\r
464                 jointList[i].rotation[2] = curRotation[currentStack][2];\r
465                 jointList[i].rotation[0] = curRotation[currentStack][0];\r
466 \r
467                 TK_Beyond(TK_TRANSLATION);\r
468 \r
469                 ParseVec3d(curTranslation[currentStack]);\r
470 \r
471 //              jointList[i].placement.origin[1] = curTranslation[currentStack][1];\r
472 //              jointList[i].placement.origin[2] = curTranslation[currentStack][2];\r
473 //              jointList[i].placement.origin[0] = curTranslation[currentStack][0];\r
474 \r
475                 jointList[i].placement.origin[1] = 0.0;\r
476                 jointList[i].placement.origin[2] = 0.0;\r
477                 jointList[i].placement.origin[0] = 0.0;\r
478 \r
479                 jointList[i].placement.direction[1] = 20.0;\r
480                 jointList[i].placement.direction[2] = 0.0;\r
481                 jointList[i].placement.direction[0] = 0.0;\r
482 \r
483                 jointList[i].placement.up[1] = 0.0;\r
484                 jointList[i].placement.up[2] = 20.0;\r
485                 jointList[i].placement.up[0] = 0.0;\r
486 \r
487                 curCorrespondingJoint[currentStack] = i;\r
488 \r
489                 ++currentStack;\r
490         }\r
491 \r
492         stackSize = currentStack;\r
493 \r
494 #if 0\r
495         // rotate the direction and up vectors to correspond to the rotation\r
496         for(i = 0; i < numJointsInSkeleton[skelType]; ++i)\r
497         {\r
498                 rx = jointList[i].rotation[0]*ANGLE_TO_RAD;\r
499                 ry = jointList[i].rotation[1]*ANGLE_TO_RAD;\r
500                 rz = jointList[i].rotation[2]*ANGLE_TO_RAD;\r
501 \r
502                 cx = cos(rx);\r
503                 sx = sin(rx);\r
504 \r
505                 cy = cos(ry);\r
506                 sy = sin(ry);\r
507 \r
508                 cz = cos(rz);\r
509                 sz = sin(rz);\r
510 \r
511                 // y-axis rotation for direction\r
512                 x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;\r
513                 z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;\r
514                 jointList[i].placement.direction[0] = x2;\r
515                 jointList[i].placement.direction[2] = z2;\r
516 \r
517                 // y-axis rotation for up\r
518                 x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;\r
519                 z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;\r
520                 jointList[i].placement.up[0] = x2;\r
521                 jointList[i].placement.up[2] = z2;\r
522 \r
523                 // z-axis rotation for direction\r
524                 x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;\r
525                 y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;\r
526                 jointList[i].placement.direction[0] = x2;\r
527                 jointList[i].placement.direction[1] = y2;\r
528 \r
529                 // z-axis rotation for up\r
530                 x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;\r
531                 y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;\r
532                 jointList[i].placement.up[0] = x2;\r
533                 jointList[i].placement.up[1] = y2;\r
534 \r
535                 // x-axis rotation for direction vector\r
536                 y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;\r
537                 z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;\r
538                 jointList[i].placement.direction[1] = y2;\r
539                 jointList[i].placement.direction[2] = z2;\r
540 \r
541                 // x-axis rotation for up vector\r
542                 y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;\r
543                 z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;\r
544                 jointList[i].placement.up[1] = y2;\r
545                 jointList[i].placement.up[2] = z2;\r
546 \r
547                 // translate direction to a point in the model\r
548                 jointList[i].placement.direction[0] += jointList[i].placement.origin[0];\r
549                 jointList[i].placement.direction[1] += jointList[i].placement.origin[1];\r
550                 jointList[i].placement.direction[2] += jointList[i].placement.origin[2];\r
551 \r
552                 // translate up to a point in the model\r
553                 jointList[i].placement.up[0] += jointList[i].placement.origin[0];\r
554                 jointList[i].placement.up[1] += jointList[i].placement.origin[1];\r
555                 jointList[i].placement.up[2] += jointList[i].placement.origin[2];\r
556         }\r
557 #endif\r
558 \r
559         for(i = stackSize - 1; i >= 0; --i)\r
560         {\r
561                 rx = curRotation[i][0]*ANGLE_TO_RAD;\r
562                 ry = curRotation[i][1]*ANGLE_TO_RAD;\r
563                 rz = curRotation[i][2]*ANGLE_TO_RAD;\r
564 \r
565                 cx = cos(rx);\r
566                 sx = sin(rx);\r
567 \r
568                 cy = cos(ry);\r
569                 sy = sin(ry);\r
570 \r
571                 cz = cos(rz);\r
572                 sz = sin(rz);\r
573 \r
574 #if 1\r
575                 for(j = i; j < stackSize; ++j)\r
576                 {\r
577                         if(curCorrespondingJoint[j] != -1)\r
578                         {\r
579                                 placement = &jointList[curCorrespondingJoint[j]].placement;\r
580 \r
581                                 // y-axis rotation for origin\r
582                                 x2 = placement->origin[0]*cy+placement->origin[2]*sy;\r
583                                 z2 = -placement->origin[0]*sy+placement->origin[2]*cy;\r
584                                 placement->origin[0] = x2;\r
585                                 placement->origin[2] = z2;\r
586 \r
587                                 // y-axis rotation for direction\r
588                                 x2 = placement->direction[0]*cy+placement->direction[2]*sy;\r
589                                 z2 = -placement->direction[0]*sy+placement->direction[2]*cy;\r
590                                 placement->direction[0] = x2;\r
591                                 placement->direction[2] = z2;\r
592 \r
593                                 // y-axis rotation for up\r
594                                 x2 = placement->up[0]*cy+placement->up[2]*sy;\r
595                                 z2 = -placement->up[0]*sy+placement->up[2]*cy;\r
596                                 placement->up[0] = x2;\r
597                                 placement->up[2] = z2;\r
598 \r
599                                 // z-axis rotation for origin\r
600                                 x2 = placement->origin[0]*cz-placement->origin[1]*sz;\r
601                                 y2 = placement->origin[0]*sz+placement->origin[1]*cz;\r
602                                 placement->origin[0] = x2;\r
603                                 placement->origin[1] = y2;\r
604 \r
605                                 // z-axis rotation for direction\r
606                                 x2 = placement->direction[0]*cz-placement->direction[1]*sz;\r
607                                 y2 = placement->direction[0]*sz+placement->direction[1]*cz;\r
608                                 placement->direction[0] = x2;\r
609                                 placement->direction[1] = y2;\r
610 \r
611                                 // z-axis rotation for up\r
612                                 x2 = placement->up[0]*cz-placement->up[1]*sz;\r
613                                 y2 = placement->up[0]*sz+placement->up[1]*cz;\r
614                                 placement->up[0] = x2;\r
615                                 placement->up[1] = y2;\r
616 \r
617                                 // x-axis rotation for origin\r
618                                 y2 = placement->origin[1]*cx-placement->origin[2]*sx;\r
619                                 z2 = placement->origin[1]*sx+placement->origin[2]*cx;\r
620                                 placement->origin[1] = y2;\r
621                                 placement->origin[2] = z2;\r
622 \r
623                                 // x-axis rotation for direction vector\r
624                                 y2 = placement->direction[1]*cx-placement->direction[2]*sx;\r
625                                 z2 = placement->direction[1]*sx+placement->direction[2]*cx;\r
626                                 placement->direction[1] = y2;\r
627                                 placement->direction[2] = z2;\r
628 \r
629                                 // x-axis rotation for up vector\r
630                                 y2 = placement->up[1]*cx-placement->up[2]*sx;\r
631                                 z2 = placement->up[1]*sx+placement->up[2]*cx;\r
632                                 placement->up[1] = y2;\r
633                                 placement->up[2] = z2;\r
634 \r
635                                 // translate origin\r
636                                 placement->origin[0] += curTranslation[i][0];\r
637                                 placement->origin[1] += curTranslation[i][1];\r
638                                 placement->origin[2] += curTranslation[i][2];\r
639 \r
640                                 // translate back to local coord\r
641                                 placement->direction[0] += curTranslation[i][0];\r
642                                 placement->direction[1] += curTranslation[i][1];\r
643                                 placement->direction[2] += curTranslation[i][2];\r
644 \r
645                                 // translate back to local coord\r
646                                 placement->up[0] += curTranslation[i][0];\r
647                                 placement->up[1] += curTranslation[i][1];\r
648                                 placement->up[2] += curTranslation[i][2];\r
649                         }\r
650                 }\r
651 #else\r
652                 // This screwed up and needs to be sorted out!!!\r
653                 // The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton\r
654                 for(j = i-1; j < stackSize-1; ++j)\r
655                 {\r
656                         // y-axis rotation for origin\r
657                         x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;\r
658                         z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;\r
659                         jointList[j].placement.origin[0] = x2;\r
660                         jointList[j].placement.origin[2] = z2;\r
661 \r
662                         // y-axis rotation for direction\r
663                         x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;\r
664                         z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;\r
665                         jointList[j].placement.direction[0] = x2;\r
666                         jointList[j].placement.direction[2] = z2;\r
667 \r
668                         // y-axis rotation for up\r
669                         x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;\r
670                         z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;\r
671                         jointList[j].placement.up[0] = x2;\r
672                         jointList[j].placement.up[2] = z2;\r
673 \r
674                         // z-axis rotation for origin\r
675                         x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;\r
676                         y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;\r
677                         jointList[j].placement.origin[0] = x2;\r
678                         jointList[j].placement.origin[1] = y2;\r
679 \r
680                         // z-axis rotation for direction\r
681                         x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;\r
682                         y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;\r
683                         jointList[j].placement.direction[0] = x2;\r
684                         jointList[j].placement.direction[1] = y2;\r
685 \r
686                         // z-axis rotation for up\r
687                         x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;\r
688                         y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;\r
689                         jointList[j].placement.up[0] = x2;\r
690                         jointList[j].placement.up[1] = y2;\r
691 \r
692                         // x-axis rotation for origin\r
693                         y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;\r
694                         z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;\r
695                         jointList[j].placement.origin[1] = y2;\r
696                         jointList[j].placement.origin[2] = z2;\r
697 \r
698                         // x-axis rotation for direction vector\r
699                         y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;\r
700                         z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;\r
701                         jointList[j].placement.direction[1] = y2;\r
702                         jointList[j].placement.direction[2] = z2;\r
703 \r
704                         // x-axis rotation for up vector\r
705                         y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;\r
706                         z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;\r
707                         jointList[j].placement.up[1] = y2;\r
708                         jointList[j].placement.up[2] = z2;\r
709 \r
710                         if(curCorrespondingJoint[j+1] != -1)\r
711                         {\r
712                                 // translate origin\r
713                                 jointList[j].placement.origin[0] += curTranslation[i-1][0];\r
714                                 jointList[j].placement.origin[1] += curTranslation[i-1][1];\r
715                                 jointList[j].placement.origin[2] += curTranslation[i-1][2];\r
716 \r
717                                 // translate back to local coord\r
718                                 jointList[j].placement.direction[0] += curTranslation[i-1][0];\r
719                                 jointList[j].placement.direction[1] += curTranslation[i-1][1];\r
720                                 jointList[j].placement.direction[2] += curTranslation[i-1][2];\r
721 \r
722                                 // translate back to local coord\r
723                                 jointList[j].placement.up[0] += curTranslation[i-1][0];\r
724                                 jointList[j].placement.up[1] += curTranslation[i-1][1];\r
725                                 jointList[j].placement.up[2] += curTranslation[i-1][2];\r
726                         }\r
727                 }\r
728 #endif\r
729         }\r
730 }\r
731 \r
732 void LoadModelTransform(char *fileName)\r
733 {\r
734         FILE *file1;\r
735     int dot = '.';\r
736         char *dotstart;\r
737         char    InputFileName[256];\r
738 \r
739         dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?\r
740 \r
741         if (!dotstart)\r
742         {\r
743                 strcpy(InputFileName, fileName);\r
744                 strcat(InputFileName, ".hrc");\r
745                 if((file1 = fopen(InputFileName, "rb")) != NULL)\r
746                 {\r
747                         fclose(file1);\r
748 \r
749                         LoadHRCGlobals(InputFileName);\r
750 \r
751                         printf(" - assuming .HRC\n");\r
752                         return;\r
753                 }\r
754 \r
755                 Error("\n Could not open file '%s':\n"\r
756                         "No HRC match.\n", fileName);\r
757         }\r
758         else\r
759         {\r
760                 if((file1 = fopen(fileName, "rb")) != NULL)\r
761                 {\r
762 //                      printf("\n");\r
763                         fclose(file1);\r
764                         if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)\r
765                         {\r
766                                 LoadHRCGlobals(fileName);\r
767                                 return;\r
768                         }\r
769                 }\r
770 \r
771                 Error("Could not open file '%s':\n",fileName);\r
772         }\r
773 }\r
774 \r
775 void LoadModelClusters(char *fileName, int **clusterList, int *num_verts, int skelType)\r
776 {\r
777         FILE *file1;\r
778     int dot = '.';\r
779         char *dotstart;\r
780         char    InputFileName[256];\r
781 \r
782         dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?\r
783 \r
784         if (!dotstart)\r
785         {\r
786                 strcpy(InputFileName, fileName);\r
787                 strcat(InputFileName, ".hrc");\r
788                 if((file1 = fopen(InputFileName, "rb")) != NULL)\r
789                 {\r
790                         fclose(file1);\r
791 \r
792                         LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);\r
793 \r
794                         printf(" - assuming .HRC\n");\r
795                         return;\r
796                 }\r
797 \r
798                 Error("\n Could not open file '%s':\n"\r
799                         "No HRC match.\n", fileName);\r
800         }\r
801         else\r
802         {\r
803                 if((file1 = fopen(fileName, "rb")) != NULL)\r
804                 {\r
805 //                      printf("\n");\r
806                         fclose(file1);\r
807                         if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)\r
808                         {\r
809                                 LoadHRCClustered(fileName, clusterList, num_verts, skelType);\r
810                                 return;\r
811                         }\r
812                 }\r
813 \r
814                 Error("Could not open file '%s':\n",fileName);\r
815         }\r
816 }\r
817 \r
818 void LoadSkeleton(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)\r
819 {\r
820         FILE *file1;\r
821     int dot = '.';\r
822         char *dotstart;\r
823         char    InputFileName[256];\r
824 \r
825         dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?\r
826 \r
827         if (!dotstart)\r
828         {\r
829                 strcpy(InputFileName, fileName);\r
830                 strcat(InputFileName, ".hrc");\r
831                 if((file1 = fopen(InputFileName, "rb")) != NULL)\r
832                 {\r
833                         fclose(file1);\r
834 \r
835                         LoadHRCJointList(InputFileName, jointList, skelType);\r
836 \r
837                         printf(" - assuming .HRC\n");\r
838                         return;\r
839                 }\r
840 \r
841                 Error("\n Could not open file '%s':\n"\r
842                         "No HRC.\n", fileName);\r
843         }\r
844         else\r
845         {\r
846                 if((file1 = fopen(fileName, "rb")) != NULL)\r
847                 {\r
848 //                      printf("\n");\r
849                         fclose(file1);\r
850                         if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)\r
851                         {\r
852                                 LoadHRCJointList(fileName, jointList, skelType);\r
853 \r
854                                 return;\r
855                         }\r
856                 }\r
857 \r
858                 Error("Could not open file '%s':\n",fileName);\r
859         }\r
860 }\r
861 \r
862 /*\r
863 ===============\r
864 GrabSkeletalFrame\r
865 ===============\r
866 */\r
867 void GrabSkeletalFrame(char *frame)\r
868 {\r
869         char    file1[1024];\r
870         char    *framefile;\r
871         fmframe_t       *fr;\r
872 \r
873         framefile = FindFrameFile (frame);\r
874 \r
875         sprintf (file1, "%s/%s", cdarchive, framefile);\r
876         ExpandPathAndArchive (file1);\r
877 \r
878         sprintf (file1, "%s/%s",cddir, framefile);\r
879 \r
880         printf ("Grabbing Skeletal Frame %s\n", file1);\r
881 \r
882         fr = &g_frames[fmheader.num_frames - 1]; // last frame read in\r
883 \r
884         LoadSkeleton(file1, fr->joints, g_skelModel.type);\r
885 }\r
886 \r
887 /*\r
888 ===============\r
889 GrabModelTransform\r
890 ===============\r
891 */\r
892 void GrabModelTransform(char *frame)\r
893 {\r
894         char    file1[1024];\r
895         char    *framefile;\r
896         fmframe_t       *fr;\r
897 \r
898         framefile = FindFrameFile (frame);\r
899 \r
900         sprintf (file1, "%s/%s", cdarchive, framefile);\r
901         ExpandPathAndArchive (file1);\r
902 \r
903         sprintf (file1, "%s/%s",cddir, framefile);\r
904 \r
905 //      printf ("grabbing %s\n", file1);\r
906 \r
907         fr = &g_frames[fmheader.num_frames - 1]; // last frame read in\r
908 \r
909         LoadModelTransform(file1);\r
910 }\r
911 \r
912 void Cmd_FMCluster()\r
913 {\r
914         char file1[1024];\r
915 \r
916         GetScriptToken (false);\r
917 \r
918         printf ("---------------------\n");\r
919         sprintf (file1, "%s/%s", cdpartial, token);\r
920         printf ("%s\n", file1);\r
921 \r
922         ExpandPathAndArchive (file1);\r
923 \r
924         sprintf (file1, "%s/%s", cddir, token);\r
925 \r
926         g_skelModel.clustered = -1;\r
927 \r
928         LoadModelClusters(file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type);\r
929 \r
930         g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0];\r
931 \r
932         g_skelModel.clustered = true;\r
933 }\r
934 \r
935 void Cmd_FMSkeleton()\r
936 {\r
937         GetScriptToken (false);\r
938         g_skelModel.type = atoi(token);\r
939 }\r
940 \r
941 void Cmd_FMSkeletalFrame()\r
942 {\r
943         while (ScriptTokenAvailable())\r
944         {\r
945                 GetScriptToken (false);\r
946                 if (g_skipmodel)\r
947                 {\r
948                         GetScriptToken (false);\r
949                         continue;\r
950                 }\r
951                 if (g_release || g_archive)\r
952                 {\r
953                         fmheader.num_frames = 1;        // don't skip the writeout\r
954                         GetScriptToken (false);\r
955                         continue;\r
956                 }\r
957 \r
958                 H_printf("#define FRAME_%-16s\t%i\n", token, fmheader.num_frames);\r
959 \r
960                 GrabModelTransform (token);\r
961                 GrabFrame (token);\r
962                 GrabSkeletalFrame (token);\r
963 \r
964                 // need to add the up and dir points to the frame bounds here\r
965                 // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);\r
966                 // then remove fudge in determining scale on frame write out\r
967         }\r
968 }\r
969 \r
970 static void LoadHRCReferences(char *fileName, fmframe_t *fr)\r
971 {\r
972 #define MAX_STACK 64\r
973         int i, j, k;\r
974         vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK];\r
975         int curCorrespondingJoint[MAX_STACK];\r
976         int currentStack, stackSize;\r
977         double cx, sx, cy, sy, cz, sz;\r
978         double rx, ry, rz;\r
979         double x2, y2, z2;\r
980         char stripped[SKELETAL_NAME_MAX];\r
981         Placement_d_t *placement;\r
982         int refnum;\r
983 \r
984         TK_OpenSource(fileName);\r
985         TK_FetchRequire(TK_HRCH);\r
986         TK_FetchRequire(TK_COLON);\r
987         TK_FetchRequire(TK_SOFTIMAGE);\r
988 \r
989         if (RefPointNum <= 0)\r
990         {       // There were no labels indicated in the QDT, so use the hard-coded stuff.\r
991                 refnum = numReferences[g_skelModel.references];\r
992         }\r
993         else\r
994         {\r
995                 refnum = RefPointNum;\r
996         }\r
997 \r
998         for(k = 0; k < refnum; ++k)\r
999         {\r
1000                 currentStack = 0;\r
1001 \r
1002                 // Load the root to get translation and initial rotation\r
1003 //              TK_Beyond(TK_MODEL);\r
1004 \r
1005                 while(TK_Search(TK_NAME) != TK_EOF)\r
1006                 {\r
1007                         TK_Require(TK_STRING);\r
1008 \r
1009                         StripTrailingDigits(tk_String, stripped);\r
1010 \r
1011                         if (RefPointNum == 0)\r
1012                         {       // Hard coded refpoint labels\r
1013                                 if(stricmp(stripped, \r
1014                                         referenceRootNames[referenceRootNameOffsets[g_skelModel.references]+k]) == 0)\r
1015                                 {\r
1016                                         break;\r
1017                                 }\r
1018                         }\r
1019                         else\r
1020                         {       // labels indicated by the QDT\r
1021                                 if(stricmp(stripped, RefPointNameList[k]) == 0)\r
1022                                 {\r
1023                                         break;\r
1024                                 }\r
1025                         }\r
1026                 }\r
1027 \r
1028                 if(tk_Token == TK_EOF)\r
1029                 {\r
1030                         if (RefPointNum == 0)\r
1031                         {       // Hard coded refpoint labels\r
1032                                 Error("Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]]);\r
1033                         }\r
1034                         else\r
1035                         {       // labels indicated by the QDT\r
1036                                 Error("Bone Chain Root: %s not found\n", RefPointNameList[k]);\r
1037                         }\r
1038                         return;\r
1039                 }\r
1040 \r
1041 //              TK_Beyond(TK_SCALING);\r
1042 \r
1043 //              ParseVec3d(curScale[currentStack]);\r
1044 \r
1045                 TK_Beyond(TK_ROTATION);\r
1046 \r
1047                 ParseRotation3d(curRotation[currentStack]);\r
1048 \r
1049                 TK_Beyond(TK_TRANSLATION);\r
1050 \r
1051                 ParseVec3d(curTranslation[currentStack]);\r
1052 \r
1053                 // account for global model translation\r
1054                 curTranslation[currentStack][1] += g_skelModel.translation[0];\r
1055                 curTranslation[currentStack][2] += g_skelModel.translation[1];\r
1056                 curTranslation[currentStack][0] += g_skelModel.translation[2];\r
1057 \r
1058                 curCorrespondingJoint[currentStack] = -1;\r
1059 \r
1060 //              rjr - this one not needed, as there is also a stack increment 20 lines below???\r
1061 //              ++currentStack;\r
1062 \r
1063                 // Load the joint to get orientation\r
1064                 TK_Beyond(TK_MODEL);\r
1065 \r
1066 //              TK_Beyond(TK_SCALING);\r
1067 \r
1068 //              ParseVec3d(curScale[currentStack]);\r
1069 \r
1070                 TK_Beyond(TK_ROTATION);\r
1071 \r
1072                 ParseRotation3d(curRotation[currentStack]);\r
1073 \r
1074 //              TK_Beyond(TK_TRANSLATION);\r
1075 \r
1076 //              ParseVec3d(curTranslation[currentStack]);\r
1077 \r
1078                 fr->references[k].placement.origin[1] = 0.0;\r
1079                 fr->references[k].placement.origin[2] = 0.0;\r
1080                 fr->references[k].placement.origin[0] = 0.0;\r
1081 \r
1082                 fr->references[k].placement.direction[1] = 20.0;\r
1083                 fr->references[k].placement.direction[2] = 0.0;\r
1084                 fr->references[k].placement.direction[0] = 0.0;\r
1085 \r
1086                 fr->references[k].placement.up[1] = 0.0;\r
1087                 fr->references[k].placement.up[2] = 20.0;\r
1088                 fr->references[k].placement.up[0] = 0.0;\r
1089 \r
1090                 curCorrespondingJoint[currentStack] = k;\r
1091 \r
1092                 ++currentStack;\r
1093 \r
1094                 stackSize = currentStack;\r
1095 \r
1096                 for(i = stackSize - 1; i >= 0; --i)\r
1097                 {\r
1098                         rx = curRotation[i][0]*ANGLE_TO_RAD;\r
1099                         ry = curRotation[i][1]*ANGLE_TO_RAD;\r
1100                         rz = curRotation[i][2]*ANGLE_TO_RAD;\r
1101 \r
1102                         cx = cos(rx);\r
1103                         sx = sin(rx);\r
1104 \r
1105                         cy = cos(ry);\r
1106                         sy = sin(ry);\r
1107 \r
1108                         cz = cos(rz);\r
1109                         sz = sin(rz);\r
1110 \r
1111                         for(j = i; j < stackSize; ++j)\r
1112                         {\r
1113                                 if(curCorrespondingJoint[j] != -1)\r
1114                                 {\r
1115                                         placement = &fr->references[curCorrespondingJoint[j]].placement;\r
1116 \r
1117                                         // y-axis rotation for origin\r
1118                                         x2 = placement->origin[0]*cy+placement->origin[2]*sy;\r
1119                                         z2 = -placement->origin[0]*sy+placement->origin[2]*cy;\r
1120                                         placement->origin[0] = x2;\r
1121                                         placement->origin[2] = z2;\r
1122 \r
1123                                         // y-axis rotation for direction\r
1124                                         x2 = placement->direction[0]*cy+placement->direction[2]*sy;\r
1125                                         z2 = -placement->direction[0]*sy+placement->direction[2]*cy;\r
1126                                         placement->direction[0] = x2;\r
1127                                         placement->direction[2] = z2;\r
1128 \r
1129                                         // y-axis rotation for up\r
1130                                         x2 = placement->up[0]*cy+placement->up[2]*sy;\r
1131                                         z2 = -placement->up[0]*sy+placement->up[2]*cy;\r
1132                                         placement->up[0] = x2;\r
1133                                         placement->up[2] = z2;\r
1134 \r
1135                                         // z-axis rotation for origin\r
1136                                         x2 = placement->origin[0]*cz-placement->origin[1]*sz;\r
1137                                         y2 = placement->origin[0]*sz+placement->origin[1]*cz;\r
1138                                         placement->origin[0] = x2;\r
1139                                         placement->origin[1] = y2;\r
1140 \r
1141                                         // z-axis rotation for direction\r
1142                                         x2 = placement->direction[0]*cz-placement->direction[1]*sz;\r
1143                                         y2 = placement->direction[0]*sz+placement->direction[1]*cz;\r
1144                                         placement->direction[0] = x2;\r
1145                                         placement->direction[1] = y2;\r
1146 \r
1147                                         // z-axis rotation for up\r
1148                                         x2 = placement->up[0]*cz-placement->up[1]*sz;\r
1149                                         y2 = placement->up[0]*sz+placement->up[1]*cz;\r
1150                                         placement->up[0] = x2;\r
1151                                         placement->up[1] = y2;\r
1152 \r
1153                                         // x-axis rotation for origin\r
1154                                         y2 = placement->origin[1]*cx-placement->origin[2]*sx;\r
1155                                         z2 = placement->origin[1]*sx+placement->origin[2]*cx;\r
1156                                         placement->origin[1] = y2;\r
1157                                         placement->origin[2] = z2;\r
1158 \r
1159                                         // x-axis rotation for direction vector\r
1160                                         y2 = placement->direction[1]*cx-placement->direction[2]*sx;\r
1161                                         z2 = placement->direction[1]*sx+placement->direction[2]*cx;\r
1162                                         placement->direction[1] = y2;\r
1163                                         placement->direction[2] = z2;\r
1164 \r
1165                                         // x-axis rotation for up vector\r
1166                                         y2 = placement->up[1]*cx-placement->up[2]*sx;\r
1167                                         z2 = placement->up[1]*sx+placement->up[2]*cx;\r
1168                                         placement->up[1] = y2;\r
1169                                         placement->up[2] = z2;\r
1170 \r
1171                                         // translate origin\r
1172                                         placement->origin[0] += curTranslation[i][0];\r
1173                                         placement->origin[1] += curTranslation[i][1];\r
1174                                         placement->origin[2] += curTranslation[i][2];\r
1175 \r
1176                                         // translate back to local coord\r
1177                                         placement->direction[0] += curTranslation[i][0];\r
1178                                         placement->direction[1] += curTranslation[i][1];\r
1179                                         placement->direction[2] += curTranslation[i][2];\r
1180 \r
1181                                         // translate back to local coord\r
1182                                         placement->up[0] += curTranslation[i][0];\r
1183                                         placement->up[1] += curTranslation[i][1];\r
1184                                         placement->up[2] += curTranslation[i][2];\r
1185 \r
1186                                 }\r
1187                         }\r
1188                 }\r
1189                 printf("%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2]);\r
1190         }\r
1191         printf("\n");\r
1192 }\r
1193 \r
1194 void Cmd_FMReferenced()\r
1195 {\r
1196         int i;\r
1197 \r
1198         GetScriptToken (false);\r
1199         g_skelModel.references = atoi(token);\r
1200 \r
1201         // Guess what?  Now, we now want a list of strings to look for here instead of a hard-coded list\r
1202         for (i=0; i<REF_MAX_POINTS; i++)\r
1203         {\r
1204                 if (ScriptTokenAvailable())\r
1205                 {       // There is yet another reference point waiting.\r
1206                         GetScriptToken(false);\r
1207                         strcpy(RefPointNameList[i], token);\r
1208                 }\r
1209                 else\r
1210                 {\r
1211                         break;\r
1212                 }\r
1213         }\r
1214 \r
1215         RefPointNum = i;\r
1216 \r
1217         if (RefPointNum > 0)\r
1218         {\r
1219                 printf("Searching for %d different reference points.\n", RefPointNum);\r
1220         }\r
1221         else\r
1222         {\r
1223                 printf("Using built-in reference points.\n");\r
1224         }\r
1225 \r
1226 }\r
1227 \r
1228 void LoadReferences(char *fileName, fmframe_t *fr)\r
1229 {\r
1230         FILE *file1;\r
1231     int dot = '.';\r
1232         char *dotstart;\r
1233         char    InputFileName[256];\r
1234 \r
1235         dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?\r
1236 \r
1237         if (!dotstart)\r
1238         {\r
1239                 strcpy(InputFileName, fileName);\r
1240                 strcat(InputFileName, ".hrc");\r
1241                 if((file1 = fopen(InputFileName, "rb")) != NULL)\r
1242                 {\r
1243                         fclose(file1);\r
1244 \r
1245                         LoadHRCReferences(InputFileName, fr);\r
1246 \r
1247                         printf(" - assuming .HRC\n");\r
1248                         return;\r
1249                 }\r
1250 \r
1251                 Error("\n Could not open file '%s':\n"\r
1252                         "No HRC.\n", fileName);\r
1253         }\r
1254         else\r
1255         {\r
1256                 if((file1 = fopen(fileName, "rb")) != NULL)\r
1257                 {\r
1258                         printf("\n");\r
1259                         fclose(file1);\r
1260                         if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)\r
1261                         {\r
1262                                 LoadHRCReferences(fileName, fr);\r
1263 \r
1264                                 return;\r
1265                         }\r
1266                 }\r
1267 \r
1268                 Error("Could not open file '%s':\n",fileName);\r
1269         }\r
1270 }\r
1271 \r
1272 void GrabReferencedFrame(char *frame)\r
1273 {\r
1274         char    file1[1024];\r
1275         char    *framefile;\r
1276         fmframe_t       *fr;\r
1277 \r
1278         framefile = FindFrameFile (frame);\r
1279 \r
1280         sprintf (file1, "%s/%s", cdarchive, framefile);\r
1281         ExpandPathAndArchive (file1);\r
1282 \r
1283         sprintf (file1, "%s/%s",cddir, framefile);\r
1284 \r
1285         printf ("Grabbing Referenced %s\n", file1);\r
1286 \r
1287         fr = &g_frames[fmheader.num_frames - 1]; // last frame read in\r
1288 \r
1289         LoadReferences(file1, fr);\r
1290 }\r
1291 \r