00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <assert.h>
00023 #include <math.h>
00024 #include <string.h>
00025 #include <stdio.h>
00026
00027 #include "path.h"
00028 #include "Quatern.h"
00029 #include "errorlog.h"
00030 #include "ram.h"
00031 #include "tkarray.h"
00032 #include "VKFrame.h"
00033 #include "QKFrame.h"
00034 #include "vec3d.h"
00035
00036 #define min(aa,bb) (( (aa)>(bb) ) ? (bb) : (aa) )
00037 #define max(aa,bb) (( (aa)>(bb) ) ? (aa) : (bb) )
00038
00039
00040 #define gePath_TimeType geFloat
00041
00042 typedef int8 Bool8;
00043
00044 typedef void (GENESISCC *InterpolationFunction)(
00045 const void *KF1,
00046 const void *KF2,
00047 gePath_TimeType T,
00048 void *Result);
00049
00050
00051 #define FLAG_DIRTY (0x01)
00052 #define FLAG_LOOPED (0x01)
00053 #define FLAG_OTHER (0x696C6345)
00054 #define FLAG_EMPTY (0x21657370)
00055
00056 typedef struct
00057 {
00058 geTKArray *KeyList;
00059 int InterpolationType;
00060
00061 gePath_TimeType StartTime;
00062 gePath_TimeType EndTime;
00063
00064
00065 int32 LastKey1;
00066 int32 LastKey2;
00067 gePath_TimeType LastKey1Time;
00068 gePath_TimeType LastKey2Time;
00069
00070 } gePath_Channel;
00071
00072
00073 typedef struct _gePath
00074 {
00075 gePath_Channel Rotation;
00076 gePath_Channel Translation;
00077 unsigned int Dirty : 1;
00078 unsigned int Looped : 1;
00079 unsigned int RefCount:30;
00080 } gePath;
00081
00082 typedef enum
00083 {
00084 GE_PATH_VK_LINEAR,
00085 GE_PATH_VK_HERMITE,
00086 GE_PATH_VK_HERMITE_ZERO_DERIV,
00087 GE_PATH_QK_LINEAR,
00088 GE_PATH_QK_SLERP,
00089 GE_PATH_QK_SQUAD,
00090 GE_PATH_MANY_INTERPOLATORS
00091 } gePath_InterpolationType;
00092
00093 typedef struct
00094 {
00095 InterpolationFunction InterpolationTable[GE_PATH_MANY_INTERPOLATORS];
00096 int32 Flags[2];
00097 } gePath_StaticType;
00098
00099 gePath_StaticType gePath_Statics =
00100 {
00101 { geVKFrame_LinearInterpolation,
00102 geVKFrame_HermiteInterpolation,
00103 geVKFrame_HermiteInterpolation,
00104 geQKFrame_LinearInterpolation,
00105 geQKFrame_SlerpInterpolation,
00106 geQKFrame_SquadInterpolation
00107 },
00108 {FLAG_OTHER,FLAG_EMPTY}
00109 };
00110
00111
00112 static geVKFrame_InterpolationType GENESISCC gePath_PathToVKInterpolation(gePath_InterpolationType I)
00113 {
00114 switch (I)
00115 {
00116 case (GE_PATH_VK_LINEAR): return VKFRAME_LINEAR;
00117 case (GE_PATH_VK_HERMITE): return VKFRAME_HERMITE;
00118 case (GE_PATH_VK_HERMITE_ZERO_DERIV): return VKFRAME_HERMITE_ZERO_DERIV;
00119 default: assert(0);
00120 }
00121 return VKFRAME_LINEAR;
00122 }
00123
00124 static gePath_InterpolationType GENESISCC gePath_VKToPathInterpolation(geVKFrame_InterpolationType I)
00125 {
00126 switch (I)
00127 {
00128 case (VKFRAME_LINEAR): return GE_PATH_VK_LINEAR;
00129 case (VKFRAME_HERMITE): return GE_PATH_VK_HERMITE;
00130 case (VKFRAME_HERMITE_ZERO_DERIV): return GE_PATH_VK_HERMITE_ZERO_DERIV;
00131 default: assert(0);
00132 }
00133 return GE_PATH_VK_LINEAR;
00134 }
00135
00136 static geQKFrame_InterpolationType GENESISCC gePath_PathToQKInterpolation(gePath_InterpolationType I)
00137 {
00138 switch (I)
00139 {
00140 case (GE_PATH_QK_LINEAR): return QKFRAME_LINEAR;
00141 case (GE_PATH_QK_SLERP): return QKFRAME_SLERP;
00142 case (GE_PATH_QK_SQUAD): return QKFRAME_SQUAD;
00143 default: assert(0);
00144 }
00145 return QKFRAME_LINEAR;
00146 }
00147
00148 static gePath_InterpolationType GENESISCC gePath_QKToPathInterpolation(geQKFrame_InterpolationType I)
00149 {
00150 switch (I)
00151 {
00152 case (QKFRAME_LINEAR): return GE_PATH_QK_LINEAR;
00153 case (QKFRAME_SLERP): return GE_PATH_QK_SLERP;
00154 case (QKFRAME_SQUAD): return GE_PATH_QK_SQUAD;
00155 default: assert(0);
00156 }
00157 return GE_PATH_QK_LINEAR;
00158 }
00159
00160
00161 GENESISAPI void GENESISCC gePath_CreateRef( gePath *P )
00162 {
00163 assert( P != NULL );
00164 P->RefCount++;
00165 }
00166
00167 GENESISAPI gePath *GENESISCC gePath_Create(
00168 gePath_Interpolator TranslationInterpolation,
00169 gePath_Interpolator RotationInterpolation,
00170 geBoolean Looped)
00171
00172 {
00173 gePath *P;
00174
00175 P = geRam_Allocate(sizeof(gePath));
00176
00177 if ( P == NULL )
00178 {
00179 geErrorLog_Add(ERR_PATH_CREATE_ENOMEM, NULL);
00180 return NULL;
00181 }
00182
00183 P->Rotation.KeyList = NULL;
00184 P->Translation.KeyList = NULL;
00185
00186 P->RefCount = 0;
00187 P->Dirty = FLAG_DIRTY;
00188
00189 if (Looped==GE_TRUE)
00190 P->Looped = FLAG_LOOPED;
00191 else
00192 P->Looped = 0;
00193
00194
00195 switch (RotationInterpolation)
00196 {
00197 case (GE_PATH_INTERPOLATE_LINEAR):
00198 P->Rotation.InterpolationType = GE_PATH_QK_LINEAR;
00199 break;
00200 case (GE_PATH_INTERPOLATE_SLERP):
00201 P->Rotation.InterpolationType = GE_PATH_QK_SLERP;
00202 break;
00203 case (GE_PATH_INTERPOLATE_SQUAD):
00204 P->Rotation.InterpolationType = GE_PATH_QK_SQUAD;
00205 break;
00206 default:
00207 assert(0);
00208 }
00209
00210 P->Rotation.KeyList = NULL;
00211
00212 switch (TranslationInterpolation)
00213 {
00214 case (GE_PATH_INTERPOLATE_LINEAR):
00215 P->Translation.InterpolationType = GE_PATH_VK_LINEAR;
00216 break;
00217 case (GE_PATH_INTERPOLATE_HERMITE):
00218 P->Translation.InterpolationType = GE_PATH_VK_HERMITE;
00219 break;
00220 case (GE_PATH_INTERPOLATE_HERMITE_ZERO_DERIV):
00221 P->Translation.InterpolationType = GE_PATH_VK_HERMITE_ZERO_DERIV;
00222 break;
00223 default:
00224 assert(0);
00225 }
00226
00227 P->Translation.KeyList = NULL;
00228
00229 return P;
00230 }
00231
00232 static geBoolean GENESISCC gePath_SetupRotationKeyList(gePath *P)
00233 {
00234 assert( P != NULL );
00235 switch (P->Rotation.InterpolationType)
00236 {
00237 case (GE_PATH_QK_LINEAR):
00238 P->Rotation.KeyList = geQKFrame_LinearCreate();
00239 break;
00240 case (GE_PATH_QK_SLERP):
00241 P->Rotation.KeyList = geQKFrame_SlerpCreate();
00242 break;
00243 case (GE_PATH_QK_SQUAD):
00244 P->Rotation.KeyList = geQKFrame_SquadCreate();
00245 break;
00246 default:
00247 assert(0);
00248 }
00249 if (P->Rotation.KeyList == NULL)
00250 {
00251 return GE_FALSE;
00252 }
00253 return GE_TRUE;
00254 }
00255
00256 static geBoolean GENESISCC gePath_SetupTranslationKeyList(gePath *P)
00257 {
00258 assert( P != NULL );
00259 switch (P->Translation.InterpolationType)
00260 {
00261 case (GE_PATH_VK_LINEAR):
00262 P->Translation.KeyList = geVKFrame_LinearCreate();
00263 break;
00264 case (GE_PATH_VK_HERMITE):
00265 P->Translation.KeyList = geVKFrame_HermiteCreate();
00266 break;
00267 case (GE_PATH_VK_HERMITE_ZERO_DERIV):
00268 P->Translation.KeyList = geVKFrame_HermiteCreate();
00269 break;
00270 default:
00271 assert(0);
00272 }
00273 if (P->Translation.KeyList == NULL)
00274 {
00275 return GE_FALSE;
00276 }
00277 return GE_TRUE;
00278 }
00279
00280 GENESISAPI gePath *GENESISCC gePath_CreateCopy(const gePath *Src)
00281 {
00282 gePath *P;
00283 gePath_TimeType Time;
00284 geBoolean Looped;
00285
00286 int i,Count;
00287 int RInterp=0;
00288 int TInterp=0;
00289
00290 assert ( Src != NULL );
00291
00292 switch (Src->Rotation.InterpolationType)
00293 {
00294 case (GE_PATH_QK_LINEAR):
00295 RInterp = GE_PATH_INTERPOLATE_LINEAR;
00296 break;
00297 case (GE_PATH_QK_SLERP):
00298 RInterp = GE_PATH_INTERPOLATE_SLERP;
00299 break;
00300 case (GE_PATH_QK_SQUAD):
00301 RInterp = GE_PATH_INTERPOLATE_SQUAD;
00302 break;
00303 default:
00304 assert(0);
00305 }
00306
00307 switch (Src->Translation.InterpolationType)
00308 {
00309 case (GE_PATH_VK_LINEAR):
00310 TInterp = GE_PATH_INTERPOLATE_LINEAR;
00311 break;
00312 case (GE_PATH_VK_HERMITE):
00313 TInterp = GE_PATH_INTERPOLATE_HERMITE;
00314 break;
00315 case (GE_PATH_VK_HERMITE_ZERO_DERIV):
00316 TInterp = GE_PATH_INTERPOLATE_HERMITE_ZERO_DERIV;
00317 break;
00318 default:
00319 assert(0);
00320 }
00321
00322 if (Src->Looped)
00323 Looped = GE_TRUE;
00324 else
00325 Looped = GE_FALSE;
00326
00327 P = gePath_Create(TInterp, RInterp, Looped);
00328 if (P == NULL)
00329 {
00330 geErrorLog_Add(ERR_PATH_CREATE_ENOMEM, NULL);
00331 return NULL;
00332 }
00333
00334 {
00335 geVec3d V;
00336 Count = 0;
00337 if (Src->Translation.KeyList != NULL)
00338 {
00339 Count = geTKArray_NumElements(Src->Translation.KeyList);
00340 }
00341 if (Count>0)
00342 {
00343 if (gePath_SetupTranslationKeyList(P)==GE_FALSE)
00344 {
00345 geErrorLog_Add(ERR_PATH_CREATE_ENOMEM, NULL);
00346 gePath_Destroy(&P);
00347 return NULL;
00348 }
00349
00350 for (i=0; i<Count; i++)
00351 {
00352 int Index;
00353 geVKFrame_Query(Src->Translation.KeyList, i, &Time, &V);
00354 if (geVKFrame_Insert(&(P->Translation.KeyList), Time, &V,&Index) == GE_FALSE)
00355 {
00356 geErrorLog_Add(ERR_PATH_CREATE_ENOMEM, NULL);
00357 gePath_Destroy(&P);
00358 return NULL;
00359 }
00360 }
00361 }
00362 }
00363
00364 {
00365 geQuaternion Q;
00366 Count = 0;
00367 if (Src->Rotation.KeyList != NULL)
00368 {
00369 Count = geTKArray_NumElements(Src->Rotation.KeyList);
00370 }
00371 if (Count>0)
00372 {
00373 if (gePath_SetupRotationKeyList(P)==GE_FALSE)
00374 {
00375 geErrorLog_Add(ERR_PATH_CREATE_ENOMEM, NULL);
00376 gePath_Destroy(&P);
00377 return NULL;
00378 }
00379
00380 for (i=0; i<Count; i++)
00381 {
00382 int Index;
00383 geQKFrame_Query(Src->Rotation.KeyList, i, &Time, &Q);
00384 if (geQKFrame_Insert(&(P->Rotation.KeyList), Time, &Q, &Index) == GE_FALSE)
00385 {
00386 geErrorLog_Add(ERR_PATH_CREATE_ENOMEM, NULL);
00387 gePath_Destroy(&P);
00388 return NULL;
00389 }
00390 }
00391 }
00392 }
00393 return P;
00394 }
00395
00396
00397
00398 GENESISAPI void GENESISCC gePath_Destroy(gePath **PP)
00399 {
00400 gePath *P;
00401
00402 assert( PP != NULL );
00403 assert( *PP != NULL );
00404
00405 P = *PP;
00406
00407 if ( P->RefCount > 0)
00408 {
00409 P->RefCount -- ;
00410 return;
00411 }
00412 if ( P->Rotation.KeyList != NULL)
00413 {
00414 geTKArray_Destroy(&(P->Rotation.KeyList));
00415 P->Rotation.KeyList = NULL;
00416 }
00417
00418 if ( P->Translation.KeyList != NULL)
00419 {
00420 geTKArray_Destroy(&(P->Translation.KeyList));
00421 P->Translation.KeyList = NULL;
00422 }
00423
00424 geRam_Free(*PP);
00425
00426 *PP = NULL;
00427 }
00428
00429
00430 static void GENESISCC gePath_Recompute(gePath *P)
00431
00432 {
00433 geBoolean Looped;
00434 assert(P);
00435
00436 P->Dirty = 0;
00437
00438 P->Translation.LastKey1Time = 0.0f;
00439 P->Translation.LastKey2Time = -1.0f;
00440 if (P->Looped)
00441 Looped = GE_TRUE;
00442 else
00443 Looped = GE_FALSE;
00444
00445 if (P->Translation.KeyList != NULL)
00446 {
00447 if (geTKArray_NumElements(P->Translation.KeyList) > 0 )
00448 {
00449 P->Translation.StartTime = geTKArray_ElementTime(P->Translation.KeyList,0);
00450 P->Translation.EndTime = geTKArray_ElementTime(P->Translation.KeyList,
00451 geTKArray_NumElements(P->Translation.KeyList) - 1);
00452 }
00453 if(P->Translation.InterpolationType == GE_PATH_VK_HERMITE)
00454 geVKFrame_HermiteRecompute(Looped, GE_FALSE, P->Translation.KeyList);
00455 else if (P->Translation.InterpolationType == GE_PATH_VK_HERMITE_ZERO_DERIV)
00456 geVKFrame_HermiteRecompute(Looped, GE_TRUE, P->Translation.KeyList);
00457 }
00458
00459 P->Rotation.LastKey1Time = 0.0f;
00460 P->Rotation.LastKey2Time = -1.0f;
00461
00462 if (P->Rotation.KeyList != NULL)
00463 {
00464 if (geTKArray_NumElements(P->Rotation.KeyList) > 0 )
00465 {
00466 P->Rotation.StartTime = geTKArray_ElementTime(P->Rotation.KeyList,0);
00467 P->Rotation.EndTime = geTKArray_ElementTime(P->Rotation.KeyList,
00468 geTKArray_NumElements(P->Rotation.KeyList) - 1);
00469 }
00470 if (P->Rotation.InterpolationType == GE_PATH_QK_SQUAD)
00471 geQKFrame_SquadRecompute(Looped, P->Rotation.KeyList);
00472 else if (P->Rotation.InterpolationType == GE_PATH_QK_SLERP)
00473 geQKFrame_SlerpRecompute(P->Rotation.KeyList);
00474 }
00475 }
00476
00477
00478 GENESISAPI geBoolean GENESISCC gePath_InsertKeyframe(
00479 gePath *P,
00480 int ChannelMask,
00481 gePath_TimeType Time,
00482 const geXForm3d *Matrix)
00483 {
00484 int VIndex;
00485 int QIndex=0;
00486 assert( P != NULL );
00487 assert( Matrix != NULL );
00488 assert( ( ChannelMask & GE_PATH_ROTATION_CHANNEL ) ||
00489 ( ChannelMask & GE_PATH_TRANSLATION_CHANNEL ) );
00490
00491 if (ChannelMask & GE_PATH_ROTATION_CHANNEL)
00492 {
00493 geQuaternion Q;
00494 geQuaternion_FromMatrix(Matrix, &Q);
00495 geQuaternion_Normalize(&Q);
00496 if (P->Rotation.KeyList==NULL)
00497 {
00498 if (gePath_SetupRotationKeyList(P)==GE_FALSE)
00499 {
00500 geErrorLog_Add(ERR_PATH_INSERT_R_KEYFRAME, NULL);
00501 return GE_FALSE;
00502 }
00503 }
00504 if (geQKFrame_Insert(&(P->Rotation.KeyList), Time, &Q, &QIndex) == GE_FALSE)
00505 {
00506 geErrorLog_Add(ERR_PATH_INSERT_R_KEYFRAME, NULL);
00507 return GE_FALSE;
00508 }
00509 }
00510
00511
00512 if (ChannelMask & GE_PATH_TRANSLATION_CHANNEL)
00513 {
00514 geBoolean ErrorOccured = GE_FALSE;
00515 if (P->Translation.KeyList == NULL)
00516 {
00517 if (gePath_SetupTranslationKeyList(P)==GE_FALSE)
00518 {
00519 geErrorLog_Add(ERR_PATH_INSERT_R_KEYFRAME, NULL);
00520 ErrorOccured = GE_TRUE;
00521 }
00522 }
00523 if (ErrorOccured == GE_FALSE)
00524 {
00525 if (geVKFrame_Insert( &(P->Translation.KeyList), Time, &(Matrix->Translation), &VIndex) == GE_FALSE)
00526 {
00527 geErrorLog_Add(ERR_PATH_INSERT_T_KEYFRAME, NULL);
00528 ErrorOccured = GE_TRUE;
00529 }
00530 }
00531 if (ErrorOccured != GE_FALSE)
00532 {
00533 if (ChannelMask & GE_PATH_ROTATION_CHANNEL)
00534 {
00535 if (geTKArray_DeleteElement(&(P->Rotation.KeyList),QIndex)==GE_FALSE)
00536 {
00537 geErrorLog_Add(ERR_PATH_DELETE_T_KEYFRAME, NULL);
00538 }
00539 }
00540 P->Dirty = FLAG_DIRTY;
00541 return GE_FALSE;
00542 }
00543 }
00544
00545 P->Dirty = FLAG_DIRTY;
00546
00547 return GE_TRUE;
00548 }
00549
00550 GENESISAPI geBoolean GENESISCC gePath_DeleteKeyframe(
00551 gePath *P,
00552 int Index,
00553 int ChannelMask)
00554 {
00555 int ErrorOccured= 0;
00556
00557 assert( P != NULL );
00558 assert( ( ChannelMask & GE_PATH_ROTATION_CHANNEL ) ||
00559 ( ChannelMask & GE_PATH_TRANSLATION_CHANNEL ) );
00560
00561 if (ChannelMask & GE_PATH_ROTATION_CHANNEL)
00562 {
00563 if (geTKArray_DeleteElement( &(P->Rotation.KeyList), Index) == GE_FALSE)
00564 {
00565 ErrorOccured = 1;
00566 geErrorLog_Add(ERR_PATH_DELETE_R_KEYFRAME, NULL);
00567 }
00568 }
00569
00570 if (ChannelMask & GE_PATH_TRANSLATION_CHANNEL)
00571 {
00572 if (geTKArray_DeleteElement( &(P->Translation.KeyList), Index) == GE_FALSE)
00573 {
00574 ErrorOccured = 1;
00575 geErrorLog_Add(ERR_PATH_DELETE_T_KEYFRAME, NULL);
00576 }
00577 }
00578
00579 P->Dirty = FLAG_DIRTY;
00580
00581
00582 if (ErrorOccured)
00583 {
00584 return GE_FALSE;
00585 }
00586
00587 return GE_TRUE;
00588 }
00589
00590
00591 GENESISAPI void GENESISCC gePath_GetKeyframe(
00592 const gePath *P,
00593 int Index,
00594 int Channel,
00595 gePath_TimeType *Time,
00596 geXForm3d *Matrix)
00597 {
00598 assert( P != NULL );
00599 assert( Index >= 0 );
00600 assert( Time != NULL );
00601 assert( Matrix != NULL );
00602
00603 geXForm3d_SetIdentity(Matrix);
00604
00605 switch (Channel)
00606 {
00607 case (GE_PATH_ROTATION_CHANNEL):
00608 {
00609 geQuaternion Q;
00610 assert( Index < geTKArray_NumElements(P->Rotation.KeyList) );
00611 geQKFrame_Query(P->Rotation.KeyList, Index, Time, &Q);
00612 geQuaternion_ToMatrix(&Q, Matrix);
00613 }
00614 break;
00615
00616 case (GE_PATH_TRANSLATION_CHANNEL):
00617 {
00618 assert( Index < geTKArray_NumElements(P->Translation.KeyList) );
00619 geVKFrame_Query(P->Translation.KeyList, Index, Time, &(Matrix->Translation));
00620 }
00621 break;
00622
00623 default:
00624 assert(0);
00625 }
00626 }
00627
00628 GENESISAPI geBoolean GENESISCC gePath_ModifyKeyframe(
00629 gePath *P,
00630 int Index,
00631 int ChannelMask,
00632 const geXForm3d *Matrix)
00633 {
00634 assert( P != NULL );
00635 assert( Index >= 0 );
00636 assert( Matrix != NULL );
00637 assert( ( ChannelMask & GE_PATH_ROTATION_CHANNEL ) ||
00638 ( ChannelMask & GE_PATH_TRANSLATION_CHANNEL ) );
00639
00640
00641 if (ChannelMask & GE_PATH_ROTATION_CHANNEL)
00642 {
00643 geQuaternion Q;
00644 assert( Index < geTKArray_NumElements(P->Rotation.KeyList) );
00645 geQuaternion_FromMatrix(Matrix, &Q);
00646 geQuaternion_Normalize(&Q);
00647 geQKFrame_Modify(P->Rotation.KeyList, Index, &Q);
00648 }
00649
00650 if (ChannelMask & GE_PATH_TRANSLATION_CHANNEL)
00651 {
00652 assert( Index < geTKArray_NumElements(P->Translation.KeyList) );
00653 geVKFrame_Modify(P->Translation.KeyList, Index, &(Matrix->Translation));
00654 }
00655
00656 P->Dirty = FLAG_DIRTY;
00657 return GE_TRUE;
00658 }
00659
00660
00661 GENESISAPI int GENESISCC gePath_GetKeyframeCount(const gePath *P, int Channel)
00662 {
00663 assert( P != NULL );
00664
00665 switch (Channel)
00666 {
00667 case (GE_PATH_ROTATION_CHANNEL):
00668 if (P->Rotation.KeyList!=NULL)
00669 {
00670 return geTKArray_NumElements(P->Rotation.KeyList);
00671 }
00672 else
00673 {
00674 return 0;
00675 }
00676 break;
00677
00678 case (GE_PATH_TRANSLATION_CHANNEL):
00679 if (P->Translation.KeyList!=NULL)
00680 {
00681 return geTKArray_NumElements(P->Translation.KeyList);
00682 }
00683 else
00684 {
00685 return 0;
00686 }
00687 break;
00688
00689 default:
00690 assert(0);
00691 }
00692 return 0;
00693 }
00694
00695 GENESISAPI int GENESISCC gePath_GetKeyframeIndex(const gePath *P, int Channel, geFloat Time)
00696
00697 {
00698 int KeyIndex;
00699 geTKArray *Array = NULL;
00700
00701 assert ((Channel == GE_PATH_TRANSLATION_CHANNEL) ||
00702 (Channel == GE_PATH_ROTATION_CHANNEL));
00703
00704 switch (Channel)
00705 {
00706 case GE_PATH_ROTATION_CHANNEL :
00707 Array = P->Rotation.KeyList;
00708 break;
00709
00710 case GE_PATH_TRANSLATION_CHANNEL :
00711 Array = P->Translation.KeyList;
00712 break;
00713 }
00714
00715
00716 KeyIndex = geTKArray_BSearch (Array, Time);
00717 if (KeyIndex != -1)
00718 {
00719
00720
00721 if (fabs (Time - geTKArray_ElementTime (Array, KeyIndex)) > GE_TKA_TIME_TOLERANCE)
00722 {
00723 KeyIndex = -1;
00724 }
00725 }
00726
00727 return KeyIndex;
00728 }
00729
00730
00731 static gePath_TimeType GENESISCC gePath_AdjustTimeForLooping(
00732 geBoolean Looped,
00733 gePath_TimeType Time,
00734 gePath_TimeType TStart,
00735 gePath_TimeType TEnd)
00736 {
00737 if (Looped!=GE_FALSE)
00738 {
00739 if (Time < TStart)
00740 {
00741 return (gePath_TimeType)fmod(Time - TStart, TEnd - TStart) + TStart + TEnd;
00742 }
00743 else
00744 {
00745 if (Time >= TEnd)
00746 {
00747 if(TStart + GE_TKA_TIME_TOLERANCE > TEnd)
00748 return TStart;
00749
00750 return (gePath_TimeType)fmod(Time - TStart, TEnd - TStart) + TStart;
00751 }
00752 else
00753 {
00754 return Time;
00755 }
00756 }
00757 }
00758 else
00759 {
00760 return Time;
00761 }
00762 }
00763
00764
00765 static geBoolean GENESISCC gePath_SampleChannel(
00766 const gePath_Channel *Channel,
00767 geBoolean Looped,
00768 gePath_TimeType Time,
00769 void *Result)
00770
00771
00772 {
00773 int Index1,Index2;
00774 gePath_TimeType Time1, Time2;
00775 gePath_TimeType T;
00776 gePath_TimeType AdjTime;
00777 int Length;
00778
00779 assert( Channel != NULL );
00780 assert( Result != NULL );
00781
00782 if (Channel->KeyList == NULL)
00783 return GE_FALSE;
00784
00785 Length = geTKArray_NumElements( Channel->KeyList );
00786
00787 if ( Length == 0 )
00788 {
00789
00790 return GE_FALSE;
00791 }
00792
00793 AdjTime = gePath_AdjustTimeForLooping(Looped,Time,
00794 Channel->StartTime,Channel->EndTime);
00795
00796 if ( ( Channel->LastKey1Time <= AdjTime ) &&
00797 ( AdjTime < Channel->LastKey2Time ) )
00798 {
00799 Index1 = Channel->LastKey1;
00800 Index2 = Channel->LastKey2;
00801 Time1 = Channel->LastKey1Time;
00802 Time2 = Channel->LastKey2Time;
00803 }
00804 else
00805 {
00806 Index1 = geTKArray_BSearch( Channel->KeyList,
00807 AdjTime);
00808 Index2 = Index1 + 1;
00809
00810
00811 if ( Index1 < 0 )
00812 {
00813 if (Looped!=GE_FALSE)
00814 {
00815 Index1 = Length -1;
00816 }
00817 else
00818 {
00819 Index1 = 0;
00820 }
00821 }
00822 if ( Index2 >= Length )
00823 {
00824 if (Looped!=GE_FALSE)
00825 {
00826 Index2 = 0;
00827 }
00828 else
00829 {
00830 Index2 = Length - 1;
00831 }
00832 }
00833 ((gePath_Channel *)Channel)->LastKey1 = Index1;
00834 ((gePath_Channel *)Channel)->LastKey2 = Index2;
00835 Time1 = ((gePath_Channel *)Channel)->LastKey1Time = geTKArray_ElementTime(Channel->KeyList, Index1);
00836 Time2 = ((gePath_Channel *)Channel)->LastKey2Time = geTKArray_ElementTime(Channel->KeyList, Index2);
00837 }
00838
00839 if (Index1 == Index2)
00840 T=0.0f;
00841 else
00842 T = (AdjTime-Time1) / (Time2 - Time1);
00843
00844 gePath_Statics.InterpolationTable[Channel->InterpolationType](
00845 geTKArray_Element(Channel->KeyList,Index1),
00846 geTKArray_Element(Channel->KeyList,Index2),
00847 T,Result);
00848
00849 return GE_TRUE;
00850 }
00851
00852
00853 GENESISAPI void GENESISCC gePath_Sample(const gePath *P, gePath_TimeType Time, geXForm3d *Matrix)
00854 {
00855 geQuaternion Rotation;
00856 geVec3d Translation;
00857 geBoolean Looped;
00858
00859 assert( P != NULL );
00860 assert( Matrix != NULL );
00861
00862
00863 if (P->Dirty)
00864 {
00865 gePath_Recompute((gePath *)P);
00866 }
00867 if (P->Looped)
00868 Looped = GE_TRUE;
00869 else
00870 Looped = GE_FALSE;
00871
00872 if(gePath_SampleChannel(&(P->Rotation), Looped, Time, (void*)&Rotation) == GE_TRUE)
00873 {
00874 geQuaternion_ToMatrix(&Rotation, Matrix);
00875 }
00876 else
00877 {
00878 geXForm3d_SetIdentity(Matrix);
00879 }
00880
00881 if(gePath_SampleChannel(&(P->Translation), Looped, Time, (void*)&Translation) == GE_TRUE)
00882 {
00883 Matrix->Translation = Translation;
00884 }
00885 else
00886 {
00887 Matrix->Translation.X = Matrix->Translation.Y = Matrix->Translation.Z = 0.0f;
00888 }
00889
00890 }
00891
00892 void GENESISCC gePath_SampleChannels(const gePath *P, gePath_TimeType Time, geQuaternion *Rotation, geVec3d *Translation)
00893 {
00894 geBoolean Looped;
00895 assert( P != NULL );
00896 assert( Rotation != NULL );
00897 assert( Translation != NULL );
00898
00899 if (P->Dirty)
00900 {
00901 gePath_Recompute((gePath *)P);
00902 }
00903
00904 if (P->Looped)
00905 Looped = GE_TRUE;
00906 else
00907 Looped = GE_FALSE;
00908
00909 if(gePath_SampleChannel(&(P->Rotation), Looped, Time, (void*)Rotation) == GE_FALSE)
00910 {
00911 geQuaternion_SetNoRotation(Rotation);
00912 }
00913
00914 if(gePath_SampleChannel(&(P->Translation), Looped, Time, (void*)Translation) == GE_FALSE)
00915 {
00916 Translation->X = Translation->Y = Translation->Z = 0.0f;
00917 }
00918 }
00919
00920
00921 GENESISAPI geBoolean GENESISCC gePath_GetTimeExtents(const gePath *P, gePath_TimeType *StartTime, gePath_TimeType *EndTime)
00922
00923 {
00924 gePath_TimeType TransStart,TransEnd,RotStart,RotEnd;
00925
00926 int RCount,TCount;
00927 assert( P != NULL );
00928 assert( StartTime != NULL );
00929 assert( EndTime != NULL );
00930
00931
00932 if (P->Rotation.KeyList!=NULL)
00933 RCount = geTKArray_NumElements( P->Rotation.KeyList );
00934 else
00935 RCount = 0;
00936
00937 if (P->Translation.KeyList!=NULL)
00938 TCount = geTKArray_NumElements( P->Translation.KeyList );
00939 else
00940 TCount = 0;
00941
00942 if (RCount>0)
00943 {
00944 RotStart = geTKArray_ElementTime(P->Rotation.KeyList, 0);
00945 if (RCount>1)
00946 {
00947 RotEnd = geTKArray_ElementTime(P->Rotation.KeyList, RCount-1);
00948 }
00949 else
00950 {
00951 RotEnd = RotStart;
00952 }
00953 if (TCount>0)
00954 {
00955 TransStart = geTKArray_ElementTime(P->Translation.KeyList, 0);
00956 if (TCount>1)
00957 {
00958 TransEnd = geTKArray_ElementTime(P->Translation.KeyList,TCount-1);
00959 }
00960 else
00961 {
00962 TransEnd = TransStart;
00963 }
00964
00965 *StartTime = min(TransStart,RotStart);
00966 *EndTime = max(TransEnd,RotEnd);
00967 }
00968 else
00969 {
00970 *StartTime = RotStart;
00971 *EndTime = RotEnd;
00972 }
00973 }
00974 else
00975 {
00976 if (TCount>0)
00977 {
00978 *StartTime = geTKArray_ElementTime(P->Translation.KeyList, 0);
00979 if (TCount>1)
00980 {
00981 *EndTime = geTKArray_ElementTime(P->Translation.KeyList,TCount-1);
00982 }
00983 else
00984 {
00985 *EndTime = *StartTime;
00986 }
00987 }
00988 else
00989 {
00990 return GE_FALSE;
00991 }
00992 }
00993 return GE_TRUE;
00994 }
00995
00996
00997
00998
00999
01000 #define GE_PATH_BINARY_FILE_VERSION 0x1001
01001 static gePath *GENESISCC gePath_CreateFromBinaryFile(geVFile *F,uint32 Header);
01002
01003
01004 #define CHECK_FOR_WRITE(uu) if(uu <= 0) { geErrorLog_Add( ERR_PATH_FILE_WRITE , NULL); return GE_FALSE; }
01005
01006 #define GE_PATH_CHANNEL_ASCII_FILE_TYPE 0x4C4E4843 // 'CHNL'
01007 #define GE_PATH_CHANNEL_FILE_VERSION 0x00F0 // Restrict version to 16 bits
01008
01009 #define GE_PATH_CHANNEL_INTERPOLATE_ID "InterpolationType"
01010 #define GE_PATH_CHANNEL_STARTTIME_ID "StartTime"
01011 #define GE_PATH_CHANNEL_ENDTIME_ID "EndTime"
01012 #define GE_PATH_CHANNEL_KEYLIST_ID "KeyList"
01013 #define GE_PATH_CHANNEL_NUM_ASCII_IDS 4 // Keep this up to date
01014
01015 geBoolean GENESISCC gePath_ReadChannel_F0_(int ChannelMask, gePath_Channel *C, geVFile* pFile)
01016 {
01017 uint32 u, v;
01018 int NumItemsNeeded=0;
01019 int NumItemsRead = 0;
01020 #define LINE_LENGTH 256
01021 char line[LINE_LENGTH];
01022 geBoolean (GENESISCC *FrameRead)(geVFile*, void*);
01023 gePath_TimeType Time;
01024 int Interp=0;
01025 void* pElement;
01026 char VersionString[32];
01027
01028 assert( C != NULL );
01029 assert( pFile != NULL );
01030
01031
01032 if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
01033 {
01034 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01035 return GE_FALSE;
01036 }
01037
01038 if(u != GE_PATH_CHANNEL_ASCII_FILE_TYPE)
01039 {
01040 geErrorLog_Add( ERR_PATH_FILE_VERSION , NULL);
01041 return GE_FALSE;
01042 }
01043
01044
01045 if (geVFile_GetS(pFile, VersionString, sizeof(VersionString)) == GE_FALSE)
01046 {
01047 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01048 return GE_FALSE;
01049 }
01050
01051 if (sscanf(VersionString, "%X.%X\n", &u, &v) != 2)
01052 {
01053 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01054 return GE_FALSE;
01055 }
01056 v |= (u << 8);
01057 if(v >= GE_PATH_CHANNEL_FILE_VERSION)
01058 {
01059 NumItemsNeeded = GE_PATH_CHANNEL_NUM_ASCII_IDS;
01060 }
01061
01062
01063
01064 C->InterpolationType = -1;
01065
01066
01067 C->LastKey1Time = 0.0f;
01068 C->LastKey2Time = -1.0f;
01069
01070 while(NumItemsRead < NumItemsNeeded)
01071 {
01072 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
01073 {
01074 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01075 break;
01076 }
01077
01078 if(strnicmp(line, GE_PATH_CHANNEL_INTERPOLATE_ID, sizeof(GE_PATH_CHANNEL_INTERPOLATE_ID)-1) == 0)
01079 {
01080 if(sscanf(line + sizeof(GE_PATH_CHANNEL_INTERPOLATE_ID)-1, "%d", &Interp) != 1)
01081 {
01082 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01083 break;
01084 }
01085 NumItemsRead++;
01086 }
01087 else if(strnicmp(line, GE_PATH_CHANNEL_STARTTIME_ID, sizeof(GE_PATH_CHANNEL_STARTTIME_ID)-1) == 0)
01088 {
01089 if(sscanf(line + sizeof(GE_PATH_CHANNEL_STARTTIME_ID)-1, "%f", &C->StartTime) != 1)
01090 {
01091 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01092 break;
01093 }
01094 NumItemsRead++;
01095 }
01096 else if(strnicmp(line, GE_PATH_CHANNEL_ENDTIME_ID, sizeof(GE_PATH_CHANNEL_ENDTIME_ID)-1) == 0)
01097 {
01098 if(sscanf(line + sizeof(GE_PATH_CHANNEL_ENDTIME_ID)-1, "%f", &C->EndTime) != 1)
01099 {
01100 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01101 break;
01102 }
01103 NumItemsRead++;
01104 }
01105 else if(strnicmp(line, GE_PATH_CHANNEL_KEYLIST_ID, sizeof(GE_PATH_CHANNEL_KEYLIST_ID)-1) == 0)
01106 {
01107 assert(C->KeyList == NULL);
01108
01109
01110 if(sscanf(line + sizeof(GE_PATH_CHANNEL_KEYLIST_ID)-1, "%d", &v) != 1)
01111 {
01112 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01113 break;
01114 }
01115
01116 if(ChannelMask == GE_PATH_ROTATION_CHANNEL)
01117 {
01118 switch(Interp)
01119 {
01120 case GE_PATH_INTERPOLATE_LINEAR:
01121 C->KeyList = geQKFrame_LinearCreate();
01122 C->InterpolationType = GE_PATH_QK_LINEAR;
01123 FrameRead = geQKFrame_LinearRead;
01124 break;
01125
01126 case GE_PATH_INTERPOLATE_SLERP:
01127 C->KeyList = geQKFrame_SlerpCreate();
01128 C->InterpolationType = GE_PATH_QK_SLERP;
01129 FrameRead = geQKFrame_SlerpRead;
01130 break;
01131
01132 case GE_PATH_INTERPOLATE_SQUAD:
01133 C->KeyList = geQKFrame_SquadCreate();
01134 C->InterpolationType = GE_PATH_QK_SQUAD;
01135 FrameRead = geQKFrame_SquadRead;
01136 break;
01137
01138 default:
01139 geErrorLog_Add( ERR_PATH_FILE_PARSE , NULL);
01140 return GE_FALSE;
01141 }
01142 }
01143 else
01144 {
01145 assert(ChannelMask == GE_PATH_TRANSLATION_CHANNEL);
01146
01147 switch(Interp)
01148 {
01149 case GE_PATH_INTERPOLATE_LINEAR:
01150 C->KeyList = geVKFrame_LinearCreate();
01151 C->InterpolationType = GE_PATH_VK_LINEAR;
01152 FrameRead = geVKFrame_LinearRead;
01153 break;
01154
01155 case GE_PATH_INTERPOLATE_HERMITE:
01156 C->KeyList = geVKFrame_HermiteCreate();
01157 C->InterpolationType = GE_PATH_VK_HERMITE;
01158 FrameRead = geVKFrame_HermiteRead;
01159 break;
01160
01161 case GE_PATH_INTERPOLATE_HERMITE_ZERO_DERIV:
01162 C->KeyList = geVKFrame_HermiteCreate();
01163 C->InterpolationType = GE_PATH_VK_HERMITE_ZERO_DERIV;
01164 FrameRead = geVKFrame_HermiteRead;
01165 break;
01166
01167 default:
01168 geErrorLog_Add( ERR_PATH_FILE_PARSE , NULL);
01169 return GE_FALSE;
01170 }
01171 }
01172
01173 while( v > 0 )
01174 {
01175 char TimeString[32];
01176 v--;
01177
01178 if(geVFile_GetS(pFile, TimeString, sizeof(TimeString)) == GE_FALSE)
01179 {
01180 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01181 break;
01182 }
01183 if(sscanf(TimeString, "%f ", &Time) != 1)
01184 {
01185 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01186 break;
01187 }
01188
01189 {
01190 int NewlyAddedElement;
01191 if(geTKArray_Insert(&C->KeyList, Time, &NewlyAddedElement) == GE_FALSE)
01192 break;
01193 pElement = geTKArray_Element(C->KeyList, NewlyAddedElement);
01194 }
01195 if(FrameRead(pFile, pElement) == GE_FALSE)
01196 break;
01197 }
01198
01199 if( v > 0 )
01200 {
01201
01202 geErrorLog_Add( ERR_PATH_FILE_PARSE , NULL);
01203 break;
01204 }
01205
01206 NumItemsRead++;
01207 }
01208 else
01209 {
01210
01211 geErrorLog_Add( ERR_PATH_FILE_PARSE , NULL);
01212 break;
01213 }
01214 }
01215 if (NumItemsNeeded == NumItemsRead)
01216 {
01217 return GE_TRUE;
01218 }
01219 else
01220 {
01221 geErrorLog_Add( ERR_PATH_FILE_PARSE , NULL);
01222 return GE_FALSE;
01223 }
01224 }
01225
01226
01227 #define GE_PATH_ASCII_FILE_TYPE 0x48544150 // 'PATH'
01228 #define GE_PATH_FILE_VERSION0 0x00F0 // Restrict version to 16 bits
01229 #define GE_PATH_FILE_VERSION1 0x00F1 // Restrict version to 16 bits
01230 #define GE_PATH_FILE_VERSION 0x00F2 // Restrict version to 16 bits
01231
01232 #define GE_PATH_ROTATION_ID "Rotation"
01233 #define GE_PATH_TRANSLATION_ID "Translation"
01234 #define GE_PATH_LOOPED_ID "Looped"
01235 #define GE_PATH_NUM_ASCII_IDS 2 // Keep this up to date
01236
01237 #define EXIT_ERROR { gePath_Destroy(&P); geErrorLog_Add( ERR_PATH_FILE_READ , NULL); return NULL; }
01238
01239 gePath* GENESISCC gePath_CreateFromFile_F0_(geVFile* pFile)
01240 {
01241 gePath* P;
01242 int flag;
01243
01244 #define LINE_LENGTH 256
01245 char line[LINE_LENGTH];
01246
01247 assert( pFile != NULL );
01248
01249 P = gePath_Create(0, 0, GE_FALSE);
01250 if( P == NULL )
01251 {
01252 return NULL;
01253 }
01254
01255 P->Translation.InterpolationType = 0;
01256 P->Rotation.InterpolationType = 0;
01257
01258 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
01259 EXIT_ERROR
01260 if(strnicmp(line, GE_PATH_LOOPED_ID, sizeof(GE_PATH_LOOPED_ID)-1) != 0)
01261 EXIT_ERROR
01262
01263 if(sscanf(line + sizeof(GE_PATH_LOOPED_ID)-1, "%d", &flag) != 1)
01264 EXIT_ERROR
01265
01266 if (flag == GE_TRUE)
01267 {
01268 P->Looped = FLAG_LOOPED;
01269 }
01270
01271 if(!geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
01272 EXIT_ERROR
01273 if(strnicmp(line, GE_PATH_ROTATION_ID, sizeof(GE_PATH_ROTATION_ID)-1) != 0)
01274 EXIT_ERROR
01275
01276 if(sscanf(line + sizeof(GE_PATH_ROTATION_ID)-1, "%d", &flag) != 1)
01277 EXIT_ERROR
01278 if (flag!=GE_FALSE)
01279 {
01280 if(!gePath_ReadChannel_F0_(GE_PATH_ROTATION_CHANNEL, &P->Rotation, pFile))
01281 EXIT_ERROR
01282 }
01283 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
01284 EXIT_ERROR
01285 if(strnicmp(line, GE_PATH_TRANSLATION_ID, sizeof(GE_PATH_TRANSLATION_ID)-1) != 0)
01286 EXIT_ERROR
01287 if(sscanf(line + sizeof(GE_PATH_TRANSLATION_ID)-1, "%d", &flag) != 1)
01288 EXIT_ERROR
01289
01290 if (flag!=GE_FALSE)
01291 if(!gePath_ReadChannel_F0_(GE_PATH_TRANSLATION_CHANNEL, &P->Translation, pFile))
01292 EXIT_ERROR
01293
01294 P->Dirty = FLAG_DIRTY;
01295 return P;
01296 }
01297
01298 GENESISAPI gePath* GENESISCC gePath_CreateFromFile(geVFile* pFile)
01299 {
01300 uint32 u, v, flag;
01301 int Interp,Loop;
01302 gePath* P;
01303 #define LINE_LENGTH 256
01304 char line[LINE_LENGTH];
01305
01306 assert( pFile != NULL );
01307 if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
01308 {
01309 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01310 return NULL;
01311 }
01312
01313 if ( (u>>16) == GE_PATH_BINARY_FILE_VERSION)
01314 return gePath_CreateFromBinaryFile(pFile,u);
01315
01316
01317 if(u != GE_PATH_ASCII_FILE_TYPE)
01318 {
01319 geErrorLog_Add( ERR_PATH_FILE_PARSE , NULL);
01320 return NULL;
01321 }
01322
01323
01324 if (geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
01325 {
01326 geErrorLog_Add( ERR_PATH_FILE_READ , NULL);
01327 return NULL;
01328 }
01329 if (sscanf(line, "%X.%X\n", &u, &v) != 2)
01330 {
01331 geErrorLog_Add( ERR_PATH_FILE_PARSE , NULL);
01332 return NULL;
01333 }
01334 v |= (u << 8);
01335 if(v == GE_PATH_FILE_VERSION0)
01336 return gePath_CreateFromFile_F0_(pFile);
01337 if (! ((v == GE_PATH_FILE_VERSION1) || (v== GE_PATH_FILE_VERSION)) )
01338 {
01339 geErrorLog_Add( ERR_PATH_FILE_PARSE , NULL);
01340 return NULL;
01341 }
01342
01343 P = gePath_Create(0, 0, GE_FALSE);
01344 if( P == NULL )
01345 {
01346 return NULL;
01347 }
01348
01349 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
01350 EXIT_ERROR
01351 if(strnicmp(line, GE_PATH_ROTATION_ID, sizeof(GE_PATH_ROTATION_ID)-1) != 0)
01352 EXIT_ERROR
01353 if (v==GE_PATH_FILE_VERSION1)
01354 {
01355 P->Rotation.InterpolationType = 0;
01356 if(sscanf(line + sizeof(GE_PATH_ROTATION_ID)-1, "%d", &flag) != 1)
01357 EXIT_ERROR
01358 }
01359 else
01360 {
01361 if (v==GE_PATH_FILE_VERSION)
01362 {
01363 if(sscanf(line + sizeof(GE_PATH_ROTATION_ID)-1, "%d %d", &flag, &(P->Rotation.InterpolationType)) != 2)
01364 EXIT_ERROR
01365 }
01366 else
01367 EXIT_ERROR
01368 }
01369 if (flag!=GE_FALSE)
01370 {
01371 P->Rotation.KeyList = geQKFrame_CreateFromFile(pFile,&Interp,&Loop);
01372 if (P->Rotation.KeyList == NULL)
01373 EXIT_ERROR
01374 P->Rotation.InterpolationType = gePath_QKToPathInterpolation(Interp);
01375 if (Loop)
01376 P->Looped = FLAG_LOOPED;
01377 }
01378
01379 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
01380 EXIT_ERROR
01381 if(strnicmp(line, GE_PATH_TRANSLATION_ID, sizeof(GE_PATH_TRANSLATION_ID)-1) != 0)
01382 EXIT_ERROR
01383 if (v==GE_PATH_FILE_VERSION1)
01384 {
01385 P->Translation.InterpolationType = 0;
01386 if(sscanf(line + sizeof(GE_PATH_TRANSLATION_ID)-1, "%d", &flag) != 1)
01387 EXIT_ERROR
01388 }
01389 else
01390 {
01391 if (v==GE_PATH_FILE_VERSION)
01392 {
01393 if(sscanf(line + sizeof(GE_PATH_TRANSLATION_ID)-1, "%d %d", &flag, &(P->Translation.InterpolationType)) != 2)
01394 EXIT_ERROR
01395 }
01396 else
01397 EXIT_ERROR
01398 }
01399
01400 if (flag!=GE_FALSE)
01401 {
01402 P->Translation.KeyList = geVKFrame_CreateFromFile(pFile,&Interp,&Loop);
01403 if (P->Translation.KeyList == NULL)
01404 EXIT_ERROR
01405 P->Translation.InterpolationType = gePath_VKToPathInterpolation(Interp);
01406 if (Loop)
01407 P->Looped = FLAG_LOOPED;
01408 }
01409
01410 P->Dirty = FLAG_DIRTY;
01411 return P;
01412 }
01413
01414 GENESISAPI geBoolean GENESISCC gePath_WriteToFile(const gePath *P,geVFile *pFile)
01415 {
01416 uint32 u;
01417 int Looped=0;
01418
01419 assert( P != NULL );
01420 assert( pFile != NULL );
01421
01422 if (P->Dirty)
01423 gePath_Recompute((gePath *)P);
01424
01425
01426 u = GE_PATH_ASCII_FILE_TYPE;
01427 if(geVFile_Write(pFile, &u,sizeof(u)) == GE_FALSE)
01428 {
01429 geErrorLog_Add( ERR_PATH_FILE_WRITE , NULL);
01430 return GE_FALSE;
01431 }
01432
01433
01434 if (geVFile_Printf(pFile, " %X.%.2X\n", (GE_PATH_FILE_VERSION & 0xFF00) >> 8,
01435 GE_PATH_FILE_VERSION & 0x00FF) == GE_FALSE)
01436 {
01437 geErrorLog_Add( ERR_PATH_FILE_WRITE , NULL);
01438 return GE_FALSE;
01439 }
01440
01441 {
01442 int flag;
01443 flag = GE_FALSE;
01444
01445 if (P->Rotation.KeyList != NULL)
01446 {
01447 if (geTKArray_NumElements(P->Rotation.KeyList)>0)
01448 {
01449 flag = GE_TRUE;
01450 }
01451 }
01452 if (geVFile_Printf(pFile,
01453 "%s %d %d\n",
01454 GE_PATH_ROTATION_ID,
01455 flag,
01456 P->Rotation.InterpolationType) == GE_FALSE)
01457 {
01458 geErrorLog_Add( ERR_PATH_FILE_WRITE , NULL);
01459 return GE_FALSE;
01460 }
01461
01462 if (P->Looped)
01463 Looped = 1;
01464
01465 if (flag!=GE_FALSE)
01466 if (geQKFrame_WriteToFile( pFile, P->Rotation.KeyList,
01467 gePath_PathToQKInterpolation(P->Rotation.InterpolationType),
01468 Looped)==GE_FALSE)
01469 {
01470 return GE_FALSE;
01471 }
01472
01473 flag = GE_FALSE;
01474 if (P->Translation.KeyList != NULL)
01475 {
01476 if (geTKArray_NumElements(P->Translation.KeyList)>0)
01477 {
01478 flag = GE_TRUE;
01479 }
01480 }
01481 if (geVFile_Printf(pFile,
01482 "%s %d %d\n",
01483 GE_PATH_TRANSLATION_ID,
01484 flag,
01485 P->Translation.InterpolationType) == GE_FALSE)
01486 {
01487 geErrorLog_Add( ERR_PATH_FILE_WRITE , NULL);
01488 return GE_FALSE;
01489 }
01490
01491 if (flag!=GE_FALSE)
01492 if (geVKFrame_WriteToFile( pFile, P->Translation.KeyList,
01493 gePath_PathToVKInterpolation(P->Translation.InterpolationType),
01494 Looped)==GE_FALSE)
01495 {
01496 return GE_FALSE;
01497 }
01498 }
01499
01500
01501 return GE_TRUE;
01502 }
01503
01504
01505
01506
01507
01508
01509
01510 #define GE_PATH_MAX_INT_TYPE_COUNT (127) // 7 bits
01511 #define GE_PATH_TRANS_SHIFT_INTO_HEADER (9) // 7 bits shifted into bits 9..15
01512 #define GE_PATH_ROT_SHIFT_INTO_HEADER (2) // 7 bits shifted into bits 2..8
01513
01514 GENESISAPI geBoolean GENESISCC gePath_WriteToBinaryFile(const gePath *P, geVFile *F)
01515 {
01516 uint32 Header;
01517 int R,T,Looped;
01518
01519 assert( F != NULL );
01520 assert( P != NULL );
01521 assert( GE_PATH_BINARY_FILE_VERSION < 0xFFFF );
01522
01523 R=T=0;
01524
01525 if (P->Rotation.KeyList != NULL)
01526 {
01527 if (geTKArray_NumElements(P->Rotation.KeyList)>0)
01528 {
01529 R = GE_TRUE;
01530 }
01531 }
01532
01533 if (P->Translation.KeyList != NULL)
01534 {
01535 if (geTKArray_NumElements(P->Translation.KeyList)>0)
01536 {
01537 T = GE_TRUE;
01538 }
01539 }
01540
01541 if (P->Looped)
01542 Looped = 1;
01543 else
01544 Looped = 0;
01545 assert( P->Translation.InterpolationType <= GE_PATH_MAX_INT_TYPE_COUNT);
01546 assert( P->Rotation.InterpolationType <= GE_PATH_MAX_INT_TYPE_COUNT);
01547
01548 Header =
01549 (GE_PATH_BINARY_FILE_VERSION << 16) |
01550 (T<<1) |
01551 (R) |
01552 (P->Translation.InterpolationType << GE_PATH_TRANS_SHIFT_INTO_HEADER) |
01553 (P->Rotation.InterpolationType << GE_PATH_ROT_SHIFT_INTO_HEADER );
01554
01555 if (geVFile_Write(F, &Header,sizeof(uint32)) == GE_FALSE)
01556 {
01557 geErrorLog_AddString( -1 ,"Failure to write Path Binary File Header", NULL);
01558 return GE_FALSE;
01559 }
01560
01561 if (T==1)
01562 {
01563 if (geVKFrame_WriteToBinaryFile( F, P->Translation.KeyList,
01564 gePath_PathToVKInterpolation(P->Translation.InterpolationType),
01565 Looped)==GE_FALSE)
01566 {
01567 geErrorLog_AddString( -1 ,"Failure to write Path data", NULL);
01568 return GE_FALSE;
01569 }
01570 }
01571 if (R==1)
01572 {
01573 if (geQKFrame_WriteToBinaryFile( F, P->Rotation.KeyList,
01574 gePath_PathToQKInterpolation(P->Rotation.InterpolationType),
01575 Looped)==GE_FALSE)
01576 {
01577 geErrorLog_AddString( -1 ,"Failure to write Path data", NULL);
01578 return GE_FALSE;
01579 }
01580 }
01581
01582 return GE_TRUE;
01583 }
01584
01585
01586
01587 static gePath * GENESISCC gePath_CreateFromBinaryFile(geVFile *F,uint32 Header)
01588 {
01589 gePath *P;
01590 int Interp,Looping;
01591
01592 assert( F != NULL );
01593
01594 if ((Header>>16) != GE_PATH_BINARY_FILE_VERSION)
01595 {
01596 geErrorLog_AddString( -1, "Bad path binary file version" , NULL);
01597 return NULL;
01598 }
01599
01600 P = geRam_Allocate(sizeof(gePath));
01601 P->Translation.KeyList = NULL;
01602 P->Rotation.KeyList = NULL;
01603 if (P == NULL)
01604 {
01605 geErrorLog_AddString( -1, "Failure to allocate memory for path" , NULL);
01606 return NULL;
01607 }
01608
01609 P->Translation.InterpolationType = (Header >> GE_PATH_TRANS_SHIFT_INTO_HEADER) & GE_PATH_MAX_INT_TYPE_COUNT;
01610 P->Rotation.InterpolationType = (Header >> GE_PATH_ROT_SHIFT_INTO_HEADER) & GE_PATH_MAX_INT_TYPE_COUNT;
01611
01612
01613 P->Translation.LastKey1Time = 0.0f;
01614 P->Translation.LastKey2Time = -1.0f;
01615
01616 P->Rotation.LastKey1Time = 0.0f;
01617 P->Rotation.LastKey2Time = -1.0f;
01618 P-> Dirty = 0;
01619 P-> Looped = 0;
01620 P-> RefCount = 0;
01621
01622 if ((Header >> 1) & 0x1)
01623 {
01624 P->Translation.KeyList = geVKFrame_CreateFromBinaryFile(F,&Interp,&Looping);
01625 if (P->Translation.KeyList == NULL)
01626 {
01627 geErrorLog_AddString( -1, "Failure to read translation keys" , NULL);
01628 geRam_Free(P);
01629 return NULL;
01630 }
01631 P->Translation.InterpolationType = gePath_VKToPathInterpolation(Interp);
01632 if( Looping != 0 )
01633 P->Looped = FLAG_LOOPED;
01634 }
01635
01636 if (Header & 0x1)
01637 {
01638 P->Rotation.KeyList = geQKFrame_CreateFromBinaryFile(F,&Interp,&Looping);
01639 if (P->Rotation.KeyList == NULL)
01640 {
01641 geErrorLog_AddString( -1, "Failure to read rotation keys" , NULL);
01642 if (P->Translation.KeyList != NULL)
01643 {
01644 geTKArray_Destroy(&P->Translation.KeyList);
01645 }
01646 geRam_Free(P);
01647 return NULL;
01648 }
01649 P->Rotation.InterpolationType = gePath_QKToPathInterpolation(Interp);
01650 if( Looping != 0 )
01651 P->Looped = FLAG_LOOPED;
01652
01653 }
01654 P->Dirty = FLAG_DIRTY;
01655 return P;
01656 }
01657