123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../../idlib/precompiled.h"
- #pragma hdrstop
- #include "../Game_local.h"
- static const char *channelNames[ ANIM_NumAnimChannels ] = {
- "all", "torso", "legs", "head", "eyelids"
- };
- /***********************************************************************
- idAnim
- ***********************************************************************/
- /*
- =====================
- idAnim::idAnim
- =====================
- */
- idAnim::idAnim() {
- modelDef = NULL;
- numAnims = 0;
- memset( anims, 0, sizeof( anims ) );
- memset( &flags, 0, sizeof( flags ) );
- }
- /*
- =====================
- idAnim::idAnim
- =====================
- */
- idAnim::idAnim( const idDeclModelDef *modelDef, const idAnim *anim ) {
- int i;
- this->modelDef = modelDef;
- numAnims = anim->numAnims;
- name = anim->name;
- realname = anim->realname;
- flags = anim->flags;
- memset( anims, 0, sizeof( anims ) );
- for( i = 0; i < numAnims; i++ ) {
- anims[ i ] = anim->anims[ i ];
- anims[ i ]->IncreaseRefs();
- }
- frameLookup.SetNum( anim->frameLookup.Num() );
- memcpy( frameLookup.Ptr(), anim->frameLookup.Ptr(), frameLookup.MemoryUsed() );
- frameCommands.SetNum( anim->frameCommands.Num() );
- for( i = 0; i < frameCommands.Num(); i++ ) {
- frameCommands[ i ] = anim->frameCommands[ i ];
- if ( anim->frameCommands[ i ].string ) {
- frameCommands[ i ].string = new idStr( *anim->frameCommands[ i ].string );
- }
- }
- }
- /*
- =====================
- idAnim::~idAnim
- =====================
- */
- idAnim::~idAnim() {
- int i;
- for( i = 0; i < numAnims; i++ ) {
- anims[ i ]->DecreaseRefs();
- }
- for( i = 0; i < frameCommands.Num(); i++ ) {
- delete frameCommands[ i ].string;
- }
- }
- /*
- =====================
- idAnim::SetAnim
- =====================
- */
- void idAnim::SetAnim( const idDeclModelDef *modelDef, const char *sourcename, const char *animname, int num, const idMD5Anim *md5anims[ ANIM_MaxSyncedAnims ] ) {
- int i;
- this->modelDef = modelDef;
- for( i = 0; i < numAnims; i++ ) {
- anims[ i ]->DecreaseRefs();
- anims[ i ] = NULL;
- }
- assert( ( num > 0 ) && ( num <= ANIM_MaxSyncedAnims ) );
- numAnims = num;
- realname = sourcename;
- name = animname;
- for( i = 0; i < num; i++ ) {
- anims[ i ] = md5anims[ i ];
- anims[ i ]->IncreaseRefs();
- }
- memset( &flags, 0, sizeof( flags ) );
- for( i = 0; i < frameCommands.Num(); i++ ) {
- delete frameCommands[ i ].string;
- }
- frameLookup.Clear();
- frameCommands.Clear();
- }
- /*
- =====================
- idAnim::Name
- =====================
- */
- const char *idAnim::Name( void ) const {
- return name;
- }
- /*
- =====================
- idAnim::FullName
- =====================
- */
- const char *idAnim::FullName( void ) const {
- return realname;
- }
- /*
- =====================
- idAnim::MD5Anim
- index 0 will never be NULL. Any anim >= NumAnims will return NULL.
- =====================
- */
- const idMD5Anim *idAnim::MD5Anim( int num ) const {
- if ( anims == NULL || anims[0] == NULL ) {
- return NULL;
- }
- return anims[ num ];
- }
- /*
- =====================
- idAnim::ModelDef
- =====================
- */
- const idDeclModelDef *idAnim::ModelDef( void ) const {
- return modelDef;
- }
- /*
- =====================
- idAnim::Length
- =====================
- */
- int idAnim::Length( void ) const {
- if ( !anims[ 0 ] ) {
- return 0;
- }
- return anims[ 0 ]->Length();
- }
- /*
- =====================
- idAnim::NumFrames
- =====================
- */
- int idAnim::NumFrames( void ) const {
- if ( !anims[ 0 ] ) {
- return 0;
- }
-
- return anims[ 0 ]->NumFrames();
- }
- /*
- =====================
- idAnim::NumAnims
- =====================
- */
- int idAnim::NumAnims( void ) const {
- return numAnims;
- }
- /*
- =====================
- idAnim::TotalMovementDelta
- =====================
- */
- const idVec3 &idAnim::TotalMovementDelta( void ) const {
- if ( !anims[ 0 ] ) {
- return vec3_zero;
- }
-
- return anims[ 0 ]->TotalMovementDelta();
- }
- /*
- =====================
- idAnim::GetOrigin
- =====================
- */
- bool idAnim::GetOrigin( idVec3 &offset, int animNum, int currentTime, int cyclecount ) const {
- if ( !anims[ animNum ] ) {
- offset.Zero();
- return false;
- }
- anims[ animNum ]->GetOrigin( offset, currentTime, cyclecount );
- return true;
- }
- /*
- =====================
- idAnim::GetOriginRotation
- =====================
- */
- bool idAnim::GetOriginRotation( idQuat &rotation, int animNum, int currentTime, int cyclecount ) const {
- if ( !anims[ animNum ] ) {
- rotation.Set( 0.0f, 0.0f, 0.0f, 1.0f );
- return false;
- }
- anims[ animNum ]->GetOriginRotation( rotation, currentTime, cyclecount );
- return true;
- }
- /*
- =====================
- idAnim::GetBounds
- =====================
- */
- ID_INLINE bool idAnim::GetBounds( idBounds &bounds, int animNum, int currentTime, int cyclecount ) const {
- if ( !anims[ animNum ] ) {
- return false;
- }
- anims[ animNum ]->GetBounds( bounds, currentTime, cyclecount );
- return true;
- }
- /*
- =====================
- idAnim::AddFrameCommand
- Returns NULL if no error.
- =====================
- */
- const char *idAnim::AddFrameCommand( const idDeclModelDef *modelDef, int framenum, idLexer &src, const idDict *def ) {
- int i;
- int index;
- idStr text;
- idStr funcname;
- frameCommand_t fc;
- idToken token;
- const jointInfo_t *jointInfo;
- // make sure we're within bounds
- if ( ( framenum < 1 ) || ( framenum > anims[ 0 ]->NumFrames() ) ) {
- return va( "Frame %d out of range", framenum );
- }
- // frame numbers are 1 based in .def files, but 0 based internally
- framenum--;
- memset( &fc, 0, sizeof( fc ) );
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- if ( token == "call" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SCRIPTFUNCTION;
- fc.function = gameLocal.program.FindFunction( token );
- if ( !fc.function ) {
- return va( "Function '%s' not found", token.c_str() );
- }
- } else if ( token == "object_call" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SCRIPTFUNCTIONOBJECT;
- fc.string = new idStr( token );
- } else if ( token == "event" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_EVENTFUNCTION;
- const idEventDef *ev = idEventDef::FindEvent( token );
- if ( !ev ) {
- return va( "Event '%s' not found", token.c_str() );
- }
- if ( ev->GetNumArgs() != 0 ) {
- return va( "Event '%s' has arguments", token.c_str() );
- }
- fc.string = new idStr( token );
- } else if ( token == "sound" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_voice" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_VOICE;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_voice2" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_VOICE2;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_body" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_BODY;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_body2" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_BODY2;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_body3" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_BODY3;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_weapon" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_WEAPON;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_global" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_GLOBAL;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_item" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_ITEM;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "sound_chatter" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SOUND_CHATTER;
- if ( !token.Cmpn( "snd_", 4 ) ) {
- fc.string = new idStr( token );
- } else {
- fc.soundShader = declManager->FindSound( token );
- if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
- gameLocal.Warning( "Sound '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "skin" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_SKIN;
- if ( token == "none" ) {
- fc.skin = NULL;
- } else {
- fc.skin = declManager->FindSkin( token );
- if ( !fc.skin ) {
- return va( "Skin '%s' not found", token.c_str() );
- }
- }
- } else if ( token == "fx" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_FX;
- if ( !declManager->FindType( DECL_FX, token.c_str() ) ) {
- return va( "fx '%s' not found", token.c_str() );
- }
- fc.string = new idStr( token );
- } else if ( token == "trigger" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_TRIGGER;
- fc.string = new idStr( token );
- } else if ( token == "triggerSmokeParticle" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_TRIGGER_SMOKE_PARTICLE;
- fc.string = new idStr( token );
- } else if ( token == "melee" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_MELEE;
- if ( !gameLocal.FindEntityDef( token.c_str(), false ) ) {
- return va( "Unknown entityDef '%s'", token.c_str() );
- }
- fc.string = new idStr( token );
- } else if ( token == "direct_damage" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_DIRECTDAMAGE;
- if ( !gameLocal.FindEntityDef( token.c_str(), false ) ) {
- return va( "Unknown entityDef '%s'", token.c_str() );
- }
- fc.string = new idStr( token );
- } else if ( token == "attack_begin" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_BEGINATTACK;
- if ( !gameLocal.FindEntityDef( token.c_str(), false ) ) {
- return va( "Unknown entityDef '%s'", token.c_str() );
- }
- fc.string = new idStr( token );
- } else if ( token == "attack_end" ) {
- fc.type = FC_ENDATTACK;
- } else if ( token == "muzzle_flash" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- if ( ( token != "" ) && !modelDef->FindJoint( token ) ) {
- return va( "Joint '%s' not found", token.c_str() );
- }
- fc.type = FC_MUZZLEFLASH;
- fc.string = new idStr( token );
- } else if ( token == "muzzle_flash" ) {
- fc.type = FC_MUZZLEFLASH;
- fc.string = new idStr( "" );
- } else if ( token == "create_missile" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- if ( !modelDef->FindJoint( token ) ) {
- return va( "Joint '%s' not found", token.c_str() );
- }
- fc.type = FC_CREATEMISSILE;
- fc.string = new idStr( token );
- } else if ( token == "launch_missile" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- if ( !modelDef->FindJoint( token ) ) {
- return va( "Joint '%s' not found", token.c_str() );
- }
- fc.type = FC_LAUNCHMISSILE;
- fc.string = new idStr( token );
- } else if ( token == "fire_missile_at_target" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- jointInfo = modelDef->FindJoint( token );
- if ( !jointInfo ) {
- return va( "Joint '%s' not found", token.c_str() );
- }
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_FIREMISSILEATTARGET;
- fc.string = new idStr( token );
- fc.index = jointInfo->num;
- #ifdef _D3XP
- } else if ( token == "launch_projectile" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- if ( !declManager->FindDeclWithoutParsing( DECL_ENTITYDEF, token, false ) ) {
- return "Unknown projectile def";
- }
- fc.type = FC_LAUNCH_PROJECTILE;
- fc.string = new idStr( token );
- } else if ( token == "trigger_fx" ) {
-
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- jointInfo = modelDef->FindJoint( token );
- if ( !jointInfo ) {
- return va( "Joint '%s' not found", token.c_str() );
- }
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- if ( !declManager->FindType( DECL_FX, token, false ) ) {
- return "Unknown FX def";
- }
- fc.type = FC_TRIGGER_FX;
- fc.string = new idStr( token );
- fc.index = jointInfo->num;
- } else if ( token == "start_emitter" ) {
- idStr str;
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- str = token + " ";
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- jointInfo = modelDef->FindJoint( token );
- if ( !jointInfo ) {
- return va( "Joint '%s' not found", token.c_str() );
- }
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- str += token;
- fc.type = FC_START_EMITTER;
- fc.string = new idStr( str );
- fc.index = jointInfo->num;
- } else if ( token == "stop_emitter" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_STOP_EMITTER;
- fc.string = new idStr( token );
- #endif
- } else if ( token == "footstep" ) {
- fc.type = FC_FOOTSTEP;
- } else if ( token == "leftfoot" ) {
- fc.type = FC_LEFTFOOT;
- } else if ( token == "rightfoot" ) {
- fc.type = FC_RIGHTFOOT;
- } else if ( token == "enableEyeFocus" ) {
- fc.type = FC_ENABLE_EYE_FOCUS;
- } else if ( token == "disableEyeFocus" ) {
- fc.type = FC_DISABLE_EYE_FOCUS;
- } else if ( token == "disableGravity" ) {
- fc.type = FC_DISABLE_GRAVITY;
- } else if ( token == "enableGravity" ) {
- fc.type = FC_ENABLE_GRAVITY;
- } else if ( token == "jump" ) {
- fc.type = FC_JUMP;
- } else if ( token == "enableClip" ) {
- fc.type = FC_ENABLE_CLIP;
- } else if ( token == "disableClip" ) {
- fc.type = FC_DISABLE_CLIP;
- } else if ( token == "enableWalkIK" ) {
- fc.type = FC_ENABLE_WALK_IK;
- } else if ( token == "disableWalkIK" ) {
- fc.type = FC_DISABLE_WALK_IK;
- } else if ( token == "enableLegIK" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_ENABLE_LEG_IK;
- fc.index = atoi( token );
- } else if ( token == "disableLegIK" ) {
- if( !src.ReadTokenOnLine( &token ) ) {
- return "Unexpected end of line";
- }
- fc.type = FC_DISABLE_LEG_IK;
- fc.index = atoi( token );
- } else if ( token == "recordDemo" ) {
- fc.type = FC_RECORDDEMO;
- if( src.ReadTokenOnLine( &token ) ) {
- fc.string = new idStr( token );
- }
- } else if ( token == "aviGame" ) {
- fc.type = FC_AVIGAME;
- if( src.ReadTokenOnLine( &token ) ) {
- fc.string = new idStr( token );
- }
- } else {
- return va( "Unknown command '%s'", token.c_str() );
- }
- // check if we've initialized the frame loopup table
- if ( !frameLookup.Num() ) {
- // we haven't, so allocate the table and initialize it
- frameLookup.SetGranularity( 1 );
- frameLookup.SetNum( anims[ 0 ]->NumFrames() );
- for( i = 0; i < frameLookup.Num(); i++ ) {
- frameLookup[ i ].num = 0;
- frameLookup[ i ].firstCommand = 0;
- }
- }
- // allocate space for a new command
- frameCommands.Alloc();
- // calculate the index of the new command
- index = frameLookup[ framenum ].firstCommand + frameLookup[ framenum ].num;
- // move all commands from our index onward up one to give us space for our new command
- for( i = frameCommands.Num() - 1; i > index; i-- ) {
- frameCommands[ i ] = frameCommands[ i - 1 ];
- }
- // fix the indices of any later frames to account for the inserted command
- for( i = framenum + 1; i < frameLookup.Num(); i++ ) {
- frameLookup[ i ].firstCommand++;
- }
- // store the new command
- frameCommands[ index ] = fc;
- // increase the number of commands on this frame
- frameLookup[ framenum ].num++;
- // return with no error
- return NULL;
- }
- /*
- =====================
- idAnim::CallFrameCommands
- =====================
- */
- void idAnim::CallFrameCommands( idEntity *ent, int from, int to ) const {
- int index;
- int end;
- int frame;
- int numframes;
- numframes = anims[ 0 ]->NumFrames();
- frame = from;
- while( frame != to ) {
- frame++;
- if ( frame >= numframes ) {
- frame = 0;
- }
- index = frameLookup[ frame ].firstCommand;
- end = index + frameLookup[ frame ].num;
- while( index < end ) {
- const frameCommand_t &command = frameCommands[ index++ ];
- switch( command.type ) {
- case FC_SCRIPTFUNCTION: {
- gameLocal.CallFrameCommand( ent, command.function );
- break;
- }
- case FC_SCRIPTFUNCTIONOBJECT: {
- gameLocal.CallObjectFrameCommand( ent, command.string->c_str() );
- break;
- }
- case FC_EVENTFUNCTION: {
- const idEventDef *ev = idEventDef::FindEvent( command.string->c_str() );
- ent->ProcessEvent( ev );
- break;
- }
- case FC_SOUND: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_ANY, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_ANY, 0, false, NULL );
- }
- break;
- }
- case FC_SOUND_VOICE: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_VOICE, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_voice' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_VOICE, 0, false, NULL );
- }
- break;
- }
- case FC_SOUND_VOICE2: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_VOICE2, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_voice2' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_VOICE2, 0, false, NULL );
- }
- break;
- }
- case FC_SOUND_BODY: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_BODY, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_body' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_BODY, 0, false, NULL );
- }
- break;
- }
- case FC_SOUND_BODY2: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_BODY2, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_body2' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_BODY2, 0, false, NULL );
- }
- break;
- }
- case FC_SOUND_BODY3: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_BODY3, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_body3' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_BODY3, 0, false, NULL );
- }
- break;
- }
- case FC_SOUND_WEAPON: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_WEAPON, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_weapon' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_WEAPON, 0, false, NULL );
- }
- break;
- }
- case FC_SOUND_GLOBAL: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_global' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
- }
- break;
- }
- case FC_SOUND_ITEM: {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_ITEM, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_item' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_ITEM, 0, false, NULL );
- }
- break;
- }
- case FC_SOUND_CHATTER: {
- if ( ent->CanPlayChatterSounds() ) {
- if ( !command.soundShader ) {
- if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_VOICE, 0, false, NULL ) ) {
- gameLocal.Warning( "Framecommand 'sound_chatter' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- } else {
- ent->StartSoundShader( command.soundShader, SND_CHANNEL_VOICE, 0, false, NULL );
- }
- }
- break;
- }
- case FC_FX: {
- idEntityFx::StartFx( command.string->c_str(), NULL, NULL, ent, true );
- break;
- }
- case FC_SKIN: {
- ent->SetSkin( command.skin );
- break;
- }
- case FC_TRIGGER: {
- idEntity *target;
- target = gameLocal.FindEntity( command.string->c_str() );
- if ( target ) {
- #ifdef _D3XP
- SetTimeState ts(target->timeGroup);
- #endif
- target->Signal( SIG_TRIGGER );
- target->ProcessEvent( &EV_Activate, ent );
- target->TriggerGuis();
- } else {
- gameLocal.Warning( "Framecommand 'trigger' on entity '%s', anim '%s', frame %d: Could not find entity '%s'",
- ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
- }
- break;
- }
- case FC_TRIGGER_SMOKE_PARTICLE: {
- ent->ProcessEvent( &AI_TriggerParticles, command.string->c_str() );
- break;
- }
- case FC_MELEE: {
- ent->ProcessEvent( &AI_AttackMelee, command.string->c_str() );
- break;
- }
- case FC_DIRECTDAMAGE: {
- ent->ProcessEvent( &AI_DirectDamage, command.string->c_str() );
- break;
- }
- case FC_BEGINATTACK: {
- ent->ProcessEvent( &AI_BeginAttack, command.string->c_str() );
- break;
- }
- case FC_ENDATTACK: {
- ent->ProcessEvent( &AI_EndAttack );
- break;
- }
- case FC_MUZZLEFLASH: {
- ent->ProcessEvent( &AI_MuzzleFlash, command.string->c_str() );
- break;
- }
- case FC_CREATEMISSILE: {
- ent->ProcessEvent( &AI_CreateMissile, command.string->c_str() );
- break;
- }
- case FC_LAUNCHMISSILE: {
- ent->ProcessEvent( &AI_AttackMissile, command.string->c_str() );
- break;
- }
- case FC_FIREMISSILEATTARGET: {
- ent->ProcessEvent( &AI_FireMissileAtTarget, modelDef->GetJointName( command.index ), command.string->c_str() );
- break;
- }
- #ifdef _D3XP
- case FC_LAUNCH_PROJECTILE: {
- ent->ProcessEvent( &AI_LaunchProjectile, command.string->c_str() );
- break;
- }
- case FC_TRIGGER_FX: {
- ent->ProcessEvent( &AI_TriggerFX, modelDef->GetJointName( command.index ), command.string->c_str() );
- break;
- }
- case FC_START_EMITTER: {
- int index = command.string->Find(" ");
- if(index >= 0) {
- idStr name = command.string->Left(index);
- idStr particle = command.string->Right(command.string->Length() - index - 1);
- ent->ProcessEvent( &AI_StartEmitter, name.c_str(), modelDef->GetJointName( command.index ), particle.c_str() );
- }
- }
- case FC_STOP_EMITTER: {
- ent->ProcessEvent( &AI_StopEmitter, command.string->c_str() );
- }
- #endif
- case FC_FOOTSTEP : {
- ent->ProcessEvent( &EV_Footstep );
- break;
- }
- case FC_LEFTFOOT: {
- ent->ProcessEvent( &EV_FootstepLeft );
- break;
- }
- case FC_RIGHTFOOT: {
- ent->ProcessEvent( &EV_FootstepRight );
- break;
- }
- case FC_ENABLE_EYE_FOCUS: {
- ent->ProcessEvent( &AI_EnableEyeFocus );
- break;
- }
- case FC_DISABLE_EYE_FOCUS: {
- ent->ProcessEvent( &AI_DisableEyeFocus );
- break;
- }
- case FC_DISABLE_GRAVITY: {
- ent->ProcessEvent( &AI_DisableGravity );
- break;
- }
- case FC_ENABLE_GRAVITY: {
- ent->ProcessEvent( &AI_EnableGravity );
- break;
- }
- case FC_JUMP: {
- ent->ProcessEvent( &AI_JumpFrame );
- break;
- }
- case FC_ENABLE_CLIP: {
- ent->ProcessEvent( &AI_EnableClip );
- break;
- }
- case FC_DISABLE_CLIP: {
- ent->ProcessEvent( &AI_DisableClip );
- break;
- }
- case FC_ENABLE_WALK_IK: {
- ent->ProcessEvent( &EV_EnableWalkIK );
- break;
- }
- case FC_DISABLE_WALK_IK: {
- ent->ProcessEvent( &EV_DisableWalkIK );
- break;
- }
- case FC_ENABLE_LEG_IK: {
- ent->ProcessEvent( &EV_EnableLegIK, command.index );
- break;
- }
- case FC_DISABLE_LEG_IK: {
- ent->ProcessEvent( &EV_DisableLegIK, command.index );
- break;
- }
- case FC_RECORDDEMO: {
- if ( command.string ) {
- cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "recordDemo %s", command.string->c_str() ) );
- } else {
- cmdSystem->BufferCommandText( CMD_EXEC_NOW, "stoprecording" );
- }
- break;
- }
- case FC_AVIGAME: {
- if ( command.string ) {
- cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "aviGame %s", command.string->c_str() ) );
- } else {
- cmdSystem->BufferCommandText( CMD_EXEC_NOW, "aviGame" );
- }
- break;
- }
- }
- }
- }
- }
- /*
- =====================
- idAnim::FindFrameForFrameCommand
- =====================
- */
- int idAnim::FindFrameForFrameCommand( frameCommandType_t framecommand, const frameCommand_t **command ) const {
- int frame;
- int index;
- int numframes;
- int end;
- if ( !frameCommands.Num() ) {
- return -1;
- }
- numframes = anims[ 0 ]->NumFrames();
- for( frame = 0; frame < numframes; frame++ ) {
- end = frameLookup[ frame ].firstCommand + frameLookup[ frame ].num;
- for( index = frameLookup[ frame ].firstCommand; index < end; index++ ) {
- if ( frameCommands[ index ].type == framecommand ) {
- if ( command ) {
- *command = &frameCommands[ index ];
- }
- return frame;
- }
- }
- }
- if ( command ) {
- *command = NULL;
- }
- return -1;
- }
- /*
- =====================
- idAnim::HasFrameCommands
- =====================
- */
- bool idAnim::HasFrameCommands( void ) const {
- if ( !frameCommands.Num() ) {
- return false;
- }
- return true;
- }
- /*
- =====================
- idAnim::SetAnimFlags
- =====================
- */
- void idAnim::SetAnimFlags( const animFlags_t &animflags ) {
- flags = animflags;
- }
- /*
- =====================
- idAnim::GetAnimFlags
- =====================
- */
- const animFlags_t &idAnim::GetAnimFlags( void ) const {
- return flags;
- }
- /***********************************************************************
- idAnimBlend
- ***********************************************************************/
- /*
- =====================
- idAnimBlend::idAnimBlend
- =====================
- */
- idAnimBlend::idAnimBlend( void ) {
- Reset( NULL );
- }
- /*
- =====================
- idAnimBlend::Save
- archives object for save game file
- =====================
- */
- void idAnimBlend::Save( idSaveGame *savefile ) const {
- int i;
- savefile->WriteInt( starttime );
- savefile->WriteInt( endtime );
- savefile->WriteInt( timeOffset );
- savefile->WriteFloat( rate );
- savefile->WriteInt( blendStartTime );
- savefile->WriteInt( blendDuration );
- savefile->WriteFloat( blendStartValue );
- savefile->WriteFloat( blendEndValue );
- for( i = 0; i < ANIM_MaxSyncedAnims; i++ ) {
- savefile->WriteFloat( animWeights[ i ] );
- }
- savefile->WriteShort( cycle );
- savefile->WriteShort( frame );
- savefile->WriteShort( animNum );
- savefile->WriteBool( allowMove );
- savefile->WriteBool( allowFrameCommands );
- }
- /*
- =====================
- idAnimBlend::Restore
- unarchives object from save game file
- =====================
- */
- void idAnimBlend::Restore( idRestoreGame *savefile, const idDeclModelDef *modelDef ) {
- int i;
- this->modelDef = modelDef;
- savefile->ReadInt( starttime );
- savefile->ReadInt( endtime );
- savefile->ReadInt( timeOffset );
- savefile->ReadFloat( rate );
- savefile->ReadInt( blendStartTime );
- savefile->ReadInt( blendDuration );
- savefile->ReadFloat( blendStartValue );
- savefile->ReadFloat( blendEndValue );
- for( i = 0; i < ANIM_MaxSyncedAnims; i++ ) {
- savefile->ReadFloat( animWeights[ i ] );
- }
- savefile->ReadShort( cycle );
- savefile->ReadShort( frame );
- savefile->ReadShort( animNum );
- if ( !modelDef ) {
- animNum = 0;
- } else if ( ( animNum < 0 ) || ( animNum > modelDef->NumAnims() ) ) {
- gameLocal.Warning( "Anim number %d out of range for model '%s' during save game", animNum, modelDef->GetModelName() );
- animNum = 0;
- }
- savefile->ReadBool( allowMove );
- savefile->ReadBool( allowFrameCommands );
- }
- /*
- =====================
- idAnimBlend::Reset
- =====================
- */
- void idAnimBlend::Reset( const idDeclModelDef *_modelDef ) {
- modelDef = _modelDef;
- cycle = 1;
- starttime = 0;
- endtime = 0;
- timeOffset = 0;
- rate = 1.0f;
- frame = 0;
- allowMove = true;
- allowFrameCommands = true;
- animNum = 0;
- memset( animWeights, 0, sizeof( animWeights ) );
- blendStartValue = 0.0f;
- blendEndValue = 0.0f;
- blendStartTime = 0;
- blendDuration = 0;
- }
- /*
- =====================
- idAnimBlend::FullName
- =====================
- */
- const char *idAnimBlend::AnimFullName( void ) const {
- const idAnim *anim = Anim();
- if ( !anim ) {
- return "";
- }
- return anim->FullName();
- }
- /*
- =====================
- idAnimBlend::AnimName
- =====================
- */
- const char *idAnimBlend::AnimName( void ) const {
- const idAnim *anim = Anim();
- if ( !anim ) {
- return "";
- }
- return anim->Name();
- }
- /*
- =====================
- idAnimBlend::NumFrames
- =====================
- */
- int idAnimBlend::NumFrames( void ) const {
- const idAnim *anim = Anim();
- if ( !anim ) {
- return 0;
- }
- return anim->NumFrames();
- }
- /*
- =====================
- idAnimBlend::Length
- =====================
- */
- int idAnimBlend::Length( void ) const {
- const idAnim *anim = Anim();
- if ( !anim ) {
- return 0;
- }
- return anim->Length();
- }
- /*
- =====================
- idAnimBlend::GetWeight
- =====================
- */
- float idAnimBlend::GetWeight( int currentTime ) const {
- int timeDelta;
- float frac;
- float w;
- timeDelta = currentTime - blendStartTime;
- if ( timeDelta <= 0 ) {
- w = blendStartValue;
- } else if ( timeDelta >= blendDuration ) {
- w = blendEndValue;
- } else {
- frac = ( float )timeDelta / ( float )blendDuration;
- w = blendStartValue + ( blendEndValue - blendStartValue ) * frac;
- }
- return w;
- }
- /*
- =====================
- idAnimBlend::GetFinalWeight
- =====================
- */
- float idAnimBlend::GetFinalWeight( void ) const {
- return blendEndValue;
- }
- /*
- =====================
- idAnimBlend::SetWeight
- =====================
- */
- void idAnimBlend::SetWeight( float newweight, int currentTime, int blendTime ) {
- blendStartValue = GetWeight( currentTime );
- blendEndValue = newweight;
- blendStartTime = currentTime - 1;
- blendDuration = blendTime;
- if ( !newweight ) {
- endtime = currentTime + blendTime;
- }
- }
- /*
- =====================
- idAnimBlend::NumSyncedAnims
- =====================
- */
- int idAnimBlend::NumSyncedAnims( void ) const {
- const idAnim *anim = Anim();
- if ( !anim ) {
- return 0;
- }
- return anim->NumAnims();
- }
- /*
- =====================
- idAnimBlend::SetSyncedAnimWeight
- =====================
- */
- bool idAnimBlend::SetSyncedAnimWeight( int num, float weight ) {
- const idAnim *anim = Anim();
- if ( !anim ) {
- return false;
- }
- if ( ( num < 0 ) || ( num > anim->NumAnims() ) ) {
- return false;
- }
- animWeights[ num ] = weight;
- return true;
- }
- /*
- =====================
- idAnimBlend::SetFrame
- =====================
- */
- void idAnimBlend::SetFrame( const idDeclModelDef *modelDef, int _animNum, int _frame, int currentTime, int blendTime ) {
- Reset( modelDef );
- if ( !modelDef ) {
- return;
- }
-
- const idAnim *_anim = modelDef->GetAnim( _animNum );
- if ( !_anim ) {
- return;
- }
- const idMD5Anim *md5anim = _anim->MD5Anim( 0 );
- if ( modelDef->Joints().Num() != md5anim->NumJoints() ) {
- gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", modelDef->GetModelName(), md5anim->Name() );
- return;
- }
-
- animNum = _animNum;
- starttime = currentTime;
- endtime = -1;
- cycle = -1;
- animWeights[ 0 ] = 1.0f;
- frame = _frame;
- // a frame of 0 means it's not a single frame blend, so we set it to frame + 1
- if ( frame <= 0 ) {
- frame = 1;
- } else if ( frame > _anim->NumFrames() ) {
- frame = _anim->NumFrames();
- }
- // set up blend
- blendEndValue = 1.0f;
- blendStartTime = currentTime - 1;
- blendDuration = blendTime;
- blendStartValue = 0.0f;
- }
- /*
- =====================
- idAnimBlend::CycleAnim
- =====================
- */
- void idAnimBlend::CycleAnim( const idDeclModelDef *modelDef, int _animNum, int currentTime, int blendTime ) {
- Reset( modelDef );
- if ( !modelDef ) {
- return;
- }
-
- const idAnim *_anim = modelDef->GetAnim( _animNum );
- if ( !_anim ) {
- return;
- }
- const idMD5Anim *md5anim = _anim->MD5Anim( 0 );
- if ( modelDef->Joints().Num() != md5anim->NumJoints() ) {
- gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", modelDef->GetModelName(), md5anim->Name() );
- return;
- }
- animNum = _animNum;
- animWeights[ 0 ] = 1.0f;
- endtime = -1;
- cycle = -1;
- if ( _anim->GetAnimFlags().random_cycle_start ) {
- // start the animation at a random time so that characters don't walk in sync
- starttime = currentTime - gameLocal.random.RandomFloat() * _anim->Length();
- } else {
- starttime = currentTime;
- }
- // set up blend
- blendEndValue = 1.0f;
- blendStartTime = currentTime - 1;
- blendDuration = blendTime;
- blendStartValue = 0.0f;
- }
- /*
- =====================
- idAnimBlend::PlayAnim
- =====================
- */
- void idAnimBlend::PlayAnim( const idDeclModelDef *modelDef, int _animNum, int currentTime, int blendTime ) {
- Reset( modelDef );
- if ( !modelDef ) {
- return;
- }
-
- const idAnim *_anim = modelDef->GetAnim( _animNum );
- if ( !_anim ) {
- return;
- }
- const idMD5Anim *md5anim = _anim->MD5Anim( 0 );
- if ( modelDef->Joints().Num() != md5anim->NumJoints() ) {
- gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", modelDef->GetModelName(), md5anim->Name() );
- return;
- }
- animNum = _animNum;
- starttime = currentTime;
- endtime = starttime + _anim->Length();
- cycle = 1;
- animWeights[ 0 ] = 1.0f;
- // set up blend
- blendEndValue = 1.0f;
- blendStartTime = currentTime - 1;
- blendDuration = blendTime;
- blendStartValue = 0.0f;
- }
- /*
- =====================
- idAnimBlend::Clear
- =====================
- */
- void idAnimBlend::Clear( int currentTime, int clearTime ) {
- if ( !clearTime ) {
- Reset( modelDef );
- } else {
- SetWeight( 0.0f, currentTime, clearTime );
- }
- }
- /*
- =====================
- idAnimBlend::IsDone
- =====================
- */
- bool idAnimBlend::IsDone( int currentTime ) const {
- if ( !frame && ( endtime > 0 ) && ( currentTime >= endtime ) ) {
- return true;
- }
- if ( ( blendEndValue <= 0.0f ) && ( currentTime >= ( blendStartTime + blendDuration ) ) ) {
- return true;
- }
- return false;
- }
- /*
- =====================
- idAnimBlend::FrameHasChanged
- =====================
- */
- bool idAnimBlend::FrameHasChanged( int currentTime ) const {
- // if we don't have an anim, no change
- if ( !animNum ) {
- return false;
- }
- // if anim is done playing, no change
- if ( ( endtime > 0 ) && ( currentTime > endtime ) ) {
- return false;
- }
- // if our blend weight changes, we need to update
- if ( ( currentTime < ( blendStartTime + blendDuration ) && ( blendStartValue != blendEndValue ) ) ) {
- return true;
- }
- // if we're a single frame anim and this isn't the frame we started on, we don't need to update
- if ( ( frame || ( NumFrames() == 1 ) ) && ( currentTime != starttime ) ) {
- return false;
- }
- return true;
- }
- /*
- =====================
- idAnimBlend::GetCycleCount
- =====================
- */
- int idAnimBlend::GetCycleCount( void ) const {
- return cycle;
- }
- /*
- =====================
- idAnimBlend::SetCycleCount
- =====================
- */
- void idAnimBlend::SetCycleCount( int count ) {
- const idAnim *anim = Anim();
- if ( !anim ) {
- cycle = -1;
- endtime = 0;
- } else {
- cycle = count;
- if ( cycle < 0 ) {
- cycle = -1;
- endtime = -1;
- } else if ( cycle == 0 ) {
- cycle = 1;
- // most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
- if ( rate == 1.0f ) {
- endtime = starttime - timeOffset + anim->Length();
- } else if ( rate != 0.0f ) {
- endtime = starttime - timeOffset + anim->Length() / rate;
- } else {
- endtime = -1;
- }
- } else {
- // most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
- if ( rate == 1.0f ) {
- endtime = starttime - timeOffset + anim->Length() * cycle;
- } else if ( rate != 0.0f ) {
- endtime = starttime - timeOffset + ( anim->Length() * cycle ) / rate;
- } else {
- endtime = -1;
- }
- }
- }
- }
- /*
- =====================
- idAnimBlend::SetPlaybackRate
- =====================
- */
- void idAnimBlend::SetPlaybackRate( int currentTime, float newRate ) {
- int animTime;
- if ( rate == newRate ) {
- return;
- }
- animTime = AnimTime( currentTime );
- if ( newRate == 1.0f ) {
- timeOffset = animTime - ( currentTime - starttime );
- } else {
- timeOffset = animTime - ( currentTime - starttime ) * newRate;
- }
- rate = newRate;
- // update the anim endtime
- SetCycleCount( cycle );
- }
- /*
- =====================
- idAnimBlend::GetPlaybackRate
- =====================
- */
- float idAnimBlend::GetPlaybackRate( void ) const {
- return rate;
- }
- /*
- =====================
- idAnimBlend::SetStartTime
- =====================
- */
- void idAnimBlend::SetStartTime( int _startTime ) {
- starttime = _startTime;
- // update the anim endtime
- SetCycleCount( cycle );
- }
- /*
- =====================
- idAnimBlend::GetStartTime
- =====================
- */
- int idAnimBlend::GetStartTime( void ) const {
- if ( !animNum ) {
- return 0;
- }
- return starttime;
- }
- /*
- =====================
- idAnimBlend::GetEndTime
- =====================
- */
- int idAnimBlend::GetEndTime( void ) const {
- if ( !animNum ) {
- return 0;
- }
- return endtime;
- }
- /*
- =====================
- idAnimBlend::PlayLength
- =====================
- */
- int idAnimBlend::PlayLength( void ) const {
- if ( !animNum ) {
- return 0;
- }
- if ( endtime < 0 ) {
- return -1;
- }
- return endtime - starttime + timeOffset;
- }
- /*
- =====================
- idAnimBlend::AllowMovement
- =====================
- */
- void idAnimBlend::AllowMovement( bool allow ) {
- allowMove = allow;
- }
- /*
- =====================
- idAnimBlend::AllowFrameCommands
- =====================
- */
- void idAnimBlend::AllowFrameCommands( bool allow ) {
- allowFrameCommands = allow;
- }
- /*
- =====================
- idAnimBlend::Anim
- =====================
- */
- const idAnim *idAnimBlend::Anim( void ) const {
- if ( !modelDef ) {
- return NULL;
- }
- const idAnim *anim = modelDef->GetAnim( animNum );
- return anim;
- }
- /*
- =====================
- idAnimBlend::AnimNum
- =====================
- */
- int idAnimBlend::AnimNum( void ) const {
- return animNum;
- }
- /*
- =====================
- idAnimBlend::AnimTime
- =====================
- */
- int idAnimBlend::AnimTime( int currentTime ) const {
- int time;
- int length;
- const idAnim *anim = Anim();
- if ( anim ) {
- if ( frame ) {
- return FRAME2MS( frame - 1 );
- }
- // most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
- if ( rate == 1.0f ) {
- time = currentTime - starttime + timeOffset;
- } else {
- time = static_cast<int>( ( currentTime - starttime ) * rate ) + timeOffset;
- }
- // given enough time, we can easily wrap time around in our frame calculations, so
- // keep cycling animations' time within the length of the anim.
- length = anim->Length();
- if ( ( cycle < 0 ) && ( length > 0 ) ) {
- time %= length;
- // time will wrap after 24 days (oh no!), resulting in negative results for the %.
- // adding the length gives us the proper result.
- if ( time < 0 ) {
- time += length;
- }
- }
- return time;
- } else {
- return 0;
- }
- }
- /*
- =====================
- idAnimBlend::GetFrameNumber
- =====================
- */
- int idAnimBlend::GetFrameNumber( int currentTime ) const {
- const idMD5Anim *md5anim;
- frameBlend_t frameinfo;
- int animTime;
- const idAnim *anim = Anim();
- if ( !anim ) {
- return 1;
- }
- if ( frame ) {
- return frame;
- }
- md5anim = anim->MD5Anim( 0 );
- animTime = AnimTime( currentTime );
- md5anim->ConvertTimeToFrame( animTime, cycle, frameinfo );
- return frameinfo.frame1 + 1;
- }
- /*
- =====================
- idAnimBlend::CallFrameCommands
- =====================
- */
- void idAnimBlend::CallFrameCommands( idEntity *ent, int fromtime, int totime ) const {
- const idMD5Anim *md5anim;
- frameBlend_t frame1;
- frameBlend_t frame2;
- int fromFrameTime;
- int toFrameTime;
- if ( !allowFrameCommands || !ent || frame || ( ( endtime > 0 ) && ( fromtime > endtime ) ) ) {
- return;
- }
- const idAnim *anim = Anim();
- if ( !anim || !anim->HasFrameCommands() ) {
- return;
- }
- if ( totime <= starttime ) {
- // don't play until next frame or we'll play commands twice.
- // this happens on the player sometimes.
- return;
- }
- fromFrameTime = AnimTime( fromtime );
- toFrameTime = AnimTime( totime );
- if ( toFrameTime < fromFrameTime ) {
- toFrameTime += anim->Length();
- }
- md5anim = anim->MD5Anim( 0 );
- md5anim->ConvertTimeToFrame( fromFrameTime, cycle, frame1 );
- md5anim->ConvertTimeToFrame( toFrameTime, cycle, frame2 );
- if ( fromFrameTime <= 0 ) {
- // make sure first frame is called
- anim->CallFrameCommands( ent, -1, frame2.frame1 );
- } else {
- anim->CallFrameCommands( ent, frame1.frame1, frame2.frame1 );
- }
- }
- /*
- =====================
- idAnimBlend::BlendAnim
- =====================
- */
- bool idAnimBlend::BlendAnim( int currentTime, int channel, int numJoints, idJointQuat *blendFrame, float &blendWeight, bool removeOriginOffset, bool overrideBlend, bool printInfo ) const {
- int i;
- float lerp;
- float mixWeight;
- const idMD5Anim *md5anim;
- idJointQuat *ptr;
- frameBlend_t frametime;
- idJointQuat *jointFrame;
- idJointQuat *mixFrame;
- int numAnims;
- int time;
- const idAnim *anim = Anim();
- if ( !anim ) {
- return false;
- }
- float weight = GetWeight( currentTime );
- if ( blendWeight > 0.0f ) {
- if ( ( endtime >= 0 ) && ( currentTime >= endtime ) ) {
- return false;
- }
- if ( !weight ) {
- return false;
- }
- if ( overrideBlend ) {
- blendWeight = 1.0f - weight;
- }
- }
- if ( ( channel == ANIMCHANNEL_ALL ) && !blendWeight ) {
- // we don't need a temporary buffer, so just store it directly in the blend frame
- jointFrame = blendFrame;
- } else {
- // allocate a temporary buffer to copy the joints from
- jointFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( *jointFrame ) );
- }
- time = AnimTime( currentTime );
- numAnims = anim->NumAnims();
- if ( numAnims == 1 ) {
- md5anim = anim->MD5Anim( 0 );
- if ( frame ) {
- md5anim->GetSingleFrame( frame - 1, jointFrame, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
- } else {
- md5anim->ConvertTimeToFrame( time, cycle, frametime );
- md5anim->GetInterpolatedFrame( frametime, jointFrame, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
- }
- } else {
- //
- // need to mix the multipoint anim together first
- //
- // allocate a temporary buffer to copy the joints to
- mixFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( *jointFrame ) );
- if ( !frame ) {
- anim->MD5Anim( 0 )->ConvertTimeToFrame( time, cycle, frametime );
- }
- ptr = jointFrame;
- mixWeight = 0.0f;
- for( i = 0; i < numAnims; i++ ) {
- if ( animWeights[ i ] > 0.0f ) {
- mixWeight += animWeights[ i ];
- lerp = animWeights[ i ] / mixWeight;
- md5anim = anim->MD5Anim( i );
- if ( frame ) {
- md5anim->GetSingleFrame( frame - 1, ptr, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
- } else {
- md5anim->GetInterpolatedFrame( frametime, ptr, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
- }
- // only blend after the first anim is mixed in
- if ( ptr != jointFrame ) {
- SIMDProcessor->BlendJoints( jointFrame, ptr, lerp, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
- }
- ptr = mixFrame;
- }
- }
- if ( !mixWeight ) {
- return false;
- }
- }
- if ( removeOriginOffset ) {
- if ( allowMove ) {
- #ifdef VELOCITY_MOVE
- jointFrame[ 0 ].t.x = 0.0f;
- #else
- jointFrame[ 0 ].t.Zero();
- #endif
- }
- if ( anim->GetAnimFlags().anim_turn ) {
- jointFrame[ 0 ].q.Set( -0.70710677f, 0.0f, 0.0f, 0.70710677f );
- }
- }
- if ( !blendWeight ) {
- blendWeight = weight;
- if ( channel != ANIMCHANNEL_ALL ) {
- const int *index = modelDef->GetChannelJoints( channel );
- const int num = modelDef->NumJointsOnChannel( channel );
- for( i = 0; i < num; i++ ) {
- int j = index[i];
- blendFrame[j].t = jointFrame[j].t;
- blendFrame[j].q = jointFrame[j].q;
- }
- }
- } else {
- blendWeight += weight;
- lerp = weight / blendWeight;
- SIMDProcessor->BlendJoints( blendFrame, jointFrame, lerp, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
- }
- if ( printInfo ) {
- if ( frame ) {
- gameLocal.Printf( " %s: '%s', %d, %.2f%%\n", channelNames[ channel ], anim->FullName(), frame, weight * 100.0f );
- } else {
- gameLocal.Printf( " %s: '%s', %.3f, %.2f%%\n", channelNames[ channel ], anim->FullName(), ( float )frametime.frame1 + frametime.backlerp, weight * 100.0f );
- }
- }
- return true;
- }
- /*
- =====================
- idAnimBlend::BlendOrigin
- =====================
- */
- void idAnimBlend::BlendOrigin( int currentTime, idVec3 &blendPos, float &blendWeight, bool removeOriginOffset ) const {
- float lerp;
- idVec3 animpos;
- idVec3 pos;
- int time;
- int num;
- int i;
- if ( frame || ( ( endtime > 0 ) && ( currentTime > endtime ) ) ) {
- return;
- }
- const idAnim *anim = Anim();
- if ( !anim ) {
- return;
- }
- if ( allowMove && removeOriginOffset ) {
- return;
- }
- float weight = GetWeight( currentTime );
- if ( !weight ) {
- return;
- }
- time = AnimTime( currentTime );
- pos.Zero();
- num = anim->NumAnims();
- for( i = 0; i < num; i++ ) {
- anim->GetOrigin( animpos, i, time, cycle );
- pos += animpos * animWeights[ i ];
- }
- if ( !blendWeight ) {
- blendPos = pos;
- blendWeight = weight;
- } else {
- lerp = weight / ( blendWeight + weight );
- blendPos += lerp * ( pos - blendPos );
- blendWeight += weight;
- }
- }
- /*
- =====================
- idAnimBlend::BlendDelta
- =====================
- */
- void idAnimBlend::BlendDelta( int fromtime, int totime, idVec3 &blendDelta, float &blendWeight ) const {
- idVec3 pos1;
- idVec3 pos2;
- idVec3 animpos;
- idVec3 delta;
- int time1;
- int time2;
- float lerp;
- int num;
- int i;
-
- if ( frame || !allowMove || ( ( endtime > 0 ) && ( fromtime > endtime ) ) ) {
- return;
- }
- const idAnim *anim = Anim();
- if ( !anim ) {
- return;
- }
- float weight = GetWeight( totime );
- if ( !weight ) {
- return;
- }
- time1 = AnimTime( fromtime );
- time2 = AnimTime( totime );
- if ( time2 < time1 ) {
- time2 += anim->Length();
- }
- num = anim->NumAnims();
- pos1.Zero();
- pos2.Zero();
- for( i = 0; i < num; i++ ) {
- anim->GetOrigin( animpos, i, time1, cycle );
- pos1 += animpos * animWeights[ i ];
- anim->GetOrigin( animpos, i, time2, cycle );
- pos2 += animpos * animWeights[ i ];
- }
- delta = pos2 - pos1;
- if ( !blendWeight ) {
- blendDelta = delta;
- blendWeight = weight;
- } else {
- lerp = weight / ( blendWeight + weight );
- blendDelta += lerp * ( delta - blendDelta );
- blendWeight += weight;
- }
- }
- /*
- =====================
- idAnimBlend::BlendDeltaRotation
- =====================
- */
- void idAnimBlend::BlendDeltaRotation( int fromtime, int totime, idQuat &blendDelta, float &blendWeight ) const {
- idQuat q1;
- idQuat q2;
- idQuat q3;
- int time1;
- int time2;
- float lerp;
- float mixWeight;
- int num;
- int i;
-
- if ( frame || !allowMove || ( ( endtime > 0 ) && ( fromtime > endtime ) ) ) {
- return;
- }
- const idAnim *anim = Anim();
- if ( !anim || !anim->GetAnimFlags().anim_turn ) {
- return;
- }
- float weight = GetWeight( totime );
- if ( !weight ) {
- return;
- }
- time1 = AnimTime( fromtime );
- time2 = AnimTime( totime );
- if ( time2 < time1 ) {
- time2 += anim->Length();
- }
- q1.Set( 0.0f, 0.0f, 0.0f, 1.0f );
- q2.Set( 0.0f, 0.0f, 0.0f, 1.0f );
- mixWeight = 0.0f;
- num = anim->NumAnims();
- for( i = 0; i < num; i++ ) {
- if ( animWeights[ i ] > 0.0f ) {
- mixWeight += animWeights[ i ];
- if ( animWeights[ i ] == mixWeight ) {
- anim->GetOriginRotation( q1, i, time1, cycle );
- anim->GetOriginRotation( q2, i, time2, cycle );
- } else {
- lerp = animWeights[ i ] / mixWeight;
- anim->GetOriginRotation( q3, i, time1, cycle );
- q1.Slerp( q1, q3, lerp );
- anim->GetOriginRotation( q3, i, time2, cycle );
- q2.Slerp( q1, q3, lerp );
- }
- }
- }
- q3 = q1.Inverse() * q2;
- if ( !blendWeight ) {
- blendDelta = q3;
- blendWeight = weight;
- } else {
- lerp = weight / ( blendWeight + weight );
- blendDelta.Slerp( blendDelta, q3, lerp );
- blendWeight += weight;
- }
- }
- /*
- =====================
- idAnimBlend::AddBounds
- =====================
- */
- bool idAnimBlend::AddBounds( int currentTime, idBounds &bounds, bool removeOriginOffset ) const {
- int i;
- int num;
- idBounds b;
- int time;
- idVec3 pos;
- bool addorigin;
- if ( ( endtime > 0 ) && ( currentTime > endtime ) ) {
- return false;
- }
- const idAnim *anim = Anim();
- if ( !anim ) {
- return false;
- }
- float weight = GetWeight( currentTime );
- if ( !weight ) {
- return false;
- }
- time = AnimTime( currentTime );
- num = anim->NumAnims();
-
- addorigin = !allowMove || !removeOriginOffset;
- for( i = 0; i < num; i++ ) {
- if ( anim->GetBounds( b, i, time, cycle ) ) {
- if ( addorigin ) {
- anim->GetOrigin( pos, i, time, cycle );
- b.TranslateSelf( pos );
- }
- bounds.AddBounds( b );
- }
- }
- return true;
- }
- /***********************************************************************
- idDeclModelDef
- ***********************************************************************/
- /*
- =====================
- idDeclModelDef::idDeclModelDef
- =====================
- */
- idDeclModelDef::idDeclModelDef() {
- modelHandle = NULL;
- skin = NULL;
- offset.Zero();
- for ( int i = 0; i < ANIM_NumAnimChannels; i++ ) {
- channelJoints[i].Clear();
- }
- }
- /*
- =====================
- idDeclModelDef::~idDeclModelDef
- =====================
- */
- idDeclModelDef::~idDeclModelDef() {
- FreeData();
- }
- /*
- =================
- idDeclModelDef::Size
- =================
- */
- size_t idDeclModelDef::Size( void ) const {
- return sizeof( idDeclModelDef );
- }
- /*
- =====================
- idDeclModelDef::CopyDecl
- =====================
- */
- void idDeclModelDef::CopyDecl( const idDeclModelDef *decl ) {
- int i;
- FreeData();
- offset = decl->offset;
- modelHandle = decl->modelHandle;
- skin = decl->skin;
- anims.SetNum( decl->anims.Num() );
- for( i = 0; i < anims.Num(); i++ ) {
- anims[ i ] = new idAnim( this, decl->anims[ i ] );
- }
- joints.SetNum( decl->joints.Num() );
- memcpy( joints.Ptr(), decl->joints.Ptr(), decl->joints.Num() * sizeof( joints[0] ) );
- jointParents.SetNum( decl->jointParents.Num() );
- memcpy( jointParents.Ptr(), decl->jointParents.Ptr(), decl->jointParents.Num() * sizeof( jointParents[0] ) );
- for ( i = 0; i < ANIM_NumAnimChannels; i++ ) {
- channelJoints[i] = decl->channelJoints[i];
- }
- }
- /*
- =====================
- idDeclModelDef::FreeData
- =====================
- */
- void idDeclModelDef::FreeData( void ) {
- anims.DeleteContents( true );
- joints.Clear();
- jointParents.Clear();
- modelHandle = NULL;
- skin = NULL;
- offset.Zero();
- for ( int i = 0; i < ANIM_NumAnimChannels; i++ ) {
- channelJoints[i].Clear();
- }
- }
- /*
- ================
- idDeclModelDef::DefaultDefinition
- ================
- */
- const char *idDeclModelDef::DefaultDefinition( void ) const {
- return "{ }";
- }
- /*
- ====================
- idDeclModelDef::FindJoint
- ====================
- */
- const jointInfo_t *idDeclModelDef::FindJoint( const char *name ) const {
- int i;
- const idMD5Joint *joint;
- if ( !modelHandle ) {
- return NULL;
- }
-
- joint = modelHandle->GetJoints();
- for( i = 0; i < joints.Num(); i++, joint++ ) {
- if ( !joint->name.Icmp( name ) ) {
- return &joints[ i ];
- }
- }
- return NULL;
- }
- /*
- =====================
- idDeclModelDef::ModelHandle
- =====================
- */
- idRenderModel *idDeclModelDef::ModelHandle( void ) const {
- return ( idRenderModel * )modelHandle;
- }
- /*
- =====================
- idDeclModelDef::GetJointList
- =====================
- */
- void idDeclModelDef::GetJointList( const char *jointnames, idList<jointHandle_t> &jointList ) const {
- const char *pos;
- idStr jointname;
- const jointInfo_t *joint;
- const jointInfo_t *child;
- int i;
- int num;
- bool getChildren;
- bool subtract;
- if ( !modelHandle ) {
- return;
- }
- jointList.Clear();
- num = modelHandle->NumJoints();
- // scan through list of joints and add each to the joint list
- pos = jointnames;
- while( *pos ) {
- // skip over whitespace
- while( ( *pos != 0 ) && isspace( *pos ) ) {
- pos++;
- }
- if ( !*pos ) {
- // no more names
- break;
- }
- // copy joint name
- jointname = "";
- if ( *pos == '-' ) {
- subtract = true;
- pos++;
- } else {
- subtract = false;
- }
- if ( *pos == '*' ) {
- getChildren = true;
- pos++;
- } else {
- getChildren = false;
- }
- while( ( *pos != 0 ) && !isspace( *pos ) ) {
- jointname += *pos;
- pos++;
- }
- joint = FindJoint( jointname );
- if ( !joint ) {
- gameLocal.Warning( "Unknown joint '%s' in '%s' for model '%s'", jointname.c_str(), jointnames, GetName() );
- continue;
- }
- if ( !subtract ) {
- jointList.AddUnique( joint->num );
- } else {
- jointList.Remove( joint->num );
- }
- if ( getChildren ) {
- // include all joint's children
- child = joint + 1;
- for( i = joint->num + 1; i < num; i++, child++ ) {
- // all children of the joint should follow it in the list.
- // once we reach a joint without a parent or with a parent
- // who is earlier in the list than the specified joint, then
- // we've gone through all it's children.
- if ( child->parentNum < joint->num ) {
- break;
- }
- if ( !subtract ) {
- jointList.AddUnique( child->num );
- } else {
- jointList.Remove( child->num );
- }
- }
- }
- }
- }
- /*
- =====================
- idDeclModelDef::Touch
- =====================
- */
- void idDeclModelDef::Touch( void ) const {
- if ( modelHandle ) {
- renderModelManager->FindModel( modelHandle->Name() );
- }
- }
- /*
- =====================
- idDeclModelDef::GetDefaultSkin
- =====================
- */
- const idDeclSkin *idDeclModelDef::GetDefaultSkin( void ) const {
- return skin;
- }
- /*
- =====================
- idDeclModelDef::GetDefaultPose
- =====================
- */
- const idJointQuat *idDeclModelDef::GetDefaultPose( void ) const {
- return modelHandle->GetDefaultPose();
- }
- /*
- =====================
- idDeclModelDef::SetupJoints
- =====================
- */
- void idDeclModelDef::SetupJoints( int *numJoints, idJointMat **jointList, idBounds &frameBounds, bool removeOriginOffset ) const {
- int num;
- const idJointQuat *pose;
- idJointMat *list;
- if ( !modelHandle || modelHandle->IsDefaultModel() ) {
- Mem_Free16( (*jointList) );
- (*jointList) = NULL;
- frameBounds.Clear();
- return;
- }
- // get the number of joints
- num = modelHandle->NumJoints();
- if ( !num ) {
- gameLocal.Error( "model '%s' has no joints", modelHandle->Name() );
- }
- // set up initial pose for model (with no pose, model is just a jumbled mess)
- list = (idJointMat *) Mem_Alloc16( num * sizeof( list[0] ) );
- pose = GetDefaultPose();
- // convert the joint quaternions to joint matrices
- SIMDProcessor->ConvertJointQuatsToJointMats( list, pose, joints.Num() );
- // check if we offset the model by the origin joint
- if ( removeOriginOffset ) {
- #ifdef VELOCITY_MOVE
- list[ 0 ].SetTranslation( idVec3( offset.x, offset.y + pose[0].t.y, offset.z + pose[0].t.z ) );
- #else
- list[ 0 ].SetTranslation( offset );
- #endif
- } else {
- list[ 0 ].SetTranslation( pose[0].t + offset );
- }
- // transform the joint hierarchy
- SIMDProcessor->TransformJoints( list, jointParents.Ptr(), 1, joints.Num() - 1 );
- *numJoints = num;
- *jointList = list;
- // get the bounds of the default pose
- frameBounds = modelHandle->Bounds( NULL );
- }
- /*
- =====================
- idDeclModelDef::ParseAnim
- =====================
- */
- bool idDeclModelDef::ParseAnim( idLexer &src, int numDefaultAnims ) {
- int i;
- int len;
- idAnim *anim;
- const idMD5Anim *md5anims[ ANIM_MaxSyncedAnims ];
- const idMD5Anim *md5anim;
- idStr alias;
- idToken realname;
- idToken token;
- int numAnims;
- animFlags_t flags;
- numAnims = 0;
- memset( md5anims, 0, sizeof( md5anims ) );
- if( !src.ReadToken( &realname ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
- alias = realname;
- for( i = 0; i < anims.Num(); i++ ) {
- if ( !strcmp( anims[ i ]->FullName(), realname ) ) {
- break;
- }
- }
- if ( ( i < anims.Num() ) && ( i >= numDefaultAnims ) ) {
- src.Warning( "Duplicate anim '%s'", realname.c_str() );
- MakeDefault();
- return false;
- }
- if ( i < numDefaultAnims ) {
- anim = anims[ i ];
- } else {
- // create the alias associated with this animation
- anim = new idAnim();
- anims.Append( anim );
- }
- // random anims end with a number. find the numeric suffix of the animation.
- len = alias.Length();
- for( i = len - 1; i > 0; i-- ) {
- if ( !isdigit( alias[ i ] ) ) {
- break;
- }
- }
- // check for zero length name, or a purely numeric name
- if ( i <= 0 ) {
- src.Warning( "Invalid animation name '%s'", alias.c_str() );
- MakeDefault();
- return false;
- }
- // remove the numeric suffix
- alias.CapLength( i + 1 );
- // parse the anims from the string
- do {
- if( !src.ReadToken( &token ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
- // lookup the animation
- md5anim = animationLib.GetAnim( token );
- if ( !md5anim ) {
- src.Warning( "Couldn't load anim '%s'", token.c_str() );
- MakeDefault();
- return false;
- }
- md5anim->CheckModelHierarchy( modelHandle );
- if ( numAnims > 0 ) {
- // make sure it's the same length as the other anims
- if ( md5anim->Length() != md5anims[ 0 ]->Length() ) {
- src.Warning( "Anim '%s' does not match length of anim '%s'", md5anim->Name(), md5anims[ 0 ]->Name() );
- MakeDefault();
- return false;
- }
- }
- if ( numAnims >= ANIM_MaxSyncedAnims ) {
- src.Warning( "Exceeded max synced anims (%d)", ANIM_MaxSyncedAnims );
- MakeDefault();
- return false;
- }
- // add it to our list
- md5anims[ numAnims ] = md5anim;
- numAnims++;
- } while ( src.CheckTokenString( "," ) );
- if ( !numAnims ) {
- src.Warning( "No animation specified" );
- MakeDefault();
- return false;
- }
- anim->SetAnim( this, realname, alias, numAnims, md5anims );
- memset( &flags, 0, sizeof( flags ) );
- // parse any frame commands or animflags
- if ( src.CheckTokenString( "{" ) ) {
- while( 1 ) {
- if( !src.ReadToken( &token ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
- if ( token == "}" ) {
- break;
- }else if ( token == "prevent_idle_override" ) {
- flags.prevent_idle_override = true;
- } else if ( token == "random_cycle_start" ) {
- flags.random_cycle_start = true;
- } else if ( token == "ai_no_turn" ) {
- flags.ai_no_turn = true;
- } else if ( token == "anim_turn" ) {
- flags.anim_turn = true;
- } else if ( token == "frame" ) {
- // create a frame command
- int framenum;
- const char *err;
- // make sure we don't have any line breaks while reading the frame command so the error line # will be correct
- if ( !src.ReadTokenOnLine( &token ) ) {
- src.Warning( "Missing frame # after 'frame'" );
- MakeDefault();
- return false;
- }
- if ( token.type == TT_PUNCTUATION && token == "-" ) {
- src.Warning( "Invalid frame # after 'frame'" );
- MakeDefault();
- return false;
- } else if ( token.type != TT_NUMBER || token.subtype == TT_FLOAT ) {
- src.Error( "expected integer value, found '%s'", token.c_str() );
- }
- // get the frame number
- framenum = token.GetIntValue();
- // put the command on the specified frame of the animation
- err = anim->AddFrameCommand( this, framenum, src, NULL );
- if ( err ) {
- src.Warning( "%s", err );
- MakeDefault();
- return false;
- }
- } else {
- src.Warning( "Unknown command '%s'", token.c_str() );
- MakeDefault();
- return false;
- }
- }
- }
- // set the flags
- anim->SetAnimFlags( flags );
- return true;
- }
- /*
- ================
- idDeclModelDef::Parse
- ================
- */
- bool idDeclModelDef::Parse( const char *text, const int textLength ) {
- int i;
- int num;
- idStr filename;
- idStr extension;
- const idMD5Joint *md5joint;
- const idMD5Joint *md5joints;
- idLexer src;
- idToken token;
- idToken token2;
- idStr jointnames;
- int channel;
- jointHandle_t jointnum;
- idList<jointHandle_t> jointList;
- int numDefaultAnims;
- src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
- src.SetFlags( DECL_LEXER_FLAGS );
- src.SkipUntilString( "{" );
- numDefaultAnims = 0;
- while( 1 ) {
- if ( !src.ReadToken( &token ) ) {
- break;
- }
- if ( !token.Icmp( "}" ) ) {
- break;
- }
- if ( token == "inherit" ) {
- if( !src.ReadToken( &token2 ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
-
- const idDeclModelDef *copy = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, token2, false ) );
- if ( !copy ) {
- common->Warning( "Unknown model definition '%s'", token2.c_str() );
- } else if ( copy->GetState() == DS_DEFAULTED ) {
- common->Warning( "inherited model definition '%s' defaulted", token2.c_str() );
- MakeDefault();
- return false;
- } else {
- CopyDecl( copy );
- numDefaultAnims = anims.Num();
- }
- } else if ( token == "skin" ) {
- if( !src.ReadToken( &token2 ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
- skin = declManager->FindSkin( token2 );
- if ( !skin ) {
- src.Warning( "Skin '%s' not found", token2.c_str() );
- MakeDefault();
- return false;
- }
- } else if ( token == "mesh" ) {
- if( !src.ReadToken( &token2 ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
- filename = token2;
- filename.ExtractFileExtension( extension );
- if ( extension != MD5_MESH_EXT ) {
- src.Warning( "Invalid model for MD5 mesh" );
- MakeDefault();
- return false;
- }
- modelHandle = renderModelManager->FindModel( filename );
- if ( !modelHandle ) {
- src.Warning( "Model '%s' not found", filename.c_str() );
- MakeDefault();
- return false;
- }
- if ( modelHandle->IsDefaultModel() ) {
- src.Warning( "Model '%s' defaulted", filename.c_str() );
- MakeDefault();
- return false;
- }
- // get the number of joints
- num = modelHandle->NumJoints();
- if ( !num ) {
- src.Warning( "Model '%s' has no joints", filename.c_str() );
- }
- // set up the joint hierarchy
- joints.SetGranularity( 1 );
- joints.SetNum( num );
- jointParents.SetNum( num );
- channelJoints[0].SetNum( num );
- md5joints = modelHandle->GetJoints();
- md5joint = md5joints;
- for( i = 0; i < num; i++, md5joint++ ) {
- joints[i].channel = ANIMCHANNEL_ALL;
- joints[i].num = static_cast<jointHandle_t>( i );
- if ( md5joint->parent ) {
- joints[i].parentNum = static_cast<jointHandle_t>( md5joint->parent - md5joints );
- } else {
- joints[i].parentNum = INVALID_JOINT;
- }
- jointParents[i] = joints[i].parentNum;
- channelJoints[0][i] = i;
- }
- } else if ( token == "remove" ) {
- // removes any anims whos name matches
- if( !src.ReadToken( &token2 ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
- num = 0;
- for( i = 0; i < anims.Num(); i++ ) {
- if ( ( token2 == anims[ i ]->Name() ) || ( token2 == anims[ i ]->FullName() ) ) {
- delete anims[ i ];
- anims.RemoveIndex( i );
- if ( i >= numDefaultAnims ) {
- src.Warning( "Anim '%s' was not inherited. Anim should be removed from the model def.", token2.c_str() );
- MakeDefault();
- return false;
- }
- i--;
- numDefaultAnims--;
- num++;
- continue;
- }
- }
- if ( !num ) {
- src.Warning( "Couldn't find anim '%s' to remove", token2.c_str() );
- MakeDefault();
- return false;
- }
- } else if ( token == "anim" ) {
- if ( !modelHandle ) {
- src.Warning( "Must specify mesh before defining anims" );
- MakeDefault();
- return false;
- }
- if ( !ParseAnim( src, numDefaultAnims ) ) {
- MakeDefault();
- return false;
- }
- } else if ( token == "offset" ) {
- if ( !src.Parse1DMatrix( 3, offset.ToFloatPtr() ) ) {
- src.Warning( "Expected vector following 'offset'" );
- MakeDefault();
- return false;
- }
- } else if ( token == "channel" ) {
- if ( !modelHandle ) {
- src.Warning( "Must specify mesh before defining channels" );
- MakeDefault();
- return false;
- }
- // set the channel for a group of joints
- if( !src.ReadToken( &token2 ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
- if ( !src.CheckTokenString( "(" ) ) {
- src.Warning( "Expected { after '%s'\n", token2.c_str() );
- MakeDefault();
- return false;
- }
- for( i = ANIMCHANNEL_ALL + 1; i < ANIM_NumAnimChannels; i++ ) {
- if ( !idStr::Icmp( channelNames[ i ], token2 ) ) {
- break;
- }
- }
- if ( i >= ANIM_NumAnimChannels ) {
- src.Warning( "Unknown channel '%s'", token2.c_str() );
- MakeDefault();
- return false;
- }
- channel = i;
- jointnames = "";
- while( !src.CheckTokenString( ")" ) ) {
- if( !src.ReadToken( &token2 ) ) {
- src.Warning( "Unexpected end of file" );
- MakeDefault();
- return false;
- }
- jointnames += token2;
- if ( ( token2 != "*" ) && ( token2 != "-" ) ) {
- jointnames += " ";
- }
- }
- GetJointList( jointnames, jointList );
- channelJoints[ channel ].SetNum( jointList.Num() );
- for( num = i = 0; i < jointList.Num(); i++ ) {
- jointnum = jointList[ i ];
- if ( joints[ jointnum ].channel != ANIMCHANNEL_ALL ) {
- src.Warning( "Joint '%s' assigned to multiple channels", modelHandle->GetJointName( jointnum ) );
- continue;
- }
- joints[ jointnum ].channel = channel;
- channelJoints[ channel ][ num++ ] = jointnum;
- }
- channelJoints[ channel ].SetNum( num );
- } else {
- src.Warning( "unknown token '%s'", token.c_str() );
- MakeDefault();
- return false;
- }
- }
- // shrink the anim list down to save space
- anims.SetGranularity( 1 );
- anims.SetNum( anims.Num() );
- return true;
- }
- /*
- =====================
- idDeclModelDef::HasAnim
- =====================
- */
- bool idDeclModelDef::HasAnim( const char *name ) const {
- int i;
- // find any animations with same name
- for( i = 0; i < anims.Num(); i++ ) {
- if ( !strcmp( anims[ i ]->Name(), name ) ) {
- return true;
- }
- }
-
- return false;
- }
- /*
- =====================
- idDeclModelDef::NumAnims
- =====================
- */
- int idDeclModelDef::NumAnims( void ) const {
- return anims.Num() + 1;
- }
- /*
- =====================
- idDeclModelDef::GetSpecificAnim
- Gets the exact anim for the name, without randomization.
- =====================
- */
- int idDeclModelDef::GetSpecificAnim( const char *name ) const {
- int i;
- // find a specific animation
- for( i = 0; i < anims.Num(); i++ ) {
- if ( !strcmp( anims[ i ]->FullName(), name ) ) {
- return i + 1;
- }
- }
- // didn't find it
- return 0;
- }
- /*
- =====================
- idDeclModelDef::GetAnim
- =====================
- */
- const idAnim *idDeclModelDef::GetAnim( int index ) const {
- if ( ( index < 1 ) || ( index > anims.Num() ) ) {
- return NULL;
- }
-
- return anims[ index - 1 ];
- }
- /*
- =====================
- idDeclModelDef::GetAnim
- =====================
- */
- int idDeclModelDef::GetAnim( const char *name ) const {
- int i;
- int which;
- const int MAX_ANIMS = 64;
- int animList[ MAX_ANIMS ];
- int numAnims;
- int len;
- len = strlen( name );
- if ( len && idStr::CharIsNumeric( name[ len - 1 ] ) ) {
- // find a specific animation
- return GetSpecificAnim( name );
- }
- // find all animations with same name
- numAnims = 0;
- for( i = 0; i < anims.Num(); i++ ) {
- if ( !strcmp( anims[ i ]->Name(), name ) ) {
- animList[ numAnims++ ] = i;
- if ( numAnims >= MAX_ANIMS ) {
- break;
- }
- }
- }
- if ( !numAnims ) {
- return 0;
- }
- // get a random anim
- //FIXME: don't access gameLocal here?
- which = gameLocal.random.RandomInt( numAnims );
- return animList[ which ] + 1;
- }
- /*
- =====================
- idDeclModelDef::GetSkin
- =====================
- */
- const idDeclSkin *idDeclModelDef::GetSkin( void ) const {
- return skin;
- }
- /*
- =====================
- idDeclModelDef::GetModelName
- =====================
- */
- const char *idDeclModelDef::GetModelName( void ) const {
- if ( modelHandle ) {
- return modelHandle->Name();
- } else {
- return "";
- }
- }
- /*
- =====================
- idDeclModelDef::Joints
- =====================
- */
- const idList<jointInfo_t> &idDeclModelDef::Joints( void ) const {
- return joints;
- }
- /*
- =====================
- idDeclModelDef::JointParents
- =====================
- */
- const int * idDeclModelDef::JointParents( void ) const {
- return jointParents.Ptr();
- }
- /*
- =====================
- idDeclModelDef::NumJoints
- =====================
- */
- int idDeclModelDef::NumJoints( void ) const {
- return joints.Num();
- }
- /*
- =====================
- idDeclModelDef::GetJoint
- =====================
- */
- const jointInfo_t *idDeclModelDef::GetJoint( int jointHandle ) const {
- if ( ( jointHandle < 0 ) || ( jointHandle > joints.Num() ) ) {
- gameLocal.Error( "idDeclModelDef::GetJoint : joint handle out of range" );
- }
- return &joints[ jointHandle ];
- }
- /*
- ====================
- idDeclModelDef::GetJointName
- ====================
- */
- const char *idDeclModelDef::GetJointName( int jointHandle ) const {
- const idMD5Joint *joint;
- if ( !modelHandle ) {
- return NULL;
- }
-
- if ( ( jointHandle < 0 ) || ( jointHandle > joints.Num() ) ) {
- gameLocal.Error( "idDeclModelDef::GetJointName : joint handle out of range" );
- }
- joint = modelHandle->GetJoints();
- return joint[ jointHandle ].name.c_str();
- }
- /*
- =====================
- idDeclModelDef::NumJointsOnChannel
- =====================
- */
- int idDeclModelDef::NumJointsOnChannel( int channel ) const {
- if ( ( channel < 0 ) || ( channel >= ANIM_NumAnimChannels ) ) {
- gameLocal.Error( "idDeclModelDef::NumJointsOnChannel : channel out of range" );
- }
- return channelJoints[ channel ].Num();
- }
- /*
- =====================
- idDeclModelDef::GetChannelJoints
- =====================
- */
- const int * idDeclModelDef::GetChannelJoints( int channel ) const {
- if ( ( channel < 0 ) || ( channel >= ANIM_NumAnimChannels ) ) {
- gameLocal.Error( "idDeclModelDef::GetChannelJoints : channel out of range" );
- }
- return channelJoints[ channel ].Ptr();
- }
- /*
- =====================
- idDeclModelDef::GetVisualOffset
- =====================
- */
- const idVec3 &idDeclModelDef::GetVisualOffset( void ) const {
- return offset;
- }
- /***********************************************************************
- idAnimator
- ***********************************************************************/
- /*
- =====================
- idAnimator::idAnimator
- =====================
- */
- idAnimator::idAnimator() {
- int i, j;
- modelDef = NULL;
- entity = NULL;
- numJoints = 0;
- joints = NULL;
- lastTransformTime = -1;
- stoppedAnimatingUpdate = false;
- removeOriginOffset = false;
- forceUpdate = false;
- frameBounds.Clear();
- AFPoseJoints.SetGranularity( 1 );
- AFPoseJointMods.SetGranularity( 1 );
- AFPoseJointFrame.SetGranularity( 1 );
- ClearAFPose();
- for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
- channels[ i ][ j ].Reset( NULL );
- }
- }
- }
- /*
- =====================
- idAnimator::~idAnimator
- =====================
- */
- idAnimator::~idAnimator() {
- FreeData();
- }
- /*
- =====================
- idAnimator::Allocated
- =====================
- */
- size_t idAnimator::Allocated( void ) const {
- size_t size;
- size = jointMods.Allocated() + numJoints * sizeof( joints[0] ) + jointMods.Num() * sizeof( jointMods[ 0 ] ) + AFPoseJointMods.Allocated() + AFPoseJointFrame.Allocated() + AFPoseJoints.Allocated();
- return size;
- }
- /*
- =====================
- idAnimator::Save
- archives object for save game file
- =====================
- */
- void idAnimator::Save( idSaveGame *savefile ) const {
- int i;
- int j;
- savefile->WriteModelDef( modelDef );
- savefile->WriteObject( entity );
- savefile->WriteInt( jointMods.Num() );
- for( i = 0; i < jointMods.Num(); i++ ) {
- savefile->WriteInt( jointMods[ i ]->jointnum );
- savefile->WriteMat3( jointMods[ i ]->mat );
- savefile->WriteVec3( jointMods[ i ]->pos );
- savefile->WriteInt( (int&)jointMods[ i ]->transform_pos );
- savefile->WriteInt( (int&)jointMods[ i ]->transform_axis );
- }
-
- savefile->WriteInt( numJoints );
- for ( i = 0; i < numJoints; i++ ) {
- float *data = joints[i].ToFloatPtr();
- for ( j = 0; j < 12; j++ ) {
- savefile->WriteFloat( data[j] );
- }
- }
- savefile->WriteInt( lastTransformTime );
- savefile->WriteBool( stoppedAnimatingUpdate );
- savefile->WriteBool( forceUpdate );
- savefile->WriteBounds( frameBounds );
- savefile->WriteFloat( AFPoseBlendWeight );
- savefile->WriteInt( AFPoseJoints.Num() );
- for ( i = 0; i < AFPoseJoints.Num(); i++ ) {
- savefile->WriteInt( AFPoseJoints[i] );
- }
-
- savefile->WriteInt( AFPoseJointMods.Num() );
- for ( i = 0; i < AFPoseJointMods.Num(); i++ ) {
- savefile->WriteInt( (int&)AFPoseJointMods[i].mod );
- savefile->WriteMat3( AFPoseJointMods[i].axis );
- savefile->WriteVec3( AFPoseJointMods[i].origin );
- }
-
- savefile->WriteInt( AFPoseJointFrame.Num() );
- for ( i = 0; i < AFPoseJointFrame.Num(); i++ ) {
- savefile->WriteFloat( AFPoseJointFrame[i].q.x );
- savefile->WriteFloat( AFPoseJointFrame[i].q.y );
- savefile->WriteFloat( AFPoseJointFrame[i].q.z );
- savefile->WriteFloat( AFPoseJointFrame[i].q.w );
- savefile->WriteVec3( AFPoseJointFrame[i].t );
- }
-
- savefile->WriteBounds( AFPoseBounds );
- savefile->WriteInt( AFPoseTime );
- savefile->WriteBool( removeOriginOffset );
- for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
- channels[ i ][ j ].Save( savefile );
- }
- }
- }
- /*
- =====================
- idAnimator::Restore
- unarchives object from save game file
- =====================
- */
- void idAnimator::Restore( idRestoreGame *savefile ) {
- int i;
- int j;
- int num;
- savefile->ReadModelDef( modelDef );
- savefile->ReadObject( reinterpret_cast<idClass *&>( entity ) );
- savefile->ReadInt( num );
- jointMods.SetNum( num );
- for( i = 0; i < num; i++ ) {
- jointMods[ i ] = new jointMod_t;
- savefile->ReadInt( (int&)jointMods[ i ]->jointnum );
- savefile->ReadMat3( jointMods[ i ]->mat );
- savefile->ReadVec3( jointMods[ i ]->pos );
- savefile->ReadInt( (int&)jointMods[ i ]->transform_pos );
- savefile->ReadInt( (int&)jointMods[ i ]->transform_axis );
- }
-
- savefile->ReadInt( numJoints );
- joints = (idJointMat *) Mem_Alloc16( numJoints * sizeof( joints[0] ) );
- for ( i = 0; i < numJoints; i++ ) {
- float *data = joints[i].ToFloatPtr();
- for ( j = 0; j < 12; j++ ) {
- savefile->ReadFloat( data[j] );
- }
- }
-
- savefile->ReadInt( lastTransformTime );
- savefile->ReadBool( stoppedAnimatingUpdate );
- savefile->ReadBool( forceUpdate );
- savefile->ReadBounds( frameBounds );
- savefile->ReadFloat( AFPoseBlendWeight );
- savefile->ReadInt( num );
- AFPoseJoints.SetGranularity( 1 );
- AFPoseJoints.SetNum( num );
- for ( i = 0; i < AFPoseJoints.Num(); i++ ) {
- savefile->ReadInt( AFPoseJoints[i] );
- }
-
- savefile->ReadInt( num );
- AFPoseJointMods.SetGranularity( 1 );
- AFPoseJointMods.SetNum( num );
- for ( i = 0; i < AFPoseJointMods.Num(); i++ ) {
- savefile->ReadInt( (int&)AFPoseJointMods[i].mod );
- savefile->ReadMat3( AFPoseJointMods[i].axis );
- savefile->ReadVec3( AFPoseJointMods[i].origin );
- }
-
- savefile->ReadInt( num );
- AFPoseJointFrame.SetGranularity( 1 );
- AFPoseJointFrame.SetNum( num );
- for ( i = 0; i < AFPoseJointFrame.Num(); i++ ) {
- savefile->ReadFloat( AFPoseJointFrame[i].q.x );
- savefile->ReadFloat( AFPoseJointFrame[i].q.y );
- savefile->ReadFloat( AFPoseJointFrame[i].q.z );
- savefile->ReadFloat( AFPoseJointFrame[i].q.w );
- savefile->ReadVec3( AFPoseJointFrame[i].t );
- }
-
- savefile->ReadBounds( AFPoseBounds );
- savefile->ReadInt( AFPoseTime );
- savefile->ReadBool( removeOriginOffset );
- for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
- channels[ i ][ j ].Restore( savefile, modelDef );
- }
- }
- }
- /*
- =====================
- idAnimator::FreeData
- =====================
- */
- void idAnimator::FreeData( void ) {
- int i, j;
- if ( entity ) {
- entity->BecomeInactive( TH_ANIMATE );
- }
- for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
- channels[ i ][ j ].Reset( NULL );
- }
- }
- jointMods.DeleteContents( true );
- Mem_Free16( joints );
- joints = NULL;
- numJoints = 0;
- modelDef = NULL;
- ForceUpdate();
- }
- /*
- =====================
- idAnimator::PushAnims
- =====================
- */
- void idAnimator::PushAnims( int channelNum, int currentTime, int blendTime ) {
- int i;
- idAnimBlend *channel;
- channel = channels[ channelNum ];
- if ( !channel[ 0 ].GetWeight( currentTime ) || ( channel[ 0 ].starttime == currentTime ) ) {
- return;
- }
- for( i = ANIM_MaxAnimsPerChannel - 1; i > 0; i-- ) {
- channel[ i ] = channel[ i - 1 ];
- }
- channel[ 0 ].Reset( modelDef );
- channel[ 1 ].Clear( currentTime, blendTime );
- ForceUpdate();
- }
- /*
- =====================
- idAnimator::SetModel
- =====================
- */
- idRenderModel *idAnimator::SetModel( const char *modelname ) {
- int i, j;
- FreeData();
- // check if we're just clearing the model
- if ( !modelname || !*modelname ) {
- return NULL;
- }
- modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelname, false ) );
- if ( !modelDef ) {
- return NULL;
- }
-
- idRenderModel *renderModel = modelDef->ModelHandle();
- if ( !renderModel ) {
- modelDef = NULL;
- return NULL;
- }
- // make sure model hasn't been purged
- modelDef->Touch();
- modelDef->SetupJoints( &numJoints, &joints, frameBounds, removeOriginOffset );
- modelDef->ModelHandle()->Reset();
- // set the modelDef on all channels
- for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
- channels[ i ][ j ].Reset( modelDef );
- }
- }
- return modelDef->ModelHandle();
- }
- /*
- =====================
- idAnimator::Size
- =====================
- */
- size_t idAnimator::Size( void ) const {
- return sizeof( *this ) + Allocated();
- }
- /*
- =====================
- idAnimator::SetEntity
- =====================
- */
- void idAnimator::SetEntity( idEntity *ent ) {
- entity = ent;
- }
- /*
- =====================
- idAnimator::GetEntity
- =====================
- */
- idEntity *idAnimator::GetEntity( void ) const {
- return entity;
- }
- /*
- =====================
- idAnimator::RemoveOriginOffset
- =====================
- */
- void idAnimator::RemoveOriginOffset( bool remove ) {
- removeOriginOffset = remove;
- }
- /*
- =====================
- idAnimator::RemoveOrigin
- =====================
- */
- bool idAnimator::RemoveOrigin( void ) const {
- return removeOriginOffset;
- }
- /*
- =====================
- idAnimator::GetJointList
- =====================
- */
- void idAnimator::GetJointList( const char *jointnames, idList<jointHandle_t> &jointList ) const {
- if ( modelDef ) {
- modelDef->GetJointList( jointnames, jointList );
- }
- }
- /*
- =====================
- idAnimator::NumAnims
- =====================
- */
- int idAnimator::NumAnims( void ) const {
- if ( !modelDef ) {
- return 0;
- }
-
- return modelDef->NumAnims();
- }
- /*
- =====================
- idAnimator::GetAnim
- =====================
- */
- const idAnim *idAnimator::GetAnim( int index ) const {
- if ( !modelDef ) {
- return NULL;
- }
-
- return modelDef->GetAnim( index );
- }
- /*
- =====================
- idAnimator::GetAnim
- =====================
- */
- int idAnimator::GetAnim( const char *name ) const {
- if ( !modelDef ) {
- return 0;
- }
-
- return modelDef->GetAnim( name );
- }
- /*
- =====================
- idAnimator::HasAnim
- =====================
- */
- bool idAnimator::HasAnim( const char *name ) const {
- if ( !modelDef ) {
- return false;
- }
-
- return modelDef->HasAnim( name );
- }
- /*
- =====================
- idAnimator::NumJoints
- =====================
- */
- int idAnimator::NumJoints( void ) const {
- return numJoints;
- }
- /*
- =====================
- idAnimator::ModelHandle
- =====================
- */
- idRenderModel *idAnimator::ModelHandle( void ) const {
- if ( !modelDef ) {
- return NULL;
- }
-
- return modelDef->ModelHandle();
- }
- /*
- =====================
- idAnimator::ModelDef
- =====================
- */
- const idDeclModelDef *idAnimator::ModelDef( void ) const {
- return modelDef;
- }
- /*
- =====================
- idAnimator::CurrentAnim
- =====================
- */
- idAnimBlend *idAnimator::CurrentAnim( int channelNum ) {
- if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
- gameLocal.Error( "idAnimator::CurrentAnim : channel out of range" );
- }
- return &channels[ channelNum ][ 0 ];
- }
- /*
- =====================
- idAnimator::Clear
- =====================
- */
- void idAnimator::Clear( int channelNum, int currentTime, int cleartime ) {
- int i;
- idAnimBlend *blend;
- if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
- gameLocal.Error( "idAnimator::Clear : channel out of range" );
- }
- blend = channels[ channelNum ];
- for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
- blend->Clear( currentTime, cleartime );
- }
- ForceUpdate();
- }
- /*
- =====================
- idAnimator::SetFrame
- =====================
- */
- void idAnimator::SetFrame( int channelNum, int animNum, int frame, int currentTime, int blendTime ) {
- if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
- gameLocal.Error( "idAnimator::SetFrame : channel out of range" );
- }
- if ( !modelDef || !modelDef->GetAnim( animNum ) ) {
- return;
- }
- PushAnims( channelNum, currentTime, blendTime );
- channels[ channelNum ][ 0 ].SetFrame( modelDef, animNum, frame, currentTime, blendTime );
- if ( entity ) {
- entity->BecomeActive( TH_ANIMATE );
- }
- }
- /*
- =====================
- idAnimator::CycleAnim
- =====================
- */
- void idAnimator::CycleAnim( int channelNum, int animNum, int currentTime, int blendTime ) {
- if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
- gameLocal.Error( "idAnimator::CycleAnim : channel out of range" );
- }
- if ( !modelDef || !modelDef->GetAnim( animNum ) ) {
- return;
- }
-
- PushAnims( channelNum, currentTime, blendTime );
- channels[ channelNum ][ 0 ].CycleAnim( modelDef, animNum, currentTime, blendTime );
- if ( entity ) {
- entity->BecomeActive( TH_ANIMATE );
- }
- }
- /*
- =====================
- idAnimator::PlayAnim
- =====================
- */
- void idAnimator::PlayAnim( int channelNum, int animNum, int currentTime, int blendTime ) {
- if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
- gameLocal.Error( "idAnimator::PlayAnim : channel out of range" );
- }
- if ( !modelDef || !modelDef->GetAnim( animNum ) ) {
- return;
- }
-
- PushAnims( channelNum, currentTime, blendTime );
- channels[ channelNum ][ 0 ].PlayAnim( modelDef, animNum, currentTime, blendTime );
- if ( entity ) {
- entity->BecomeActive( TH_ANIMATE );
- }
- }
- /*
- =====================
- idAnimator::SyncAnimChannels
- =====================
- */
- void idAnimator::SyncAnimChannels( int channelNum, int fromChannelNum, int currentTime, int blendTime ) {
- if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) || ( fromChannelNum < 0 ) || ( fromChannelNum >= ANIM_NumAnimChannels ) ) {
- gameLocal.Error( "idAnimator::SyncToChannel : channel out of range" );
- }
- idAnimBlend &fromBlend = channels[ fromChannelNum ][ 0 ];
- idAnimBlend &toBlend = channels[ channelNum ][ 0 ];
- float weight = fromBlend.blendEndValue;
- if ( ( fromBlend.Anim() != toBlend.Anim() ) || ( fromBlend.GetStartTime() != toBlend.GetStartTime() ) || ( fromBlend.GetEndTime() != toBlend.GetEndTime() ) ) {
- PushAnims( channelNum, currentTime, blendTime );
- toBlend = fromBlend;
- toBlend.blendStartValue = 0.0f;
- toBlend.blendEndValue = 0.0f;
- }
- toBlend.SetWeight( weight, currentTime - 1, blendTime );
- // disable framecommands on the current channel so that commands aren't called twice
- toBlend.AllowFrameCommands( false );
- if ( entity ) {
- entity->BecomeActive( TH_ANIMATE );
- }
- }
- /*
- =====================
- idAnimator::SetJointPos
- =====================
- */
- void idAnimator::SetJointPos( jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos ) {
- int i;
- jointMod_t *jointMod;
- if ( !modelDef || !modelDef->ModelHandle() || ( jointnum < 0 ) || ( jointnum >= numJoints ) ) {
- return;
- }
- jointMod = NULL;
- for( i = 0; i < jointMods.Num(); i++ ) {
- if ( jointMods[ i ]->jointnum == jointnum ) {
- jointMod = jointMods[ i ];
- break;
- } else if ( jointMods[ i ]->jointnum > jointnum ) {
- break;
- }
- }
- if ( !jointMod ) {
- jointMod = new jointMod_t;
- jointMod->jointnum = jointnum;
- jointMod->mat.Identity();
- jointMod->transform_axis = JOINTMOD_NONE;
- jointMods.Insert( jointMod, i );
- }
- jointMod->pos = pos;
- jointMod->transform_pos = transform_type;
- if ( entity ) {
- entity->BecomeActive( TH_ANIMATE );
- }
- ForceUpdate();
- }
- /*
- =====================
- idAnimator::SetJointAxis
- =====================
- */
- void idAnimator::SetJointAxis( jointHandle_t jointnum, jointModTransform_t transform_type, const idMat3 &mat ) {
- int i;
- jointMod_t *jointMod;
- if ( !modelDef || !modelDef->ModelHandle() || ( jointnum < 0 ) || ( jointnum >= numJoints ) ) {
- return;
- }
- jointMod = NULL;
- for( i = 0; i < jointMods.Num(); i++ ) {
- if ( jointMods[ i ]->jointnum == jointnum ) {
- jointMod = jointMods[ i ];
- break;
- } else if ( jointMods[ i ]->jointnum > jointnum ) {
- break;
- }
- }
- if ( !jointMod ) {
- jointMod = new jointMod_t;
- jointMod->jointnum = jointnum;
- jointMod->pos.Zero();
- jointMod->transform_pos = JOINTMOD_NONE;
- jointMods.Insert( jointMod, i );
- }
- jointMod->mat = mat;
- jointMod->transform_axis = transform_type;
- if ( entity ) {
- entity->BecomeActive( TH_ANIMATE );
- }
- ForceUpdate();
- }
- /*
- =====================
- idAnimator::ClearJoint
- =====================
- */
- void idAnimator::ClearJoint( jointHandle_t jointnum ) {
- int i;
- if ( !modelDef || !modelDef->ModelHandle() || ( jointnum < 0 ) || ( jointnum >= numJoints ) ) {
- return;
- }
- for( i = 0; i < jointMods.Num(); i++ ) {
- if ( jointMods[ i ]->jointnum == jointnum ) {
- delete jointMods[ i ];
- jointMods.RemoveIndex( i );
- ForceUpdate();
- break;
- } else if ( jointMods[ i ]->jointnum > jointnum ) {
- break;
- }
- }
- }
- /*
- =====================
- idAnimator::ClearAllJoints
- =====================
- */
- void idAnimator::ClearAllJoints( void ) {
- if ( jointMods.Num() ) {
- ForceUpdate();
- }
- jointMods.DeleteContents( true );
- }
- /*
- =====================
- idAnimator::ClearAllAnims
- =====================
- */
- void idAnimator::ClearAllAnims( int currentTime, int cleartime ) {
- int i;
- for( i = 0; i < ANIM_NumAnimChannels; i++ ) {
- Clear( i, currentTime, cleartime );
- }
- ClearAFPose();
- ForceUpdate();
- }
- /*
- ====================
- idAnimator::GetDelta
- ====================
- */
- void idAnimator::GetDelta( int fromtime, int totime, idVec3 &delta ) const {
- int i;
- const idAnimBlend *blend;
- float blendWeight;
- if ( !modelDef || !modelDef->ModelHandle() || ( fromtime == totime ) ) {
- delta.Zero();
- return;
- }
- delta.Zero();
- blendWeight = 0.0f;
- blend = channels[ ANIMCHANNEL_ALL ];
- for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
- blend->BlendDelta( fromtime, totime, delta, blendWeight );
- }
- if ( modelDef->Joints()[ 0 ].channel ) {
- blend = channels[ modelDef->Joints()[ 0 ].channel ];
- for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
- blend->BlendDelta( fromtime, totime, delta, blendWeight );
- }
- }
- }
- /*
- ====================
- idAnimator::GetDeltaRotation
- ====================
- */
- bool idAnimator::GetDeltaRotation( int fromtime, int totime, idMat3 &delta ) const {
- int i;
- const idAnimBlend *blend;
- float blendWeight;
- idQuat q;
- if ( !modelDef || !modelDef->ModelHandle() || ( fromtime == totime ) ) {
- delta.Identity();
- return false;
- }
- q.Set( 0.0f, 0.0f, 0.0f, 1.0f );
- blendWeight = 0.0f;
- blend = channels[ ANIMCHANNEL_ALL ];
- for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
- blend->BlendDeltaRotation( fromtime, totime, q, blendWeight );
- }
- if ( modelDef->Joints()[ 0 ].channel ) {
- blend = channels[ modelDef->Joints()[ 0 ].channel ];
- for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
- blend->BlendDeltaRotation( fromtime, totime, q, blendWeight );
- }
- }
- if ( blendWeight > 0.0f ) {
- delta = q.ToMat3();
- return true;
- } else {
- delta.Identity();
- return false;
- }
- }
- /*
- ====================
- idAnimator::GetOrigin
- ====================
- */
- void idAnimator::GetOrigin( int currentTime, idVec3 &pos ) const {
- int i;
- const idAnimBlend *blend;
- float blendWeight;
- if ( !modelDef || !modelDef->ModelHandle() ) {
- pos.Zero();
- return;
- }
- pos.Zero();
- blendWeight = 0.0f;
- blend = channels[ ANIMCHANNEL_ALL ];
- for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
- blend->BlendOrigin( currentTime, pos, blendWeight, removeOriginOffset );
- }
- if ( modelDef->Joints()[ 0 ].channel ) {
- blend = channels[ modelDef->Joints()[ 0 ].channel ];
- for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
- blend->BlendOrigin( currentTime, pos, blendWeight, removeOriginOffset );
- }
- }
- pos += modelDef->GetVisualOffset();
- }
- /*
- ====================
- idAnimator::GetBounds
- ====================
- */
- bool idAnimator::GetBounds( int currentTime, idBounds &bounds ) {
- int i, j;
- const idAnimBlend *blend;
- int count;
- if ( !modelDef || !modelDef->ModelHandle() ) {
- return false;
- }
- if ( AFPoseJoints.Num() ) {
- bounds = AFPoseBounds;
- count = 1;
- } else {
- bounds.Clear();
- count = 0;
- }
- blend = channels[ 0 ];
- for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
- if ( blend->AddBounds( currentTime, bounds, removeOriginOffset ) ) {
- count++;
- }
- }
- }
- if ( !count ) {
- if ( !frameBounds.IsCleared() ) {
- bounds = frameBounds;
- return true;
- } else {
- bounds.Zero();
- return false;
- }
- }
- bounds.TranslateSelf( modelDef->GetVisualOffset() );
- if ( g_debugBounds.GetBool() ) {
- if ( bounds[1][0] - bounds[0][0] > 2048 || bounds[1][1] - bounds[0][1] > 2048 ) {
- if ( entity ) {
- gameLocal.Warning( "big frameBounds on entity '%s' with model '%s': %f,%f", entity->name.c_str(), modelDef->ModelHandle()->Name(), bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1] );
- } else {
- gameLocal.Warning( "big frameBounds on model '%s': %f,%f", modelDef->ModelHandle()->Name(), bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1] );
- }
- }
- }
- frameBounds = bounds;
- return true;
- }
- /*
- =====================
- idAnimator::InitAFPose
- =====================
- */
- void idAnimator::InitAFPose( void ) {
- if ( !modelDef ) {
- return;
- }
- AFPoseJoints.SetNum( modelDef->Joints().Num(), false );
- AFPoseJoints.SetNum( 0, false );
- AFPoseJointMods.SetNum( modelDef->Joints().Num(), false );
- AFPoseJointFrame.SetNum( modelDef->Joints().Num(), false );
- }
- /*
- =====================
- idAnimator::SetAFPoseJointMod
- =====================
- */
- void idAnimator::SetAFPoseJointMod( const jointHandle_t jointNum, const AFJointModType_t mod, const idMat3 &axis, const idVec3 &origin ) {
- AFPoseJointMods[jointNum].mod = mod;
- AFPoseJointMods[jointNum].axis = axis;
- AFPoseJointMods[jointNum].origin = origin;
- int index = idBinSearch_GreaterEqual<int>( AFPoseJoints.Ptr(), AFPoseJoints.Num(), jointNum );
- if ( index >= AFPoseJoints.Num() || jointNum != AFPoseJoints[index] ) {
- AFPoseJoints.Insert( jointNum, index );
- }
- }
- /*
- =====================
- idAnimator::FinishAFPose
- =====================
- */
- void idAnimator::FinishAFPose( int animNum, const idBounds &bounds, const int time ) {
- int i, j;
- int numJoints;
- int parentNum;
- int jointMod;
- int jointNum;
- const int * jointParent;
- if ( !modelDef ) {
- return;
- }
-
- const idAnim *anim = modelDef->GetAnim( animNum );
- if ( !anim ) {
- return;
- }
- numJoints = modelDef->Joints().Num();
- if ( !numJoints ) {
- return;
- }
- idRenderModel *md5 = modelDef->ModelHandle();
- const idMD5Anim *md5anim = anim->MD5Anim( 0 );
- if ( numJoints != md5anim->NumJoints() ) {
- gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", md5->Name(), md5anim->Name() );
- return;
- }
- idJointQuat *jointFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( *jointFrame ) );
- md5anim->GetSingleFrame( 0, jointFrame, modelDef->GetChannelJoints( ANIMCHANNEL_ALL ), modelDef->NumJointsOnChannel( ANIMCHANNEL_ALL ) );
- if ( removeOriginOffset ) {
- #ifdef VELOCITY_MOVE
- jointFrame[ 0 ].t.x = 0.0f;
- #else
- jointFrame[ 0 ].t.Zero();
- #endif
- }
- idJointMat *joints = ( idJointMat * )_alloca16( numJoints * sizeof( *joints ) );
- // convert the joint quaternions to joint matrices
- SIMDProcessor->ConvertJointQuatsToJointMats( joints, jointFrame, numJoints );
- // first joint is always root of entire hierarchy
- if ( AFPoseJoints.Num() && AFPoseJoints[0] == 0 ) {
- switch( AFPoseJointMods[0].mod ) {
- case AF_JOINTMOD_AXIS: {
- joints[0].SetRotation( AFPoseJointMods[0].axis );
- break;
- }
- case AF_JOINTMOD_ORIGIN: {
- joints[0].SetTranslation( AFPoseJointMods[0].origin );
- break;
- }
- case AF_JOINTMOD_BOTH: {
- joints[0].SetRotation( AFPoseJointMods[0].axis );
- joints[0].SetTranslation( AFPoseJointMods[0].origin );
- break;
- }
- }
- j = 1;
- } else {
- j = 0;
- }
- // pointer to joint info
- jointParent = modelDef->JointParents();
- // transform the child joints
- for( i = 1; j < AFPoseJoints.Num(); j++, i++ ) {
- jointMod = AFPoseJoints[j];
- // transform any joints preceding the joint modifier
- SIMDProcessor->TransformJoints( joints, jointParent, i, jointMod - 1 );
- i = jointMod;
- parentNum = jointParent[i];
- switch( AFPoseJointMods[jointMod].mod ) {
- case AF_JOINTMOD_AXIS: {
- joints[i].SetRotation( AFPoseJointMods[jointMod].axis );
- joints[i].SetTranslation( joints[parentNum].ToVec3() + joints[i].ToVec3() * joints[parentNum].ToMat3() );
- break;
- }
- case AF_JOINTMOD_ORIGIN: {
- joints[i].SetRotation( joints[i].ToMat3() * joints[parentNum].ToMat3() );
- joints[i].SetTranslation( AFPoseJointMods[jointMod].origin );
- break;
- }
- case AF_JOINTMOD_BOTH: {
- joints[i].SetRotation( AFPoseJointMods[jointMod].axis );
- joints[i].SetTranslation( AFPoseJointMods[jointMod].origin );
- break;
- }
- }
- }
- // transform the rest of the hierarchy
- SIMDProcessor->TransformJoints( joints, jointParent, i, numJoints - 1 );
- // untransform hierarchy
- SIMDProcessor->UntransformJoints( joints, jointParent, 1, numJoints - 1 );
- // convert joint matrices back to joint quaternions
- SIMDProcessor->ConvertJointMatsToJointQuats( AFPoseJointFrame.Ptr(), joints, numJoints );
- // find all modified joints and their parents
- bool *blendJoints = (bool *) _alloca16( numJoints * sizeof( bool ) );
- memset( blendJoints, 0, numJoints * sizeof( bool ) );
- // mark all modified joints and their parents
- for( i = 0; i < AFPoseJoints.Num(); i++ ) {
- for( jointNum = AFPoseJoints[i]; jointNum != INVALID_JOINT; jointNum = jointParent[jointNum] ) {
- blendJoints[jointNum] = true;
- }
- }
- // lock all parents of modified joints
- AFPoseJoints.SetNum( 0, false );
- for ( i = 0; i < numJoints; i++ ) {
- if ( blendJoints[i] ) {
- AFPoseJoints.Append( i );
- }
- }
- AFPoseBounds = bounds;
- AFPoseTime = time;
- ForceUpdate();
- }
- /*
- =====================
- idAnimator::SetAFPoseBlendWeight
- =====================
- */
- void idAnimator::SetAFPoseBlendWeight( float blendWeight ) {
- AFPoseBlendWeight = blendWeight;
- }
- /*
- =====================
- idAnimator::BlendAFPose
- =====================
- */
- bool idAnimator::BlendAFPose( idJointQuat *blendFrame ) const {
- if ( !AFPoseJoints.Num() ) {
- return false;
- }
- SIMDProcessor->BlendJoints( blendFrame, AFPoseJointFrame.Ptr(), AFPoseBlendWeight, AFPoseJoints.Ptr(), AFPoseJoints.Num() );
- return true;
- }
- /*
- =====================
- idAnimator::ClearAFPose
- =====================
- */
- void idAnimator::ClearAFPose( void ) {
- if ( AFPoseJoints.Num() ) {
- ForceUpdate();
- }
- AFPoseBlendWeight = 1.0f;
- AFPoseJoints.SetNum( 0, false );
- AFPoseBounds.Clear();
- AFPoseTime = 0;
- }
- /*
- =====================
- idAnimator::ServiceAnims
- =====================
- */
- void idAnimator::ServiceAnims( int fromtime, int totime ) {
- int i, j;
- idAnimBlend *blend;
- if ( !modelDef ) {
- return;
- }
- if ( modelDef->ModelHandle() ) {
- blend = channels[ 0 ];
- for( i = 0; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
- blend->CallFrameCommands( entity, fromtime, totime );
- }
- }
- }
- if ( !IsAnimating( totime ) ) {
- stoppedAnimatingUpdate = true;
- if ( entity ) {
- entity->BecomeInactive( TH_ANIMATE );
- // present one more time with stopped animations so the renderer can properly recreate interactions
- entity->BecomeActive( TH_UPDATEVISUALS );
- }
- }
- }
- /*
- =====================
- idAnimator::IsAnimating
- =====================
- */
- bool idAnimator::IsAnimating( int currentTime ) const {
- int i, j;
- const idAnimBlend *blend;
- if ( !modelDef || !modelDef->ModelHandle() ) {
- return false;
- }
- // if animating with an articulated figure
- if ( AFPoseJoints.Num() && currentTime <= AFPoseTime ) {
- return true;
- }
- blend = channels[ 0 ];
- for( i = 0; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
- if ( !blend->IsDone( currentTime ) ) {
- return true;
- }
- }
- }
- return false;
- }
- /*
- =====================
- idAnimator::FrameHasChanged
- =====================
- */
- bool idAnimator::FrameHasChanged( int currentTime ) const {
- int i, j;
- const idAnimBlend *blend;
- if ( !modelDef || !modelDef->ModelHandle() ) {
- return false;
- }
- // if animating with an articulated figure
- if ( AFPoseJoints.Num() && currentTime <= AFPoseTime ) {
- return true;
- }
- blend = channels[ 0 ];
- for( i = 0; i < ANIM_NumAnimChannels; i++ ) {
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
- if ( blend->FrameHasChanged( currentTime ) ) {
- return true;
- }
- }
- }
- if ( forceUpdate && IsAnimating( currentTime ) ) {
- return true;
- }
- return false;
- }
- /*
- =====================
- idAnimator::CreateFrame
- =====================
- */
- bool idAnimator::CreateFrame( int currentTime, bool force ) {
- int i, j;
- int numJoints;
- int parentNum;
- bool hasAnim;
- bool debugInfo;
- float baseBlend;
- float blendWeight;
- const idAnimBlend * blend;
- const int * jointParent;
- const jointMod_t * jointMod;
- const idJointQuat * defaultPose;
- static idCVar r_showSkel( "r_showSkel", "0", CVAR_RENDERER | CVAR_INTEGER, "", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
- if ( gameLocal.inCinematic && gameLocal.skipCinematic ) {
- return false;
- }
- if ( !modelDef || !modelDef->ModelHandle() ) {
- return false;
- }
- if ( !force && !r_showSkel.GetInteger() ) {
- if ( lastTransformTime == currentTime ) {
- return false;
- }
- if ( lastTransformTime != -1 && !stoppedAnimatingUpdate && !IsAnimating( currentTime ) ) {
- return false;
- }
- }
- lastTransformTime = currentTime;
- stoppedAnimatingUpdate = false;
- if ( entity && ( ( g_debugAnim.GetInteger() == entity->entityNumber ) || ( g_debugAnim.GetInteger() == -2 ) ) ) {
- debugInfo = true;
- gameLocal.Printf( "---------------\n%d: entity '%s':\n", gameLocal.time, entity->GetName() );
- gameLocal.Printf( "model '%s':\n", modelDef->GetModelName() );
- } else {
- debugInfo = false;
- }
- // init the joint buffer
- if ( AFPoseJoints.Num() ) {
- // initialize with AF pose anim for the case where there are no other animations and no AF pose joint modifications
- defaultPose = AFPoseJointFrame.Ptr();
- } else {
- defaultPose = modelDef->GetDefaultPose();
- }
- if ( !defaultPose ) {
- //gameLocal.Warning( "idAnimator::CreateFrame: no defaultPose on '%s'", modelDef->Name() );
- return false;
- }
- numJoints = modelDef->Joints().Num();
- idJointQuat *jointFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( jointFrame[0] ) );
- SIMDProcessor->Memcpy( jointFrame, defaultPose, numJoints * sizeof( jointFrame[0] ) );
- hasAnim = false;
- // blend the all channel
- baseBlend = 0.0f;
- blend = channels[ ANIMCHANNEL_ALL ];
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
- if ( blend->BlendAnim( currentTime, ANIMCHANNEL_ALL, numJoints, jointFrame, baseBlend, removeOriginOffset, false, debugInfo ) ) {
- hasAnim = true;
- if ( baseBlend >= 1.0f ) {
- break;
- }
- }
- }
- // only blend other channels if there's enough space to blend into
- if ( baseBlend < 1.0f ) {
- for( i = ANIMCHANNEL_ALL + 1; i < ANIM_NumAnimChannels; i++ ) {
- if ( !modelDef->NumJointsOnChannel( i ) ) {
- continue;
- }
- if ( i == ANIMCHANNEL_EYELIDS ) {
- // eyelids blend over any previous anims, so skip it and blend it later
- continue;
- }
- blendWeight = baseBlend;
- blend = channels[ i ];
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
- if ( blend->BlendAnim( currentTime, i, numJoints, jointFrame, blendWeight, removeOriginOffset, false, debugInfo ) ) {
- hasAnim = true;
- if ( blendWeight >= 1.0f ) {
- // fully blended
- break;
- }
- }
- }
- if ( debugInfo && !AFPoseJoints.Num() && !blendWeight ) {
- gameLocal.Printf( "%d: %s using default pose in model '%s'\n", gameLocal.time, channelNames[ i ], modelDef->GetModelName() );
- }
- }
- }
- // blend in the eyelids
- if ( modelDef->NumJointsOnChannel( ANIMCHANNEL_EYELIDS ) ) {
- blend = channels[ ANIMCHANNEL_EYELIDS ];
- blendWeight = baseBlend;
- for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
- if ( blend->BlendAnim( currentTime, ANIMCHANNEL_EYELIDS, numJoints, jointFrame, blendWeight, removeOriginOffset, true, debugInfo ) ) {
- hasAnim = true;
- if ( blendWeight >= 1.0f ) {
- // fully blended
- break;
- }
- }
- }
- }
- // blend the articulated figure pose
- if ( BlendAFPose( jointFrame ) ) {
- hasAnim = true;
- }
- if ( !hasAnim && !jointMods.Num() ) {
- // no animations were updated
- return false;
- }
- // convert the joint quaternions to rotation matrices
- SIMDProcessor->ConvertJointQuatsToJointMats( joints, jointFrame, numJoints );
- // check if we need to modify the origin
- if ( jointMods.Num() && ( jointMods[0]->jointnum == 0 ) ) {
- jointMod = jointMods[0];
- switch( jointMod->transform_axis ) {
- case JOINTMOD_NONE:
- break;
- case JOINTMOD_LOCAL:
- joints[0].SetRotation( jointMod->mat * joints[0].ToMat3() );
- break;
-
- case JOINTMOD_WORLD:
- joints[0].SetRotation( joints[0].ToMat3() * jointMod->mat );
- break;
- case JOINTMOD_LOCAL_OVERRIDE:
- case JOINTMOD_WORLD_OVERRIDE:
- joints[0].SetRotation( jointMod->mat );
- break;
- }
- switch( jointMod->transform_pos ) {
- case JOINTMOD_NONE:
- break;
- case JOINTMOD_LOCAL:
- joints[0].SetTranslation( joints[0].ToVec3() + jointMod->pos );
- break;
-
- case JOINTMOD_LOCAL_OVERRIDE:
- case JOINTMOD_WORLD:
- case JOINTMOD_WORLD_OVERRIDE:
- joints[0].SetTranslation( jointMod->pos );
- break;
- }
- j = 1;
- } else {
- j = 0;
- }
- // add in the model offset
- joints[0].SetTranslation( joints[0].ToVec3() + modelDef->GetVisualOffset() );
- // pointer to joint info
- jointParent = modelDef->JointParents();
- // add in any joint modifications
- for( i = 1; j < jointMods.Num(); j++, i++ ) {
- jointMod = jointMods[j];
- // transform any joints preceding the joint modifier
- SIMDProcessor->TransformJoints( joints, jointParent, i, jointMod->jointnum - 1 );
- i = jointMod->jointnum;
- parentNum = jointParent[i];
- // modify the axis
- switch( jointMod->transform_axis ) {
- case JOINTMOD_NONE:
- joints[i].SetRotation( joints[i].ToMat3() * joints[ parentNum ].ToMat3() );
- break;
- case JOINTMOD_LOCAL:
- joints[i].SetRotation( jointMod->mat * ( joints[i].ToMat3() * joints[parentNum].ToMat3() ) );
- break;
-
- case JOINTMOD_LOCAL_OVERRIDE:
- joints[i].SetRotation( jointMod->mat * joints[parentNum].ToMat3() );
- break;
- case JOINTMOD_WORLD:
- joints[i].SetRotation( ( joints[i].ToMat3() * joints[parentNum].ToMat3() ) * jointMod->mat );
- break;
- case JOINTMOD_WORLD_OVERRIDE:
- joints[i].SetRotation( jointMod->mat );
- break;
- }
- // modify the position
- switch( jointMod->transform_pos ) {
- case JOINTMOD_NONE:
- joints[i].SetTranslation( joints[parentNum].ToVec3() + joints[i].ToVec3() * joints[parentNum].ToMat3() );
- break;
- case JOINTMOD_LOCAL:
- joints[i].SetTranslation( joints[parentNum].ToVec3() + ( joints[i].ToVec3() + jointMod->pos ) * joints[parentNum].ToMat3() );
- break;
-
- case JOINTMOD_LOCAL_OVERRIDE:
- joints[i].SetTranslation( joints[parentNum].ToVec3() + jointMod->pos * joints[parentNum].ToMat3() );
- break;
- case JOINTMOD_WORLD:
- joints[i].SetTranslation( joints[parentNum].ToVec3() + joints[i].ToVec3() * joints[parentNum].ToMat3() + jointMod->pos );
- break;
- case JOINTMOD_WORLD_OVERRIDE:
- joints[i].SetTranslation( jointMod->pos );
- break;
- }
- }
- // transform the rest of the hierarchy
- SIMDProcessor->TransformJoints( joints, jointParent, i, numJoints - 1 );
- return true;
- }
- /*
- =====================
- idAnimator::ForceUpdate
- =====================
- */
- void idAnimator::ForceUpdate( void ) {
- lastTransformTime = -1;
- forceUpdate = true;
- }
- /*
- =====================
- idAnimator::ClearForceUpdate
- =====================
- */
- void idAnimator::ClearForceUpdate( void ) {
- forceUpdate = false;
- }
- /*
- =====================
- idAnimator::GetJointTransform> gamex86.dll!idAnimator::ForceUpdate() Line 4268 C++
- =====================
- */
- bool idAnimator::GetJointTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ) {
- if ( !modelDef || ( jointHandle < 0 ) || ( jointHandle >= modelDef->NumJoints() ) ) {
- return false;
- }
- CreateFrame( currentTime, false );
- offset = joints[ jointHandle ].ToVec3();
- axis = joints[ jointHandle ].ToMat3();
- return true;
- }
- /*
- =====================
- idAnimator::GetJointLocalTransform
- =====================
- */
- bool idAnimator::GetJointLocalTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ) {
- if ( !modelDef ) {
- return false;
- }
- const idList<jointInfo_t> &modelJoints = modelDef->Joints();
- if ( ( jointHandle < 0 ) || ( jointHandle >= modelJoints.Num() ) ) {
- return false;
- }
- // FIXME: overkill
- CreateFrame( currentTime, false );
- if ( jointHandle > 0 ) {
- idJointMat m = joints[ jointHandle ];
- m /= joints[ modelJoints[ jointHandle ].parentNum ];
- offset = m.ToVec3();
- axis = m.ToMat3();
- } else {
- offset = joints[ jointHandle ].ToVec3();
- axis = joints[ jointHandle ].ToMat3();
- }
- return true;
- }
- /*
- =====================
- idAnimator::GetJointHandle
- =====================
- */
- jointHandle_t idAnimator::GetJointHandle( const char *name ) const {
- if ( !modelDef || !modelDef->ModelHandle() ) {
- return INVALID_JOINT;
- }
- return modelDef->ModelHandle()->GetJointHandle( name );
- }
- /*
- =====================
- idAnimator::GetJointName
- =====================
- */
- const char *idAnimator::GetJointName( jointHandle_t handle ) const {
- if ( !modelDef || !modelDef->ModelHandle() ) {
- return "";
- }
- return modelDef->ModelHandle()->GetJointName( handle );
- }
- /*
- =====================
- idAnimator::GetChannelForJoint
- =====================
- */
- int idAnimator::GetChannelForJoint( jointHandle_t joint ) const {
- if ( !modelDef ) {
- gameLocal.Error( "idAnimator::GetChannelForJoint: NULL model" );
- }
- if ( ( joint < 0 ) || ( joint >= numJoints ) ) {
- gameLocal.Error( "idAnimator::GetChannelForJoint: invalid joint num (%d)", joint );
- }
- return modelDef->GetJoint( joint )->channel;
- }
- /*
- =====================
- idAnimator::GetFirstChild
- =====================
- */
- jointHandle_t idAnimator::GetFirstChild( const char *name ) const {
- return GetFirstChild( GetJointHandle( name ) );
- }
- /*
- =====================
- idAnimator::GetFirstChild
- =====================
- */
- jointHandle_t idAnimator::GetFirstChild( jointHandle_t jointnum ) const {
- int i;
- int num;
- const jointInfo_t *joint;
- if ( !modelDef ) {
- return INVALID_JOINT;
- }
- num = modelDef->NumJoints();
- if ( !num ) {
- return jointnum;
- }
- joint = modelDef->GetJoint( 0 );
- for( i = 0; i < num; i++, joint++ ) {
- if ( joint->parentNum == jointnum ) {
- return ( jointHandle_t )joint->num;
- }
- }
- return jointnum;
- }
- /*
- =====================
- idAnimator::GetJoints
- =====================
- */
- void idAnimator::GetJoints( int *numJoints, idJointMat **jointsPtr ) {
- *numJoints = this->numJoints;
- *jointsPtr = this->joints;
- }
- /*
- =====================
- idAnimator::GetAnimFlags
- =====================
- */
- const animFlags_t idAnimator::GetAnimFlags( int animNum ) const {
- animFlags_t result;
- const idAnim *anim = GetAnim( animNum );
- if ( anim ) {
- return anim->GetAnimFlags();
- }
- memset( &result, 0, sizeof( result ) );
- return result;
- }
- /*
- =====================
- idAnimator::NumFrames
- =====================
- */
- int idAnimator::NumFrames( int animNum ) const {
- const idAnim *anim = GetAnim( animNum );
- if ( anim ) {
- return anim->NumFrames();
- } else {
- return 0;
- }
- }
- /*
- =====================
- idAnimator::NumSyncedAnims
- =====================
- */
- int idAnimator::NumSyncedAnims( int animNum ) const {
- const idAnim *anim = GetAnim( animNum );
- if ( anim ) {
- return anim->NumAnims();
- } else {
- return 0;
- }
- }
- /*
- =====================
- idAnimator::AnimName
- =====================
- */
- const char *idAnimator::AnimName( int animNum ) const {
- const idAnim *anim = GetAnim( animNum );
- if ( anim ) {
- return anim->Name();
- } else {
- return "";
- }
- }
- /*
- =====================
- idAnimator::AnimFullName
- =====================
- */
- const char *idAnimator::AnimFullName( int animNum ) const {
- const idAnim *anim = GetAnim( animNum );
- if ( anim ) {
- return anim->FullName();
- } else {
- return "";
- }
- }
- /*
- =====================
- idAnimator::AnimLength
- =====================
- */
- int idAnimator::AnimLength( int animNum ) const {
- const idAnim *anim = GetAnim( animNum );
- if ( anim ) {
- return anim->Length();
- } else {
- return 0;
- }
- }
- /*
- =====================
- idAnimator::TotalMovementDelta
- =====================
- */
- const idVec3 &idAnimator::TotalMovementDelta( int animNum ) const {
- const idAnim *anim = GetAnim( animNum );
- if ( anim ) {
- return anim->TotalMovementDelta();
- } else {
- return vec3_origin;
- }
- }
- /***********************************************************************
- Util functions
- ***********************************************************************/
- /*
- =====================
- ANIM_GetModelDefFromEntityDef
- =====================
- */
- const idDeclModelDef *ANIM_GetModelDefFromEntityDef( const idDict *args ) {
- const idDeclModelDef *modelDef;
- idStr name = args->GetString( "model" );
- modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name, false ) );
- if ( modelDef && modelDef->ModelHandle() ) {
- return modelDef;
- }
- return NULL;
- }
- /*
- =====================
- idGameEdit::ANIM_GetModelFromEntityDef
- =====================
- */
- idRenderModel *idGameEdit::ANIM_GetModelFromEntityDef( const idDict *args ) {
- idRenderModel *model;
- const idDeclModelDef *modelDef;
- model = NULL;
- idStr name = args->GetString( "model" );
- modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name, false ) );
- if ( modelDef ) {
- model = modelDef->ModelHandle();
- }
- if ( !model ) {
- model = renderModelManager->FindModel( name );
- }
- if ( model && model->IsDefaultModel() ) {
- return NULL;
- }
- return model;
- }
- /*
- =====================
- idGameEdit::ANIM_GetModelFromEntityDef
- =====================
- */
- idRenderModel *idGameEdit::ANIM_GetModelFromEntityDef( const char *classname ) {
- const idDict *args;
- args = gameLocal.FindEntityDefDict( classname, false );
- if ( !args ) {
- return NULL;
- }
- return ANIM_GetModelFromEntityDef( args );
- }
- /*
- =====================
- idGameEdit::ANIM_GetModelOffsetFromEntityDef
- =====================
- */
- const idVec3 &idGameEdit::ANIM_GetModelOffsetFromEntityDef( const char *classname ) {
- const idDict *args;
- const idDeclModelDef *modelDef;
- args = gameLocal.FindEntityDefDict( classname, false );
- if ( !args ) {
- return vec3_origin;
- }
- modelDef = ANIM_GetModelDefFromEntityDef( args );
- if ( !modelDef ) {
- return vec3_origin;
- }
- return modelDef->GetVisualOffset();
- }
- /*
- =====================
- idGameEdit::ANIM_GetModelFromName
- =====================
- */
- idRenderModel *idGameEdit::ANIM_GetModelFromName( const char *modelName ) {
- const idDeclModelDef *modelDef;
- idRenderModel *model;
- model = NULL;
- modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelName, false ) );
- if ( modelDef ) {
- model = modelDef->ModelHandle();
- }
- if ( !model ) {
- model = renderModelManager->FindModel( modelName );
- }
- return model;
- }
- /*
- =====================
- idGameEdit::ANIM_GetAnimFromEntityDef
- =====================
- */
- const idMD5Anim *idGameEdit::ANIM_GetAnimFromEntityDef( const char *classname, const char *animname ) {
- const idDict *args;
- const idMD5Anim *md5anim;
- const idAnim *anim;
- int animNum;
- const char *modelname;
- const idDeclModelDef *modelDef;
- args = gameLocal.FindEntityDefDict( classname, false );
- if ( !args ) {
- return NULL;
- }
- md5anim = NULL;
- modelname = args->GetString( "model" );
- modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelname, false ) );
- if ( modelDef ) {
- animNum = modelDef->GetAnim( animname );
- if ( animNum ) {
- anim = modelDef->GetAnim( animNum );
- if ( anim ) {
- md5anim = anim->MD5Anim( 0 );
- }
- }
- }
- return md5anim;
- }
- /*
- =====================
- idGameEdit::ANIM_GetNumAnimsFromEntityDef
- =====================
- */
- int idGameEdit::ANIM_GetNumAnimsFromEntityDef( const idDict *args ) {
- const char *modelname;
- const idDeclModelDef *modelDef;
- modelname = args->GetString( "model" );
- modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelname, false ) );
- if ( modelDef ) {
- return modelDef->NumAnims();
- }
- return 0;
- }
- /*
- =====================
- idGameEdit::ANIM_GetAnimNameFromEntityDef
- =====================
- */
- const char *idGameEdit::ANIM_GetAnimNameFromEntityDef( const idDict *args, int animNum ) {
- const char *modelname;
- const idDeclModelDef *modelDef;
- modelname = args->GetString( "model" );
- modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelname, false ) );
- if ( modelDef ) {
- const idAnim* anim = modelDef->GetAnim( animNum );
- if ( anim ) {
- return anim->FullName();
- }
- }
- return "";
- }
- /*
- =====================
- idGameEdit::ANIM_GetAnim
- =====================
- */
- const idMD5Anim *idGameEdit::ANIM_GetAnim( const char *fileName ) {
- return animationLib.GetAnim( fileName );
- }
- /*
- =====================
- idGameEdit::ANIM_GetLength
- =====================
- */
- int idGameEdit::ANIM_GetLength( const idMD5Anim *anim ) {
- if ( !anim ) {
- return 0;
- }
- return anim->Length();
- }
- /*
- =====================
- idGameEdit::ANIM_GetNumFrames
- =====================
- */
- int idGameEdit::ANIM_GetNumFrames( const idMD5Anim *anim ) {
- if ( !anim ) {
- return 0;
- }
- return anim->NumFrames();
- }
- /*
- =====================
- idGameEdit::ANIM_CreateAnimFrame
- =====================
- */
- void idGameEdit::ANIM_CreateAnimFrame( const idRenderModel *model, const idMD5Anim *anim, int numJoints, idJointMat *joints, int time, const idVec3 &offset, bool remove_origin_offset ) {
- int i;
- frameBlend_t frame;
- const idMD5Joint *md5joints;
- int *index;
- if ( !model || model->IsDefaultModel() || !anim ) {
- return;
- }
- if ( numJoints != model->NumJoints() ) {
- gameLocal.Error( "ANIM_CreateAnimFrame: different # of joints in renderEntity_t than in model (%s)", model->Name() );
- }
- if ( !model->NumJoints() ) {
- // FIXME: Print out a warning?
- return;
- }
- if ( !joints ) {
- gameLocal.Error( "ANIM_CreateAnimFrame: NULL joint frame pointer on model (%s)", model->Name() );
- }
- if ( numJoints != anim->NumJoints() ) {
- gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", model->Name(), anim->Name() );
- for( i = 0; i < numJoints; i++ ) {
- joints[i].SetRotation( mat3_identity );
- joints[i].SetTranslation( offset );
- }
- return;
- }
- // create index for all joints
- index = ( int * )_alloca16( numJoints * sizeof( int ) );
- for ( i = 0; i < numJoints; i++ ) {
- index[i] = i;
- }
- // create the frame
- anim->ConvertTimeToFrame( time, 1, frame );
- idJointQuat *jointFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( *jointFrame ) );
- anim->GetInterpolatedFrame( frame, jointFrame, index, numJoints );
- // convert joint quaternions to joint matrices
- SIMDProcessor->ConvertJointQuatsToJointMats( joints, jointFrame, numJoints );
- // first joint is always root of entire hierarchy
- if ( remove_origin_offset ) {
- joints[0].SetTranslation( offset );
- } else {
- joints[0].SetTranslation( joints[0].ToVec3() + offset );
- }
- // transform the children
- md5joints = model->GetJoints();
- for( i = 1; i < numJoints; i++ ) {
- joints[i] *= joints[ md5joints[i].parent - md5joints ];
- }
- }
- /*
- =====================
- idGameEdit::ANIM_CreateMeshForAnim
- =====================
- */
- idRenderModel *idGameEdit::ANIM_CreateMeshForAnim( idRenderModel *model, const char *classname, const char *animname, int frame, bool remove_origin_offset ) {
- renderEntity_t ent;
- const idDict *args;
- const char *temp;
- idRenderModel *newmodel;
- const idMD5Anim *md5anim;
- idStr filename;
- idStr extension;
- const idAnim *anim;
- int animNum;
- idVec3 offset;
- const idDeclModelDef *modelDef;
- if ( !model || model->IsDefaultModel() ) {
- return NULL;
- }
- args = gameLocal.FindEntityDefDict( classname, false );
- if ( !args ) {
- return NULL;
- }
- memset( &ent, 0, sizeof( ent ) );
- ent.bounds.Clear();
- ent.suppressSurfaceInViewID = 0;
- modelDef = ANIM_GetModelDefFromEntityDef( args );
- if ( modelDef ) {
- animNum = modelDef->GetAnim( animname );
- if ( !animNum ) {
- return NULL;
- }
- anim = modelDef->GetAnim( animNum );
- if ( !anim ) {
- return NULL;
- }
- md5anim = anim->MD5Anim( 0 );
- ent.customSkin = modelDef->GetDefaultSkin();
- offset = modelDef->GetVisualOffset();
- } else {
- filename = animname;
- filename.ExtractFileExtension( extension );
- if ( !extension.Length() ) {
- animname = args->GetString( va( "anim %s", animname ) );
- }
- md5anim = animationLib.GetAnim( animname );
- offset.Zero();
- }
- if ( !md5anim ) {
- return NULL;
- }
- temp = args->GetString( "skin", "" );
- if ( temp[ 0 ] ) {
- ent.customSkin = declManager->FindSkin( temp );
- }
- ent.numJoints = model->NumJoints();
- ent.joints = ( idJointMat * )Mem_Alloc16( ent.numJoints * sizeof( *ent.joints ) );
- ANIM_CreateAnimFrame( model, md5anim, ent.numJoints, ent.joints, FRAME2MS( frame ), offset, remove_origin_offset );
- newmodel = model->InstantiateDynamicModel( &ent, NULL, NULL );
- Mem_Free16( ent.joints );
- ent.joints = NULL;
- return newmodel;
- }
|