--- /dev/null
+/*\r
+Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
+For a list of contributors, see the accompanying CONTRIBUTORS file.\r
+\r
+This file is part of GtkRadiant.\r
+\r
+GtkRadiant is free software; you can redistribute it and/or modify\r
+it under the terms of the GNU General Public License as published by\r
+the Free Software Foundation; either version 2 of the License, or\r
+(at your option) any later version.\r
+\r
+GtkRadiant is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with GtkRadiant; if not, write to the Free Software\r
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\r
+*/\r
+\r
+#include "qd_skeletons.h"\r
+#include "skeletons.h"\r
+#include "qd_fmodel.h"\r
+#include "angles.h"\r
+#include "token.h"\r
+#include "qdata.h"\r
+#include "reference.h"\r
+\r
+#include <assert.h>\r
+#include <math.h>\r
+#include <memory.h>\r
+\r
+\r
+// We're assuming no more than 16 reference points, with no more than 32 characters in the name\r
+char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];\r
+int RefPointNum = 0;\r
+\r
+Skeletalfmheader_t g_skelModel;\r
+\r
+void ClearSkeletalModel()\r
+{\r
+ g_skelModel.type = SKEL_NULL;\r
+ g_skelModel.clustered = false;\r
+ g_skelModel.references = REF_NULL;\r
+}\r
+\r
+//==========================================================================\r
+//\r
+// LoadHRCClustered\r
+//\r
+//==========================================================================\r
+\r
+// Places the null terminated src string into the dest string less any trailing digits or underscores\r
+void StripTrailingDigits(char *src, char *dest)\r
+{\r
+#ifndef NDEBUG\r
+ int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files\r
+#endif\r
+ int i = 0;\r
+\r
+ while(src[i] != '\0')\r
+ {\r
+ ++i;\r
+#ifndef NDEBUG\r
+ assert(i < max);\r
+#endif\r
+ }\r
+\r
+ while((src[--i] >= '0' && src[i] <= '9') || src[i] == '_')\r
+ {\r
+\r
+ }\r
+\r
+ memcpy(dest, src, ++i);\r
+\r
+ dest[i] = '\0';\r
+}\r
+\r
+static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)\r
+{\r
+ extern void HandleHRCModel(triangle_t **triList, int *triangleCount, \r
+ mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth);\r
+\r
+ extern mesh_node_t *pmnodes;\r
+\r
+ triangle_t *triList;\r
+// mesh_node_t *nodesList;\r
+ int num_mesh_nodes = 0, triangleCount = 0;\r
+\r
+#if 0\r
+ int i;\r
+ int j, numVerts;\r
+ char stripped[SKELETAL_NAME_MAX];\r
+\r
+ for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)\r
+ {\r
+ num_verts[i] = 0;\r
+ }\r
+\r
+ TK_OpenSource(fileName);\r
+ TK_FetchRequire(TK_HRCH);\r
+ TK_FetchRequire(TK_COLON);\r
+ TK_FetchRequire(TK_SOFTIMAGE);\r
+\r
+ TK_Beyond(TK_CLUSTERS);\r
+\r
+ while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)\r
+ {\r
+ TK_Require(TK_STRING);\r
+\r
+ StripTrailingDigits(tk_String, stripped);\r
+\r
+ for( i = 0; i < numJointsInSkeleton[skelType]; ++i)\r
+ {\r
+ if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)\r
+ {\r
+ i = -i + numJointsInSkeleton[skelType] - 1;\r
+\r
+ TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);\r
+\r
+ numVerts = tk_IntNumber;\r
+\r
+ if(!num_verts[i+1]) // first set of verts for cluster\r
+ {\r
+ clusterList[i] = SafeMalloc(numVerts*sizeof(int), "LoadHRCClustered");\r
+ assert(clusterList[i]);\r
+ }\r
+ else // any later sets of verts need to copy current\r
+ {\r
+ int *temp;\r
+\r
+ temp = SafeMalloc((num_verts[i+1]+numVerts)*sizeof(int), "LoadHRCClustered");\r
+ assert(temp);\r
+\r
+ memcpy(temp + numVerts, clusterList[i], num_verts[i+1]*sizeof(int));\r
+\r
+ free(clusterList[i]);\r
+\r
+ clusterList[i] = temp;\r
+ }\r
+\r
+ // currently this function is only called by LoadModelClusters.\r
+ // Apparently the matching free has disappeared, \r
+ // should probably be free at the end of FMCmd_Base\r
+\r
+ TK_Beyond(TK_LBRACE);\r
+\r
+ for(j = 0; j < numVerts; ++j)\r
+ {\r
+ TK_Require(TK_INTNUMBER);\r
+ clusterList[i][j] = tk_IntNumber;\r
+ TK_Fetch();\r
+ }\r
+\r
+ num_verts[i+1] += numVerts;\r
+\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ num_verts[0] = numJointsInSkeleton[skelType];\r
+#endif\r
+\r
+#if 1 // get the index number localized to the root\r
+// for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)\r
+// {\r
+// g_skelModel.num_verts[i] = 0;\r
+// }\r
+\r
+ TK_OpenSource(fileName);\r
+ TK_FetchRequire(TK_HRCH);\r
+ TK_FetchRequire(TK_COLON);\r
+ TK_FetchRequire(TK_SOFTIMAGE);\r
+\r
+ // prime it\r
+ TK_Beyond(TK_MODEL);\r
+\r
+ triList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");\r
+ memset(triList,0,MAXTRIANGLES*sizeof(triangle_t));\r
+// nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");\r
+ pmnodes = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");\r
+\r
+ memset(pmnodes, 0, MAX_FM_MESH_NODES * sizeof(mesh_node_t));\r
+\r
+ // this should eventually use a stripped down version of this\r
+ HandleHRCModel(&triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0);\r
+\r
+// free(nodesList);\r
+ free(triList);\r
+\r
+ num_verts[0] = numJointsInSkeleton[skelType];\r
+#endif\r
+}\r
+\r
+void ReadHRCClusterList(mesh_node_t *meshNode, int baseIndex)\r
+{\r
+ int i, j, numVerts;\r
+ tokenType_t nextToken;\r
+ char stripped[SKELETAL_NAME_MAX];\r
+\r
+ meshNode->clustered = true;\r
+\r
+ nextToken = TK_Get(TK_CLUSTER_NAME);\r
+\r
+ while (nextToken == TK_CLUSTER_NAME)\r
+ {\r
+ TK_FetchRequire(TK_STRING);\r
+\r
+ StripTrailingDigits(tk_String, stripped);\r
+\r
+ for( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)\r
+ {\r
+ if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type]+i]) == 0)\r
+ {\r
+ i = -i + numJointsInSkeleton[g_skelModel.type] - 1;\r
+\r
+ TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);\r
+\r
+ numVerts = tk_IntNumber;\r
+\r
+ if(!baseIndex)\r
+ {\r
+ meshNode->clusters[i] = (int *) SafeMalloc(numVerts*sizeof(int), "ReadHRCClusterList");\r
+ assert(meshNode->clusters[i]);\r
+ }\r
+ else\r
+ {\r
+ int *temp; \r
+\r
+ temp = meshNode->clusters[i];\r
+ meshNode->clusters[i] = (int *) SafeMalloc((meshNode->num_verts[i+1]+numVerts)*sizeof(int), "ReadHRCClusterList");\r
+ assert(meshNode->clusters[i]);\r
+\r
+ memcpy(meshNode->clusters[i], temp, meshNode->num_verts[i+1]*sizeof(int));\r
+ free(temp);\r
+ }\r
+\r
+ // currently this function is only called by LoadModelClusters.\r
+ // Apparently the matching free has disappeared, \r
+ // should probably be free at the end of FMCmd_Base\r
+\r
+ TK_Beyond(TK_LBRACE);\r
+\r
+ for(j = 0; j < numVerts; ++j)\r
+ {\r
+ TK_Require(TK_INTNUMBER);\r
+ meshNode->clusters[i][baseIndex+j] = tk_IntNumber+baseIndex;\r
+ TK_Fetch();\r
+ }\r
+\r
+ if(baseIndex)\r
+ {\r
+ meshNode->num_verts[i+1] += numVerts;\r
+ }\r
+ else\r
+ {\r
+ meshNode->num_verts[i+1] = numVerts;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ TK_BeyondRequire(TK_CLUSTER_STATE, TK_INTNUMBER);\r
+ nextToken = TK_Fetch();\r
+ }\r
+}\r
+\r
+static void LoadHRCGlobals(char *fileName)\r
+{\r
+ int i;\r
+\r
+ TK_OpenSource(fileName);\r
+ TK_FetchRequire(TK_HRCH);\r
+ TK_FetchRequire(TK_COLON);\r
+ TK_FetchRequire(TK_SOFTIMAGE);\r
+ TK_Beyond(TK_MODEL);\r
+\r
+ TK_Beyond(TK_SCALING);\r
+ for(i = 0; i < 3; i++)\r
+ {\r
+ TK_Require(TK_FLOATNUMBER);\r
+ g_skelModel.scaling[i] = tk_FloatNumber;\r
+ TK_Fetch();\r
+ }\r
+\r
+ TK_Beyond(TK_ROTATION);\r
+ for(i = 0; i < 3; i++)\r
+ {\r
+ TK_Require(TK_FLOATNUMBER);\r
+ g_skelModel.rotation[i] = tk_FloatNumber;\r
+ TK_Fetch();\r
+ }\r
+\r
+ TK_Beyond(TK_TRANSLATION);\r
+ for(i = 0; i < 3; i++)\r
+ {\r
+ TK_Require(TK_FLOATNUMBER);\r
+ g_skelModel.translation[i] = tk_FloatNumber;\r
+ TK_Fetch();\r
+ }\r
+}\r
+\r
+static void ParseVec3(vec3_t in)\r
+{\r
+ TK_Require(TK_FLOATNUMBER);\r
+ in[1] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[2] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[0] = tk_FloatNumber;\r
+}\r
+\r
+static void ParseVec3d(vec3d_t in)\r
+{\r
+ TK_Require(TK_FLOATNUMBER);\r
+ in[1] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[2] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[0] = tk_FloatNumber;\r
+}\r
+\r
+static void ParseRotation3(vec3_t in)\r
+{\r
+ TK_Require(TK_FLOATNUMBER);\r
+ in[1] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[2] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[0] = tk_FloatNumber;\r
+}\r
+\r
+static void ParseRotation3d(vec3d_t in)\r
+{\r
+ TK_Require(TK_FLOATNUMBER);\r
+ in[1] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[2] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[0] = tk_FloatNumber;\r
+}\r
+\r
+static void ParseTranslation3(vec3_t in)\r
+{\r
+ TK_Require(TK_FLOATNUMBER);\r
+ in[1] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[2] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[0] = tk_FloatNumber;\r
+}\r
+\r
+static void ParseTranslation3d(vec3d_t in)\r
+{\r
+ TK_Require(TK_FLOATNUMBER);\r
+ in[1] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[2] = tk_FloatNumber;\r
+ TK_FetchRequire(TK_FLOATNUMBER);\r
+ in[0] = tk_FloatNumber;\r
+}\r
+\r
+static void LoadHRCJointList(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)\r
+{\r
+#define MAX_STACK 64\r
+ int i, j;\r
+ vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];\r
+ int curCorrespondingJoint[MAX_STACK];\r
+ int currentStack = 0, stackSize;\r
+ double cx, sx, cy, sy, cz, sz;\r
+ double rx, ry, rz;\r
+ double x2, y2, z2;\r
+ char stripped[SKELETAL_NAME_MAX];\r
+ Placement_d_t *placement;\r
+\r
+ TK_OpenSource(fileName);\r
+ TK_FetchRequire(TK_HRCH);\r
+ TK_FetchRequire(TK_COLON);\r
+ TK_FetchRequire(TK_SOFTIMAGE);\r
+\r
+ TK_Beyond(TK_MODEL);\r
+\r
+ while(TK_Search(TK_NAME) != TK_EOF)\r
+ {\r
+ TK_Require(TK_STRING);\r
+\r
+ StripTrailingDigits(tk_String, stripped);\r
+\r
+ if(stricmp(stripped, skeletonRootNames[skeletonRNameOffsets[skelType]]) == 0)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if(tk_Token == TK_EOF)\r
+ {\r
+ Error("Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]]);\r
+ return;\r
+ }\r
+\r
+ TK_Beyond(TK_SCALING);\r
+\r
+ ParseVec3d(curScale[currentStack]);\r
+\r
+ TK_Beyond(TK_ROTATION);\r
+\r
+ ParseRotation3d(curRotation[currentStack]);\r
+\r
+ TK_Beyond(TK_TRANSLATION);\r
+\r
+ ParseVec3d(curTranslation[currentStack]);\r
+\r
+ // account for global model translation\r
+ curTranslation[currentStack][1] += g_skelModel.translation[0];\r
+ curTranslation[currentStack][2] += g_skelModel.translation[1];\r
+ curTranslation[currentStack][0] += g_skelModel.translation[2];\r
+\r
+ curCorrespondingJoint[currentStack] = -1;\r
+\r
+ ++currentStack;\r
+\r
+ for(i = 0; i < numJointsInSkeleton[skelType]; ++i)\r
+ {\r
+ while(1)\r
+ {\r
+ TK_Beyond(TK_MODEL);\r
+\r
+ TK_BeyondRequire(TK_NAME, TK_STRING);\r
+\r
+ StripTrailingDigits(tk_String, stripped);\r
+\r
+ if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)\r
+ break;\r
+\r
+ TK_Beyond(TK_SCALING);\r
+\r
+ ParseVec3d(curScale[currentStack]);\r
+\r
+ TK_Beyond(TK_ROTATION);\r
+\r
+ ParseRotation3d(curRotation[currentStack]);\r
+\r
+ TK_Beyond(TK_TRANSLATION);\r
+\r
+ ParseVec3d(curTranslation[currentStack]);\r
+\r
+ curCorrespondingJoint[currentStack] = -1;\r
+\r
+ ++currentStack;\r
+ }\r
+\r
+ TK_Beyond(TK_SCALING);\r
+\r
+ ParseVec3d(curScale[currentStack]);\r
+\r
+ TK_Beyond(TK_ROTATION);\r
+\r
+ ParseRotation3d(curRotation[currentStack]);\r
+\r
+ jointList[i].rotation[1] = curRotation[currentStack][1];\r
+ jointList[i].rotation[2] = curRotation[currentStack][2];\r
+ jointList[i].rotation[0] = curRotation[currentStack][0];\r
+\r
+ TK_Beyond(TK_TRANSLATION);\r
+\r
+ ParseVec3d(curTranslation[currentStack]);\r
+\r
+// jointList[i].placement.origin[1] = curTranslation[currentStack][1];\r
+// jointList[i].placement.origin[2] = curTranslation[currentStack][2];\r
+// jointList[i].placement.origin[0] = curTranslation[currentStack][0];\r
+\r
+ jointList[i].placement.origin[1] = 0.0;\r
+ jointList[i].placement.origin[2] = 0.0;\r
+ jointList[i].placement.origin[0] = 0.0;\r
+\r
+ jointList[i].placement.direction[1] = 20.0;\r
+ jointList[i].placement.direction[2] = 0.0;\r
+ jointList[i].placement.direction[0] = 0.0;\r
+\r
+ jointList[i].placement.up[1] = 0.0;\r
+ jointList[i].placement.up[2] = 20.0;\r
+ jointList[i].placement.up[0] = 0.0;\r
+\r
+ curCorrespondingJoint[currentStack] = i;\r
+\r
+ ++currentStack;\r
+ }\r
+\r
+ stackSize = currentStack;\r
+\r
+#if 0\r
+ // rotate the direction and up vectors to correspond to the rotation\r
+ for(i = 0; i < numJointsInSkeleton[skelType]; ++i)\r
+ {\r
+ rx = jointList[i].rotation[0]*ANGLE_TO_RAD;\r
+ ry = jointList[i].rotation[1]*ANGLE_TO_RAD;\r
+ rz = jointList[i].rotation[2]*ANGLE_TO_RAD;\r
+\r
+ cx = cos(rx);\r
+ sx = sin(rx);\r
+\r
+ cy = cos(ry);\r
+ sy = sin(ry);\r
+\r
+ cz = cos(rz);\r
+ sz = sin(rz);\r
+\r
+ // y-axis rotation for direction\r
+ x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;\r
+ z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;\r
+ jointList[i].placement.direction[0] = x2;\r
+ jointList[i].placement.direction[2] = z2;\r
+\r
+ // y-axis rotation for up\r
+ x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;\r
+ z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;\r
+ jointList[i].placement.up[0] = x2;\r
+ jointList[i].placement.up[2] = z2;\r
+\r
+ // z-axis rotation for direction\r
+ x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;\r
+ y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;\r
+ jointList[i].placement.direction[0] = x2;\r
+ jointList[i].placement.direction[1] = y2;\r
+\r
+ // z-axis rotation for up\r
+ x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;\r
+ y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;\r
+ jointList[i].placement.up[0] = x2;\r
+ jointList[i].placement.up[1] = y2;\r
+\r
+ // x-axis rotation for direction vector\r
+ y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;\r
+ z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;\r
+ jointList[i].placement.direction[1] = y2;\r
+ jointList[i].placement.direction[2] = z2;\r
+\r
+ // x-axis rotation for up vector\r
+ y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;\r
+ z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;\r
+ jointList[i].placement.up[1] = y2;\r
+ jointList[i].placement.up[2] = z2;\r
+\r
+ // translate direction to a point in the model\r
+ jointList[i].placement.direction[0] += jointList[i].placement.origin[0];\r
+ jointList[i].placement.direction[1] += jointList[i].placement.origin[1];\r
+ jointList[i].placement.direction[2] += jointList[i].placement.origin[2];\r
+\r
+ // translate up to a point in the model\r
+ jointList[i].placement.up[0] += jointList[i].placement.origin[0];\r
+ jointList[i].placement.up[1] += jointList[i].placement.origin[1];\r
+ jointList[i].placement.up[2] += jointList[i].placement.origin[2];\r
+ }\r
+#endif\r
+\r
+ for(i = stackSize - 1; i >= 0; --i)\r
+ {\r
+ rx = curRotation[i][0]*ANGLE_TO_RAD;\r
+ ry = curRotation[i][1]*ANGLE_TO_RAD;\r
+ rz = curRotation[i][2]*ANGLE_TO_RAD;\r
+\r
+ cx = cos(rx);\r
+ sx = sin(rx);\r
+\r
+ cy = cos(ry);\r
+ sy = sin(ry);\r
+\r
+ cz = cos(rz);\r
+ sz = sin(rz);\r
+\r
+#if 1\r
+ for(j = i; j < stackSize; ++j)\r
+ {\r
+ if(curCorrespondingJoint[j] != -1)\r
+ {\r
+ placement = &jointList[curCorrespondingJoint[j]].placement;\r
+\r
+ // y-axis rotation for origin\r
+ x2 = placement->origin[0]*cy+placement->origin[2]*sy;\r
+ z2 = -placement->origin[0]*sy+placement->origin[2]*cy;\r
+ placement->origin[0] = x2;\r
+ placement->origin[2] = z2;\r
+\r
+ // y-axis rotation for direction\r
+ x2 = placement->direction[0]*cy+placement->direction[2]*sy;\r
+ z2 = -placement->direction[0]*sy+placement->direction[2]*cy;\r
+ placement->direction[0] = x2;\r
+ placement->direction[2] = z2;\r
+\r
+ // y-axis rotation for up\r
+ x2 = placement->up[0]*cy+placement->up[2]*sy;\r
+ z2 = -placement->up[0]*sy+placement->up[2]*cy;\r
+ placement->up[0] = x2;\r
+ placement->up[2] = z2;\r
+\r
+ // z-axis rotation for origin\r
+ x2 = placement->origin[0]*cz-placement->origin[1]*sz;\r
+ y2 = placement->origin[0]*sz+placement->origin[1]*cz;\r
+ placement->origin[0] = x2;\r
+ placement->origin[1] = y2;\r
+\r
+ // z-axis rotation for direction\r
+ x2 = placement->direction[0]*cz-placement->direction[1]*sz;\r
+ y2 = placement->direction[0]*sz+placement->direction[1]*cz;\r
+ placement->direction[0] = x2;\r
+ placement->direction[1] = y2;\r
+\r
+ // z-axis rotation for up\r
+ x2 = placement->up[0]*cz-placement->up[1]*sz;\r
+ y2 = placement->up[0]*sz+placement->up[1]*cz;\r
+ placement->up[0] = x2;\r
+ placement->up[1] = y2;\r
+\r
+ // x-axis rotation for origin\r
+ y2 = placement->origin[1]*cx-placement->origin[2]*sx;\r
+ z2 = placement->origin[1]*sx+placement->origin[2]*cx;\r
+ placement->origin[1] = y2;\r
+ placement->origin[2] = z2;\r
+\r
+ // x-axis rotation for direction vector\r
+ y2 = placement->direction[1]*cx-placement->direction[2]*sx;\r
+ z2 = placement->direction[1]*sx+placement->direction[2]*cx;\r
+ placement->direction[1] = y2;\r
+ placement->direction[2] = z2;\r
+\r
+ // x-axis rotation for up vector\r
+ y2 = placement->up[1]*cx-placement->up[2]*sx;\r
+ z2 = placement->up[1]*sx+placement->up[2]*cx;\r
+ placement->up[1] = y2;\r
+ placement->up[2] = z2;\r
+\r
+ // translate origin\r
+ placement->origin[0] += curTranslation[i][0];\r
+ placement->origin[1] += curTranslation[i][1];\r
+ placement->origin[2] += curTranslation[i][2];\r
+\r
+ // translate back to local coord\r
+ placement->direction[0] += curTranslation[i][0];\r
+ placement->direction[1] += curTranslation[i][1];\r
+ placement->direction[2] += curTranslation[i][2];\r
+\r
+ // translate back to local coord\r
+ placement->up[0] += curTranslation[i][0];\r
+ placement->up[1] += curTranslation[i][1];\r
+ placement->up[2] += curTranslation[i][2];\r
+ }\r
+ }\r
+#else\r
+ // This screwed up and needs to be sorted out!!!\r
+ // The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton\r
+ for(j = i-1; j < stackSize-1; ++j)\r
+ {\r
+ // y-axis rotation for origin\r
+ x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;\r
+ z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;\r
+ jointList[j].placement.origin[0] = x2;\r
+ jointList[j].placement.origin[2] = z2;\r
+\r
+ // y-axis rotation for direction\r
+ x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;\r
+ z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;\r
+ jointList[j].placement.direction[0] = x2;\r
+ jointList[j].placement.direction[2] = z2;\r
+\r
+ // y-axis rotation for up\r
+ x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;\r
+ z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;\r
+ jointList[j].placement.up[0] = x2;\r
+ jointList[j].placement.up[2] = z2;\r
+\r
+ // z-axis rotation for origin\r
+ x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;\r
+ y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;\r
+ jointList[j].placement.origin[0] = x2;\r
+ jointList[j].placement.origin[1] = y2;\r
+\r
+ // z-axis rotation for direction\r
+ x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;\r
+ y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;\r
+ jointList[j].placement.direction[0] = x2;\r
+ jointList[j].placement.direction[1] = y2;\r
+\r
+ // z-axis rotation for up\r
+ x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;\r
+ y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;\r
+ jointList[j].placement.up[0] = x2;\r
+ jointList[j].placement.up[1] = y2;\r
+\r
+ // x-axis rotation for origin\r
+ y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;\r
+ z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;\r
+ jointList[j].placement.origin[1] = y2;\r
+ jointList[j].placement.origin[2] = z2;\r
+\r
+ // x-axis rotation for direction vector\r
+ y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;\r
+ z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;\r
+ jointList[j].placement.direction[1] = y2;\r
+ jointList[j].placement.direction[2] = z2;\r
+\r
+ // x-axis rotation for up vector\r
+ y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;\r
+ z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;\r
+ jointList[j].placement.up[1] = y2;\r
+ jointList[j].placement.up[2] = z2;\r
+\r
+ if(curCorrespondingJoint[j+1] != -1)\r
+ {\r
+ // translate origin\r
+ jointList[j].placement.origin[0] += curTranslation[i-1][0];\r
+ jointList[j].placement.origin[1] += curTranslation[i-1][1];\r
+ jointList[j].placement.origin[2] += curTranslation[i-1][2];\r
+\r
+ // translate back to local coord\r
+ jointList[j].placement.direction[0] += curTranslation[i-1][0];\r
+ jointList[j].placement.direction[1] += curTranslation[i-1][1];\r
+ jointList[j].placement.direction[2] += curTranslation[i-1][2];\r
+\r
+ // translate back to local coord\r
+ jointList[j].placement.up[0] += curTranslation[i-1][0];\r
+ jointList[j].placement.up[1] += curTranslation[i-1][1];\r
+ jointList[j].placement.up[2] += curTranslation[i-1][2];\r
+ }\r
+ }\r
+#endif\r
+ }\r
+}\r
+\r
+void LoadModelTransform(char *fileName)\r
+{\r
+ FILE *file1;\r
+ int dot = '.';\r
+ char *dotstart;\r
+ char InputFileName[256];\r
+\r
+ dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?\r
+\r
+ if (!dotstart)\r
+ {\r
+ strcpy(InputFileName, fileName);\r
+ strcat(InputFileName, ".hrc");\r
+ if((file1 = fopen(InputFileName, "rb")) != NULL)\r
+ {\r
+ fclose(file1);\r
+\r
+ LoadHRCGlobals(InputFileName);\r
+\r
+ printf(" - assuming .HRC\n");\r
+ return;\r
+ }\r
+\r
+ Error("\n Could not open file '%s':\n"\r
+ "No HRC match.\n", fileName);\r
+ }\r
+ else\r
+ {\r
+ if((file1 = fopen(fileName, "rb")) != NULL)\r
+ {\r
+// printf("\n");\r
+ fclose(file1);\r
+ if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)\r
+ {\r
+ LoadHRCGlobals(fileName);\r
+ return;\r
+ }\r
+ }\r
+\r
+ Error("Could not open file '%s':\n",fileName);\r
+ }\r
+}\r
+\r
+void LoadModelClusters(char *fileName, int **clusterList, int *num_verts, int skelType)\r
+{\r
+ FILE *file1;\r
+ int dot = '.';\r
+ char *dotstart;\r
+ char InputFileName[256];\r
+\r
+ dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?\r
+\r
+ if (!dotstart)\r
+ {\r
+ strcpy(InputFileName, fileName);\r
+ strcat(InputFileName, ".hrc");\r
+ if((file1 = fopen(InputFileName, "rb")) != NULL)\r
+ {\r
+ fclose(file1);\r
+\r
+ LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);\r
+\r
+ printf(" - assuming .HRC\n");\r
+ return;\r
+ }\r
+\r
+ Error("\n Could not open file '%s':\n"\r
+ "No HRC match.\n", fileName);\r
+ }\r
+ else\r
+ {\r
+ if((file1 = fopen(fileName, "rb")) != NULL)\r
+ {\r
+// printf("\n");\r
+ fclose(file1);\r
+ if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)\r
+ {\r
+ LoadHRCClustered(fileName, clusterList, num_verts, skelType);\r
+ return;\r
+ }\r
+ }\r
+\r
+ Error("Could not open file '%s':\n",fileName);\r
+ }\r
+}\r
+\r
+void LoadSkeleton(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)\r
+{\r
+ FILE *file1;\r
+ int dot = '.';\r
+ char *dotstart;\r
+ char InputFileName[256];\r
+\r
+ dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?\r
+\r
+ if (!dotstart)\r
+ {\r
+ strcpy(InputFileName, fileName);\r
+ strcat(InputFileName, ".hrc");\r
+ if((file1 = fopen(InputFileName, "rb")) != NULL)\r
+ {\r
+ fclose(file1);\r
+\r
+ LoadHRCJointList(InputFileName, jointList, skelType);\r
+\r
+ printf(" - assuming .HRC\n");\r
+ return;\r
+ }\r
+\r
+ Error("\n Could not open file '%s':\n"\r
+ "No HRC.\n", fileName);\r
+ }\r
+ else\r
+ {\r
+ if((file1 = fopen(fileName, "rb")) != NULL)\r
+ {\r
+// printf("\n");\r
+ fclose(file1);\r
+ if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)\r
+ {\r
+ LoadHRCJointList(fileName, jointList, skelType);\r
+\r
+ return;\r
+ }\r
+ }\r
+\r
+ Error("Could not open file '%s':\n",fileName);\r
+ }\r
+}\r
+\r
+/*\r
+===============\r
+GrabSkeletalFrame\r
+===============\r
+*/\r
+void GrabSkeletalFrame(char *frame)\r
+{\r
+ char file1[1024];\r
+ char *framefile;\r
+ fmframe_t *fr;\r
+\r
+ framefile = FindFrameFile (frame);\r
+\r
+ sprintf (file1, "%s/%s", cdarchive, framefile);\r
+ ExpandPathAndArchive (file1);\r
+\r
+ sprintf (file1, "%s/%s",cddir, framefile);\r
+\r
+ printf ("Grabbing Skeletal Frame %s\n", file1);\r
+\r
+ fr = &g_frames[fmheader.num_frames - 1]; // last frame read in\r
+\r
+ LoadSkeleton(file1, fr->joints, g_skelModel.type);\r
+}\r
+\r
+/*\r
+===============\r
+GrabModelTransform\r
+===============\r
+*/\r
+void GrabModelTransform(char *frame)\r
+{\r
+ char file1[1024];\r
+ char *framefile;\r
+ fmframe_t *fr;\r
+\r
+ framefile = FindFrameFile (frame);\r
+\r
+ sprintf (file1, "%s/%s", cdarchive, framefile);\r
+ ExpandPathAndArchive (file1);\r
+\r
+ sprintf (file1, "%s/%s",cddir, framefile);\r
+\r
+// printf ("grabbing %s\n", file1);\r
+\r
+ fr = &g_frames[fmheader.num_frames - 1]; // last frame read in\r
+\r
+ LoadModelTransform(file1);\r
+}\r
+\r
+void Cmd_FMCluster()\r
+{\r
+ char file1[1024];\r
+\r
+ GetScriptToken (false);\r
+\r
+ printf ("---------------------\n");\r
+ sprintf (file1, "%s/%s", cdpartial, token);\r
+ printf ("%s\n", file1);\r
+\r
+ ExpandPathAndArchive (file1);\r
+\r
+ sprintf (file1, "%s/%s", cddir, token);\r
+\r
+ g_skelModel.clustered = -1;\r
+\r
+ LoadModelClusters(file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type);\r
+\r
+ g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0];\r
+\r
+ g_skelModel.clustered = true;\r
+}\r
+\r
+void Cmd_FMSkeleton()\r
+{\r
+ GetScriptToken (false);\r
+ g_skelModel.type = atoi(token);\r
+}\r
+\r
+void Cmd_FMSkeletalFrame()\r
+{\r
+ while (ScriptTokenAvailable())\r
+ {\r
+ GetScriptToken (false);\r
+ if (g_skipmodel)\r
+ {\r
+ GetScriptToken (false);\r
+ continue;\r
+ }\r
+ if (g_release || g_archive)\r
+ {\r
+ fmheader.num_frames = 1; // don't skip the writeout\r
+ GetScriptToken (false);\r
+ continue;\r
+ }\r
+\r
+ H_printf("#define FRAME_%-16s\t%i\n", token, fmheader.num_frames);\r
+\r
+ GrabModelTransform (token);\r
+ GrabFrame (token);\r
+ GrabSkeletalFrame (token);\r
+\r
+ // need to add the up and dir points to the frame bounds here\r
+ // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);\r
+ // then remove fudge in determining scale on frame write out\r
+ }\r
+}\r
+\r
+static void LoadHRCReferences(char *fileName, fmframe_t *fr)\r
+{\r
+#define MAX_STACK 64\r
+ int i, j, k;\r
+ vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK];\r
+ int curCorrespondingJoint[MAX_STACK];\r
+ int currentStack, stackSize;\r
+ double cx, sx, cy, sy, cz, sz;\r
+ double rx, ry, rz;\r
+ double x2, y2, z2;\r
+ char stripped[SKELETAL_NAME_MAX];\r
+ Placement_d_t *placement;\r
+ int refnum;\r
+\r
+ TK_OpenSource(fileName);\r
+ TK_FetchRequire(TK_HRCH);\r
+ TK_FetchRequire(TK_COLON);\r
+ TK_FetchRequire(TK_SOFTIMAGE);\r
+\r
+ if (RefPointNum <= 0)\r
+ { // There were no labels indicated in the QDT, so use the hard-coded stuff.\r
+ refnum = numReferences[g_skelModel.references];\r
+ }\r
+ else\r
+ {\r
+ refnum = RefPointNum;\r
+ }\r
+\r
+ for(k = 0; k < refnum; ++k)\r
+ {\r
+ currentStack = 0;\r
+\r
+ // Load the root to get translation and initial rotation\r
+// TK_Beyond(TK_MODEL);\r
+\r
+ while(TK_Search(TK_NAME) != TK_EOF)\r
+ {\r
+ TK_Require(TK_STRING);\r
+\r
+ StripTrailingDigits(tk_String, stripped);\r
+\r
+ if (RefPointNum == 0)\r
+ { // Hard coded refpoint labels\r
+ if(stricmp(stripped, \r
+ referenceRootNames[referenceRootNameOffsets[g_skelModel.references]+k]) == 0)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ { // labels indicated by the QDT\r
+ if(stricmp(stripped, RefPointNameList[k]) == 0)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if(tk_Token == TK_EOF)\r
+ {\r
+ if (RefPointNum == 0)\r
+ { // Hard coded refpoint labels\r
+ Error("Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]]);\r
+ }\r
+ else\r
+ { // labels indicated by the QDT\r
+ Error("Bone Chain Root: %s not found\n", RefPointNameList[k]);\r
+ }\r
+ return;\r
+ }\r
+\r
+// TK_Beyond(TK_SCALING);\r
+\r
+// ParseVec3d(curScale[currentStack]);\r
+\r
+ TK_Beyond(TK_ROTATION);\r
+\r
+ ParseRotation3d(curRotation[currentStack]);\r
+\r
+ TK_Beyond(TK_TRANSLATION);\r
+\r
+ ParseVec3d(curTranslation[currentStack]);\r
+\r
+ // account for global model translation\r
+ curTranslation[currentStack][1] += g_skelModel.translation[0];\r
+ curTranslation[currentStack][2] += g_skelModel.translation[1];\r
+ curTranslation[currentStack][0] += g_skelModel.translation[2];\r
+\r
+ curCorrespondingJoint[currentStack] = -1;\r
+\r
+// rjr - this one not needed, as there is also a stack increment 20 lines below???\r
+// ++currentStack;\r
+\r
+ // Load the joint to get orientation\r
+ TK_Beyond(TK_MODEL);\r
+\r
+// TK_Beyond(TK_SCALING);\r
+\r
+// ParseVec3d(curScale[currentStack]);\r
+\r
+ TK_Beyond(TK_ROTATION);\r
+\r
+ ParseRotation3d(curRotation[currentStack]);\r
+\r
+// TK_Beyond(TK_TRANSLATION);\r
+\r
+// ParseVec3d(curTranslation[currentStack]);\r
+\r
+ fr->references[k].placement.origin[1] = 0.0;\r
+ fr->references[k].placement.origin[2] = 0.0;\r
+ fr->references[k].placement.origin[0] = 0.0;\r
+\r
+ fr->references[k].placement.direction[1] = 20.0;\r
+ fr->references[k].placement.direction[2] = 0.0;\r
+ fr->references[k].placement.direction[0] = 0.0;\r
+\r
+ fr->references[k].placement.up[1] = 0.0;\r
+ fr->references[k].placement.up[2] = 20.0;\r
+ fr->references[k].placement.up[0] = 0.0;\r
+\r
+ curCorrespondingJoint[currentStack] = k;\r
+\r
+ ++currentStack;\r
+\r
+ stackSize = currentStack;\r
+\r
+ for(i = stackSize - 1; i >= 0; --i)\r
+ {\r
+ rx = curRotation[i][0]*ANGLE_TO_RAD;\r
+ ry = curRotation[i][1]*ANGLE_TO_RAD;\r
+ rz = curRotation[i][2]*ANGLE_TO_RAD;\r
+\r
+ cx = cos(rx);\r
+ sx = sin(rx);\r
+\r
+ cy = cos(ry);\r
+ sy = sin(ry);\r
+\r
+ cz = cos(rz);\r
+ sz = sin(rz);\r
+\r
+ for(j = i; j < stackSize; ++j)\r
+ {\r
+ if(curCorrespondingJoint[j] != -1)\r
+ {\r
+ placement = &fr->references[curCorrespondingJoint[j]].placement;\r
+\r
+ // y-axis rotation for origin\r
+ x2 = placement->origin[0]*cy+placement->origin[2]*sy;\r
+ z2 = -placement->origin[0]*sy+placement->origin[2]*cy;\r
+ placement->origin[0] = x2;\r
+ placement->origin[2] = z2;\r
+\r
+ // y-axis rotation for direction\r
+ x2 = placement->direction[0]*cy+placement->direction[2]*sy;\r
+ z2 = -placement->direction[0]*sy+placement->direction[2]*cy;\r
+ placement->direction[0] = x2;\r
+ placement->direction[2] = z2;\r
+\r
+ // y-axis rotation for up\r
+ x2 = placement->up[0]*cy+placement->up[2]*sy;\r
+ z2 = -placement->up[0]*sy+placement->up[2]*cy;\r
+ placement->up[0] = x2;\r
+ placement->up[2] = z2;\r
+\r
+ // z-axis rotation for origin\r
+ x2 = placement->origin[0]*cz-placement->origin[1]*sz;\r
+ y2 = placement->origin[0]*sz+placement->origin[1]*cz;\r
+ placement->origin[0] = x2;\r
+ placement->origin[1] = y2;\r
+\r
+ // z-axis rotation for direction\r
+ x2 = placement->direction[0]*cz-placement->direction[1]*sz;\r
+ y2 = placement->direction[0]*sz+placement->direction[1]*cz;\r
+ placement->direction[0] = x2;\r
+ placement->direction[1] = y2;\r
+\r
+ // z-axis rotation for up\r
+ x2 = placement->up[0]*cz-placement->up[1]*sz;\r
+ y2 = placement->up[0]*sz+placement->up[1]*cz;\r
+ placement->up[0] = x2;\r
+ placement->up[1] = y2;\r
+\r
+ // x-axis rotation for origin\r
+ y2 = placement->origin[1]*cx-placement->origin[2]*sx;\r
+ z2 = placement->origin[1]*sx+placement->origin[2]*cx;\r
+ placement->origin[1] = y2;\r
+ placement->origin[2] = z2;\r
+\r
+ // x-axis rotation for direction vector\r
+ y2 = placement->direction[1]*cx-placement->direction[2]*sx;\r
+ z2 = placement->direction[1]*sx+placement->direction[2]*cx;\r
+ placement->direction[1] = y2;\r
+ placement->direction[2] = z2;\r
+\r
+ // x-axis rotation for up vector\r
+ y2 = placement->up[1]*cx-placement->up[2]*sx;\r
+ z2 = placement->up[1]*sx+placement->up[2]*cx;\r
+ placement->up[1] = y2;\r
+ placement->up[2] = z2;\r
+\r
+ // translate origin\r
+ placement->origin[0] += curTranslation[i][0];\r
+ placement->origin[1] += curTranslation[i][1];\r
+ placement->origin[2] += curTranslation[i][2];\r
+\r
+ // translate back to local coord\r
+ placement->direction[0] += curTranslation[i][0];\r
+ placement->direction[1] += curTranslation[i][1];\r
+ placement->direction[2] += curTranslation[i][2];\r
+\r
+ // translate back to local coord\r
+ placement->up[0] += curTranslation[i][0];\r
+ placement->up[1] += curTranslation[i][1];\r
+ placement->up[2] += curTranslation[i][2];\r
+\r
+ }\r
+ }\r
+ }\r
+ printf("%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2]);\r
+ }\r
+ printf("\n");\r
+}\r
+\r
+void Cmd_FMReferenced()\r
+{\r
+ int i;\r
+\r
+ GetScriptToken (false);\r
+ g_skelModel.references = atoi(token);\r
+\r
+ // Guess what? Now, we now want a list of strings to look for here instead of a hard-coded list\r
+ for (i=0; i<REF_MAX_POINTS; i++)\r
+ {\r
+ if (ScriptTokenAvailable())\r
+ { // There is yet another reference point waiting.\r
+ GetScriptToken(false);\r
+ strcpy(RefPointNameList[i], token);\r
+ }\r
+ else\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ RefPointNum = i;\r
+\r
+ if (RefPointNum > 0)\r
+ {\r
+ printf("Searching for %d different reference points.\n", RefPointNum);\r
+ }\r
+ else\r
+ {\r
+ printf("Using built-in reference points.\n");\r
+ }\r
+\r
+}\r
+\r
+void LoadReferences(char *fileName, fmframe_t *fr)\r
+{\r
+ FILE *file1;\r
+ int dot = '.';\r
+ char *dotstart;\r
+ char InputFileName[256];\r
+\r
+ dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?\r
+\r
+ if (!dotstart)\r
+ {\r
+ strcpy(InputFileName, fileName);\r
+ strcat(InputFileName, ".hrc");\r
+ if((file1 = fopen(InputFileName, "rb")) != NULL)\r
+ {\r
+ fclose(file1);\r
+\r
+ LoadHRCReferences(InputFileName, fr);\r
+\r
+ printf(" - assuming .HRC\n");\r
+ return;\r
+ }\r
+\r
+ Error("\n Could not open file '%s':\n"\r
+ "No HRC.\n", fileName);\r
+ }\r
+ else\r
+ {\r
+ if((file1 = fopen(fileName, "rb")) != NULL)\r
+ {\r
+ printf("\n");\r
+ fclose(file1);\r
+ if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)\r
+ {\r
+ LoadHRCReferences(fileName, fr);\r
+\r
+ return;\r
+ }\r
+ }\r
+\r
+ Error("Could not open file '%s':\n",fileName);\r
+ }\r
+}\r
+\r
+void GrabReferencedFrame(char *frame)\r
+{\r
+ char file1[1024];\r
+ char *framefile;\r
+ fmframe_t *fr;\r
+\r
+ framefile = FindFrameFile (frame);\r
+\r
+ sprintf (file1, "%s/%s", cdarchive, framefile);\r
+ ExpandPathAndArchive (file1);\r
+\r
+ sprintf (file1, "%s/%s",cddir, framefile);\r
+\r
+ printf ("Grabbing Referenced %s\n", file1);\r
+\r
+ fr = &g_frames[fmheader.num_frames - 1]; // last frame read in\r
+\r
+ LoadReferences(file1, fr);\r
+}\r
+\r