2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
22 #include "qd_skeletons.h"
23 #include "skeletons.h"
24 #include "qd_fmodel.h"
28 #include "reference.h"
35 // We're assuming no more than 16 reference points, with no more than 32 characters in the name
36 char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
39 Skeletalfmheader_t g_skelModel;
41 void ClearSkeletalModel()
43 g_skelModel.type = SKEL_NULL;
44 g_skelModel.clustered = false;
45 g_skelModel.references = REF_NULL;
48 //==========================================================================
52 //==========================================================================
54 // Places the null terminated src string into the dest string less any trailing digits or underscores
55 void StripTrailingDigits(char *src, char *dest)
58 int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files
70 while((src[--i] >= '0' && src[i] <= '9') || src[i] == '_')
75 memcpy(dest, src, ++i);
80 static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)
82 extern void HandleHRCModel(triangle_t **triList, int *triangleCount,
83 mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth);
85 extern mesh_node_t *pmnodes;
88 // mesh_node_t *nodesList;
89 int num_mesh_nodes = 0, triangleCount = 0;
94 char stripped[SKELETAL_NAME_MAX];
96 for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
101 TK_OpenSource(fileName);
102 TK_FetchRequire(TK_HRCH);
103 TK_FetchRequire(TK_COLON);
104 TK_FetchRequire(TK_SOFTIMAGE);
106 TK_Beyond(TK_CLUSTERS);
108 while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)
110 TK_Require(TK_STRING);
112 StripTrailingDigits(tk_String, stripped);
114 for( i = 0; i < numJointsInSkeleton[skelType]; ++i)
116 if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)
118 i = -i + numJointsInSkeleton[skelType] - 1;
120 TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
122 numVerts = tk_IntNumber;
124 if(!num_verts[i+1]) // first set of verts for cluster
126 clusterList[i] = SafeMalloc(numVerts*sizeof(int), "LoadHRCClustered");
127 assert(clusterList[i]);
129 else // any later sets of verts need to copy current
133 temp = SafeMalloc((num_verts[i+1]+numVerts)*sizeof(int), "LoadHRCClustered");
136 memcpy(temp + numVerts, clusterList[i], num_verts[i+1]*sizeof(int));
138 free(clusterList[i]);
140 clusterList[i] = temp;
143 // currently this function is only called by LoadModelClusters.
144 // Apparently the matching free has disappeared,
145 // should probably be free at the end of FMCmd_Base
147 TK_Beyond(TK_LBRACE);
149 for(j = 0; j < numVerts; ++j)
151 TK_Require(TK_INTNUMBER);
152 clusterList[i][j] = tk_IntNumber;
156 num_verts[i+1] += numVerts;
163 num_verts[0] = numJointsInSkeleton[skelType];
166 #if 1 // get the index number localized to the root
167 // for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
169 // g_skelModel.num_verts[i] = 0;
172 TK_OpenSource(fileName);
173 TK_FetchRequire(TK_HRCH);
174 TK_FetchRequire(TK_COLON);
175 TK_FetchRequire(TK_SOFTIMAGE);
180 triList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
181 memset(triList,0,MAXTRIANGLES*sizeof(triangle_t));
182 // nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
183 pmnodes = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
185 memset(pmnodes, 0, MAX_FM_MESH_NODES * sizeof(mesh_node_t));
187 // this should eventually use a stripped down version of this
188 HandleHRCModel(&triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0);
193 num_verts[0] = numJointsInSkeleton[skelType];
197 void ReadHRCClusterList(mesh_node_t *meshNode, int baseIndex)
200 tokenType_t nextToken;
201 char stripped[SKELETAL_NAME_MAX];
203 meshNode->clustered = true;
205 nextToken = TK_Get(TK_CLUSTER_NAME);
207 while (nextToken == TK_CLUSTER_NAME)
209 TK_FetchRequire(TK_STRING);
211 StripTrailingDigits(tk_String, stripped);
213 for( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)
215 if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type]+i]) == 0)
217 i = -i + numJointsInSkeleton[g_skelModel.type] - 1;
219 TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
221 numVerts = tk_IntNumber;
225 meshNode->clusters[i] = (int *) SafeMalloc(numVerts*sizeof(int), "ReadHRCClusterList");
226 assert(meshNode->clusters[i]);
232 temp = meshNode->clusters[i];
233 meshNode->clusters[i] = (int *) SafeMalloc((meshNode->num_verts[i+1]+numVerts)*sizeof(int), "ReadHRCClusterList");
234 assert(meshNode->clusters[i]);
236 memcpy(meshNode->clusters[i], temp, meshNode->num_verts[i+1]*sizeof(int));
240 // currently this function is only called by LoadModelClusters.
241 // Apparently the matching free has disappeared,
242 // should probably be free at the end of FMCmd_Base
244 TK_Beyond(TK_LBRACE);
246 for(j = 0; j < numVerts; ++j)
248 TK_Require(TK_INTNUMBER);
249 meshNode->clusters[i][baseIndex+j] = tk_IntNumber+baseIndex;
255 meshNode->num_verts[i+1] += numVerts;
259 meshNode->num_verts[i+1] = numVerts;
266 TK_BeyondRequire(TK_CLUSTER_STATE, TK_INTNUMBER);
267 nextToken = TK_Fetch();
271 static void LoadHRCGlobals(char *fileName)
275 TK_OpenSource(fileName);
276 TK_FetchRequire(TK_HRCH);
277 TK_FetchRequire(TK_COLON);
278 TK_FetchRequire(TK_SOFTIMAGE);
281 TK_Beyond(TK_SCALING);
282 for(i = 0; i < 3; i++)
284 TK_Require(TK_FLOATNUMBER);
285 g_skelModel.scaling[i] = tk_FloatNumber;
289 TK_Beyond(TK_ROTATION);
290 for(i = 0; i < 3; i++)
292 TK_Require(TK_FLOATNUMBER);
293 g_skelModel.rotation[i] = tk_FloatNumber;
297 TK_Beyond(TK_TRANSLATION);
298 for(i = 0; i < 3; i++)
300 TK_Require(TK_FLOATNUMBER);
301 g_skelModel.translation[i] = tk_FloatNumber;
306 static void ParseVec3(vec3_t in)
308 TK_Require(TK_FLOATNUMBER);
309 in[1] = tk_FloatNumber;
310 TK_FetchRequire(TK_FLOATNUMBER);
311 in[2] = tk_FloatNumber;
312 TK_FetchRequire(TK_FLOATNUMBER);
313 in[0] = tk_FloatNumber;
316 static void ParseVec3d(vec3d_t in)
318 TK_Require(TK_FLOATNUMBER);
319 in[1] = tk_FloatNumber;
320 TK_FetchRequire(TK_FLOATNUMBER);
321 in[2] = tk_FloatNumber;
322 TK_FetchRequire(TK_FLOATNUMBER);
323 in[0] = tk_FloatNumber;
326 static void ParseRotation3(vec3_t in)
328 TK_Require(TK_FLOATNUMBER);
329 in[1] = tk_FloatNumber;
330 TK_FetchRequire(TK_FLOATNUMBER);
331 in[2] = tk_FloatNumber;
332 TK_FetchRequire(TK_FLOATNUMBER);
333 in[0] = tk_FloatNumber;
336 static void ParseRotation3d(vec3d_t in)
338 TK_Require(TK_FLOATNUMBER);
339 in[1] = tk_FloatNumber;
340 TK_FetchRequire(TK_FLOATNUMBER);
341 in[2] = tk_FloatNumber;
342 TK_FetchRequire(TK_FLOATNUMBER);
343 in[0] = tk_FloatNumber;
346 static void ParseTranslation3(vec3_t in)
348 TK_Require(TK_FLOATNUMBER);
349 in[1] = tk_FloatNumber;
350 TK_FetchRequire(TK_FLOATNUMBER);
351 in[2] = tk_FloatNumber;
352 TK_FetchRequire(TK_FLOATNUMBER);
353 in[0] = tk_FloatNumber;
356 static void ParseTranslation3d(vec3d_t in)
358 TK_Require(TK_FLOATNUMBER);
359 in[1] = tk_FloatNumber;
360 TK_FetchRequire(TK_FLOATNUMBER);
361 in[2] = tk_FloatNumber;
362 TK_FetchRequire(TK_FLOATNUMBER);
363 in[0] = tk_FloatNumber;
366 static void LoadHRCJointList(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)
370 vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
371 int curCorrespondingJoint[MAX_STACK];
372 int currentStack = 0, stackSize;
373 double cx, sx, cy, sy, cz, sz;
376 char stripped[SKELETAL_NAME_MAX];
377 Placement_d_t *placement;
379 TK_OpenSource(fileName);
380 TK_FetchRequire(TK_HRCH);
381 TK_FetchRequire(TK_COLON);
382 TK_FetchRequire(TK_SOFTIMAGE);
386 while(TK_Search(TK_NAME) != TK_EOF)
388 TK_Require(TK_STRING);
390 StripTrailingDigits(tk_String, stripped);
392 if(stricmp(stripped, skeletonRootNames[skeletonRNameOffsets[skelType]]) == 0)
398 if(tk_Token == TK_EOF)
400 Error("Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]]);
404 TK_Beyond(TK_SCALING);
406 ParseVec3d(curScale[currentStack]);
408 TK_Beyond(TK_ROTATION);
410 ParseRotation3d(curRotation[currentStack]);
412 TK_Beyond(TK_TRANSLATION);
414 ParseVec3d(curTranslation[currentStack]);
416 // account for global model translation
417 curTranslation[currentStack][1] += g_skelModel.translation[0];
418 curTranslation[currentStack][2] += g_skelModel.translation[1];
419 curTranslation[currentStack][0] += g_skelModel.translation[2];
421 curCorrespondingJoint[currentStack] = -1;
425 for(i = 0; i < numJointsInSkeleton[skelType]; ++i)
431 TK_BeyondRequire(TK_NAME, TK_STRING);
433 StripTrailingDigits(tk_String, stripped);
435 if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)
438 TK_Beyond(TK_SCALING);
440 ParseVec3d(curScale[currentStack]);
442 TK_Beyond(TK_ROTATION);
444 ParseRotation3d(curRotation[currentStack]);
446 TK_Beyond(TK_TRANSLATION);
448 ParseVec3d(curTranslation[currentStack]);
450 curCorrespondingJoint[currentStack] = -1;
455 TK_Beyond(TK_SCALING);
457 ParseVec3d(curScale[currentStack]);
459 TK_Beyond(TK_ROTATION);
461 ParseRotation3d(curRotation[currentStack]);
463 jointList[i].rotation[1] = curRotation[currentStack][1];
464 jointList[i].rotation[2] = curRotation[currentStack][2];
465 jointList[i].rotation[0] = curRotation[currentStack][0];
467 TK_Beyond(TK_TRANSLATION);
469 ParseVec3d(curTranslation[currentStack]);
471 // jointList[i].placement.origin[1] = curTranslation[currentStack][1];
472 // jointList[i].placement.origin[2] = curTranslation[currentStack][2];
473 // jointList[i].placement.origin[0] = curTranslation[currentStack][0];
475 jointList[i].placement.origin[1] = 0.0;
476 jointList[i].placement.origin[2] = 0.0;
477 jointList[i].placement.origin[0] = 0.0;
479 jointList[i].placement.direction[1] = 20.0;
480 jointList[i].placement.direction[2] = 0.0;
481 jointList[i].placement.direction[0] = 0.0;
483 jointList[i].placement.up[1] = 0.0;
484 jointList[i].placement.up[2] = 20.0;
485 jointList[i].placement.up[0] = 0.0;
487 curCorrespondingJoint[currentStack] = i;
492 stackSize = currentStack;
495 // rotate the direction and up vectors to correspond to the rotation
496 for(i = 0; i < numJointsInSkeleton[skelType]; ++i)
498 rx = jointList[i].rotation[0]*ANGLE_TO_RAD;
499 ry = jointList[i].rotation[1]*ANGLE_TO_RAD;
500 rz = jointList[i].rotation[2]*ANGLE_TO_RAD;
511 // y-axis rotation for direction
512 x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;
513 z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;
514 jointList[i].placement.direction[0] = x2;
515 jointList[i].placement.direction[2] = z2;
517 // y-axis rotation for up
518 x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;
519 z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;
520 jointList[i].placement.up[0] = x2;
521 jointList[i].placement.up[2] = z2;
523 // z-axis rotation for direction
524 x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;
525 y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;
526 jointList[i].placement.direction[0] = x2;
527 jointList[i].placement.direction[1] = y2;
529 // z-axis rotation for up
530 x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;
531 y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;
532 jointList[i].placement.up[0] = x2;
533 jointList[i].placement.up[1] = y2;
535 // x-axis rotation for direction vector
536 y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;
537 z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;
538 jointList[i].placement.direction[1] = y2;
539 jointList[i].placement.direction[2] = z2;
541 // x-axis rotation for up vector
542 y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;
543 z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;
544 jointList[i].placement.up[1] = y2;
545 jointList[i].placement.up[2] = z2;
547 // translate direction to a point in the model
548 jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
549 jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
550 jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
552 // translate up to a point in the model
553 jointList[i].placement.up[0] += jointList[i].placement.origin[0];
554 jointList[i].placement.up[1] += jointList[i].placement.origin[1];
555 jointList[i].placement.up[2] += jointList[i].placement.origin[2];
559 for(i = stackSize - 1; i >= 0; --i)
561 rx = curRotation[i][0]*ANGLE_TO_RAD;
562 ry = curRotation[i][1]*ANGLE_TO_RAD;
563 rz = curRotation[i][2]*ANGLE_TO_RAD;
575 for(j = i; j < stackSize; ++j)
577 if(curCorrespondingJoint[j] != -1)
579 placement = &jointList[curCorrespondingJoint[j]].placement;
581 // y-axis rotation for origin
582 x2 = placement->origin[0]*cy+placement->origin[2]*sy;
583 z2 = -placement->origin[0]*sy+placement->origin[2]*cy;
584 placement->origin[0] = x2;
585 placement->origin[2] = z2;
587 // y-axis rotation for direction
588 x2 = placement->direction[0]*cy+placement->direction[2]*sy;
589 z2 = -placement->direction[0]*sy+placement->direction[2]*cy;
590 placement->direction[0] = x2;
591 placement->direction[2] = z2;
593 // y-axis rotation for up
594 x2 = placement->up[0]*cy+placement->up[2]*sy;
595 z2 = -placement->up[0]*sy+placement->up[2]*cy;
596 placement->up[0] = x2;
597 placement->up[2] = z2;
599 // z-axis rotation for origin
600 x2 = placement->origin[0]*cz-placement->origin[1]*sz;
601 y2 = placement->origin[0]*sz+placement->origin[1]*cz;
602 placement->origin[0] = x2;
603 placement->origin[1] = y2;
605 // z-axis rotation for direction
606 x2 = placement->direction[0]*cz-placement->direction[1]*sz;
607 y2 = placement->direction[0]*sz+placement->direction[1]*cz;
608 placement->direction[0] = x2;
609 placement->direction[1] = y2;
611 // z-axis rotation for up
612 x2 = placement->up[0]*cz-placement->up[1]*sz;
613 y2 = placement->up[0]*sz+placement->up[1]*cz;
614 placement->up[0] = x2;
615 placement->up[1] = y2;
617 // x-axis rotation for origin
618 y2 = placement->origin[1]*cx-placement->origin[2]*sx;
619 z2 = placement->origin[1]*sx+placement->origin[2]*cx;
620 placement->origin[1] = y2;
621 placement->origin[2] = z2;
623 // x-axis rotation for direction vector
624 y2 = placement->direction[1]*cx-placement->direction[2]*sx;
625 z2 = placement->direction[1]*sx+placement->direction[2]*cx;
626 placement->direction[1] = y2;
627 placement->direction[2] = z2;
629 // x-axis rotation for up vector
630 y2 = placement->up[1]*cx-placement->up[2]*sx;
631 z2 = placement->up[1]*sx+placement->up[2]*cx;
632 placement->up[1] = y2;
633 placement->up[2] = z2;
636 placement->origin[0] += curTranslation[i][0];
637 placement->origin[1] += curTranslation[i][1];
638 placement->origin[2] += curTranslation[i][2];
640 // translate back to local coord
641 placement->direction[0] += curTranslation[i][0];
642 placement->direction[1] += curTranslation[i][1];
643 placement->direction[2] += curTranslation[i][2];
645 // translate back to local coord
646 placement->up[0] += curTranslation[i][0];
647 placement->up[1] += curTranslation[i][1];
648 placement->up[2] += curTranslation[i][2];
652 // This screwed up and needs to be sorted out!!!
653 // The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton
654 for(j = i-1; j < stackSize-1; ++j)
656 // y-axis rotation for origin
657 x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;
658 z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;
659 jointList[j].placement.origin[0] = x2;
660 jointList[j].placement.origin[2] = z2;
662 // y-axis rotation for direction
663 x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;
664 z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;
665 jointList[j].placement.direction[0] = x2;
666 jointList[j].placement.direction[2] = z2;
668 // y-axis rotation for up
669 x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;
670 z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;
671 jointList[j].placement.up[0] = x2;
672 jointList[j].placement.up[2] = z2;
674 // z-axis rotation for origin
675 x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;
676 y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;
677 jointList[j].placement.origin[0] = x2;
678 jointList[j].placement.origin[1] = y2;
680 // z-axis rotation for direction
681 x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;
682 y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;
683 jointList[j].placement.direction[0] = x2;
684 jointList[j].placement.direction[1] = y2;
686 // z-axis rotation for up
687 x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;
688 y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;
689 jointList[j].placement.up[0] = x2;
690 jointList[j].placement.up[1] = y2;
692 // x-axis rotation for origin
693 y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;
694 z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;
695 jointList[j].placement.origin[1] = y2;
696 jointList[j].placement.origin[2] = z2;
698 // x-axis rotation for direction vector
699 y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;
700 z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;
701 jointList[j].placement.direction[1] = y2;
702 jointList[j].placement.direction[2] = z2;
704 // x-axis rotation for up vector
705 y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;
706 z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;
707 jointList[j].placement.up[1] = y2;
708 jointList[j].placement.up[2] = z2;
710 if(curCorrespondingJoint[j+1] != -1)
713 jointList[j].placement.origin[0] += curTranslation[i-1][0];
714 jointList[j].placement.origin[1] += curTranslation[i-1][1];
715 jointList[j].placement.origin[2] += curTranslation[i-1][2];
717 // translate back to local coord
718 jointList[j].placement.direction[0] += curTranslation[i-1][0];
719 jointList[j].placement.direction[1] += curTranslation[i-1][1];
720 jointList[j].placement.direction[2] += curTranslation[i-1][2];
722 // translate back to local coord
723 jointList[j].placement.up[0] += curTranslation[i-1][0];
724 jointList[j].placement.up[1] += curTranslation[i-1][1];
725 jointList[j].placement.up[2] += curTranslation[i-1][2];
732 void LoadModelTransform(char *fileName)
737 char InputFileName[256];
739 dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
743 strcpy(InputFileName, fileName);
744 strcat(InputFileName, ".hrc");
745 if((file1 = fopen(InputFileName, "rb")) != NULL)
749 LoadHRCGlobals(InputFileName);
751 printf(" - assuming .HRC\n");
755 Error("\n Could not open file '%s':\n"
756 "No HRC match.\n", fileName);
760 if((file1 = fopen(fileName, "rb")) != NULL)
764 if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
766 LoadHRCGlobals(fileName);
771 Error("Could not open file '%s':\n",fileName);
775 void LoadModelClusters(char *fileName, int **clusterList, int *num_verts, int skelType)
780 char InputFileName[256];
782 dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
786 strcpy(InputFileName, fileName);
787 strcat(InputFileName, ".hrc");
788 if((file1 = fopen(InputFileName, "rb")) != NULL)
792 LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);
794 printf(" - assuming .HRC\n");
798 Error("\n Could not open file '%s':\n"
799 "No HRC match.\n", fileName);
803 if((file1 = fopen(fileName, "rb")) != NULL)
807 if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
809 LoadHRCClustered(fileName, clusterList, num_verts, skelType);
814 Error("Could not open file '%s':\n",fileName);
818 void LoadSkeleton(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)
823 char InputFileName[256];
825 dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
829 strcpy(InputFileName, fileName);
830 strcat(InputFileName, ".hrc");
831 if((file1 = fopen(InputFileName, "rb")) != NULL)
835 LoadHRCJointList(InputFileName, jointList, skelType);
837 printf(" - assuming .HRC\n");
841 Error("\n Could not open file '%s':\n"
842 "No HRC.\n", fileName);
846 if((file1 = fopen(fileName, "rb")) != NULL)
850 if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
852 LoadHRCJointList(fileName, jointList, skelType);
858 Error("Could not open file '%s':\n",fileName);
867 void GrabSkeletalFrame(char *frame)
873 framefile = FindFrameFile (frame);
875 sprintf (file1, "%s/%s", cdarchive, framefile);
876 ExpandPathAndArchive (file1);
878 sprintf (file1, "%s/%s",cddir, framefile);
880 printf ("Grabbing Skeletal Frame %s\n", file1);
882 fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
884 LoadSkeleton(file1, fr->joints, g_skelModel.type);
892 void GrabModelTransform(char *frame)
898 framefile = FindFrameFile (frame);
900 sprintf (file1, "%s/%s", cdarchive, framefile);
901 ExpandPathAndArchive (file1);
903 sprintf (file1, "%s/%s",cddir, framefile);
905 // printf ("grabbing %s\n", file1);
907 fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
909 LoadModelTransform(file1);
916 GetScriptToken (false);
918 printf ("---------------------\n");
919 sprintf (file1, "%s/%s", cdpartial, token);
920 printf ("%s\n", file1);
922 ExpandPathAndArchive (file1);
924 sprintf (file1, "%s/%s", cddir, token);
926 g_skelModel.clustered = -1;
928 LoadModelClusters(file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type);
930 g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0];
932 g_skelModel.clustered = true;
935 void Cmd_FMSkeleton()
937 GetScriptToken (false);
938 g_skelModel.type = atoi(token);
941 void Cmd_FMSkeletalFrame()
943 while (ScriptTokenAvailable())
945 GetScriptToken (false);
948 GetScriptToken (false);
951 if (g_release || g_archive)
953 fmheader.num_frames = 1; // don't skip the writeout
954 GetScriptToken (false);
958 H_printf("#define FRAME_%-16s\t%i\n", token, fmheader.num_frames);
960 GrabModelTransform (token);
962 GrabSkeletalFrame (token);
964 // need to add the up and dir points to the frame bounds here
965 // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
966 // then remove fudge in determining scale on frame write out
970 static void LoadHRCReferences(char *fileName, fmframe_t *fr)
974 vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK];
975 int curCorrespondingJoint[MAX_STACK];
976 int currentStack, stackSize;
977 double cx, sx, cy, sy, cz, sz;
980 char stripped[SKELETAL_NAME_MAX];
981 Placement_d_t *placement;
984 TK_OpenSource(fileName);
985 TK_FetchRequire(TK_HRCH);
986 TK_FetchRequire(TK_COLON);
987 TK_FetchRequire(TK_SOFTIMAGE);
989 if (RefPointNum <= 0)
990 { // There were no labels indicated in the QDT, so use the hard-coded stuff.
991 refnum = numReferences[g_skelModel.references];
995 refnum = RefPointNum;
998 for(k = 0; k < refnum; ++k)
1002 // Load the root to get translation and initial rotation
1003 // TK_Beyond(TK_MODEL);
1005 while(TK_Search(TK_NAME) != TK_EOF)
1007 TK_Require(TK_STRING);
1009 StripTrailingDigits(tk_String, stripped);
1011 if (RefPointNum == 0)
1012 { // Hard coded refpoint labels
1013 if(stricmp(stripped,
1014 referenceRootNames[referenceRootNameOffsets[g_skelModel.references]+k]) == 0)
1020 { // labels indicated by the QDT
1021 if(stricmp(stripped, RefPointNameList[k]) == 0)
1028 if(tk_Token == TK_EOF)
1030 if (RefPointNum == 0)
1031 { // Hard coded refpoint labels
1032 Error("Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]]);
1035 { // labels indicated by the QDT
1036 Error("Bone Chain Root: %s not found\n", RefPointNameList[k]);
1041 // TK_Beyond(TK_SCALING);
1043 // ParseVec3d(curScale[currentStack]);
1045 TK_Beyond(TK_ROTATION);
1047 ParseRotation3d(curRotation[currentStack]);
1049 TK_Beyond(TK_TRANSLATION);
1051 ParseVec3d(curTranslation[currentStack]);
1053 // account for global model translation
1054 curTranslation[currentStack][1] += g_skelModel.translation[0];
1055 curTranslation[currentStack][2] += g_skelModel.translation[1];
1056 curTranslation[currentStack][0] += g_skelModel.translation[2];
1058 curCorrespondingJoint[currentStack] = -1;
1060 // rjr - this one not needed, as there is also a stack increment 20 lines below???
1063 // Load the joint to get orientation
1064 TK_Beyond(TK_MODEL);
1066 // TK_Beyond(TK_SCALING);
1068 // ParseVec3d(curScale[currentStack]);
1070 TK_Beyond(TK_ROTATION);
1072 ParseRotation3d(curRotation[currentStack]);
1074 // TK_Beyond(TK_TRANSLATION);
1076 // ParseVec3d(curTranslation[currentStack]);
1078 fr->references[k].placement.origin[1] = 0.0;
1079 fr->references[k].placement.origin[2] = 0.0;
1080 fr->references[k].placement.origin[0] = 0.0;
1082 fr->references[k].placement.direction[1] = 20.0;
1083 fr->references[k].placement.direction[2] = 0.0;
1084 fr->references[k].placement.direction[0] = 0.0;
1086 fr->references[k].placement.up[1] = 0.0;
1087 fr->references[k].placement.up[2] = 20.0;
1088 fr->references[k].placement.up[0] = 0.0;
1090 curCorrespondingJoint[currentStack] = k;
1094 stackSize = currentStack;
1096 for(i = stackSize - 1; i >= 0; --i)
1098 rx = curRotation[i][0]*ANGLE_TO_RAD;
1099 ry = curRotation[i][1]*ANGLE_TO_RAD;
1100 rz = curRotation[i][2]*ANGLE_TO_RAD;
1111 for(j = i; j < stackSize; ++j)
1113 if(curCorrespondingJoint[j] != -1)
1115 placement = &fr->references[curCorrespondingJoint[j]].placement;
1117 // y-axis rotation for origin
1118 x2 = placement->origin[0]*cy+placement->origin[2]*sy;
1119 z2 = -placement->origin[0]*sy+placement->origin[2]*cy;
1120 placement->origin[0] = x2;
1121 placement->origin[2] = z2;
1123 // y-axis rotation for direction
1124 x2 = placement->direction[0]*cy+placement->direction[2]*sy;
1125 z2 = -placement->direction[0]*sy+placement->direction[2]*cy;
1126 placement->direction[0] = x2;
1127 placement->direction[2] = z2;
1129 // y-axis rotation for up
1130 x2 = placement->up[0]*cy+placement->up[2]*sy;
1131 z2 = -placement->up[0]*sy+placement->up[2]*cy;
1132 placement->up[0] = x2;
1133 placement->up[2] = z2;
1135 // z-axis rotation for origin
1136 x2 = placement->origin[0]*cz-placement->origin[1]*sz;
1137 y2 = placement->origin[0]*sz+placement->origin[1]*cz;
1138 placement->origin[0] = x2;
1139 placement->origin[1] = y2;
1141 // z-axis rotation for direction
1142 x2 = placement->direction[0]*cz-placement->direction[1]*sz;
1143 y2 = placement->direction[0]*sz+placement->direction[1]*cz;
1144 placement->direction[0] = x2;
1145 placement->direction[1] = y2;
1147 // z-axis rotation for up
1148 x2 = placement->up[0]*cz-placement->up[1]*sz;
1149 y2 = placement->up[0]*sz+placement->up[1]*cz;
1150 placement->up[0] = x2;
1151 placement->up[1] = y2;
1153 // x-axis rotation for origin
1154 y2 = placement->origin[1]*cx-placement->origin[2]*sx;
1155 z2 = placement->origin[1]*sx+placement->origin[2]*cx;
1156 placement->origin[1] = y2;
1157 placement->origin[2] = z2;
1159 // x-axis rotation for direction vector
1160 y2 = placement->direction[1]*cx-placement->direction[2]*sx;
1161 z2 = placement->direction[1]*sx+placement->direction[2]*cx;
1162 placement->direction[1] = y2;
1163 placement->direction[2] = z2;
1165 // x-axis rotation for up vector
1166 y2 = placement->up[1]*cx-placement->up[2]*sx;
1167 z2 = placement->up[1]*sx+placement->up[2]*cx;
1168 placement->up[1] = y2;
1169 placement->up[2] = z2;
1172 placement->origin[0] += curTranslation[i][0];
1173 placement->origin[1] += curTranslation[i][1];
1174 placement->origin[2] += curTranslation[i][2];
1176 // translate back to local coord
1177 placement->direction[0] += curTranslation[i][0];
1178 placement->direction[1] += curTranslation[i][1];
1179 placement->direction[2] += curTranslation[i][2];
1181 // translate back to local coord
1182 placement->up[0] += curTranslation[i][0];
1183 placement->up[1] += curTranslation[i][1];
1184 placement->up[2] += curTranslation[i][2];
1189 printf("%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2]);
1194 void Cmd_FMReferenced()
1198 GetScriptToken (false);
1199 g_skelModel.references = atoi(token);
1201 // Guess what? Now, we now want a list of strings to look for here instead of a hard-coded list
1202 for (i=0; i<REF_MAX_POINTS; i++)
1204 if (ScriptTokenAvailable())
1205 { // There is yet another reference point waiting.
1206 GetScriptToken(false);
1207 strcpy(RefPointNameList[i], token);
1217 if (RefPointNum > 0)
1219 printf("Searching for %d different reference points.\n", RefPointNum);
1223 printf("Using built-in reference points.\n");
1228 void LoadReferences(char *fileName, fmframe_t *fr)
1233 char InputFileName[256];
1235 dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
1239 strcpy(InputFileName, fileName);
1240 strcat(InputFileName, ".hrc");
1241 if((file1 = fopen(InputFileName, "rb")) != NULL)
1245 LoadHRCReferences(InputFileName, fr);
1247 printf(" - assuming .HRC\n");
1251 Error("\n Could not open file '%s':\n"
1252 "No HRC.\n", fileName);
1256 if((file1 = fopen(fileName, "rb")) != NULL)
1260 if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
1262 LoadHRCReferences(fileName, fr);
1268 Error("Could not open file '%s':\n",fileName);
1272 void GrabReferencedFrame(char *frame)
1278 framefile = FindFrameFile (frame);
1280 sprintf (file1, "%s/%s", cdarchive, framefile);
1281 ExpandPathAndArchive (file1);
1283 sprintf (file1, "%s/%s",cddir, framefile);
1285 printf ("Grabbing Referenced %s\n", file1);
1287 fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
1289 LoadReferences(file1, fr);