/** ******************************************************************************* @file /gui/engine/Animation.cpp @brief Datove struktury pro klicovanou animaci @author Vajicek @version 0.2 ******************************************************************************/ #include "gui/engine/Animation.h" #include "gui/common/mymath.h" #include "common/mm.h" #include "common/exc.h" #include "common/Log.h" #include #include #include using namespace std; /******************************************************************************/ namespace gui{ /** Instance cache pro animace. */ static TAnimTablesCache anim_cache; void ACache_Init(){ anim_cache.Tables_c = 0; anim_cache.Tables = NULL; } void ACache_AddTable(PAnimTable at){ anim_cache.Tables = (PAnimTable*)KExtArrayRealloc( anim_cache.Tables, sizeof(PAnimTable), anim_cache.Tables_c + 1, anim_cache.Tables_c); at->iFlags |= AT_CACHED; anim_cache.Tables[ anim_cache.Tables_c ] = at; anim_cache.Tables_c++; } PAnimTable ACache_ReleasedTable(PAnimTable at){ for(int i = 0; i < anim_cache.Tables_c; i++) { if(anim_cache.Tables[i] == at){ if(anim_cache.Tables_c - i - 1) memcpy( anim_cache.Tables + i, anim_cache.Tables + i + 1, (anim_cache.Tables_c - i - 1)*sizeof(PAnimTable)); anim_cache.Tables = (PAnimTable*)KExtArrayRealloc( anim_cache.Tables, sizeof(PAnimTable), anim_cache.Tables_c, anim_cache.Tables_c - 1); anim_cache.Tables_c--; return at; } } return NULL; } PAnimTable ACache_GetTable(int iID){ for(int i = 0; i < anim_cache.Tables_c; i++) { if(anim_cache.Tables[i]->iID == iID) return anim_cache.Tables[i]; } return NULL; } void ACache_Free(){ for(int i = 0; i < anim_cache.Tables_c; i++) FreeAnimTable(anim_cache.Tables[i]); if(anim_cache.Tables) KMemFree(anim_cache.Tables); } void ACache_DestroyTable(PAnimTable at) { ACache_ReleasedTable(at); FreeAnimTable(at); } PAnimTable ACache_CreateTable(int iID) { PAnimTable at; at = (PAnimTable)KMemAlloc( sizeof(TAnimTable) ); at -> iID = iID; at -> iTracks_c = 0; at -> Tracks = NULL; at -> iFlags = 0; at -> iAnimLen = 0; ACache_AddTable(at); return at; } /////////////////////////////////////////////////////////////////////////////// /* generuje tabulky do cache, vraci identifikatory FOR EVERY KEYFRAMER VYTVOR ANIMTABLE V CACHE VYTVOR BUFFER NA KLICE FOR EVERY ANIMOBJECT_NODE VLOZ STOPU PRO EXISTUJICI ROTACNI/TRANSLACNI VYTVOR KLICE Z BUFFERU FOR EVERY ANIMOBJECT_NODE IF EXISTUJE TRANSLACNI STOPA VLOZ KLICE DO STOPY IF EXISTUJE ROTACNI STOPA VLOZ KLICE DO STOPY */ int CreateTablesForModel(TModel* mod){ int s = (int)mod->keyframers.size(); for(int kf_i = 0; kf_i < s; kf_i++) CreateTableForModel(mod, kf_i); return s; } int CreateTableForModel(TModel* mod, int aid){ PKeyframer kf; TAnim_object* ao; TAnimTable* at; TMeshNode* mn; if((int)mod->keyframers.size() < aid) return -1; kf = mod->keyframers.at(aid); //pokus se najit tabulku v cache, klic je PKeyframer at = ACache_CreateTable(PID(mod) + aid); //vytvor tracky int* keys = (int*)KMemAlloc(kf->anim_object_nodes_c*2*sizeof(int)); int keys_c = 0; //vytvoreni klic jmen for(int i = 0; i < kf->anim_object_nodes_c; i++) { ao = kf->anim_object_nodes + i; mn = mod->findMeshNode(ao->mesh_name); //vytvor jmena klicu if(ao->pos_track_c) keys[keys_c++] = PID(mn) ; if(ao->rot_track_c) keys[keys_c++] = PID(mn) + 1; } AddTracks(at,keys, keys_c); KMemFree(keys); // at->iAnimLen = (int)ROUND( (kf->frames*1000.0f)/kf->frame_per_sec ); at->iFlags = AT_MODEL; // //nahrat do klicu tracky for(int j = 0; j < kf->anim_object_nodes_c; j++){ ao = kf->anim_object_nodes + j; mn = mod->findMeshNode(ao->mesh_name); //projde tabulku a naplni klice pro tento anim object if(ao->pos_track_c){ //je nula? int zero = (ao->pos_track[0].keyframe == 0)?0:1; //dej sem track int tr_i = GetTrack(at, PID(mn) ); TTrack* tr = at->Tracks + tr_i; //vytvor volne AddKeyFramesToTrack(at, PID(mn), ao->pos_track_c + zero); //pokud neni nula vloz nulu if(zero){ SETV3( tr->Keys[0].pos_val.p, 0, 0, 0); tr->Stamps[0] = 0; } //vkladej klice for(int k = 0; k < ao->pos_track_c; k++){ CopyV3(tr->Keys[zero + k].pos_val.p, ao->pos_track[k].position.p); tr->Stamps[zero + k] = ao->pos_track[k].keyframe; } //vyhodnot KPS tr->KPS = ROUND( ao->pos_track[ao->pos_track_c - 1].keyframe / float(ao->pos_track_c) ); }//pozice if(ao->rot_track_c){ //dej sem track int tr_i = GetTrack(at, PID(mn)+1 ); TTrack* tr = at->Tracks + tr_i; //vytvor volne AddKeyFramesToTrack(at, PID(mn)+1, ao->rot_track_c); //vkladej klice P3F ax; float ang; for(int k = 0; k < ao->rot_track_c; k++){ CopyV3(ax.p, ao->rot_track[k].axis.p); ang = ao->rot_track[k].angle; // AATOQ(&ax, ang, &(tr->Keys[k].rot_val)); tr->Stamps[k] = ao->rot_track[k].keyframe; } //vyhodnot KPS tr->KPS = ROUND( ao->rot_track[ao->rot_track_c - 1].keyframe / float(ao->rot_track_c) ); }//if rot_track_c }//for anim objs return 1; } void FreeAnimTable(PAnimTable at){ for( int k = 0; k < at -> iTracks_c; k++){ KMemFree(at -> Tracks[k].Stamps); KMemFree(at -> Tracks[k].Keys); } KMemFree(at -> Tracks); KMemFree(at); } int AddTracks(TAnimTable* at,int* names, int names_c) { at->Tracks = (TTrack*)KExtArrayRealloc( at -> Tracks, sizeof(TTrack), at -> iTracks_c + names_c, at -> iTracks_c); for(int i = 0; i < names_c;i++){ TTrack* t = at->Tracks + i + at->iTracks_c; t->Keys = NULL; t->Name = names[i]; t->KPS = 0; t->Stamps = NULL; t->Keys_l = 0; } at->iTracks_c += names_c; return at -> iTracks_c - 1; } int GetTrack(TAnimTable* at,int chindx){ for(int i = 0; i < at -> iTracks_c; i++){ if( at -> Tracks[i].Name == chindx) return i; } return -1; } TTrack* AddKeyFramesToTrack(TAnimTable* at, int name, int count) { int k = GetTrack(at, name); at->Tracks[k].Keys = (TKey*)KExtArrayRealloc( at -> Tracks[k].Keys, sizeof(TKey), count, 0); at->Tracks[k].Keys_l = count; at->Tracks[k].Stamps = (int*)KExtArrayRealloc( at->Tracks[k].Stamps, sizeof(int), count, 0); return at->Tracks + k; } }//namespace /*****************************************************************************/