00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <assert.h>
00044 #include <string.h>
00045 #include <stdio.h>
00046
00047 #include "vec3d.h"
00048 #include "QKFrame.h"
00049 #include "errorlog.h"
00050 #include "ram.h"
00051
00052 #define LINEAR_BLEND(a,b,t) ( (t)*((b)-(a)) + (a) )
00053
00054
00055 typedef struct
00056 {
00057 geTKArray_TimeType Time;
00058 geQuaternion Q;
00059 } QKeyframe;
00060
00061
00062
00063
00064 typedef struct
00065 {
00066 QKeyframe Key;
00067 } geQKFrame_Linear;
00068
00069
00070
00071 typedef struct
00072 {
00073 QKeyframe Key;
00074 } geQKFrame_Slerp;
00075
00076
00077
00078 typedef struct
00079 {
00080 QKeyframe Key;
00081 geQuaternion QuadrangleCorner;
00082 } geQKFrame_Squad;
00083
00084
00085
00086 geTKArray *GENESISCC geQKFrame_LinearCreate()
00087
00088 {
00089 return geTKArray_Create(sizeof(geQKFrame_Linear) );
00090 }
00091
00092
00093 geTKArray *GENESISCC geQKFrame_SlerpCreate()
00094
00095 {
00096 return geTKArray_Create(sizeof(geQKFrame_Slerp) );
00097 }
00098
00099 geTKArray *GENESISCC geQKFrame_SquadCreate()
00100
00101 {
00102 return geTKArray_Create(sizeof(geQKFrame_Squad) );
00103 }
00104
00105
00106 geBoolean GENESISCC geQKFrame_Insert(
00107 geTKArray **KeyList,
00108 geTKArray_TimeType Time,
00109 const geQuaternion *Q,
00110 int *Index)
00111
00112 {
00113 assert( KeyList != NULL );
00114 assert( *KeyList != NULL );
00115 assert( Q != NULL );
00116 assert( sizeof(geQKFrame_Squad) == geTKArray_ElementSize(*KeyList)
00117 || sizeof(geQKFrame_Slerp) == geTKArray_ElementSize(*KeyList)
00118 || sizeof(geQKFrame_Linear) == geTKArray_ElementSize(*KeyList) );
00119
00120 if (geTKArray_Insert(KeyList, Time, Index) == GE_FALSE)
00121 {
00122 geErrorLog_Add(ERR_QKARRAY_INSERT, NULL);
00123 return GE_FALSE;
00124 }
00125 else
00126 {
00127 QKeyframe *KF;
00128 KF = (QKeyframe *)geTKArray_Element(*KeyList,*Index);
00129 KF->Q = *Q;
00130 return GE_TRUE;
00131 }
00132 }
00133
00134 void GENESISCC geQKFrame_Query(
00135 const geTKArray *KeyList,
00136 int Index,
00137 geTKArray_TimeType *Time,
00138 geQuaternion *Q)
00139
00140 {
00141 QKeyframe *KF;
00142 assert( KeyList != NULL );
00143 assert( Time != NULL );
00144 assert( Q != NULL );
00145 assert( Index < geTKArray_NumElements(KeyList) );
00146 assert( Index >= 0 );
00147 assert( sizeof(geQKFrame_Squad) == geTKArray_ElementSize(KeyList)
00148 || sizeof(geQKFrame_Slerp) == geTKArray_ElementSize(KeyList)
00149 || sizeof(geQKFrame_Linear) == geTKArray_ElementSize(KeyList) );
00150
00151 KF = (QKeyframe *)geTKArray_Element(KeyList,Index);
00152 *Time = KF->Time;
00153 *Q = KF->Q;
00154 }
00155
00156 void GENESISCC geQKFrame_Modify(
00157 geTKArray *KeyList,
00158 int Index,
00159 const geQuaternion *Q)
00160 {
00161 QKeyframe *KF;
00162 assert( KeyList != NULL );
00163 assert( Q != NULL );
00164 assert( Index < geTKArray_NumElements(KeyList) );
00165 assert( Index >= 0 );
00166 assert( sizeof(geQKFrame_Squad) == geTKArray_ElementSize(KeyList)
00167 || sizeof(geQKFrame_Slerp) == geTKArray_ElementSize(KeyList)
00168 || sizeof(geQKFrame_Linear) == geTKArray_ElementSize(KeyList) );
00169
00170 KF = (QKeyframe *)geTKArray_Element(KeyList,Index);
00171 KF->Q = *Q;
00172 }
00173
00174
00175
00176 void GENESISCC geQKFrame_LinearInterpolation(
00177 const void *KF1,
00178 const void *KF2,
00179 geFloat T,
00180 void *Result)
00181
00182
00183
00184
00185 {
00186 geQuaternion *Q1,*Q2;
00187 geQuaternion *QNew = (geQuaternion *)Result;
00188
00189 assert( Result != NULL );
00190 assert( KF1 != NULL );
00191 assert( KF2 != NULL );
00192
00193 assert( T >= (geFloat)0.0f );
00194 assert( T <= (geFloat)1.0f );
00195
00196 if ( KF1 == KF2 )
00197 {
00198 *QNew = ((geQKFrame_Linear *)KF1)->Key.Q;
00199 return;
00200 }
00201
00202 Q1 = &( ((geQKFrame_Linear *)KF1)->Key.Q);
00203 Q2 = &( ((geQKFrame_Linear *)KF2)->Key.Q);
00204
00205 QNew->X = LINEAR_BLEND(Q1->X,Q2->X,T);
00206 QNew->Y = LINEAR_BLEND(Q1->Y,Q2->Y,T);
00207 QNew->Z = LINEAR_BLEND(Q1->Z,Q2->Z,T);
00208 QNew->W = LINEAR_BLEND(Q1->W,Q2->W,T);
00209 if (geQuaternion_Normalize(QNew)==0.0f)
00210 {
00211 geQuaternion_SetNoRotation(QNew);
00212 }
00213
00214 }
00215
00216
00217
00218 void GENESISCC geQKFrame_SlerpInterpolation(
00219 const void *KF1,
00220 const void *KF2,
00221 geFloat T,
00222 void *Result)
00223
00224
00225
00226
00227 {
00228 geQuaternion *Q1,*Q2;
00229 geQuaternion *QNew = (geQuaternion *)Result;
00230
00231 assert( Result != NULL );
00232 assert( KF1 != NULL );
00233 assert( KF2 != NULL );
00234
00235 assert( T >= (geFloat)0.0f );
00236 assert( T <= (geFloat)1.0f );
00237
00238 if ( KF1 == KF2 )
00239 {
00240 *QNew = ((geQKFrame_Slerp *)KF1)->Key.Q;
00241 return;
00242 }
00243
00244 Q1 = &( ((geQKFrame_Slerp *)KF1)->Key.Q);
00245 Q2 = &( ((geQKFrame_Slerp *)KF2)->Key.Q);
00246 geQuaternion_SlerpNotShortest(Q1,Q2,T,QNew);
00247 }
00248
00249
00250
00251
00252 void GENESISCC geQKFrame_SquadInterpolation(
00253 const void *KF1,
00254 const void *KF2,
00255 geFloat T,
00256 void *Result)
00257
00258
00259
00260
00261 {
00262 geQuaternion *Q1,*Q2;
00263 geQuaternion *QNew = (geQuaternion *)Result;
00264
00265 assert( Result != NULL );
00266 assert( KF1 != NULL );
00267 assert( KF2 != NULL );
00268
00269 assert( T >= (geFloat)0.0f );
00270 assert( T <= (geFloat)1.0f );
00271
00272 if ( KF1 == KF2 )
00273 {
00274 *QNew = ((geQKFrame_Squad *)KF1)->Key.Q;
00275 return;
00276 }
00277
00278 Q1 = &( ((geQKFrame_Squad *)KF1)->Key.Q);
00279 Q2 = &( ((geQKFrame_Squad *)KF2)->Key.Q);
00280
00281 {
00282 geQuaternion *A1,*B2;
00283 geQuaternion SL1,SL2;
00284
00285 A1 = &( ((geQKFrame_Squad *)KF1)->QuadrangleCorner);
00286 B2 = &( ((geQKFrame_Squad *)KF2)->QuadrangleCorner);
00287
00288 geQuaternion_SlerpNotShortest(Q1, Q2, T, &SL1);
00289 assert( geQuaternion_IsUnit(&SL1) == GE_TRUE);
00290 geQuaternion_SlerpNotShortest(A1, B2, T, &SL2);
00291 assert( geQuaternion_IsUnit(&SL2) == GE_TRUE);
00292 geQuaternion_SlerpNotShortest(&SL1, &SL2, (2.0f*T*(1.0f-T)), QNew);
00293 assert( geQuaternion_IsUnit(QNew) == GE_TRUE);
00294 }
00295 }
00296
00297
00298 static void GENESISCC geQKFrame_QuadrangleCorner(
00299 const geQuaternion *Q0,
00300 const geQuaternion *Q1,
00301 const geQuaternion *Q2,
00302 geQuaternion *Corner)
00303
00304
00305
00306 {
00307 geQuaternion Q1Inv,LnSum;
00308
00309 assert( Q0 != NULL );
00310 assert( Q1 != NULL );
00311 assert( Q2 != NULL );
00312 assert( Corner != NULL );
00313
00314 assert( geQuaternion_IsUnit(Q1) == GE_TRUE );
00315
00316 Q1Inv.W = Q1->W;
00317 Q1Inv.X = -Q1->X;
00318 Q1Inv.Y = -Q1->Y;
00319 Q1Inv.Z = -Q1->Z;
00320
00321 {
00322 geQuaternion Q1InvQ2, Q1InvQ0;
00323 geQuaternion Ln1,Ln2;
00324
00325 geQuaternion_Multiply(&Q1Inv,Q2,&Q1InvQ2);
00326 geQuaternion_Multiply(&Q1Inv,Q0,&Q1InvQ0);
00327 geQuaternion_Ln(&Q1InvQ0,&Ln1);
00328 geQuaternion_Ln(&Q1InvQ2,&Ln2);
00329 geQuaternion_Add(&Ln1,&Ln2,&LnSum);
00330 geQuaternion_Scale(&LnSum,-0.25f,&LnSum);
00331 }
00332
00333 geQuaternion_Exp(&LnSum,Corner);
00334 geQuaternion_Multiply(Q1,Corner,Corner);
00335 }
00336
00337 static void GENESISCC geQKFrame_ChooseBestQuat(const geQuaternion *Q0,geQuaternion *Q1)
00338
00339
00340 {
00341 geQuaternion pLessQ,pPlusQ;
00342 geFloat MagpLessQ,MagpPlusQ;
00343
00344 assert( Q0 != NULL );
00345 assert( Q1 != NULL );
00346
00347 geQuaternion_Add(Q0,Q1,&pPlusQ);
00348 geQuaternion_Subtract(Q0,Q1,&pLessQ);
00349
00350 geQuaternion_Multiply(&pPlusQ,&pPlusQ,&pPlusQ);
00351 geQuaternion_Multiply(&pLessQ,&pLessQ,&pLessQ);
00352
00353 MagpLessQ= (pLessQ.W * pLessQ.W) + (pLessQ.X * pLessQ.X)
00354 + (pLessQ.Y * pLessQ.Y) + (pLessQ.Z * pLessQ.Z);
00355
00356 MagpPlusQ= (pPlusQ.W * pPlusQ.W) + (pPlusQ.X * pPlusQ.X)
00357 + (pPlusQ.Y * pPlusQ.Y) + (pPlusQ.Z * pPlusQ.Z);
00358
00359 if (MagpLessQ >= MagpPlusQ)
00360 {
00361 Q1->X = -Q1->X;
00362 Q1->Y = -Q1->Y;
00363 Q1->Z = -Q1->Z;
00364 Q1->W = -Q1->W;
00365 }
00366 }
00367
00368
00369
00370
00371 void GENESISCC geQKFrame_SquadRecompute(
00372 int Looped,
00373 geTKArray *KeyList)
00374
00375 {
00376
00377
00378
00379
00380 int i;
00381 geQKFrame_Squad *QList=NULL;
00382 int count;
00383
00384 int Index0,Index1,Index2;
00385 assert( KeyList != NULL );
00386
00387 count = geTKArray_NumElements(KeyList);
00388
00389 if (count > 0)
00390 {
00391 QList = (geQKFrame_Squad *)geTKArray_Element(KeyList,0);
00392
00393 for (i =0; i< count-1; i++)
00394 {
00395 geQKFrame_ChooseBestQuat(&(QList[i].Key.Q),&(QList[i+1].Key.Q) );
00396 }
00397 }
00398
00399 if (count<3)
00400 {
00401 Looped = 0;
00402
00403
00404 }
00405 for (i =0; i< count; i++)
00406 {
00407 Index0 = i-1;
00408 Index1 = i;
00409 Index2 = i+1;
00410
00411 if (Index1 == 0)
00412 {
00413 if (Looped != GE_TRUE)
00414 {
00415 Index0 = 0;
00416 }
00417 else
00418 {
00419 Index0 = count-2;
00420 }
00421 }
00422
00423 if (Index2 == count)
00424 {
00425 if (Looped != GE_TRUE)
00426 {
00427 Index2 = count-1;
00428 }
00429 else
00430 {
00431 Index2 = 1;
00432 }
00433 }
00434
00435 if (( Looped != GE_TRUE) && (Index1 == 0) )
00436 {
00437 geQuaternion_Copy(
00438 &(QList[i].Key.Q),
00439 &(QList[i].QuadrangleCorner) );
00440 }
00441 else if (( Looped != GE_TRUE) && (Index1 == count-1))
00442 {
00443 geQuaternion_Copy(
00444 &(QList[i].Key.Q),
00445 &(QList[i].QuadrangleCorner) );
00446 }
00447 else
00448 {
00449 geQKFrame_QuadrangleCorner(
00450 &(QList[Index0].Key.Q),
00451 &(QList[Index1].Key.Q),
00452 &(QList[Index2].Key.Q),
00453 &(QList[i].QuadrangleCorner) );
00454
00455 }
00456 }
00457 }
00458
00459
00460
00461 void GENESISCC geQKFrame_SlerpRecompute(
00462 geTKArray *KeyList)
00463
00464
00465
00466 {
00467
00468 int i;
00469 geQKFrame_Slerp *QList;
00470 int count;
00471 assert( KeyList != NULL );
00472
00473 count = geTKArray_NumElements(KeyList);
00474
00475 if (count > 0)
00476 {
00477 QList = (geQKFrame_Slerp *)geTKArray_Element(KeyList,0);
00478 for (i =0; i< count-1; i++)
00479 {
00480 geQKFrame_ChooseBestQuat(&(QList[i].Key.Q),&(QList[i+1].Key.Q) );
00481 }
00482 }
00483 }
00484
00485
00486 #define QKFRAME_LINEAR_ASCII_FILE 0x4C464B51 // 'QKFL'
00487 #define QKFRAME_SLERP_ASCII_FILE 0x53464B51 // 'QKFS'
00488 #define QKFRAME_SQUAD_ASCII_FILE 0x51464B51 // 'QKFQ'
00489 #define CHECK_FOR_WRITE(uu) if(uu <= 0) { geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL); return GE_FALSE; }
00490 #define CHECK_FOR_READ(uu, nn) if(uu != nn) { geErrorLog_Add(ERR_PATH_FILE_READ, NULL); return GE_FALSE; }
00491
00492 #define QKFRAME_KEYLIST_ID "Keys"
00493
00494
00495
00496
00497 geBoolean GENESISCC geQKFrame_LinearRead(geVFile* pFile, void* geQKFrame)
00498 {
00499 uint32 u;
00500 char QKeyString[64];
00501 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geQKFrame;
00502
00503 assert( pFile != NULL );
00504 assert( geQKFrame != NULL );
00505
00506
00507 if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00508 {
00509 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00510 return GE_FALSE;
00511 }
00512
00513 if(u != QKFRAME_LINEAR_ASCII_FILE)
00514 {
00515 geErrorLog_Add(ERR_PATH_FILE_VERSION, NULL);
00516 return GE_FALSE;
00517 }
00518
00519 if (geVFile_GetS(pFile, QKeyString, sizeof(QKeyString)) == GE_FALSE)
00520 {
00521 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00522 return GE_FALSE;
00523 }
00524
00525 u = sscanf(QKeyString, "%f %f %f %f\n", &pLinear->Key.Q.W,
00526 &pLinear->Key.Q.X,
00527 &pLinear->Key.Q.Y,
00528 &pLinear->Key.Q.Z);
00529 CHECK_FOR_READ(u, 4);
00530
00531 return GE_TRUE;
00532 }
00533
00534 geBoolean GENESISCC geQKFrame_SlerpRead(geVFile* pFile, void* geQKFrame)
00535 {
00536 uint32 u;
00537 char QKeyString[64];
00538 geQKFrame_Slerp* pSlerp = (geQKFrame_Slerp*)geQKFrame;
00539
00540 assert( pFile != NULL );
00541 assert( geQKFrame != NULL );
00542
00543
00544 if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00545 {
00546 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00547 return GE_FALSE;
00548 }
00549
00550 if(u != QKFRAME_SLERP_ASCII_FILE)
00551 {
00552 geErrorLog_Add(ERR_PATH_FILE_VERSION, NULL);
00553 return GE_FALSE;
00554 }
00555
00556 if (geVFile_GetS(pFile, QKeyString, sizeof(QKeyString)) == GE_FALSE)
00557 {
00558 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00559 return GE_FALSE;
00560 }
00561
00562 u = sscanf(QKeyString, "%f %f %f %f\n", &pSlerp->Key.Q.W,
00563 &pSlerp->Key.Q.X,
00564 &pSlerp->Key.Q.Y,
00565 &pSlerp->Key.Q.Z);
00566 CHECK_FOR_READ(u, 4);
00567
00568 return GE_TRUE;
00569 }
00570
00571
00572 geBoolean GENESISCC geQKFrame_SquadRead(geVFile* pFile, void* geQKFrame)
00573 {
00574 uint32 u;
00575 char SQuadKeyString[128];
00576 geQKFrame_Squad* pSquad = (geQKFrame_Squad*)geQKFrame;
00577
00578 assert( pFile != NULL );
00579 assert( geQKFrame != NULL );
00580
00581
00582 if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00583 {
00584 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00585 return GE_FALSE;
00586 }
00587
00588 if(u != QKFRAME_SQUAD_ASCII_FILE)
00589 {
00590 geErrorLog_Add(ERR_PATH_FILE_VERSION, NULL);
00591 return GE_FALSE;
00592 }
00593
00594 if (geVFile_GetS(pFile, SQuadKeyString, sizeof(SQuadKeyString)) == GE_FALSE)
00595 {
00596 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00597 return GE_FALSE;
00598 }
00599
00600 u = sscanf(SQuadKeyString, "%f %f %f %f %f %f %f %f\n", &pSquad->Key.Q.W,
00601 &pSquad->Key.Q.X,
00602 &pSquad->Key.Q.Y,
00603 &pSquad->Key.Q.Z,
00604 &pSquad->QuadrangleCorner.W,
00605 &pSquad->QuadrangleCorner.X,
00606 &pSquad->QuadrangleCorner.Y,
00607 &pSquad->QuadrangleCorner.Z);
00608 CHECK_FOR_READ(u, 8);
00609
00610 return GE_TRUE;
00611 }
00612
00613
00614 #define QKFRAME_HINGE_COMPRESSION 0x1
00615 #define QKFRAME_LINEARTIME_COMPRESSION 0x2
00616
00617
00618 #define HINGE_TOLERANCE (0.0001f)
00619 #define LINEARTIME_TOLERANCE (0.0001f)
00620
00621 static geBoolean GENESISCC geQKFrame_PathIsHinged(geTKArray *KeyList, geFloat Tolerance)
00622 {
00623 int i,Count;
00624 geVec3d Axis;
00625 geVec3d NextAxis;
00626 geFloat Angle;
00627 geQKFrame_Linear* pLinear;
00628
00629 assert( KeyList != NULL );
00630
00631 Count = geTKArray_NumElements(KeyList);
00632
00633 if (Count<2)
00634 return GE_FALSE;
00635 pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, 0);
00636 if (geQuaternion_GetAxisAngle(&(pLinear->Key.Q),&Axis,&Angle)==GE_FALSE)
00637 {
00638 return GE_FALSE;
00639 }
00640
00641 for (i=1; i<Count; i++)
00642 {
00643 pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, i);
00644 if (geQuaternion_GetAxisAngle(&(pLinear->Key.Q),&NextAxis,&Angle)==GE_FALSE)
00645 {
00646 return GE_FALSE;
00647 }
00648
00649 if (geVec3d_Compare(&Axis,&NextAxis,Tolerance) == GE_FALSE)
00650 {
00651 return GE_FALSE;
00652 }
00653 }
00654 return GE_TRUE;
00655 }
00656
00657
00658 static int GENESISCC geQKFrame_DetermineCompressionType(geTKArray *KeyList)
00659 {
00660 int Compression=0;
00661 int NumElements=0;
00662
00663 assert( KeyList != NULL );
00664
00665 NumElements = geTKArray_NumElements(KeyList);
00666
00667 if (NumElements>2)
00668 {
00669 if ( geTKArray_SamplesAreTimeLinear(KeyList,LINEARTIME_TOLERANCE) != GE_FALSE )
00670 {
00671 Compression |= QKFRAME_LINEARTIME_COMPRESSION;
00672 }
00673 }
00674
00675
00676 if (NumElements>3)
00677 {
00678 if ( geQKFrame_PathIsHinged(KeyList,HINGE_TOLERANCE)!=GE_FALSE )
00679 {
00680 Compression |= QKFRAME_HINGE_COMPRESSION;
00681 }
00682 }
00683
00684 return Compression;
00685 }
00686
00687
00688
00689 geBoolean GENESISCC geQKFrame_WriteToFile(geVFile *pFile, geTKArray *KeyList,
00690 geQKFrame_InterpolationType InterpolationType, int Looping)
00691 {
00692 int NumElements,i;
00693 geFloat Time,DeltaTime;
00694 int Compression;
00695
00696 assert( pFile != NULL );
00697 assert( KeyList != NULL );
00698
00699 NumElements = geTKArray_NumElements(KeyList);
00700
00701 Compression = geQKFrame_DetermineCompressionType(KeyList);
00702
00703 if (geVFile_Printf(pFile,
00704 "%s %d %d %d %d\n",
00705 QKFRAME_KEYLIST_ID,
00706 NumElements,
00707 InterpolationType,
00708 Compression,
00709 Looping) == GE_FALSE)
00710 {
00711 geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00712 return GE_FALSE;
00713 }
00714
00715 if (Compression & QKFRAME_LINEARTIME_COMPRESSION)
00716 {
00717 Time = geTKArray_ElementTime(KeyList, 0);
00718 DeltaTime = geTKArray_ElementTime(KeyList, 1)- Time;
00719 if (geVFile_Printf(pFile,"%f %f Start T,Delta T\n",Time,DeltaTime) == GE_FALSE)
00720 {
00721 geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00722 return GE_FALSE;
00723 }
00724 }
00725
00726 switch (Compression & (~QKFRAME_LINEARTIME_COMPRESSION) )
00727 {
00728 case (0):
00729 {
00730 for(i=0;i<NumElements;i++)
00731 {
00732 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, i);
00733 if (!(Compression & QKFRAME_LINEARTIME_COMPRESSION))
00734 {
00735 Time = geTKArray_ElementTime(KeyList, i);
00736 if (geVFile_Printf(pFile, "%f ",Time) == GE_FALSE)
00737 {
00738 geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00739 return GE_FALSE;
00740 }
00741 }
00742 if (geVFile_Printf(pFile,
00743 "%f %f %f %f\n", pLinear->Key.Q.W, pLinear->Key.Q.X,
00744 pLinear->Key.Q.Y, pLinear->Key.Q.Z) == GE_FALSE)
00745 {
00746 geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00747 return GE_FALSE;
00748 }
00749 }
00750 }
00751 break;
00752 case (QKFRAME_HINGE_COMPRESSION):
00753 {
00754 geVec3d Hinge;
00755 geFloat Angle;
00756
00757 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, 0);
00758 geQuaternion_GetAxisAngle(&(pLinear->Key.Q),&Hinge,&Angle);
00759 geVec3d_Normalize(&Hinge);
00760 if (geVFile_Printf(pFile,"%f %f %f Axis\n",Hinge.X,Hinge.Y,Hinge.Z) == GE_FALSE)
00761 {
00762 geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00763 return GE_FALSE;
00764 }
00765 for(i=0;i<NumElements;i++)
00766 {
00767 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, i);
00768 if (!(Compression & QKFRAME_LINEARTIME_COMPRESSION))
00769 {
00770 Time = geTKArray_ElementTime(KeyList, i);
00771 if (geVFile_Printf(pFile, "%f ",Time) == GE_FALSE)
00772 {
00773 geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00774 return GE_FALSE;
00775 }
00776 }
00777 geQuaternion_GetAxisAngle(&(pLinear->Key.Q),&Hinge,&Angle);
00778 if (geVFile_Printf(pFile,"%f\n", Angle) == GE_FALSE)
00779 {
00780 geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00781 return GE_FALSE;
00782 }
00783 }
00784 }
00785 break;
00786 default:
00787 assert(0);
00788
00789 }
00790 return GE_TRUE;
00791 }
00792
00793
00794 geTKArray *GENESISCC geQKFrame_CreateFromFile(geVFile *pFile, int *InterpolationType, int *Looping)
00795 {
00796 int i,u,NumElements;
00797 int Compression;
00798 geFloat StartTime=0.0f;
00799 geFloat DeltaTime=0.0f;
00800
00801 #define ERROREXIT {geErrorLog_Add( ERR_PATH_FILE_READ, NULL);if (KeyList != NULL){geTKArray_Destroy(&KeyList);} return NULL;}
00802
00803 #define LINE_LENGTH 256
00804 char line[LINE_LENGTH];
00805 geTKArray *KeyList=NULL;
00806
00807 assert( pFile != NULL );
00808 assert( InterpolationType != NULL );
00809
00810 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00811 ERROREXIT;
00812 if(strnicmp(line, QKFRAME_KEYLIST_ID, sizeof(QKFRAME_KEYLIST_ID)-1) != 0)
00813 ERROREXIT;
00814
00815 if(sscanf(line + sizeof(QKFRAME_KEYLIST_ID)-1, "%d %d %d %d",
00816 &NumElements,InterpolationType,&Compression,Looping) != 4)
00817 ERROREXIT;
00818
00819 if (!( (*InterpolationType == QKFRAME_LINEAR) || (*InterpolationType == QKFRAME_SLERP) || (*InterpolationType == QKFRAME_SQUAD) ))
00820 ERROREXIT;
00821
00822 if ( Compression > 0xFF)
00823 ERROREXIT;
00824
00825
00826
00827 switch (*InterpolationType)
00828 {
00829 case (QKFRAME_LINEAR):
00830 KeyList = geTKArray_CreateEmpty(sizeof(geQKFrame_Linear),NumElements);
00831 break;
00832 case (QKFRAME_SLERP):
00833 KeyList = geTKArray_CreateEmpty(sizeof(geQKFrame_Slerp),NumElements);
00834 break;
00835 case (QKFRAME_SQUAD):
00836 KeyList = geTKArray_CreateEmpty(sizeof(geQKFrame_Squad),NumElements);
00837 break;
00838 default:
00839 ERROREXIT;
00840 }
00841 if (KeyList == NULL)
00842 ERROREXIT;
00843
00844 if (Compression & QKFRAME_LINEARTIME_COMPRESSION)
00845 {
00846 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00847 ERROREXIT;
00848 if (sscanf(line,"%f %f",&StartTime,&DeltaTime) != 2)
00849 ERROREXIT;
00850 }
00851 switch (Compression & (~QKFRAME_LINEARTIME_COMPRESSION) )
00852 {
00853 case (0):
00854 {
00855 for(i=0;i<NumElements;i++)
00856 {
00857 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, i);
00858 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00859 ERROREXIT;
00860 if (Compression & QKFRAME_LINEARTIME_COMPRESSION)
00861 {
00862 pLinear->Key.Time = StartTime + DeltaTime * i;
00863 u = sscanf(line,"%f %f %f %f", &(pLinear->Key.Q.W),
00864 &(pLinear->Key.Q.X),&(pLinear->Key.Q.Y),&(pLinear->Key.Q.Z));
00865 if (u==4) u = 5;
00866 }
00867 else
00868 {
00869 u = sscanf(line,"%f %f %f %f %f",&(pLinear->Key.Time), &(pLinear->Key.Q.W),
00870 &(pLinear->Key.Q.X),&(pLinear->Key.Q.Y),&(pLinear->Key.Q.Z));
00871 }
00872 if (u!=5)
00873 ERROREXIT;
00874 }
00875 }
00876 break;
00877 case (QKFRAME_HINGE_COMPRESSION):
00878 {
00879 geVec3d Hinge;
00880 geFloat Angle;
00881 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00882 ERROREXIT;
00883 u = sscanf(line,"%f %f %f",&(Hinge.X),&(Hinge.Y),&(Hinge.Z) );
00884 if (u != 3)
00885 ERROREXIT;
00886 for(i=0;i<NumElements;i++)
00887 {
00888 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, i);
00889 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00890 ERROREXIT;
00891 if (Compression & QKFRAME_LINEARTIME_COMPRESSION)
00892 {
00893 pLinear->Key.Time = StartTime + DeltaTime * i;
00894 u = sscanf(line,"%f", &(Angle));
00895 if (u==1) u = 2;
00896 }
00897 else
00898 {
00899 u = sscanf(line,"%f %f",&(pLinear->Key.Time), &(Angle) );
00900 }
00901 if (u!=2)
00902 ERROREXIT;
00903 geQuaternion_SetFromAxisAngle(&(pLinear->Key.Q),&Hinge,Angle);
00904 }
00905 }
00906 break;
00907 default:
00908 assert(0);
00909
00910 }
00911
00912 switch (*InterpolationType)
00913 {
00914 case (QKFRAME_LINEAR):
00915 break;
00916 case (QKFRAME_SLERP):
00917 geQKFrame_SlerpRecompute( KeyList);
00918 break;
00919 case (QKFRAME_SQUAD):
00920 geQKFrame_SquadRecompute( *Looping, KeyList);
00921 break;
00922 default:
00923 assert(0);
00924 }
00925 return KeyList;
00926
00927 }
00928
00929 uint32 GENESISCC geQKFrame_ComputeBlockSize(geTKArray *KeyList, int Compression)
00930 {
00931 uint32 Size=0;
00932 int Count;
00933 assert( KeyList != NULL );
00934 assert( Compression < 0xFF);
00935
00936 Count = geTKArray_NumElements(KeyList);
00937
00938 Size += sizeof(uint32);
00939 Size += sizeof(uint32);
00940
00941 if (Compression & QKFRAME_LINEARTIME_COMPRESSION)
00942 {
00943 Size += sizeof(geFloat) * 2;
00944 }
00945 else
00946 {
00947 Size += sizeof(geFloat) * Count;
00948 }
00949
00950 switch (Compression & (~QKFRAME_LINEARTIME_COMPRESSION) )
00951 {
00952 case 0:
00953 Size += sizeof(geQuaternion) * Count;
00954 break;
00955 case QKFRAME_HINGE_COMPRESSION:
00956 Size += (sizeof(geFloat) * 3) + sizeof(geFloat) * Count;
00957 break;
00958 default:
00959 assert(0);
00960 }
00961 return Size;
00962 }
00963
00964 geTKArray *GENESISCC geQKFrame_CreateFromBinaryFile(geVFile *pFile, int *InterpolationType, int *Looping)
00965 {
00966 uint32 u;
00967 int BlockSize;
00968 int Compression;
00969 int Count,i;
00970 int FieldSize;
00971 char *Block;
00972 geFloat *Data;
00973 geTKArray *KeyList;
00974 geQKFrame_Linear* pLinear0;
00975 geQKFrame_Linear* pLinear;
00976
00977 assert( pFile != NULL );
00978 assert( InterpolationType != NULL );
00979 assert( Looping != NULL );
00980
00981 if (geVFile_Read(pFile, &BlockSize, sizeof(int)) == GE_FALSE)
00982 {
00983 geErrorLog_AddString(-1,"Failure to read binary QKFrame header", NULL);
00984 return NULL;
00985 }
00986 if (BlockSize<0)
00987 {
00988 geErrorLog_AddString(-1,"Bad Blocksize", NULL);
00989 return NULL;
00990 }
00991
00992 Block = geRam_Allocate(BlockSize);
00993 if(geVFile_Read(pFile, Block, BlockSize) == GE_FALSE)
00994 {
00995 geErrorLog_AddString(-1,"Failure to read binary QKFrame header", NULL);
00996 return NULL;
00997 }
00998 u = *(uint32 *)Block;
00999 *InterpolationType = (u>>16)& 0xFF;
01000 Compression = (u>>8) & 0xFF;
01001 *Looping = (u & 0x1);
01002 Count = *(((uint32 *)Block)+1);
01003
01004 if (Compression > 0xFF)
01005 {
01006 geRam_Free(Block);
01007 geErrorLog_AddString(-1,"Bad Compression Flag", NULL);
01008 return NULL;
01009 }
01010 switch (*InterpolationType)
01011 {
01012 case (QKFRAME_LINEAR):
01013 FieldSize = sizeof(geQKFrame_Linear);
01014 break;
01015 case (QKFRAME_SLERP):
01016 FieldSize = sizeof(geQKFrame_Slerp);
01017 break;
01018 case (QKFRAME_SQUAD):
01019 FieldSize = sizeof(geQKFrame_Squad);
01020 break;
01021 default:
01022 geRam_Free(Block);
01023 geErrorLog_AddString(-1,"Bad InterpolationType", NULL);
01024 return NULL;
01025 }
01026
01027 KeyList = geTKArray_CreateEmpty(FieldSize,Count);
01028 if (KeyList == NULL)
01029 {
01030 geRam_Free(Block);
01031 geErrorLog_AddString(-1,"Failed to allocate tkarray", NULL);
01032 return NULL;
01033 }
01034
01035 Data = (geFloat *)(Block + sizeof(uint32)*2);
01036
01037 pLinear0 = (geQKFrame_Linear*)geTKArray_Element(KeyList, 0);
01038
01039 pLinear = pLinear0;
01040
01041 if (Compression & QKFRAME_LINEARTIME_COMPRESSION)
01042 {
01043 geFloat fi;
01044 geFloat fCount = (geFloat)Count;
01045 geFloat Time,DeltaTime;
01046 Time = *(Data++);
01047 DeltaTime = *(Data++);
01048 for(fi=0.0f;fi<fCount;fi+=1.0f)
01049 {
01050 pLinear->Key.Time = Time + fi*DeltaTime;
01051 pLinear = (geQKFrame_Linear *) ( ((char *)pLinear) + FieldSize );
01052 }
01053 }
01054 else
01055 {
01056 for(i=0;i<Count;i++)
01057 {
01058 pLinear->Key.Time = *(Data++);
01059 pLinear = (geQKFrame_Linear *) ( ((char *)pLinear) + FieldSize );
01060 }
01061 }
01062
01063 pLinear = pLinear0;
01064
01065 if (Compression & QKFRAME_HINGE_COMPRESSION)
01066 {
01067 geVec3d Hinge;
01068 Hinge.X = *(Data++);
01069 Hinge.Y = *(Data++);
01070 Hinge.Z = *(Data++);
01071
01072 for(i=0;i<Count;i++)
01073 {
01074 geQuaternion_SetFromAxisAngle(&(pLinear->Key.Q),&Hinge,*(Data++));
01075 pLinear = (geQKFrame_Linear *) ( ((char *)pLinear) + FieldSize );
01076 }
01077 }
01078 else
01079 {
01080 for(i=0;i<Count;i++)
01081 {
01082 pLinear->Key.Q = *(geQuaternion *)Data;
01083 Data += 4;
01084 pLinear = (geQKFrame_Linear *) ( ((char *)pLinear) + FieldSize );
01085 }
01086 }
01087
01088 switch (*InterpolationType)
01089 {
01090 case (QKFRAME_LINEAR):
01091 break;
01092 case (QKFRAME_SLERP):
01093 geQKFrame_SlerpRecompute( KeyList);
01094 break;
01095 case (QKFRAME_SQUAD):
01096 geQKFrame_SquadRecompute( *Looping, KeyList);
01097 break;
01098 default:
01099 assert(0);
01100 }
01101 geRam_Free(Block);
01102 return KeyList;
01103 }
01104
01105 geBoolean GENESISCC geQKFrame_WriteToBinaryFile(geVFile *pFile, geTKArray *KeyList,
01106 geQKFrame_InterpolationType InterpolationType, int Looping)
01107 {
01108 #define WBERREXIT {geErrorLog_AddString( ERR_PATH_FILE_WRITE,"Failure to write binary key data", NULL);return GE_FALSE;}
01109 uint32 u,BlockSize;
01110 int Compression;
01111 int Count,i;
01112 geFloat Time,DeltaTime;
01113 assert( pFile != NULL );
01114 assert( InterpolationType < 0xFF);
01115 assert( (Looping == 0) || (Looping == 1) );
01116
01117
01118 Compression = geQKFrame_DetermineCompressionType(KeyList);
01119 u = (InterpolationType << 16) | (Compression << 8) | Looping;
01120
01121 BlockSize = geQKFrame_ComputeBlockSize(KeyList,Compression);
01122
01123 if (geVFile_Write(pFile, &BlockSize,sizeof(uint32)) == GE_FALSE)
01124 WBERREXIT;
01125
01126 if (geVFile_Write(pFile, &u, sizeof(uint32)) == GE_FALSE)
01127 WBERREXIT;
01128
01129 Count = geTKArray_NumElements(KeyList);
01130 if (geVFile_Write(pFile, &Count, sizeof(uint32)) == GE_FALSE)
01131 WBERREXIT;
01132
01133 if (Compression & QKFRAME_LINEARTIME_COMPRESSION)
01134 {
01135 Time = geTKArray_ElementTime(KeyList, 0);
01136 DeltaTime = geTKArray_ElementTime(KeyList, 1)- Time;
01137 if (geVFile_Write(pFile, &Time,sizeof(geFloat)) == GE_FALSE)
01138 WBERREXIT;
01139 if (geVFile_Write(pFile, &DeltaTime,sizeof(geFloat)) == GE_FALSE)
01140 WBERREXIT;
01141 }
01142 else
01143 {
01144 for(i=0;i<Count;i++)
01145 {
01146 Time = geTKArray_ElementTime(KeyList, i);
01147 if (geVFile_Write(pFile, &Time,sizeof(geFloat)) == GE_FALSE)
01148 WBERREXIT;
01149 }
01150 }
01151
01152 if (Compression & QKFRAME_HINGE_COMPRESSION)
01153 {
01154 geVec3d Hinge;
01155 geFloat Angle;
01156
01157 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, 0);
01158 geQuaternion_GetAxisAngle(&(pLinear->Key.Q),&Hinge,&Angle);
01159 geVec3d_Normalize(&Hinge);
01160 if (geVFile_Write(pFile, &Hinge,sizeof(geVec3d)) == GE_FALSE)
01161 WBERREXIT;
01162
01163 for(i=0;i<Count;i++)
01164 {
01165 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, i);
01166 geQuaternion_GetAxisAngle(&(pLinear->Key.Q),&Hinge,&Angle);
01167 if (geVFile_Write(pFile, &Angle,sizeof(geFloat)) == GE_FALSE)
01168 WBERREXIT;
01169 }
01170 }
01171 else
01172 {
01173 for(i=0;i<Count;i++)
01174 {
01175 geQKFrame_Linear* pLinear = (geQKFrame_Linear*)geTKArray_Element(KeyList, i);
01176 if (geVFile_Write(pFile, &(pLinear->Key.Q),sizeof(geQuaternion)) == GE_FALSE)
01177 WBERREXIT;
01178 }
01179 }
01180
01181 return GE_TRUE;
01182 }