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