Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

vkframe.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  VKFRAME.C                                                                                                                                                   */
00003 /*                                                                                      */
00004 /*  Author: Mike Sandige                                                                    */
00005 /*  Description: Vector keyframe implementation.                                                                                */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 /* geVKFrame  (Vector-Keyframe)
00023         This module handles interpolation for keyframes that contain a vector (a geVec3d)
00024         This is intended to support Path.c
00025         geTKArray supplies general support for a time-keyed array, and this supplements
00026         that support to include the two specific time-keyed arrays:
00027           An array of geVec3d interpolated linearly
00028           An array of geVec3d interpolated with hermite blending
00029         These are phycially separated and have different base structures because:
00030                 linear blending requires less data.
00031                 future blending might require more data.
00032         The two types of lists are created with different creation calls,
00033         interpolated with different calls, but insertion and queries share a call.
00034         
00035         Hermite interpolation requires additional computation after changes are
00036         made to the keyframe list.  Call geVKFrame_HermiteRecompute() to update the
00037         calculations.
00038 */
00039 #include <assert.h>
00040 #include <string.h>
00041 #include <stdio.h>
00042 
00043 #include "vec3d.h"
00044 #include "vkframe.h"
00045 #include "errorlog.h"
00046 #include "ram.h"
00047 
00048 #define LINEAR_BLEND(a,b,t)  ( (t)*((b)-(a)) + (a) )    
00049                         // linear blend of a and b  0<t<1 where  t=0 ->a and t=1 ->b
00050 
00051 typedef struct
00052 {
00053         geTKArray_TimeType      Time;           // Time for this keyframe
00054         geVec3d         V;                                      // vector for this keyframe
00055 }  geVKFrame;           
00056         // This is the root structure that geVKFrame supports
00057         // all keyframe types must begin with this structure.  Time is first, so
00058         // that this structure can be manipulated by geTKArray
00059 
00060 typedef struct
00061 {
00062         geVKFrame Key;                                  // key values for this keyframe
00063         geVec3d         SDerivative;            // Hermite Derivative (Incoming) 
00064         geVec3d         DDerivative;            // Hermite Derivative (Outgoing) 
00065 }       geVKFrame_Hermite;
00066         // keyframe data for hermite blending
00067         // The structure includes computed derivative information.  
00068 
00069 typedef struct
00070 {
00071         geVKFrame Key;                          // key values for this keyframe
00072 }       geVKFrame_Linear;
00073         // keyframe data for linear interpolation
00074         // The structure includes no additional information.
00075 
00076 geTKArray *GENESISCC geVKFrame_LinearCreate(void)
00077         // creates a frame list for linear interpolation
00078 {
00079         return geTKArray_Create(sizeof(geVKFrame_Linear) );
00080 }
00081 
00082 
00083 geTKArray *GENESISCC geVKFrame_HermiteCreate(void)
00084         // creates a frame list for hermite interpolation       
00085 {
00086         return geTKArray_Create(sizeof(geVKFrame_Hermite) );
00087 }
00088 
00089 
00090 geBoolean GENESISCC geVKFrame_Insert(
00091         geTKArray **KeyList,                    // keyframe list to insert into
00092         geTKArray_TimeType Time,                // time of new keyframe
00093         const geVec3d *V,                               // vector at new keyframe
00094         int *Index)                                     // index of new key
00095         // inserts a new keyframe with the given time and vector into the list.
00096 {
00097         assert( KeyList != NULL );
00098         assert( *KeyList != NULL );
00099         assert( V != NULL );
00100         assert(   sizeof(geVKFrame_Hermite) == geTKArray_ElementSize(*KeyList) 
00101                || sizeof(geVKFrame_Linear) == geTKArray_ElementSize(*KeyList) );
00102 
00103         if (geTKArray_Insert(KeyList, Time, Index) == GE_FALSE)
00104                 {
00105                         geErrorLog_Add(ERR_VKARRAY_INSERT, NULL);
00106                         return GE_FALSE;
00107                 }
00108         else
00109                 {
00110                         geVKFrame *KF;
00111                         KF = (geVKFrame *)geTKArray_Element(*KeyList,*Index);
00112                         KF->V = *V;
00113                         return GE_TRUE;
00114                 }
00115 }
00116 
00117 void GENESISCC geVKFrame_Query(
00118         const geTKArray *KeyList,               // keyframe list
00119         int Index,                                              // index of frame to return
00120         geTKArray_TimeType *Time,               // time of the frame is returned
00121         geVec3d *V)                                             // vector from the frame is returned
00122         // returns the vector and the time at keyframe[index] 
00123 {
00124         geVKFrame *KF;
00125         assert( KeyList != NULL );
00126         assert( Time != NULL );
00127         assert( V != NULL );
00128         assert( Index < geTKArray_NumElements(KeyList) );
00129         assert( Index >= 0 );
00130         assert(   sizeof(geVKFrame_Hermite) == geTKArray_ElementSize(KeyList) 
00131                || sizeof(geVKFrame_Linear) == geTKArray_ElementSize(KeyList) );
00132                 
00133         KF = (geVKFrame *)geTKArray_Element(KeyList,Index);
00134         *Time = KF->Time;
00135         *V    = KF->V;
00136 }
00137 
00138 
00139 void GENESISCC geVKFrame_Modify(
00140         geTKArray *KeyList,                             // keyframe list
00141         int Index,                                              // index of frame to change
00142         const geVec3d *V)                               // vector for the key
00143         // chganes the vector at keyframe[index] 
00144 {
00145         geVKFrame *KF;
00146         assert( KeyList != NULL );
00147         assert( V != NULL );
00148         assert( Index < geTKArray_NumElements(KeyList) );
00149         assert( Index >= 0 );
00150         assert(   sizeof(geVKFrame_Hermite) == geTKArray_ElementSize(KeyList) 
00151                || sizeof(geVKFrame_Linear) == geTKArray_ElementSize(KeyList) );
00152                 
00153         KF = (geVKFrame *)geTKArray_Element(KeyList,Index);
00154         KF->V = *V;
00155 }
00156 
00157 
00158 void GENESISCC geVKFrame_LinearInterpolation(
00159         const void *KF1,                // pointer to first keyframe
00160         const void *KF2,                // pointer to second keyframe
00161         geFloat T,                              // 0 <= T <= 1   blending parameter
00162         void *Result)                   // put the result in here (geVec3d)
00163                 // interpolates to get a vector between the two vectors at the two
00164                 // keyframes where T==0 returns the vector for KF1 
00165                 // and T==1 returns the vector for KF2
00166                 // interpolates linearly
00167 {
00168         geVec3d *Vec1,*Vec2;
00169         geVec3d *VNew = (geVec3d *)Result;
00170         
00171         assert( Result != NULL );
00172         assert( KF1 != NULL );
00173         assert( KF2 != NULL );
00174         
00175         assert( T >= (geFloat)0.0f );
00176         assert( T <= (geFloat)1.0f );
00177         
00178         if ( KF1 == KF2 )
00179                 {
00180                         *VNew = ((geVKFrame_Linear *)KF1)->Key.V;
00181                         return;
00182                 }
00183 
00184         Vec1 = &( ((geVKFrame_Linear *)KF1)->Key.V);
00185         Vec2 = &( ((geVKFrame_Linear *)KF2)->Key.V);
00186         
00187         VNew->X = LINEAR_BLEND(Vec1->X,Vec2->X,T);
00188         VNew->Y = LINEAR_BLEND(Vec1->Y,Vec2->Y,T);
00189         VNew->Z = LINEAR_BLEND(Vec1->Z,Vec2->Z,T);
00190 }
00191 
00192 
00193 
00194 void GENESISCC geVKFrame_HermiteInterpolation(
00195         const void *KF1,                // pointer to first keyframe
00196         const void *KF2,                // pointer to second keyframe
00197         geFloat T,                              // 0 <= T <= 1   blending parameter
00198         void *Result)                   // put the result in here (geVec3d)
00199                 // interpolates to get a vector between the two vectors at the two
00200                 // keyframes where T==0 returns the vector for KF1 
00201                 // and T==1 returns the vector for KF2
00202                 // interpolates using 'hermite' blending
00203 {
00204         geVec3d *Vec1,*Vec2;
00205         geVec3d *VNew = (geVec3d *)Result;
00206         
00207         assert( Result != NULL );
00208         assert( KF1 != NULL );
00209         assert( KF2 != NULL );
00210         
00211         assert( T >= (geFloat)0.0f );
00212         assert( T <= (geFloat)1.0f );
00213         
00214         if ( KF1 == KF2 )
00215                 {
00216                         *VNew = ((geVKFrame_Hermite *)KF1)->Key.V;
00217                         return;
00218                 }
00219 
00220         Vec1 = &( ((geVKFrame_Hermite *)KF1)->Key.V);
00221         Vec2 = &( ((geVKFrame_Hermite *)KF2)->Key.V);
00222 
00223         {
00224                 geFloat t2;                     // T sqaured
00225                 geFloat t3;                     // T cubed
00226                 geFloat   H1,H2,H3,H4;  // hermite basis function coefficients
00227 
00228                 t2 = T * T;
00229                 t3 = t2 * T;
00230         
00231                 H2 = -(t3 + t3) + t2*3.0f;
00232                 H1 = 1.0f - H2;
00233                 H4 = t3 - t2;
00234                 H3 = H4 - t2 + T;   //t3 - 2.0f * t2 + t;
00235                 
00236                 geVec3d_Scale(Vec1,H1,VNew);
00237                 geVec3d_AddScaled(VNew,Vec2,H2,VNew);
00238                 geVec3d_AddScaled(VNew,&( ((geVKFrame_Hermite *)KF1)->DDerivative),H3,VNew);
00239                 geVec3d_AddScaled(VNew,&( ((geVKFrame_Hermite *)KF2)->SDerivative),H4,VNew);
00240         }
00241 }
00242 
00243 
00244 void GENESISCC geVKFrame_HermiteRecompute(
00245         int Looped,                              // if keylist has the first key connected to last key
00246         geBoolean ZeroDerivative,// if each key should have a zero derivatives (good for 2 point S curves)
00247         geTKArray *KeyList)              // list of keys to recompute hermite values for
00248         // rebuild precomputed data for keyframe list.
00249 {
00250         // compute the incoming and outgoing derivatives at each keyframe
00251         int i;
00252         geVec3d V0,V1,V2;
00253         geFloat Time0, Time1, Time2, N0, N1, N0N1;
00254         geVKFrame_Hermite *TK;
00255         geVKFrame_Hermite *Vector= NULL;
00256         int count;
00257         int Index0,Index1,Index2;
00258 
00259         assert( KeyList != NULL );
00260         assert( sizeof(geVKFrame_Hermite) == geTKArray_ElementSize(KeyList) );
00261         
00262                         
00263         // Compute derivatives at the keyframe points:
00264         // The derivative is the average of the source chord p[i]-p[i-1]
00265         // and the destination chord p[i+1]-p[i]
00266         //     (where i is Index1 in this function)
00267         //  D = 1/2 * ( p[i+1]-p[i-1] ) = 1/2 *( (p[i+1]-p[i]) + (p[i]-p[i-1]) )
00268         //  The very first and last chords are simply the 
00269         // destination and source derivative.
00270         //   These 'averaged' D's are adjusted for variences in the time scale
00271         // between the Keyframes.  To do this, the derivative at each keyframe
00272         // is split into two parts, an incoming ('source' DS) 
00273         // and an outgoing ('destination' DD) derivative.
00274         // DD[i] = DD[i] * 2 * N[i]  / ( N[i-1] + N[i] )   
00275         // DS[i] = DS[i] * 2 * N[i-1]/ ( N[i-1] + N[i] )
00276         //    where N[i] is time between keyframes i and i+1
00277         // Since the chord dealt with on a given chord between key[i] and key[i+1], only
00278         // one of the derivates are needed for each keyframe.  For key[i] the outgoing
00279         // derivative at is needed (DD[i]).  For key[i+1], the incoming derivative
00280         // is needed (DS[i+1])   ( note that  (1/2) * 2 = 1 )
00281         count = geTKArray_NumElements(KeyList);
00282         if (count > 0)
00283                 {
00284                         Vector = (geVKFrame_Hermite *)geTKArray_Element(KeyList,0);
00285                 }
00286 
00287         if (ZeroDerivative!=GE_FALSE)
00288                 {       // in this case, just bang all derivatives to zero.
00289                         for (i =0; i< count; i++)
00290                                 {
00291                                         TK = &(Vector[i]);
00292                                         geVec3d_Clear(&(TK->DDerivative));
00293                                         geVec3d_Clear(&(TK->SDerivative));
00294                                 }
00295                         return;
00296                 }
00297 
00298         if (count < 3)                  
00299                 {
00300                         Looped = GE_FALSE;      
00301                         // cant compute slopes without a closed loop: 
00302                         // so compute slopes as if it is not closed.
00303                 }
00304         for (i =0; i< count; i++)
00305                 {
00306                         TK = &(Vector[i]);
00307                         Index0 = i-1;
00308                         Index1 = i;
00309                         Index2 = i+1;
00310 
00311                         Time1 = Vector[Index1].Key.Time;
00312                         if (Index1 == 0)
00313                                 {
00314                                         if (Looped != GE_TRUE)
00315                                                 {
00316                                                         Index0 = 0;                     
00317                                                         Time0 = Vector[Index0].Key.Time;
00318                                                 }
00319                                         else
00320                                                 {
00321                                                         Index0 = count-2;
00322                                                         Time0 = Time1 - (Vector[count-1].Key.Time - Vector[count-2].Key.Time);
00323                                                 }
00324                                 }
00325                         else
00326                                 {
00327                                         Time0 = Vector[Index0].Key.Time;
00328                                 }
00329 
00330 
00331                         if (Index2 == count)
00332                                 {
00333                                         if (Looped != GE_TRUE)
00334                                                 {
00335                                                         Index2 = count-1;
00336                                                         Time2 = Vector[Index2].Key.Time;
00337                                                 }
00338                                         else
00339                                                 {
00340                                                         Index2 = 1;
00341                                                         Time2 = Time1 + (Vector[1].Key.Time - Vector[0].Key.Time);
00342                                                 }
00343                                 }
00344                         else
00345                                 {
00346                                         Time2 = Vector[Index2].Key.Time;
00347                                 }
00348 
00349                         V0 = Vector[Index0].Key.V;
00350                         V1 = Vector[Index1].Key.V;
00351                         V2 = Vector[Index2].Key.V;
00352 
00353                         N0    = (Time1 - Time0);
00354                         N1    = (Time2 - Time1);
00355                         N0N1  = N0 + N1;
00356 
00357                         if (( Looped != GE_TRUE) && (Index1 == 0) )
00358                                 {
00359                                         geVec3d_Subtract(&V2,&V1,&(TK->SDerivative));
00360                                         geVec3d_Copy( &(TK->SDerivative), &(TK->DDerivative));
00361                                 }
00362                         else if (( Looped != GE_TRUE) && (Index1 == count-1))
00363                                 {
00364                                         geVec3d_Subtract(&V1,&V0,&(TK->SDerivative));
00365                                         geVec3d_Copy( &(TK->SDerivative), &(TK->DDerivative));
00366                                 }
00367                         else
00368                         {
00369                                 geVec3d Slope;
00370                                 geVec3d_Subtract(&V2,&V0,&Slope);
00371                                 geVec3d_Scale(&Slope, (N1 / N0N1), &(TK->DDerivative));
00372                                 geVec3d_Scale(&Slope, (N0 / N0N1), &(TK->SDerivative));
00373                         }
00374                 }       
00375 }               
00376 
00377 
00378 #define VKFRAME_LINEAR_ASCII_FILE 0x4C464B56    // 'VKFL'
00379 #define VKFRAME_HERMITE_ASCII_FILE 0x48464B56   // 'VKFH'
00380 #define CHECK_FOR_READ(uu, nn) if(uu != nn) { geErrorLog_Add(ERR_PATH_FILE_READ, NULL);  return GE_FALSE; }
00381 #define CHECK_FOR_WRITE(uu) if (uu <= 0)    { geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL); return GE_FALSE; }
00382 
00383 #define VKFRAME_KEYLIST_ID "Keys"
00384 
00385 
00386 //-----------------------------------
00387 // Support for 'old' 1.0 ascii data format
00388 
00389 geBoolean GENESISCC geVKFrame_LinearRead(geVFile* pFile, void* geVKFrame)
00390 {
00391         uint32  u;
00392         char    KeyString[64];
00393         geVKFrame_Linear* pLinear = (geVKFrame_Linear*)geVKFrame;
00394 
00395         assert( pFile != NULL );
00396         assert( geVKFrame != NULL );
00397 
00398         // Read the format/version flag
00399         if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00400         {
00401                 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00402                 return GE_FALSE;
00403         }
00404 
00405         if(u != VKFRAME_LINEAR_ASCII_FILE)
00406         {
00407                 geErrorLog_Add(ERR_PATH_FILE_VERSION, NULL);
00408                 return GE_FALSE;
00409         }
00410 
00411         if      (geVFile_GetS(pFile, KeyString, sizeof(KeyString)) == GE_FALSE)
00412         {
00413                 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00414                 return GE_FALSE;
00415         }
00416 
00417         u = sscanf(KeyString, "%f %f %f\n", &pLinear->Key.V.X,
00418                                                                                 &pLinear->Key.V.Y,
00419                                                                                 &pLinear->Key.V.Z);
00420         CHECK_FOR_READ(u, 3);
00421 
00422         return GE_TRUE;
00423 }
00424 
00425 
00426 geBoolean GENESISCC geVKFrame_HermiteRead(geVFile* pFile, void* geVKFrame)
00427 {
00428         uint32  u;
00429         char    HermiteString[128];
00430         geVKFrame_Hermite* pHermite = (geVKFrame_Hermite*)geVKFrame;
00431 
00432         assert( pFile != NULL );
00433         assert( geVKFrame != NULL );
00434 
00435         // Read the format/version flag
00436         if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00437         {
00438                 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00439                 return GE_FALSE;
00440         }
00441 
00442         if(u != VKFRAME_HERMITE_ASCII_FILE)
00443         {
00444                 geErrorLog_Add(ERR_PATH_FILE_VERSION, NULL);
00445                 return GE_FALSE;
00446         }
00447 
00448         if      (geVFile_GetS(pFile, HermiteString, sizeof(HermiteString)) == GE_FALSE)
00449         {
00450                 geErrorLog_Add(ERR_PATH_FILE_READ, NULL);
00451                 return GE_FALSE;
00452         }
00453         u = sscanf(HermiteString, "%f %f %f %f %f %f %f %f %f\n",       &pHermite->Key.V.X,
00454                                                                                                                                 &pHermite->Key.V.Y,
00455                                                                                                                                 &pHermite->Key.V.Z,
00456                                                                                                                                 &pHermite->SDerivative.X,
00457                                                                                                                                 &pHermite->SDerivative.Y,
00458                                                                                                                                 &pHermite->SDerivative.Z,
00459                                                                                                                                 &pHermite->DDerivative.X,
00460                                                                                                                                 &pHermite->DDerivative.Y,
00461                                                                                                                                 &pHermite->DDerivative.Z);
00462         CHECK_FOR_READ(u, 9);
00463 
00464         return GE_TRUE;
00465 }
00466 
00467 
00468                 // (above)Support for 'old' 1.0 ascii data format
00469 //-----------------------------------
00470 #define LINEARTIME_TOLERANCE (0.0001f)
00471 #define VKFRAME_LINEARTIME_COMPRESSION 0x2
00472 
00473 
00474 
00475 geBoolean GENESISCC geVKFrame_WriteToFile(geVFile *pFile, geTKArray *KeyList, 
00476                 geVKFrame_InterpolationType InterpolationType, int Looping)
00477 {
00478         int NumElements,i;
00479         geFloat Time,DeltaTime;
00480         int Compression=0;
00481 
00482         assert( pFile != NULL );
00483         assert( KeyList != NULL );
00484 
00485         NumElements = geTKArray_NumElements(KeyList);
00486 
00487         if (NumElements>2)
00488                 {
00489                         if ( geTKArray_SamplesAreTimeLinear(KeyList,LINEARTIME_TOLERANCE) != GE_FALSE )
00490                                 {
00491                                         Compression |= VKFRAME_LINEARTIME_COMPRESSION;
00492                                 }
00493                 }
00494 
00495 
00496         if      (geVFile_Printf(pFile,
00497                                           "%s %d %d %d %d\n",
00498                                           VKFRAME_KEYLIST_ID,
00499                                           NumElements,
00500                                           InterpolationType,
00501                                           Compression,
00502                                           Looping) == GE_FALSE)
00503     {
00504                 geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00505                 return GE_FALSE;
00506         }
00507 
00508         if (Compression & VKFRAME_LINEARTIME_COMPRESSION)
00509                 {
00510                         Time = geTKArray_ElementTime(KeyList, 0);
00511                         DeltaTime = geTKArray_ElementTime(KeyList, 1)- Time;
00512                         if(geVFile_Printf(pFile,"%f %f Start T,Delta T\n",Time,DeltaTime) == GE_FALSE)
00513                                 {
00514                                         geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00515                                         return GE_FALSE;
00516                                 }
00517                 }
00518 
00519         for(i=0;i<NumElements;i++)
00520                 {
00521                         geVKFrame_Linear* pLinear = (geVKFrame_Linear*)geTKArray_Element(KeyList, i);
00522                         if (!(Compression & VKFRAME_LINEARTIME_COMPRESSION))
00523                                 {
00524                                         Time = geTKArray_ElementTime(KeyList, i);
00525                                         if      (geVFile_Printf(pFile, "%f ", Time ) == GE_FALSE)
00526                                                 {
00527                                                         geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00528                                                         return GE_FALSE;
00529                                                 }
00530                                 }
00531                         if      (geVFile_Printf(pFile,
00532                                                           "%f %f %f\n",
00533                                                           pLinear->Key.V.X,
00534                                                           pLinear->Key.V.Y,
00535                                                           pLinear->Key.V.Z) == GE_FALSE)
00536                                 {
00537                                         geErrorLog_Add(ERR_PATH_FILE_WRITE, NULL);
00538                                         return GE_FALSE;
00539                                 }
00540                 }
00541         return GE_TRUE;
00542 }
00543 
00544 
00545 geTKArray *GENESISCC geVKFrame_CreateFromFile(geVFile *pFile, int *InterpolationType, int *Looping)
00546 {
00547         #define ERROREXIT  {geErrorLog_Add( ERR_PATH_FILE_READ , NULL);if (KeyList != NULL){geTKArray_Destroy(&KeyList);}       return NULL;}
00548         int i,u,NumElements;
00549         int Compression;
00550         #define LINE_LENGTH 256
00551         char line[LINE_LENGTH];
00552         geTKArray *KeyList= NULL;
00553         geFloat StartTime=0.0f;
00554         geFloat DeltaTime=0.0f;
00555 
00556 
00557         assert( pFile != NULL );
00558         assert( InterpolationType != NULL );
00559 
00560         if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00561                 ERROREXIT;
00562                 
00563         if(strnicmp(line, VKFRAME_KEYLIST_ID, sizeof(VKFRAME_KEYLIST_ID)-1) != 0)
00564                 ERROREXIT;
00565 
00566         if(sscanf(line + sizeof(VKFRAME_KEYLIST_ID)-1, "%d %d %d %d", 
00567                                         &NumElements,InterpolationType,&Compression,Looping) != 4)
00568                 ERROREXIT;
00569 
00570         switch (*InterpolationType)
00571                 {
00572                         case (VKFRAME_LINEAR):
00573                                         KeyList = geTKArray_CreateEmpty(sizeof(geVKFrame_Linear),NumElements);
00574                                         break;
00575                         case (VKFRAME_HERMITE):
00576                         case (VKFRAME_HERMITE_ZERO_DERIV):
00577                                         KeyList = geTKArray_CreateEmpty(sizeof(geVKFrame_Hermite),NumElements);
00578                                         break;
00579                         default:
00580                                 ERROREXIT;
00581                 }
00582         if (KeyList == NULL)
00583                 ERROREXIT;
00584 
00585         if (Compression & VKFRAME_LINEARTIME_COMPRESSION)
00586                 {
00587                         if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00588                                 ERROREXIT;
00589                         if (sscanf(line,"%f %f",&StartTime,&DeltaTime) != 2)
00590                                 ERROREXIT;
00591                 }
00592 
00593         for(i=0;i<NumElements;i++)
00594                 {
00595                         geVKFrame_Linear* pLinear = (geVKFrame_Linear*)geTKArray_Element(KeyList, i);
00596                         if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00597                                 ERROREXIT;
00598 
00599                         if (Compression & VKFRAME_LINEARTIME_COMPRESSION)
00600                                 {
00601                                         pLinear->Key.Time = StartTime + DeltaTime * i;
00602                                         u = sscanf(line,"%f %f %f",  &(pLinear->Key.V.X),
00603                                                   &(pLinear->Key.V.Y),&(pLinear->Key.V.Z));
00604                                         if (u!=3)
00605                                                 ERROREXIT;
00606                                 }
00607                         else
00608                                 {
00609                                         u = sscanf(line,"%f %f %f %f",&(pLinear->Key.Time), &(pLinear->Key.V.X),
00610                                                                           &(pLinear->Key.V.Y),&(pLinear->Key.V.Z));
00611                                         if (u!=4)
00612                                                 ERROREXIT;
00613                                 }
00614                 }
00615 
00616         switch (*InterpolationType)
00617                 {
00618                         case (VKFRAME_LINEAR):
00619                                         break;
00620                         case (VKFRAME_HERMITE):
00621                                 geVKFrame_HermiteRecompute(     *Looping, GE_FALSE, KeyList);
00622                                         break;
00623                         case (VKFRAME_HERMITE_ZERO_DERIV):
00624                                 geVKFrame_HermiteRecompute(     *Looping, GE_TRUE, KeyList);
00625                                         break;
00626                         default:
00627                                 assert(0);
00628                 }
00629 
00630         return KeyList; 
00631 }
00632 
00633 uint32 GENESISCC geVKFrame_ComputeBlockSize(geTKArray *KeyList, int Compression)
00634 {
00635         uint32 Size=0;
00636         int Count;
00637 
00638         assert( KeyList != NULL );
00639         assert( Compression < 0xFF);
00640         
00641         Count = geTKArray_NumElements(KeyList);
00642 
00643         Size += sizeof(uint32);         // flags
00644         Size += sizeof(uint32);         // count
00645 
00646         if (Compression & VKFRAME_LINEARTIME_COMPRESSION)
00647                 {
00648                         Size += sizeof(geFloat) * 2;
00649                 }
00650         else
00651                 {
00652                         Size += sizeof(geFloat) * Count;
00653                 }
00654 
00655         Size += sizeof(geVec3d) * Count;
00656         return Size;
00657 }
00658 
00659 
00660 geTKArray *GENESISCC geVKFrame_CreateFromBinaryFile(geVFile *pFile, int *InterpolationType, int *Looping)
00661 {
00662         uint32 u;
00663         int BlockSize;
00664         int Compression;
00665         int Count,i;
00666         int FieldSize;
00667         char *Block;
00668         geFloat *Data;
00669         geTKArray *KeyList;
00670         geVKFrame_Linear* pLinear0;
00671         geVKFrame_Linear* pLinear;
00672         
00673         assert( pFile != NULL );
00674         assert( InterpolationType != NULL );
00675         assert( Looping != NULL );
00676         
00677         if (geVFile_Read(pFile, &BlockSize, sizeof(int)) == GE_FALSE)
00678                 {
00679                         geErrorLog_AddString(-1,"Failure to read binary VKFrame header", NULL);
00680                         return NULL;
00681                 }
00682         if (BlockSize<0)
00683                 {
00684                         geErrorLog_AddString(-1,"Bad Blocksize", NULL);
00685                         return NULL;
00686                 }
00687                         
00688         Block = geRam_Allocate(BlockSize);
00689         if(geVFile_Read(pFile, Block, BlockSize) == GE_FALSE)
00690                 {
00691                         geErrorLog_AddString(-1,"Failure to read binary VKFrame header", NULL);
00692                         return NULL;
00693                 }
00694         u = *(uint32 *)Block;
00695         *InterpolationType = (u>>16)& 0xFF;
00696         Compression = (u>>8) & 0xFF;
00697         *Looping           = (u & 0x1);         
00698         Count = *(((uint32 *)Block)+1);
00699         
00700         if (Compression > 0xFF)
00701                 {
00702                         geRam_Free(Block);      
00703                         geErrorLog_AddString(-1,"Bad Compression Flag", NULL);
00704                         return NULL;
00705                 }
00706         switch (*InterpolationType)
00707                 {
00708                         case (VKFRAME_LINEAR):
00709                                         FieldSize = sizeof(geVKFrame_Linear);
00710                                         break;
00711                         case (VKFRAME_HERMITE):
00712                         case (VKFRAME_HERMITE_ZERO_DERIV):
00713                                         FieldSize = sizeof(geVKFrame_Hermite);
00714                                         break;
00715                         default:
00716                                         geRam_Free(Block);      
00717                                         geErrorLog_AddString(-1,"Bad InterpolationType", NULL);
00718                                         return NULL;
00719                 }
00720 
00721         KeyList = geTKArray_CreateEmpty(FieldSize,Count);
00722         if (KeyList == NULL)
00723                 {
00724                         geRam_Free(Block);      
00725                         geErrorLog_AddString(-1,"Failed to allocate tkarray", NULL);
00726                         return NULL;
00727                 }
00728 
00729         Data = (geFloat *)(Block + sizeof(uint32)*2);
00730                         
00731         pLinear0 = (geVKFrame_Linear*)geTKArray_Element(KeyList, 0);
00732 
00733         pLinear = pLinear0;
00734 
00735         if (Compression & VKFRAME_LINEARTIME_COMPRESSION)
00736                 {
00737                         geFloat fi;
00738                         geFloat fCount = (geFloat)Count;
00739                         geFloat Time,DeltaTime;
00740                         Time = *(Data++);
00741                         DeltaTime = *(Data++);
00742                         for(fi=0.0f;fi<fCount;fi+=1.0f)
00743                                 {
00744                                         pLinear->Key.Time = Time + fi*DeltaTime;
00745                                         pLinear = (geVKFrame_Linear *)  ( ((char *)pLinear) + FieldSize );
00746                                 }
00747                 }
00748         else
00749                 {
00750                         for(i=0;i<Count;i++)
00751                                 {
00752                                         pLinear->Key.Time = *(Data++);
00753                                         pLinear = (geVKFrame_Linear *)  ( ((char *)pLinear) + FieldSize );
00754                                 }
00755                 }
00756 
00757         pLinear = pLinear0;
00758         for(i=0;i<Count;i++)
00759                 {
00760                         pLinear->Key.V = *(geVec3d *)Data;
00761                         Data += 3;
00762                         pLinear = (geVKFrame_Linear *)  ( ((char *)pLinear) + FieldSize );
00763                 }
00764 
00765         switch (*InterpolationType)
00766                 {
00767                         case (VKFRAME_LINEAR):
00768                                         break;
00769                         case (VKFRAME_HERMITE):
00770                                 geVKFrame_HermiteRecompute(     *Looping, GE_FALSE, KeyList);
00771                                         break;
00772                         case (VKFRAME_HERMITE_ZERO_DERIV):
00773                                 geVKFrame_HermiteRecompute(     *Looping, GE_TRUE, KeyList);
00774                                         break;
00775                         default:
00776                                 assert(0);
00777                 }
00778         geRam_Free(Block);
00779         return KeyList; 
00780 
00781 }
00782 
00783 geBoolean GENESISCC geVKFrame_WriteToBinaryFile(geVFile *pFile, geTKArray *KeyList, 
00784                 geVKFrame_InterpolationType InterpolationType, int Looping)
00785 {
00786         #define WBERREXIT  {geErrorLog_AddString( ERR_PATH_FILE_WRITE,"Failure to write binary key data", NULL);return GE_FALSE;}
00787         uint32 u,BlockSize;
00788         int Compression=0;
00789         int Count,i;
00790         geFloat Time,DeltaTime;
00791 
00792         assert( pFile != NULL );
00793         assert( InterpolationType < 0xFF);
00794         assert( (Looping == 0) || (Looping == 1) );
00795 
00796         if (geTKArray_NumElements(KeyList)>2)
00797                 {
00798                         if ( geTKArray_SamplesAreTimeLinear(KeyList,LINEARTIME_TOLERANCE) != GE_FALSE )
00799                                 {
00800                                         Compression |= VKFRAME_LINEARTIME_COMPRESSION;
00801                                 }
00802                 }
00803 
00804         u = (InterpolationType << 16) |  (Compression << 8) |  Looping;
00805         
00806         BlockSize = geVKFrame_ComputeBlockSize(KeyList,Compression);
00807 
00808         if (geVFile_Write(pFile, &BlockSize,sizeof(uint32)) == GE_FALSE)
00809                 WBERREXIT;
00810         
00811         if (geVFile_Write(pFile, &u, sizeof(uint32)) == GE_FALSE)
00812                 WBERREXIT;
00813         
00814         Count = geTKArray_NumElements(KeyList);
00815         if (geVFile_Write(pFile, &Count, sizeof(uint32)) == GE_FALSE)
00816                 WBERREXIT;
00817 
00818         if (Compression & VKFRAME_LINEARTIME_COMPRESSION)
00819                 {
00820                         Time = geTKArray_ElementTime(KeyList, 0);
00821                         DeltaTime = geTKArray_ElementTime(KeyList, 1)- Time;
00822                         if (geVFile_Write(pFile, &Time,sizeof(geFloat)) == GE_FALSE)
00823                                 WBERREXIT;
00824                         if (geVFile_Write(pFile, &DeltaTime,sizeof(geFloat)) == GE_FALSE)
00825                                 WBERREXIT;
00826                 }
00827         else
00828                 {
00829                         for(i=0;i<Count;i++)
00830                                 {
00831                                         Time = geTKArray_ElementTime(KeyList, i);
00832                                         if (geVFile_Write(pFile, &Time,sizeof(geFloat)) == GE_FALSE)
00833                                                 WBERREXIT;
00834                                 }
00835                 }
00836 
00837         for(i=0;i<Count;i++)
00838                 {
00839                         geVKFrame_Linear* pLinear = (geVKFrame_Linear*)geTKArray_Element(KeyList, i);
00840                         if (geVFile_Write(pFile, &(pLinear->Key.V),sizeof(geVec3d)) == GE_FALSE)
00841                                 WBERREXIT;
00842                 }
00843 
00844         return GE_TRUE;
00845 }

Generated on Tue Sep 30 12:36:37 2003 for GTestAndEngine by doxygen 1.3.2