2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "qd_skeletons.h"
23 #include "skeletons.h"
24 #include "qd_fmodel.h"
28 #include "reference.h"
35 // We're assuming no more than 16 reference points, with no more than 32 characters in the name
36 char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
39 Skeletalfmheader_t g_skelModel;
41 void ClearSkeletalModel(){
42 g_skelModel.type = SKEL_NULL;
43 g_skelModel.clustered = false;
44 g_skelModel.references = REF_NULL;
47 //==========================================================================
51 //==========================================================================
53 // Places the null terminated src string into the dest string less any trailing digits or underscores
54 void StripTrailingDigits( char *src, char *dest ){
56 int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files
60 while ( src[i] != '\0' )
68 while ( ( src[--i] >= '0' && src[i] <= '9' ) || src[i] == '_' )
73 memcpy( dest, src, ++i );
78 static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){
79 extern void HandleHRCModel( triangle_t **triList, int *triangleCount,
80 mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth );
82 extern mesh_node_t *pmnodes;
85 // mesh_node_t *nodesList;
86 int num_mesh_nodes = 0, triangleCount = 0;
91 char stripped[SKELETAL_NAME_MAX];
93 for ( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i )
98 TK_OpenSource( fileName );
99 TK_FetchRequire( TK_HRCH );
100 TK_FetchRequire( TK_COLON );
101 TK_FetchRequire( TK_SOFTIMAGE );
103 TK_Beyond( TK_CLUSTERS );
105 while ( TK_Search( TK_CLUSTER_NAME ) != TK_EOF )
107 TK_Require( TK_STRING );
109 StripTrailingDigits( tk_String, stripped );
111 for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
113 if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) {
114 i = -i + numJointsInSkeleton[skelType] - 1;
116 TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
118 numVerts = tk_IntNumber;
120 if ( !num_verts[i + 1] ) { // first set of verts for cluster
121 clusterList[i] = SafeMalloc( numVerts * sizeof( int ), "LoadHRCClustered" );
122 assert( clusterList[i] );
124 else // any later sets of verts need to copy current
128 temp = SafeMalloc( ( num_verts[i + 1] + numVerts ) * sizeof( int ), "LoadHRCClustered" );
131 memcpy( temp + numVerts, clusterList[i], num_verts[i + 1] * sizeof( int ) );
133 free( clusterList[i] );
135 clusterList[i] = temp;
138 // currently this function is only called by LoadModelClusters.
139 // Apparently the matching free has disappeared,
140 // should probably be free at the end of FMCmd_Base
142 TK_Beyond( TK_LBRACE );
144 for ( j = 0; j < numVerts; ++j )
146 TK_Require( TK_INTNUMBER );
147 clusterList[i][j] = tk_IntNumber;
151 num_verts[i + 1] += numVerts;
158 num_verts[0] = numJointsInSkeleton[skelType];
161 #if 1 // get the index number localized to the root
162 // for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
164 // g_skelModel.num_verts[i] = 0;
167 TK_OpenSource( fileName );
168 TK_FetchRequire( TK_HRCH );
169 TK_FetchRequire( TK_COLON );
170 TK_FetchRequire( TK_SOFTIMAGE );
173 TK_Beyond( TK_MODEL );
175 triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
176 memset( triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
177 // nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
178 pmnodes = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
180 memset( pmnodes, 0, MAX_FM_MESH_NODES * sizeof( mesh_node_t ) );
182 // this should eventually use a stripped down version of this
183 HandleHRCModel( &triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0 );
188 num_verts[0] = numJointsInSkeleton[skelType];
192 void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex ){
194 tokenType_t nextToken;
195 char stripped[SKELETAL_NAME_MAX];
197 meshNode->clustered = true;
199 nextToken = TK_Get( TK_CLUSTER_NAME );
201 while ( nextToken == TK_CLUSTER_NAME )
203 TK_FetchRequire( TK_STRING );
205 StripTrailingDigits( tk_String, stripped );
207 for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i )
209 if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type] + i] ) == 0 ) {
210 i = -i + numJointsInSkeleton[g_skelModel.type] - 1;
212 TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
214 numVerts = tk_IntNumber;
217 meshNode->clusters[i] = (int *) SafeMalloc( numVerts * sizeof( int ), "ReadHRCClusterList" );
218 assert( meshNode->clusters[i] );
224 temp = meshNode->clusters[i];
225 meshNode->clusters[i] = (int *) SafeMalloc( ( meshNode->num_verts[i + 1] + numVerts ) * sizeof( int ), "ReadHRCClusterList" );
226 assert( meshNode->clusters[i] );
228 memcpy( meshNode->clusters[i], temp, meshNode->num_verts[i + 1] * sizeof( int ) );
232 // currently this function is only called by LoadModelClusters.
233 // Apparently the matching free has disappeared,
234 // should probably be free at the end of FMCmd_Base
236 TK_Beyond( TK_LBRACE );
238 for ( j = 0; j < numVerts; ++j )
240 TK_Require( TK_INTNUMBER );
241 meshNode->clusters[i][baseIndex + j] = tk_IntNumber + baseIndex;
246 meshNode->num_verts[i + 1] += numVerts;
250 meshNode->num_verts[i + 1] = numVerts;
257 TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER );
258 nextToken = TK_Fetch();
262 static void LoadHRCGlobals( char *fileName ){
265 TK_OpenSource( fileName );
266 TK_FetchRequire( TK_HRCH );
267 TK_FetchRequire( TK_COLON );
268 TK_FetchRequire( TK_SOFTIMAGE );
269 TK_Beyond( TK_MODEL );
271 TK_Beyond( TK_SCALING );
272 for ( i = 0; i < 3; i++ )
274 TK_Require( TK_FLOATNUMBER );
275 g_skelModel.scaling[i] = tk_FloatNumber;
279 TK_Beyond( TK_ROTATION );
280 for ( i = 0; i < 3; i++ )
282 TK_Require( TK_FLOATNUMBER );
283 g_skelModel.rotation[i] = tk_FloatNumber;
287 TK_Beyond( TK_TRANSLATION );
288 for ( i = 0; i < 3; i++ )
290 TK_Require( TK_FLOATNUMBER );
291 g_skelModel.translation[i] = tk_FloatNumber;
296 static void ParseVec3( vec3_t in ){
297 TK_Require( TK_FLOATNUMBER );
298 in[1] = tk_FloatNumber;
299 TK_FetchRequire( TK_FLOATNUMBER );
300 in[2] = tk_FloatNumber;
301 TK_FetchRequire( TK_FLOATNUMBER );
302 in[0] = tk_FloatNumber;
305 static void ParseVec3d( vec3d_t in ){
306 TK_Require( TK_FLOATNUMBER );
307 in[1] = tk_FloatNumber;
308 TK_FetchRequire( TK_FLOATNUMBER );
309 in[2] = tk_FloatNumber;
310 TK_FetchRequire( TK_FLOATNUMBER );
311 in[0] = tk_FloatNumber;
314 static void ParseRotation3( vec3_t in ){
315 TK_Require( TK_FLOATNUMBER );
316 in[1] = tk_FloatNumber;
317 TK_FetchRequire( TK_FLOATNUMBER );
318 in[2] = tk_FloatNumber;
319 TK_FetchRequire( TK_FLOATNUMBER );
320 in[0] = tk_FloatNumber;
323 static void ParseRotation3d( vec3d_t in ){
324 TK_Require( TK_FLOATNUMBER );
325 in[1] = tk_FloatNumber;
326 TK_FetchRequire( TK_FLOATNUMBER );
327 in[2] = tk_FloatNumber;
328 TK_FetchRequire( TK_FLOATNUMBER );
329 in[0] = tk_FloatNumber;
332 static void ParseTranslation3( vec3_t in ){
333 TK_Require( TK_FLOATNUMBER );
334 in[1] = tk_FloatNumber;
335 TK_FetchRequire( TK_FLOATNUMBER );
336 in[2] = tk_FloatNumber;
337 TK_FetchRequire( TK_FLOATNUMBER );
338 in[0] = tk_FloatNumber;
341 static void ParseTranslation3d( vec3d_t in ){
342 TK_Require( TK_FLOATNUMBER );
343 in[1] = tk_FloatNumber;
344 TK_FetchRequire( TK_FLOATNUMBER );
345 in[2] = tk_FloatNumber;
346 TK_FetchRequire( TK_FLOATNUMBER );
347 in[0] = tk_FloatNumber;
350 static void LoadHRCJointList( char *fileName, QD_SkeletalJoint_t *jointList, int skelType ){
353 vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
354 int curCorrespondingJoint[MAX_STACK];
355 int currentStack = 0, stackSize;
356 double cx, sx, cy, sy, cz, sz;
359 char stripped[SKELETAL_NAME_MAX];
360 Placement_d_t *placement;
362 TK_OpenSource( fileName );
363 TK_FetchRequire( TK_HRCH );
364 TK_FetchRequire( TK_COLON );
365 TK_FetchRequire( TK_SOFTIMAGE );
367 TK_Beyond( TK_MODEL );
369 while ( TK_Search( TK_NAME ) != TK_EOF )
371 TK_Require( TK_STRING );
373 StripTrailingDigits( tk_String, stripped );
375 if ( stricmp( stripped, skeletonRootNames[skeletonRNameOffsets[skelType]] ) == 0 ) {
380 if ( tk_Token == TK_EOF ) {
381 Error( "Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]] );
385 TK_Beyond( TK_SCALING );
387 ParseVec3d( curScale[currentStack] );
389 TK_Beyond( TK_ROTATION );
391 ParseRotation3d( curRotation[currentStack] );
393 TK_Beyond( TK_TRANSLATION );
395 ParseVec3d( curTranslation[currentStack] );
397 // account for global model translation
398 curTranslation[currentStack][1] += g_skelModel.translation[0];
399 curTranslation[currentStack][2] += g_skelModel.translation[1];
400 curTranslation[currentStack][0] += g_skelModel.translation[2];
402 curCorrespondingJoint[currentStack] = -1;
406 for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
410 TK_Beyond( TK_MODEL );
412 TK_BeyondRequire( TK_NAME, TK_STRING );
414 StripTrailingDigits( tk_String, stripped );
416 if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) {
420 TK_Beyond( TK_SCALING );
422 ParseVec3d( curScale[currentStack] );
424 TK_Beyond( TK_ROTATION );
426 ParseRotation3d( curRotation[currentStack] );
428 TK_Beyond( TK_TRANSLATION );
430 ParseVec3d( curTranslation[currentStack] );
432 curCorrespondingJoint[currentStack] = -1;
437 TK_Beyond( TK_SCALING );
439 ParseVec3d( curScale[currentStack] );
441 TK_Beyond( TK_ROTATION );
443 ParseRotation3d( curRotation[currentStack] );
445 jointList[i].rotation[1] = curRotation[currentStack][1];
446 jointList[i].rotation[2] = curRotation[currentStack][2];
447 jointList[i].rotation[0] = curRotation[currentStack][0];
449 TK_Beyond( TK_TRANSLATION );
451 ParseVec3d( curTranslation[currentStack] );
453 // jointList[i].placement.origin[1] = curTranslation[currentStack][1];
454 // jointList[i].placement.origin[2] = curTranslation[currentStack][2];
455 // jointList[i].placement.origin[0] = curTranslation[currentStack][0];
457 jointList[i].placement.origin[1] = 0.0;
458 jointList[i].placement.origin[2] = 0.0;
459 jointList[i].placement.origin[0] = 0.0;
461 jointList[i].placement.direction[1] = 20.0;
462 jointList[i].placement.direction[2] = 0.0;
463 jointList[i].placement.direction[0] = 0.0;
465 jointList[i].placement.up[1] = 0.0;
466 jointList[i].placement.up[2] = 20.0;
467 jointList[i].placement.up[0] = 0.0;
469 curCorrespondingJoint[currentStack] = i;
474 stackSize = currentStack;
477 // rotate the direction and up vectors to correspond to the rotation
478 for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
480 rx = jointList[i].rotation[0] * ANGLE_TO_RAD;
481 ry = jointList[i].rotation[1] * ANGLE_TO_RAD;
482 rz = jointList[i].rotation[2] * ANGLE_TO_RAD;
493 // y-axis rotation for direction
494 x2 = jointList[i].placement.direction[0] * cy + jointList[i].placement.direction[2] * sy;
495 z2 = -jointList[i].placement.direction[0] * sy + jointList[i].placement.direction[2] * cy;
496 jointList[i].placement.direction[0] = x2;
497 jointList[i].placement.direction[2] = z2;
499 // y-axis rotation for up
500 x2 = jointList[i].placement.up[0] * cy + jointList[i].placement.up[2] * sy;
501 z2 = -jointList[i].placement.up[0] * sy + jointList[i].placement.up[2] * cy;
502 jointList[i].placement.up[0] = x2;
503 jointList[i].placement.up[2] = z2;
505 // z-axis rotation for direction
506 x2 = jointList[i].placement.direction[0] * cz - jointList[i].placement.direction[1] * sz;
507 y2 = jointList[i].placement.direction[0] * sz + jointList[i].placement.direction[1] * cz;
508 jointList[i].placement.direction[0] = x2;
509 jointList[i].placement.direction[1] = y2;
511 // z-axis rotation for up
512 x2 = jointList[i].placement.up[0] * cz - jointList[i].placement.up[1] * sz;
513 y2 = jointList[i].placement.up[0] * sz + jointList[i].placement.up[1] * cz;
514 jointList[i].placement.up[0] = x2;
515 jointList[i].placement.up[1] = y2;
517 // x-axis rotation for direction vector
518 y2 = jointList[i].placement.direction[1] * cx - jointList[i].placement.direction[2] * sx;
519 z2 = jointList[i].placement.direction[1] * sx + jointList[i].placement.direction[2] * cx;
520 jointList[i].placement.direction[1] = y2;
521 jointList[i].placement.direction[2] = z2;
523 // x-axis rotation for up vector
524 y2 = jointList[i].placement.up[1] * cx - jointList[i].placement.up[2] * sx;
525 z2 = jointList[i].placement.up[1] * sx + jointList[i].placement.up[2] * cx;
526 jointList[i].placement.up[1] = y2;
527 jointList[i].placement.up[2] = z2;
529 // translate direction to a point in the model
530 jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
531 jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
532 jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
534 // translate up to a point in the model
535 jointList[i].placement.up[0] += jointList[i].placement.origin[0];
536 jointList[i].placement.up[1] += jointList[i].placement.origin[1];
537 jointList[i].placement.up[2] += jointList[i].placement.origin[2];
541 for ( i = stackSize - 1; i >= 0; --i )
543 rx = curRotation[i][0] * ANGLE_TO_RAD;
544 ry = curRotation[i][1] * ANGLE_TO_RAD;
545 rz = curRotation[i][2] * ANGLE_TO_RAD;
557 for ( j = i; j < stackSize; ++j )
559 if ( curCorrespondingJoint[j] != -1 ) {
560 placement = &jointList[curCorrespondingJoint[j]].placement;
562 // y-axis rotation for origin
563 x2 = placement->origin[0] * cy + placement->origin[2] * sy;
564 z2 = -placement->origin[0] * sy + placement->origin[2] * cy;
565 placement->origin[0] = x2;
566 placement->origin[2] = z2;
568 // y-axis rotation for direction
569 x2 = placement->direction[0] * cy + placement->direction[2] * sy;
570 z2 = -placement->direction[0] * sy + placement->direction[2] * cy;
571 placement->direction[0] = x2;
572 placement->direction[2] = z2;
574 // y-axis rotation for up
575 x2 = placement->up[0] * cy + placement->up[2] * sy;
576 z2 = -placement->up[0] * sy + placement->up[2] * cy;
577 placement->up[0] = x2;
578 placement->up[2] = z2;
580 // z-axis rotation for origin
581 x2 = placement->origin[0] * cz - placement->origin[1] * sz;
582 y2 = placement->origin[0] * sz + placement->origin[1] * cz;
583 placement->origin[0] = x2;
584 placement->origin[1] = y2;
586 // z-axis rotation for direction
587 x2 = placement->direction[0] * cz - placement->direction[1] * sz;
588 y2 = placement->direction[0] * sz + placement->direction[1] * cz;
589 placement->direction[0] = x2;
590 placement->direction[1] = y2;
592 // z-axis rotation for up
593 x2 = placement->up[0] * cz - placement->up[1] * sz;
594 y2 = placement->up[0] * sz + placement->up[1] * cz;
595 placement->up[0] = x2;
596 placement->up[1] = y2;
598 // x-axis rotation for origin
599 y2 = placement->origin[1] * cx - placement->origin[2] * sx;
600 z2 = placement->origin[1] * sx + placement->origin[2] * cx;
601 placement->origin[1] = y2;
602 placement->origin[2] = z2;
604 // x-axis rotation for direction vector
605 y2 = placement->direction[1] * cx - placement->direction[2] * sx;
606 z2 = placement->direction[1] * sx + placement->direction[2] * cx;
607 placement->direction[1] = y2;
608 placement->direction[2] = z2;
610 // x-axis rotation for up vector
611 y2 = placement->up[1] * cx - placement->up[2] * sx;
612 z2 = placement->up[1] * sx + placement->up[2] * cx;
613 placement->up[1] = y2;
614 placement->up[2] = z2;
617 placement->origin[0] += curTranslation[i][0];
618 placement->origin[1] += curTranslation[i][1];
619 placement->origin[2] += curTranslation[i][2];
621 // translate back to local coord
622 placement->direction[0] += curTranslation[i][0];
623 placement->direction[1] += curTranslation[i][1];
624 placement->direction[2] += curTranslation[i][2];
626 // translate back to local coord
627 placement->up[0] += curTranslation[i][0];
628 placement->up[1] += curTranslation[i][1];
629 placement->up[2] += curTranslation[i][2];
633 // This screwed up and needs to be sorted out!!!
634 // The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton
635 for ( j = i - 1; j < stackSize - 1; ++j )
637 // y-axis rotation for origin
638 x2 = jointList[j].placement.origin[0] * cy + jointList[j].placement.origin[2] * sy;
639 z2 = -jointList[j].placement.origin[0] * sy + jointList[j].placement.origin[2] * cy;
640 jointList[j].placement.origin[0] = x2;
641 jointList[j].placement.origin[2] = z2;
643 // y-axis rotation for direction
644 x2 = jointList[j].placement.direction[0] * cy + jointList[j].placement.direction[2] * sy;
645 z2 = -jointList[j].placement.direction[0] * sy + jointList[j].placement.direction[2] * cy;
646 jointList[j].placement.direction[0] = x2;
647 jointList[j].placement.direction[2] = z2;
649 // y-axis rotation for up
650 x2 = jointList[j].placement.up[0] * cy + jointList[j].placement.up[2] * sy;
651 z2 = -jointList[j].placement.up[0] * sy + jointList[j].placement.up[2] * cy;
652 jointList[j].placement.up[0] = x2;
653 jointList[j].placement.up[2] = z2;
655 // z-axis rotation for origin
656 x2 = jointList[j].placement.origin[0] * cz - jointList[j].placement.origin[1] * sz;
657 y2 = jointList[j].placement.origin[0] * sz + jointList[j].placement.origin[1] * cz;
658 jointList[j].placement.origin[0] = x2;
659 jointList[j].placement.origin[1] = y2;
661 // z-axis rotation for direction
662 x2 = jointList[j].placement.direction[0] * cz - jointList[j].placement.direction[1] * sz;
663 y2 = jointList[j].placement.direction[0] * sz + jointList[j].placement.direction[1] * cz;
664 jointList[j].placement.direction[0] = x2;
665 jointList[j].placement.direction[1] = y2;
667 // z-axis rotation for up
668 x2 = jointList[j].placement.up[0] * cz - jointList[j].placement.up[1] * sz;
669 y2 = jointList[j].placement.up[0] * sz + jointList[j].placement.up[1] * cz;
670 jointList[j].placement.up[0] = x2;
671 jointList[j].placement.up[1] = y2;
673 // x-axis rotation for origin
674 y2 = jointList[j].placement.origin[1] * cx - jointList[j].placement.origin[2] * sx;
675 z2 = jointList[j].placement.origin[1] * sx + jointList[j].placement.origin[2] * cx;
676 jointList[j].placement.origin[1] = y2;
677 jointList[j].placement.origin[2] = z2;
679 // x-axis rotation for direction vector
680 y2 = jointList[j].placement.direction[1] * cx - jointList[j].placement.direction[2] * sx;
681 z2 = jointList[j].placement.direction[1] * sx + jointList[j].placement.direction[2] * cx;
682 jointList[j].placement.direction[1] = y2;
683 jointList[j].placement.direction[2] = z2;
685 // x-axis rotation for up vector
686 y2 = jointList[j].placement.up[1] * cx - jointList[j].placement.up[2] * sx;
687 z2 = jointList[j].placement.up[1] * sx + jointList[j].placement.up[2] * cx;
688 jointList[j].placement.up[1] = y2;
689 jointList[j].placement.up[2] = z2;
691 if ( curCorrespondingJoint[j + 1] != -1 ) {
693 jointList[j].placement.origin[0] += curTranslation[i - 1][0];
694 jointList[j].placement.origin[1] += curTranslation[i - 1][1];
695 jointList[j].placement.origin[2] += curTranslation[i - 1][2];
697 // translate back to local coord
698 jointList[j].placement.direction[0] += curTranslation[i - 1][0];
699 jointList[j].placement.direction[1] += curTranslation[i - 1][1];
700 jointList[j].placement.direction[2] += curTranslation[i - 1][2];
702 // translate back to local coord
703 jointList[j].placement.up[0] += curTranslation[i - 1][0];
704 jointList[j].placement.up[1] += curTranslation[i - 1][1];
705 jointList[j].placement.up[2] += curTranslation[i - 1][2];
712 void LoadModelTransform( char *fileName ){
716 char InputFileName[256];
718 dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
721 strcpy( InputFileName, fileName );
722 strcat( InputFileName, ".hrc" );
723 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
726 LoadHRCGlobals( InputFileName );
728 printf( " - assuming .HRC\n" );
732 Error( "\n Could not open file '%s':\n"
733 "No HRC match.\n", fileName );
737 if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
740 if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
741 LoadHRCGlobals( fileName );
746 Error( "Could not open file '%s':\n",fileName );
750 void LoadModelClusters( char *fileName, int **clusterList, int *num_verts, int skelType ){
754 char InputFileName[256];
756 dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
759 strcpy( InputFileName, fileName );
760 strcat( InputFileName, ".hrc" );
761 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
764 LoadHRCClustered( InputFileName, clusterList, num_verts, skelType );
766 printf( " - assuming .HRC\n" );
770 Error( "\n Could not open file '%s':\n"
771 "No HRC match.\n", fileName );
775 if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
778 if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
779 LoadHRCClustered( fileName, clusterList, num_verts, skelType );
784 Error( "Could not open file '%s':\n",fileName );
788 void LoadSkeleton( char *fileName, QD_SkeletalJoint_t *jointList, int skelType ){
792 char InputFileName[256];
794 dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
797 strcpy( InputFileName, fileName );
798 strcat( InputFileName, ".hrc" );
799 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
802 LoadHRCJointList( InputFileName, jointList, skelType );
804 printf( " - assuming .HRC\n" );
808 Error( "\n Could not open file '%s':\n"
809 "No HRC.\n", fileName );
813 if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
816 if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
817 LoadHRCJointList( fileName, jointList, skelType );
823 Error( "Could not open file '%s':\n",fileName );
832 void GrabSkeletalFrame( char *frame ){
837 framefile = FindFrameFile( frame );
839 sprintf( file1, "%s/%s", cdarchive, framefile );
840 ExpandPathAndArchive( file1 );
842 sprintf( file1, "%s/%s",cddir, framefile );
844 printf( "Grabbing Skeletal Frame %s\n", file1 );
846 fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
848 LoadSkeleton( file1, fr->joints, g_skelModel.type );
856 void GrabModelTransform( char *frame ){
861 framefile = FindFrameFile( frame );
863 sprintf( file1, "%s/%s", cdarchive, framefile );
864 ExpandPathAndArchive( file1 );
866 sprintf( file1, "%s/%s",cddir, framefile );
868 // printf ("grabbing %s\n", file1);
870 fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
872 LoadModelTransform( file1 );
875 void Cmd_FMCluster(){
878 GetScriptToken( false );
880 printf( "---------------------\n" );
881 sprintf( file1, "%s/%s", cdpartial, token );
882 printf( "%s\n", file1 );
884 ExpandPathAndArchive( file1 );
886 sprintf( file1, "%s/%s", cddir, token );
888 g_skelModel.clustered = -1;
890 LoadModelClusters( file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type );
892 g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0];
894 g_skelModel.clustered = true;
897 void Cmd_FMSkeleton(){
898 GetScriptToken( false );
899 g_skelModel.type = atoi( token );
902 void Cmd_FMSkeletalFrame(){
903 while ( ScriptTokenAvailable() )
905 GetScriptToken( false );
907 GetScriptToken( false );
910 if ( g_release || g_archive ) {
911 fmheader.num_frames = 1; // don't skip the writeout
912 GetScriptToken( false );
916 H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames );
918 GrabModelTransform( token );
920 GrabSkeletalFrame( token );
922 // need to add the up and dir points to the frame bounds here
923 // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
924 // then remove fudge in determining scale on frame write out
928 static void LoadHRCReferences( char *fileName, fmframe_t *fr ){
931 vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK];
932 int curCorrespondingJoint[MAX_STACK];
933 int currentStack, stackSize;
934 double cx, sx, cy, sy, cz, sz;
937 char stripped[SKELETAL_NAME_MAX];
938 Placement_d_t *placement;
941 TK_OpenSource( fileName );
942 TK_FetchRequire( TK_HRCH );
943 TK_FetchRequire( TK_COLON );
944 TK_FetchRequire( TK_SOFTIMAGE );
946 if ( RefPointNum <= 0 ) { // There were no labels indicated in the QDT, so use the hard-coded stuff.
947 refnum = numReferences[g_skelModel.references];
951 refnum = RefPointNum;
954 for ( k = 0; k < refnum; ++k )
958 // Load the root to get translation and initial rotation
959 // TK_Beyond(TK_MODEL);
961 while ( TK_Search( TK_NAME ) != TK_EOF )
963 TK_Require( TK_STRING );
965 StripTrailingDigits( tk_String, stripped );
967 if ( RefPointNum == 0 ) { // Hard coded refpoint labels
968 if ( stricmp( stripped,
969 referenceRootNames[referenceRootNameOffsets[g_skelModel.references] + k] ) == 0 ) {
974 { // labels indicated by the QDT
975 if ( stricmp( stripped, RefPointNameList[k] ) == 0 ) {
981 if ( tk_Token == TK_EOF ) {
982 if ( RefPointNum == 0 ) { // Hard coded refpoint labels
983 Error( "Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]] );
986 { // labels indicated by the QDT
987 Error( "Bone Chain Root: %s not found\n", RefPointNameList[k] );
992 // TK_Beyond(TK_SCALING);
994 // ParseVec3d(curScale[currentStack]);
996 TK_Beyond( TK_ROTATION );
998 ParseRotation3d( curRotation[currentStack] );
1000 TK_Beyond( TK_TRANSLATION );
1002 ParseVec3d( curTranslation[currentStack] );
1004 // account for global model translation
1005 curTranslation[currentStack][1] += g_skelModel.translation[0];
1006 curTranslation[currentStack][2] += g_skelModel.translation[1];
1007 curTranslation[currentStack][0] += g_skelModel.translation[2];
1009 curCorrespondingJoint[currentStack] = -1;
1011 // rjr - this one not needed, as there is also a stack increment 20 lines below???
1014 // Load the joint to get orientation
1015 TK_Beyond( TK_MODEL );
1017 // TK_Beyond(TK_SCALING);
1019 // ParseVec3d(curScale[currentStack]);
1021 TK_Beyond( TK_ROTATION );
1023 ParseRotation3d( curRotation[currentStack] );
1025 // TK_Beyond(TK_TRANSLATION);
1027 // ParseVec3d(curTranslation[currentStack]);
1029 fr->references[k].placement.origin[1] = 0.0;
1030 fr->references[k].placement.origin[2] = 0.0;
1031 fr->references[k].placement.origin[0] = 0.0;
1033 fr->references[k].placement.direction[1] = 20.0;
1034 fr->references[k].placement.direction[2] = 0.0;
1035 fr->references[k].placement.direction[0] = 0.0;
1037 fr->references[k].placement.up[1] = 0.0;
1038 fr->references[k].placement.up[2] = 20.0;
1039 fr->references[k].placement.up[0] = 0.0;
1041 curCorrespondingJoint[currentStack] = k;
1045 stackSize = currentStack;
1047 for ( i = stackSize - 1; i >= 0; --i )
1049 rx = curRotation[i][0] * ANGLE_TO_RAD;
1050 ry = curRotation[i][1] * ANGLE_TO_RAD;
1051 rz = curRotation[i][2] * ANGLE_TO_RAD;
1062 for ( j = i; j < stackSize; ++j )
1064 if ( curCorrespondingJoint[j] != -1 ) {
1065 placement = &fr->references[curCorrespondingJoint[j]].placement;
1067 // y-axis rotation for origin
1068 x2 = placement->origin[0] * cy + placement->origin[2] * sy;
1069 z2 = -placement->origin[0] * sy + placement->origin[2] * cy;
1070 placement->origin[0] = x2;
1071 placement->origin[2] = z2;
1073 // y-axis rotation for direction
1074 x2 = placement->direction[0] * cy + placement->direction[2] * sy;
1075 z2 = -placement->direction[0] * sy + placement->direction[2] * cy;
1076 placement->direction[0] = x2;
1077 placement->direction[2] = z2;
1079 // y-axis rotation for up
1080 x2 = placement->up[0] * cy + placement->up[2] * sy;
1081 z2 = -placement->up[0] * sy + placement->up[2] * cy;
1082 placement->up[0] = x2;
1083 placement->up[2] = z2;
1085 // z-axis rotation for origin
1086 x2 = placement->origin[0] * cz - placement->origin[1] * sz;
1087 y2 = placement->origin[0] * sz + placement->origin[1] * cz;
1088 placement->origin[0] = x2;
1089 placement->origin[1] = y2;
1091 // z-axis rotation for direction
1092 x2 = placement->direction[0] * cz - placement->direction[1] * sz;
1093 y2 = placement->direction[0] * sz + placement->direction[1] * cz;
1094 placement->direction[0] = x2;
1095 placement->direction[1] = y2;
1097 // z-axis rotation for up
1098 x2 = placement->up[0] * cz - placement->up[1] * sz;
1099 y2 = placement->up[0] * sz + placement->up[1] * cz;
1100 placement->up[0] = x2;
1101 placement->up[1] = y2;
1103 // x-axis rotation for origin
1104 y2 = placement->origin[1] * cx - placement->origin[2] * sx;
1105 z2 = placement->origin[1] * sx + placement->origin[2] * cx;
1106 placement->origin[1] = y2;
1107 placement->origin[2] = z2;
1109 // x-axis rotation for direction vector
1110 y2 = placement->direction[1] * cx - placement->direction[2] * sx;
1111 z2 = placement->direction[1] * sx + placement->direction[2] * cx;
1112 placement->direction[1] = y2;
1113 placement->direction[2] = z2;
1115 // x-axis rotation for up vector
1116 y2 = placement->up[1] * cx - placement->up[2] * sx;
1117 z2 = placement->up[1] * sx + placement->up[2] * cx;
1118 placement->up[1] = y2;
1119 placement->up[2] = z2;
1122 placement->origin[0] += curTranslation[i][0];
1123 placement->origin[1] += curTranslation[i][1];
1124 placement->origin[2] += curTranslation[i][2];
1126 // translate back to local coord
1127 placement->direction[0] += curTranslation[i][0];
1128 placement->direction[1] += curTranslation[i][1];
1129 placement->direction[2] += curTranslation[i][2];
1131 // translate back to local coord
1132 placement->up[0] += curTranslation[i][0];
1133 placement->up[1] += curTranslation[i][1];
1134 placement->up[2] += curTranslation[i][2];
1139 printf( "%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2] );
1144 void Cmd_FMReferenced(){
1147 GetScriptToken( false );
1148 g_skelModel.references = atoi( token );
1150 // Guess what? Now, we now want a list of strings to look for here instead of a hard-coded list
1151 for ( i = 0; i < REF_MAX_POINTS; i++ )
1153 if ( ScriptTokenAvailable() ) { // There is yet another reference point waiting.
1154 GetScriptToken( false );
1155 strcpy( RefPointNameList[i], token );
1165 if ( RefPointNum > 0 ) {
1166 printf( "Searching for %d different reference points.\n", RefPointNum );
1170 printf( "Using built-in reference points.\n" );
1175 void LoadReferences( char *fileName, fmframe_t *fr ){
1179 char InputFileName[256];
1181 dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
1184 strcpy( InputFileName, fileName );
1185 strcat( InputFileName, ".hrc" );
1186 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
1189 LoadHRCReferences( InputFileName, fr );
1191 printf( " - assuming .HRC\n" );
1195 Error( "\n Could not open file '%s':\n"
1196 "No HRC.\n", fileName );
1200 if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
1203 if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
1204 LoadHRCReferences( fileName, fr );
1210 Error( "Could not open file '%s':\n",fileName );
1214 void GrabReferencedFrame( char *frame ){
1219 framefile = FindFrameFile( frame );
1221 sprintf( file1, "%s/%s", cdarchive, framefile );
1222 ExpandPathAndArchive( file1 );
1224 sprintf( file1, "%s/%s",cddir, framefile );
1226 printf( "Grabbing Referenced %s\n", file1 );
1228 fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
1230 LoadReferences( file1, fr );