Anim_Blend.cpp 127 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "../Game_local.h"
  23. static const char *channelNames[ ANIM_NumAnimChannels ] = {
  24. "all", "torso", "legs", "head", "eyelids"
  25. };
  26. /***********************************************************************
  27. idAnim
  28. ***********************************************************************/
  29. /*
  30. =====================
  31. idAnim::idAnim
  32. =====================
  33. */
  34. idAnim::idAnim() {
  35. modelDef = NULL;
  36. numAnims = 0;
  37. memset( anims, 0, sizeof( anims ) );
  38. memset( &flags, 0, sizeof( flags ) );
  39. }
  40. /*
  41. =====================
  42. idAnim::idAnim
  43. =====================
  44. */
  45. idAnim::idAnim( const idDeclModelDef *modelDef, const idAnim *anim ) {
  46. int i;
  47. this->modelDef = modelDef;
  48. numAnims = anim->numAnims;
  49. name = anim->name;
  50. realname = anim->realname;
  51. flags = anim->flags;
  52. memset( anims, 0, sizeof( anims ) );
  53. for( i = 0; i < numAnims; i++ ) {
  54. anims[ i ] = anim->anims[ i ];
  55. anims[ i ]->IncreaseRefs();
  56. }
  57. frameLookup.SetNum( anim->frameLookup.Num() );
  58. memcpy( frameLookup.Ptr(), anim->frameLookup.Ptr(), frameLookup.MemoryUsed() );
  59. frameCommands.SetNum( anim->frameCommands.Num() );
  60. for( i = 0; i < frameCommands.Num(); i++ ) {
  61. frameCommands[ i ] = anim->frameCommands[ i ];
  62. if ( anim->frameCommands[ i ].string ) {
  63. frameCommands[ i ].string = new idStr( *anim->frameCommands[ i ].string );
  64. }
  65. }
  66. }
  67. /*
  68. =====================
  69. idAnim::~idAnim
  70. =====================
  71. */
  72. idAnim::~idAnim() {
  73. int i;
  74. for( i = 0; i < numAnims; i++ ) {
  75. anims[ i ]->DecreaseRefs();
  76. }
  77. for( i = 0; i < frameCommands.Num(); i++ ) {
  78. delete frameCommands[ i ].string;
  79. }
  80. }
  81. /*
  82. =====================
  83. idAnim::SetAnim
  84. =====================
  85. */
  86. void idAnim::SetAnim( const idDeclModelDef *modelDef, const char *sourcename, const char *animname, int num, const idMD5Anim *md5anims[ ANIM_MaxSyncedAnims ] ) {
  87. int i;
  88. this->modelDef = modelDef;
  89. for( i = 0; i < numAnims; i++ ) {
  90. anims[ i ]->DecreaseRefs();
  91. anims[ i ] = NULL;
  92. }
  93. assert( ( num > 0 ) && ( num <= ANIM_MaxSyncedAnims ) );
  94. numAnims = num;
  95. realname = sourcename;
  96. name = animname;
  97. for( i = 0; i < num; i++ ) {
  98. anims[ i ] = md5anims[ i ];
  99. anims[ i ]->IncreaseRefs();
  100. }
  101. memset( &flags, 0, sizeof( flags ) );
  102. for( i = 0; i < frameCommands.Num(); i++ ) {
  103. delete frameCommands[ i ].string;
  104. }
  105. frameLookup.Clear();
  106. frameCommands.Clear();
  107. }
  108. /*
  109. =====================
  110. idAnim::Name
  111. =====================
  112. */
  113. const char *idAnim::Name( void ) const {
  114. return name;
  115. }
  116. /*
  117. =====================
  118. idAnim::FullName
  119. =====================
  120. */
  121. const char *idAnim::FullName( void ) const {
  122. return realname;
  123. }
  124. /*
  125. =====================
  126. idAnim::MD5Anim
  127. index 0 will never be NULL. Any anim >= NumAnims will return NULL.
  128. =====================
  129. */
  130. const idMD5Anim *idAnim::MD5Anim( int num ) const {
  131. if ( anims == NULL || anims[0] == NULL ) {
  132. return NULL;
  133. }
  134. return anims[ num ];
  135. }
  136. /*
  137. =====================
  138. idAnim::ModelDef
  139. =====================
  140. */
  141. const idDeclModelDef *idAnim::ModelDef( void ) const {
  142. return modelDef;
  143. }
  144. /*
  145. =====================
  146. idAnim::Length
  147. =====================
  148. */
  149. int idAnim::Length( void ) const {
  150. if ( !anims[ 0 ] ) {
  151. return 0;
  152. }
  153. return anims[ 0 ]->Length();
  154. }
  155. /*
  156. =====================
  157. idAnim::NumFrames
  158. =====================
  159. */
  160. int idAnim::NumFrames( void ) const {
  161. if ( !anims[ 0 ] ) {
  162. return 0;
  163. }
  164. return anims[ 0 ]->NumFrames();
  165. }
  166. /*
  167. =====================
  168. idAnim::NumAnims
  169. =====================
  170. */
  171. int idAnim::NumAnims( void ) const {
  172. return numAnims;
  173. }
  174. /*
  175. =====================
  176. idAnim::TotalMovementDelta
  177. =====================
  178. */
  179. const idVec3 &idAnim::TotalMovementDelta( void ) const {
  180. if ( !anims[ 0 ] ) {
  181. return vec3_zero;
  182. }
  183. return anims[ 0 ]->TotalMovementDelta();
  184. }
  185. /*
  186. =====================
  187. idAnim::GetOrigin
  188. =====================
  189. */
  190. bool idAnim::GetOrigin( idVec3 &offset, int animNum, int currentTime, int cyclecount ) const {
  191. if ( !anims[ animNum ] ) {
  192. offset.Zero();
  193. return false;
  194. }
  195. anims[ animNum ]->GetOrigin( offset, currentTime, cyclecount );
  196. return true;
  197. }
  198. /*
  199. =====================
  200. idAnim::GetOriginRotation
  201. =====================
  202. */
  203. bool idAnim::GetOriginRotation( idQuat &rotation, int animNum, int currentTime, int cyclecount ) const {
  204. if ( !anims[ animNum ] ) {
  205. rotation.Set( 0.0f, 0.0f, 0.0f, 1.0f );
  206. return false;
  207. }
  208. anims[ animNum ]->GetOriginRotation( rotation, currentTime, cyclecount );
  209. return true;
  210. }
  211. /*
  212. =====================
  213. idAnim::GetBounds
  214. =====================
  215. */
  216. ID_INLINE bool idAnim::GetBounds( idBounds &bounds, int animNum, int currentTime, int cyclecount ) const {
  217. if ( !anims[ animNum ] ) {
  218. return false;
  219. }
  220. anims[ animNum ]->GetBounds( bounds, currentTime, cyclecount );
  221. return true;
  222. }
  223. /*
  224. =====================
  225. idAnim::AddFrameCommand
  226. Returns NULL if no error.
  227. =====================
  228. */
  229. const char *idAnim::AddFrameCommand( const idDeclModelDef *modelDef, int framenum, idLexer &src, const idDict *def ) {
  230. int i;
  231. int index;
  232. idStr text;
  233. idStr funcname;
  234. frameCommand_t fc;
  235. idToken token;
  236. const jointInfo_t *jointInfo;
  237. // make sure we're within bounds
  238. if ( ( framenum < 1 ) || ( framenum > anims[ 0 ]->NumFrames() ) ) {
  239. return va( "Frame %d out of range", framenum );
  240. }
  241. // frame numbers are 1 based in .def files, but 0 based internally
  242. framenum--;
  243. memset( &fc, 0, sizeof( fc ) );
  244. if( !src.ReadTokenOnLine( &token ) ) {
  245. return "Unexpected end of line";
  246. }
  247. if ( token == "call" ) {
  248. if( !src.ReadTokenOnLine( &token ) ) {
  249. return "Unexpected end of line";
  250. }
  251. fc.type = FC_SCRIPTFUNCTION;
  252. fc.function = gameLocal.program.FindFunction( token );
  253. if ( !fc.function ) {
  254. return va( "Function '%s' not found", token.c_str() );
  255. }
  256. } else if ( token == "object_call" ) {
  257. if( !src.ReadTokenOnLine( &token ) ) {
  258. return "Unexpected end of line";
  259. }
  260. fc.type = FC_SCRIPTFUNCTIONOBJECT;
  261. fc.string = new idStr( token );
  262. } else if ( token == "event" ) {
  263. if( !src.ReadTokenOnLine( &token ) ) {
  264. return "Unexpected end of line";
  265. }
  266. fc.type = FC_EVENTFUNCTION;
  267. const idEventDef *ev = idEventDef::FindEvent( token );
  268. if ( !ev ) {
  269. return va( "Event '%s' not found", token.c_str() );
  270. }
  271. if ( ev->GetNumArgs() != 0 ) {
  272. return va( "Event '%s' has arguments", token.c_str() );
  273. }
  274. fc.string = new idStr( token );
  275. } else if ( token == "sound" ) {
  276. if( !src.ReadTokenOnLine( &token ) ) {
  277. return "Unexpected end of line";
  278. }
  279. fc.type = FC_SOUND;
  280. if ( !token.Cmpn( "snd_", 4 ) ) {
  281. fc.string = new idStr( token );
  282. } else {
  283. fc.soundShader = declManager->FindSound( token );
  284. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  285. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  286. }
  287. }
  288. } else if ( token == "sound_voice" ) {
  289. if( !src.ReadTokenOnLine( &token ) ) {
  290. return "Unexpected end of line";
  291. }
  292. fc.type = FC_SOUND_VOICE;
  293. if ( !token.Cmpn( "snd_", 4 ) ) {
  294. fc.string = new idStr( token );
  295. } else {
  296. fc.soundShader = declManager->FindSound( token );
  297. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  298. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  299. }
  300. }
  301. } else if ( token == "sound_voice2" ) {
  302. if( !src.ReadTokenOnLine( &token ) ) {
  303. return "Unexpected end of line";
  304. }
  305. fc.type = FC_SOUND_VOICE2;
  306. if ( !token.Cmpn( "snd_", 4 ) ) {
  307. fc.string = new idStr( token );
  308. } else {
  309. fc.soundShader = declManager->FindSound( token );
  310. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  311. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  312. }
  313. }
  314. } else if ( token == "sound_body" ) {
  315. if( !src.ReadTokenOnLine( &token ) ) {
  316. return "Unexpected end of line";
  317. }
  318. fc.type = FC_SOUND_BODY;
  319. if ( !token.Cmpn( "snd_", 4 ) ) {
  320. fc.string = new idStr( token );
  321. } else {
  322. fc.soundShader = declManager->FindSound( token );
  323. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  324. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  325. }
  326. }
  327. } else if ( token == "sound_body2" ) {
  328. if( !src.ReadTokenOnLine( &token ) ) {
  329. return "Unexpected end of line";
  330. }
  331. fc.type = FC_SOUND_BODY2;
  332. if ( !token.Cmpn( "snd_", 4 ) ) {
  333. fc.string = new idStr( token );
  334. } else {
  335. fc.soundShader = declManager->FindSound( token );
  336. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  337. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  338. }
  339. }
  340. } else if ( token == "sound_body3" ) {
  341. if( !src.ReadTokenOnLine( &token ) ) {
  342. return "Unexpected end of line";
  343. }
  344. fc.type = FC_SOUND_BODY3;
  345. if ( !token.Cmpn( "snd_", 4 ) ) {
  346. fc.string = new idStr( token );
  347. } else {
  348. fc.soundShader = declManager->FindSound( token );
  349. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  350. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  351. }
  352. }
  353. } else if ( token == "sound_weapon" ) {
  354. if( !src.ReadTokenOnLine( &token ) ) {
  355. return "Unexpected end of line";
  356. }
  357. fc.type = FC_SOUND_WEAPON;
  358. if ( !token.Cmpn( "snd_", 4 ) ) {
  359. fc.string = new idStr( token );
  360. } else {
  361. fc.soundShader = declManager->FindSound( token );
  362. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  363. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  364. }
  365. }
  366. } else if ( token == "sound_global" ) {
  367. if( !src.ReadTokenOnLine( &token ) ) {
  368. return "Unexpected end of line";
  369. }
  370. fc.type = FC_SOUND_GLOBAL;
  371. if ( !token.Cmpn( "snd_", 4 ) ) {
  372. fc.string = new idStr( token );
  373. } else {
  374. fc.soundShader = declManager->FindSound( token );
  375. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  376. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  377. }
  378. }
  379. } else if ( token == "sound_item" ) {
  380. if( !src.ReadTokenOnLine( &token ) ) {
  381. return "Unexpected end of line";
  382. }
  383. fc.type = FC_SOUND_ITEM;
  384. if ( !token.Cmpn( "snd_", 4 ) ) {
  385. fc.string = new idStr( token );
  386. } else {
  387. fc.soundShader = declManager->FindSound( token );
  388. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  389. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  390. }
  391. }
  392. } else if ( token == "sound_chatter" ) {
  393. if( !src.ReadTokenOnLine( &token ) ) {
  394. return "Unexpected end of line";
  395. }
  396. fc.type = FC_SOUND_CHATTER;
  397. if ( !token.Cmpn( "snd_", 4 ) ) {
  398. fc.string = new idStr( token );
  399. } else {
  400. fc.soundShader = declManager->FindSound( token );
  401. if ( fc.soundShader->GetState() == DS_DEFAULTED ) {
  402. gameLocal.Warning( "Sound '%s' not found", token.c_str() );
  403. }
  404. }
  405. } else if ( token == "skin" ) {
  406. if( !src.ReadTokenOnLine( &token ) ) {
  407. return "Unexpected end of line";
  408. }
  409. fc.type = FC_SKIN;
  410. if ( token == "none" ) {
  411. fc.skin = NULL;
  412. } else {
  413. fc.skin = declManager->FindSkin( token );
  414. if ( !fc.skin ) {
  415. return va( "Skin '%s' not found", token.c_str() );
  416. }
  417. }
  418. } else if ( token == "fx" ) {
  419. if( !src.ReadTokenOnLine( &token ) ) {
  420. return "Unexpected end of line";
  421. }
  422. fc.type = FC_FX;
  423. if ( !declManager->FindType( DECL_FX, token.c_str() ) ) {
  424. return va( "fx '%s' not found", token.c_str() );
  425. }
  426. fc.string = new idStr( token );
  427. } else if ( token == "trigger" ) {
  428. if( !src.ReadTokenOnLine( &token ) ) {
  429. return "Unexpected end of line";
  430. }
  431. fc.type = FC_TRIGGER;
  432. fc.string = new idStr( token );
  433. }
  434. else if ( token == "triggerSmokeParticle" )
  435. {
  436. if( !src.ReadTokenOnLine( &token ) ) {
  437. return "Unexpected end of line";
  438. }
  439. fc.type = FC_TRIGGER_SMOKE_PARTICLE;
  440. fc.string = new idStr( token );
  441. }
  442. else if ( token == "particle" )
  443. {
  444. idStr str;
  445. if( !src.ReadTokenOnLine( &token ) )
  446. {
  447. return "Unexpected end of line";
  448. }
  449. jointInfo = modelDef->FindJoint( token );
  450. if ( !jointInfo )
  451. {
  452. return va( "Joint '%s' not found", token.c_str() );
  453. }
  454. if( !src.ReadTokenOnLine( &token ) )
  455. {
  456. return "Unexpected end of line";
  457. }
  458. str += token;
  459. fc.type = FC_PARTICLE;
  460. fc.string = new idStr( str ); //particle name.
  461. fc.index = jointInfo->num; //joint to fire the effect.
  462. }
  463. else if ( token == "melee" ) {
  464. if( !src.ReadTokenOnLine( &token ) ) {
  465. return "Unexpected end of line";
  466. }
  467. fc.type = FC_MELEE;
  468. if ( !gameLocal.FindEntityDef( token.c_str(), false ) ) {
  469. return va( "Unknown entityDef '%s'", token.c_str() );
  470. }
  471. fc.string = new idStr( token );
  472. } else if ( token == "direct_damage" ) {
  473. if( !src.ReadTokenOnLine( &token ) ) {
  474. return "Unexpected end of line";
  475. }
  476. fc.type = FC_DIRECTDAMAGE;
  477. if ( !gameLocal.FindEntityDef( token.c_str(), false ) ) {
  478. return va( "Unknown entityDef '%s'", token.c_str() );
  479. }
  480. fc.string = new idStr( token );
  481. } else if ( token == "attack_begin" ) {
  482. if( !src.ReadTokenOnLine( &token ) ) {
  483. return "Unexpected end of line";
  484. }
  485. fc.type = FC_BEGINATTACK;
  486. if ( !gameLocal.FindEntityDef( token.c_str(), false ) ) {
  487. return va( "Unknown entityDef '%s'", token.c_str() );
  488. }
  489. fc.string = new idStr( token );
  490. } else if ( token == "attack_end" ) {
  491. fc.type = FC_ENDATTACK;
  492. } else if ( token == "muzzle_flash" ) {
  493. if( !src.ReadTokenOnLine( &token ) ) {
  494. return "Unexpected end of line";
  495. }
  496. if ( ( token != "" ) && !modelDef->FindJoint( token ) ) {
  497. return va( "Joint '%s' not found", token.c_str() );
  498. }
  499. fc.type = FC_MUZZLEFLASH;
  500. fc.string = new idStr( token );
  501. } else if ( token == "muzzle_flash" ) {
  502. fc.type = FC_MUZZLEFLASH;
  503. fc.string = new idStr( "" );
  504. } else if ( token == "create_missile" ) {
  505. if( !src.ReadTokenOnLine( &token ) ) {
  506. return "Unexpected end of line";
  507. }
  508. if ( !modelDef->FindJoint( token ) ) {
  509. return va( "Joint '%s' not found", token.c_str() );
  510. }
  511. fc.type = FC_CREATEMISSILE;
  512. fc.string = new idStr( token );
  513. } else if ( token == "launch_missile" ) {
  514. if( !src.ReadTokenOnLine( &token ) ) {
  515. return "Unexpected end of line";
  516. }
  517. if ( !modelDef->FindJoint( token ) ) {
  518. return va( "Joint '%s' not found", token.c_str() );
  519. }
  520. fc.type = FC_LAUNCHMISSILE;
  521. fc.string = new idStr( token );
  522. } else if ( token == "fire_missile_at_target" ) {
  523. if( !src.ReadTokenOnLine( &token ) ) {
  524. return "Unexpected end of line";
  525. }
  526. jointInfo = modelDef->FindJoint( token );
  527. if ( !jointInfo ) {
  528. return va( "Joint '%s' not found", token.c_str() );
  529. }
  530. if( !src.ReadTokenOnLine( &token ) ) {
  531. return "Unexpected end of line";
  532. }
  533. fc.type = FC_FIREMISSILEATTARGET;
  534. fc.string = new idStr( token );
  535. fc.index = jointInfo->num;
  536. #ifdef _D3XP
  537. } else if ( token == "launch_projectile" ) {
  538. if( !src.ReadTokenOnLine( &token ) ) {
  539. return "Unexpected end of line";
  540. }
  541. if ( !declManager->FindDeclWithoutParsing( DECL_ENTITYDEF, token, false ) ) {
  542. return "Unknown projectile def";
  543. }
  544. fc.type = FC_LAUNCH_PROJECTILE;
  545. fc.string = new idStr( token );
  546. } else if ( token == "trigger_fx" ) {
  547. if( !src.ReadTokenOnLine( &token ) ) {
  548. return "Unexpected end of line";
  549. }
  550. jointInfo = modelDef->FindJoint( token );
  551. if ( !jointInfo ) {
  552. return va( "Joint '%s' not found", token.c_str() );
  553. }
  554. if( !src.ReadTokenOnLine( &token ) ) {
  555. return "Unexpected end of line";
  556. }
  557. if ( !declManager->FindType( DECL_FX, token, false ) ) {
  558. return "Unknown FX def";
  559. }
  560. fc.type = FC_TRIGGER_FX;
  561. fc.string = new idStr( token );
  562. fc.index = jointInfo->num;
  563. } else if ( token == "start_emitter" ) {
  564. idStr str;
  565. if( !src.ReadTokenOnLine( &token ) ) {
  566. return "Unexpected end of line";
  567. }
  568. str = token + " ";
  569. if( !src.ReadTokenOnLine( &token ) ) {
  570. return "Unexpected end of line";
  571. }
  572. jointInfo = modelDef->FindJoint( token );
  573. if ( !jointInfo ) {
  574. return va( "Joint '%s' not found", token.c_str() );
  575. }
  576. if( !src.ReadTokenOnLine( &token ) ) {
  577. return "Unexpected end of line";
  578. }
  579. str += token;
  580. fc.type = FC_START_EMITTER;
  581. fc.string = new idStr( str );
  582. fc.index = jointInfo->num;
  583. } else if ( token == "stop_emitter" ) {
  584. if( !src.ReadTokenOnLine( &token ) ) {
  585. return "Unexpected end of line";
  586. }
  587. fc.type = FC_STOP_EMITTER;
  588. fc.string = new idStr( token );
  589. #endif
  590. } else if ( token == "footstep" ) {
  591. fc.type = FC_FOOTSTEP;
  592. } else if ( token == "leftfoot" ) {
  593. fc.type = FC_LEFTFOOT;
  594. } else if ( token == "rightfoot" ) {
  595. fc.type = FC_RIGHTFOOT;
  596. } else if ( token == "enableEyeFocus" ) {
  597. fc.type = FC_ENABLE_EYE_FOCUS;
  598. } else if ( token == "disableEyeFocus" ) {
  599. fc.type = FC_DISABLE_EYE_FOCUS;
  600. } else if ( token == "disableGravity" ) {
  601. fc.type = FC_DISABLE_GRAVITY;
  602. } else if ( token == "enableGravity" ) {
  603. fc.type = FC_ENABLE_GRAVITY;
  604. } else if ( token == "jump" ) {
  605. fc.type = FC_JUMP;
  606. } else if ( token == "enableClip" ) {
  607. fc.type = FC_ENABLE_CLIP;
  608. } else if ( token == "disableClip" ) {
  609. fc.type = FC_DISABLE_CLIP;
  610. } else if ( token == "enableWalkIK" ) {
  611. fc.type = FC_ENABLE_WALK_IK;
  612. } else if ( token == "disableWalkIK" ) {
  613. fc.type = FC_DISABLE_WALK_IK;
  614. } else if ( token == "enableLegIK" ) {
  615. if( !src.ReadTokenOnLine( &token ) ) {
  616. return "Unexpected end of line";
  617. }
  618. fc.type = FC_ENABLE_LEG_IK;
  619. fc.index = atoi( token );
  620. } else if ( token == "disableLegIK" ) {
  621. if( !src.ReadTokenOnLine( &token ) ) {
  622. return "Unexpected end of line";
  623. }
  624. fc.type = FC_DISABLE_LEG_IK;
  625. fc.index = atoi( token );
  626. } else if ( token == "recordDemo" ) {
  627. fc.type = FC_RECORDDEMO;
  628. if( src.ReadTokenOnLine( &token ) ) {
  629. fc.string = new idStr( token );
  630. }
  631. } else if ( token == "aviGame" ) {
  632. fc.type = FC_AVIGAME;
  633. if( src.ReadTokenOnLine( &token ) ) {
  634. fc.string = new idStr( token );
  635. }
  636. } else {
  637. return va( "Unknown command '%s'", token.c_str() );
  638. }
  639. // check if we've initialized the frame loopup table
  640. if ( !frameLookup.Num() ) {
  641. // we haven't, so allocate the table and initialize it
  642. frameLookup.SetGranularity( 1 );
  643. frameLookup.SetNum( anims[ 0 ]->NumFrames() );
  644. for( i = 0; i < frameLookup.Num(); i++ ) {
  645. frameLookup[ i ].num = 0;
  646. frameLookup[ i ].firstCommand = 0;
  647. }
  648. }
  649. // allocate space for a new command
  650. frameCommands.Alloc();
  651. // calculate the index of the new command
  652. index = frameLookup[ framenum ].firstCommand + frameLookup[ framenum ].num;
  653. // move all commands from our index onward up one to give us space for our new command
  654. for( i = frameCommands.Num() - 1; i > index; i-- ) {
  655. frameCommands[ i ] = frameCommands[ i - 1 ];
  656. }
  657. // fix the indices of any later frames to account for the inserted command
  658. for( i = framenum + 1; i < frameLookup.Num(); i++ ) {
  659. frameLookup[ i ].firstCommand++;
  660. }
  661. // store the new command
  662. frameCommands[ index ] = fc;
  663. // increase the number of commands on this frame
  664. frameLookup[ framenum ].num++;
  665. // return with no error
  666. return NULL;
  667. }
  668. /*
  669. =====================
  670. idAnim::CallFrameCommands
  671. =====================
  672. */
  673. void idAnim::CallFrameCommands( idEntity *ent, int from, int to ) const {
  674. int index;
  675. int end;
  676. int frame;
  677. int numframes;
  678. numframes = anims[ 0 ]->NumFrames();
  679. frame = from;
  680. while( frame != to ) {
  681. frame++;
  682. if ( frame >= numframes ) {
  683. frame = 0;
  684. }
  685. index = frameLookup[ frame ].firstCommand;
  686. end = index + frameLookup[ frame ].num;
  687. while( index < end ) {
  688. const frameCommand_t &command = frameCommands[ index++ ];
  689. switch( command.type ) {
  690. case FC_SCRIPTFUNCTION: {
  691. gameLocal.CallFrameCommand( ent, command.function );
  692. break;
  693. }
  694. case FC_SCRIPTFUNCTIONOBJECT: {
  695. gameLocal.CallObjectFrameCommand( ent, command.string->c_str() );
  696. break;
  697. }
  698. case FC_EVENTFUNCTION: {
  699. const idEventDef *ev = idEventDef::FindEvent( command.string->c_str() );
  700. ent->ProcessEvent( ev );
  701. break;
  702. }
  703. case FC_SOUND: {
  704. if ( !command.soundShader ) {
  705. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_ANY, 0, false, NULL ) ) {
  706. gameLocal.Warning( "Framecommand 'sound' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  707. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  708. }
  709. } else {
  710. ent->StartSoundShader( command.soundShader, SND_CHANNEL_ANY, 0, false, NULL );
  711. }
  712. break;
  713. }
  714. case FC_SOUND_VOICE: {
  715. if ( !command.soundShader ) {
  716. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_VOICE, 0, false, NULL ) ) {
  717. gameLocal.Warning( "Framecommand 'sound_voice' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  718. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  719. }
  720. } else {
  721. ent->StartSoundShader( command.soundShader, SND_CHANNEL_VOICE, 0, false, NULL );
  722. }
  723. break;
  724. }
  725. case FC_SOUND_VOICE2: {
  726. if ( !command.soundShader ) {
  727. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_VOICE2, 0, false, NULL ) ) {
  728. gameLocal.Warning( "Framecommand 'sound_voice2' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  729. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  730. }
  731. } else {
  732. ent->StartSoundShader( command.soundShader, SND_CHANNEL_VOICE2, 0, false, NULL );
  733. }
  734. break;
  735. }
  736. case FC_SOUND_BODY: {
  737. if ( !command.soundShader ) {
  738. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_BODY, 0, false, NULL ) ) {
  739. gameLocal.Warning( "Framecommand 'sound_body' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  740. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  741. }
  742. } else {
  743. ent->StartSoundShader( command.soundShader, SND_CHANNEL_BODY, 0, false, NULL );
  744. }
  745. break;
  746. }
  747. case FC_SOUND_BODY2: {
  748. if ( !command.soundShader ) {
  749. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_BODY2, 0, false, NULL ) ) {
  750. gameLocal.Warning( "Framecommand 'sound_body2' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  751. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  752. }
  753. } else {
  754. ent->StartSoundShader( command.soundShader, SND_CHANNEL_BODY2, 0, false, NULL );
  755. }
  756. break;
  757. }
  758. case FC_SOUND_BODY3: {
  759. if ( !command.soundShader ) {
  760. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_BODY3, 0, false, NULL ) ) {
  761. gameLocal.Warning( "Framecommand 'sound_body3' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  762. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  763. }
  764. } else {
  765. ent->StartSoundShader( command.soundShader, SND_CHANNEL_BODY3, 0, false, NULL );
  766. }
  767. break;
  768. }
  769. case FC_SOUND_WEAPON: {
  770. if ( !command.soundShader ) {
  771. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_WEAPON, 0, false, NULL ) ) {
  772. gameLocal.Warning( "Framecommand 'sound_weapon' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  773. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  774. }
  775. } else {
  776. ent->StartSoundShader( command.soundShader, SND_CHANNEL_WEAPON, 0, false, NULL );
  777. }
  778. break;
  779. }
  780. case FC_SOUND_GLOBAL: {
  781. if ( !command.soundShader ) {
  782. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL ) ) {
  783. gameLocal.Warning( "Framecommand 'sound_global' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  784. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  785. }
  786. } else {
  787. ent->StartSoundShader( command.soundShader, SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
  788. }
  789. break;
  790. }
  791. case FC_SOUND_ITEM: {
  792. if ( !command.soundShader ) {
  793. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_ITEM, 0, false, NULL ) ) {
  794. gameLocal.Warning( "Framecommand 'sound_item' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  795. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  796. }
  797. } else {
  798. ent->StartSoundShader( command.soundShader, SND_CHANNEL_ITEM, 0, false, NULL );
  799. }
  800. break;
  801. }
  802. case FC_SOUND_CHATTER: {
  803. if ( ent->CanPlayChatterSounds() ) {
  804. if ( !command.soundShader ) {
  805. if ( !ent->StartSound( command.string->c_str(), SND_CHANNEL_VOICE, 0, false, NULL ) ) {
  806. gameLocal.Warning( "Framecommand 'sound_chatter' on entity '%s', anim '%s', frame %d: Could not find sound '%s'",
  807. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  808. }
  809. } else {
  810. ent->StartSoundShader( command.soundShader, SND_CHANNEL_VOICE, 0, false, NULL );
  811. }
  812. }
  813. break;
  814. }
  815. case FC_FX: {
  816. idEntityFx::StartFx( command.string->c_str(), NULL, NULL, ent, true );
  817. break;
  818. }
  819. case FC_SKIN: {
  820. ent->SetSkin( command.skin );
  821. break;
  822. }
  823. case FC_TRIGGER: {
  824. idEntity *target;
  825. target = gameLocal.FindEntity( command.string->c_str() );
  826. if ( target ) {
  827. #ifdef _D3XP
  828. SetTimeState ts(target->timeGroup);
  829. #endif
  830. target->Signal( SIG_TRIGGER );
  831. target->ProcessEvent( &EV_Activate, ent );
  832. target->TriggerGuis();
  833. } else {
  834. gameLocal.Warning( "Framecommand 'trigger' on entity '%s', anim '%s', frame %d: Could not find entity '%s'",
  835. ent->name.c_str(), FullName(), frame + 1, command.string->c_str() );
  836. }
  837. break;
  838. }
  839. case FC_TRIGGER_SMOKE_PARTICLE: {
  840. ent->ProcessEvent( &AI_TriggerParticles, command.string->c_str() );
  841. break;
  842. }
  843. case FC_MELEE: {
  844. ent->ProcessEvent( &AI_AttackMelee, command.string->c_str() );
  845. break;
  846. }
  847. case FC_DIRECTDAMAGE: {
  848. ent->ProcessEvent( &AI_DirectDamage, command.string->c_str() );
  849. break;
  850. }
  851. case FC_BEGINATTACK: {
  852. ent->ProcessEvent( &AI_BeginAttack, command.string->c_str() );
  853. break;
  854. }
  855. case FC_ENDATTACK: {
  856. ent->ProcessEvent( &AI_EndAttack );
  857. break;
  858. }
  859. case FC_MUZZLEFLASH: {
  860. ent->ProcessEvent( &AI_MuzzleFlash, command.string->c_str() );
  861. break;
  862. }
  863. case FC_CREATEMISSILE: {
  864. ent->ProcessEvent( &AI_CreateMissile, command.string->c_str() );
  865. break;
  866. }
  867. case FC_LAUNCHMISSILE: {
  868. ent->ProcessEvent( &AI_AttackMissile, command.string->c_str() );
  869. break;
  870. }
  871. case FC_FIREMISSILEATTARGET: {
  872. ent->ProcessEvent( &AI_FireMissileAtTarget, modelDef->GetJointName( command.index ), command.string->c_str() );
  873. break;
  874. }
  875. #ifdef _D3XP
  876. case FC_LAUNCH_PROJECTILE: {
  877. ent->ProcessEvent( &AI_LaunchProjectile, command.string->c_str() );
  878. break;
  879. }
  880. case FC_TRIGGER_FX: {
  881. ent->ProcessEvent( &AI_TriggerFX, modelDef->GetJointName( command.index ), command.string->c_str() );
  882. break;
  883. }
  884. case FC_PARTICLE:
  885. {
  886. //bc
  887. //ent->ProcessEvent( &AI_StartEmitter, modelDef->GetJointName( command.index ), command.string->c_str() );
  888. const idDeclParticle *smokeFly = NULL;
  889. smokeFly = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, command.string->c_str() ) );
  890. if (smokeFly)
  891. {
  892. jointHandle_t jointNum;
  893. jointNum = ent->GetAnimator()->GetJointHandle( modelDef->GetJointName( command.index ) );
  894. idVec3 offset;
  895. idMat3 axis;
  896. //ent->GetAnimator()->GetJointTransform( jointNum, gameLocal.time, offset, axis );
  897. ent->GetAnimator()->GetJointTransform( jointNum, gameLocal.time, offset, axis );
  898. offset = ent->GetPhysics()->GetOrigin() + offset * ent->GetPhysics()->GetAxis();
  899. axis = axis * ent->GetPhysics()->GetAxis();
  900. gameLocal.smokeParticles->EmitSmoke( smokeFly, gameLocal.time, 0,
  901. offset, axis, 0 );
  902. }
  903. }
  904. case FC_START_EMITTER: {
  905. int index = command.string->Find(" ");
  906. if(index >= 0) {
  907. idStr name = command.string->Left(index);
  908. idStr particle = command.string->Right(command.string->Length() - index - 1);
  909. ent->ProcessEvent( &AI_StartEmitter, name.c_str(), modelDef->GetJointName( command.index ), particle.c_str() );
  910. }
  911. }
  912. case FC_STOP_EMITTER: {
  913. ent->ProcessEvent( &AI_StopEmitter, command.string->c_str() );
  914. }
  915. #endif
  916. case FC_FOOTSTEP : {
  917. ent->ProcessEvent( &EV_Footstep );
  918. break;
  919. }
  920. case FC_LEFTFOOT: {
  921. ent->ProcessEvent( &EV_FootstepLeft );
  922. break;
  923. }
  924. case FC_RIGHTFOOT: {
  925. ent->ProcessEvent( &EV_FootstepRight );
  926. break;
  927. }
  928. case FC_ENABLE_EYE_FOCUS: {
  929. ent->ProcessEvent( &AI_EnableEyeFocus );
  930. break;
  931. }
  932. case FC_DISABLE_EYE_FOCUS: {
  933. ent->ProcessEvent( &AI_DisableEyeFocus );
  934. break;
  935. }
  936. case FC_DISABLE_GRAVITY: {
  937. ent->ProcessEvent( &AI_DisableGravity );
  938. break;
  939. }
  940. case FC_ENABLE_GRAVITY: {
  941. ent->ProcessEvent( &AI_EnableGravity );
  942. break;
  943. }
  944. case FC_JUMP: {
  945. ent->ProcessEvent( &AI_JumpFrame );
  946. break;
  947. }
  948. case FC_ENABLE_CLIP: {
  949. ent->ProcessEvent( &AI_EnableClip );
  950. break;
  951. }
  952. case FC_DISABLE_CLIP: {
  953. ent->ProcessEvent( &AI_DisableClip );
  954. break;
  955. }
  956. case FC_ENABLE_WALK_IK: {
  957. ent->ProcessEvent( &EV_EnableWalkIK );
  958. break;
  959. }
  960. case FC_DISABLE_WALK_IK: {
  961. ent->ProcessEvent( &EV_DisableWalkIK );
  962. break;
  963. }
  964. case FC_ENABLE_LEG_IK: {
  965. ent->ProcessEvent( &EV_EnableLegIK, command.index );
  966. break;
  967. }
  968. case FC_DISABLE_LEG_IK: {
  969. ent->ProcessEvent( &EV_DisableLegIK, command.index );
  970. break;
  971. }
  972. case FC_RECORDDEMO: {
  973. if ( command.string ) {
  974. cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "recordDemo %s", command.string->c_str() ) );
  975. } else {
  976. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "stoprecording" );
  977. }
  978. break;
  979. }
  980. case FC_AVIGAME: {
  981. if ( command.string ) {
  982. cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "aviGame %s", command.string->c_str() ) );
  983. } else {
  984. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "aviGame" );
  985. }
  986. break;
  987. }
  988. }
  989. }
  990. }
  991. }
  992. /*
  993. =====================
  994. idAnim::FindFrameForFrameCommand
  995. =====================
  996. */
  997. int idAnim::FindFrameForFrameCommand( frameCommandType_t framecommand, const frameCommand_t **command ) const {
  998. int frame;
  999. int index;
  1000. int numframes;
  1001. int end;
  1002. if ( !frameCommands.Num() ) {
  1003. return -1;
  1004. }
  1005. numframes = anims[ 0 ]->NumFrames();
  1006. for( frame = 0; frame < numframes; frame++ ) {
  1007. end = frameLookup[ frame ].firstCommand + frameLookup[ frame ].num;
  1008. for( index = frameLookup[ frame ].firstCommand; index < end; index++ ) {
  1009. if ( frameCommands[ index ].type == framecommand ) {
  1010. if ( command ) {
  1011. *command = &frameCommands[ index ];
  1012. }
  1013. return frame;
  1014. }
  1015. }
  1016. }
  1017. if ( command ) {
  1018. *command = NULL;
  1019. }
  1020. return -1;
  1021. }
  1022. /*
  1023. =====================
  1024. idAnim::HasFrameCommands
  1025. =====================
  1026. */
  1027. bool idAnim::HasFrameCommands( void ) const {
  1028. if ( !frameCommands.Num() ) {
  1029. return false;
  1030. }
  1031. return true;
  1032. }
  1033. /*
  1034. =====================
  1035. idAnim::SetAnimFlags
  1036. =====================
  1037. */
  1038. void idAnim::SetAnimFlags( const animFlags_t &animflags ) {
  1039. flags = animflags;
  1040. }
  1041. /*
  1042. =====================
  1043. idAnim::GetAnimFlags
  1044. =====================
  1045. */
  1046. const animFlags_t &idAnim::GetAnimFlags( void ) const {
  1047. return flags;
  1048. }
  1049. /***********************************************************************
  1050. idAnimBlend
  1051. ***********************************************************************/
  1052. /*
  1053. =====================
  1054. idAnimBlend::idAnimBlend
  1055. =====================
  1056. */
  1057. idAnimBlend::idAnimBlend( void ) {
  1058. Reset( NULL );
  1059. }
  1060. /*
  1061. =====================
  1062. idAnimBlend::Save
  1063. archives object for save game file
  1064. =====================
  1065. */
  1066. void idAnimBlend::Save( idSaveGame *savefile ) const {
  1067. int i;
  1068. savefile->WriteInt( starttime );
  1069. savefile->WriteInt( endtime );
  1070. savefile->WriteInt( timeOffset );
  1071. savefile->WriteFloat( rate );
  1072. savefile->WriteInt( blendStartTime );
  1073. savefile->WriteInt( blendDuration );
  1074. savefile->WriteFloat( blendStartValue );
  1075. savefile->WriteFloat( blendEndValue );
  1076. for( i = 0; i < ANIM_MaxSyncedAnims; i++ ) {
  1077. savefile->WriteFloat( animWeights[ i ] );
  1078. }
  1079. savefile->WriteShort( cycle );
  1080. savefile->WriteShort( frame );
  1081. savefile->WriteShort( animNum );
  1082. savefile->WriteBool( allowMove );
  1083. savefile->WriteBool( allowFrameCommands );
  1084. }
  1085. /*
  1086. =====================
  1087. idAnimBlend::Restore
  1088. unarchives object from save game file
  1089. =====================
  1090. */
  1091. void idAnimBlend::Restore( idRestoreGame *savefile, const idDeclModelDef *modelDef ) {
  1092. int i;
  1093. this->modelDef = modelDef;
  1094. savefile->ReadInt( starttime );
  1095. savefile->ReadInt( endtime );
  1096. savefile->ReadInt( timeOffset );
  1097. savefile->ReadFloat( rate );
  1098. savefile->ReadInt( blendStartTime );
  1099. savefile->ReadInt( blendDuration );
  1100. savefile->ReadFloat( blendStartValue );
  1101. savefile->ReadFloat( blendEndValue );
  1102. for( i = 0; i < ANIM_MaxSyncedAnims; i++ ) {
  1103. savefile->ReadFloat( animWeights[ i ] );
  1104. }
  1105. savefile->ReadShort( cycle );
  1106. savefile->ReadShort( frame );
  1107. savefile->ReadShort( animNum );
  1108. if ( !modelDef ) {
  1109. animNum = 0;
  1110. } else if ( ( animNum < 0 ) || ( animNum > modelDef->NumAnims() ) ) {
  1111. gameLocal.Warning( "Anim number %d out of range for model '%s' during save game", animNum, modelDef->GetModelName() );
  1112. animNum = 0;
  1113. }
  1114. savefile->ReadBool( allowMove );
  1115. savefile->ReadBool( allowFrameCommands );
  1116. }
  1117. /*
  1118. =====================
  1119. idAnimBlend::Reset
  1120. =====================
  1121. */
  1122. void idAnimBlend::Reset( const idDeclModelDef *_modelDef ) {
  1123. modelDef = _modelDef;
  1124. cycle = 1;
  1125. starttime = 0;
  1126. endtime = 0;
  1127. timeOffset = 0;
  1128. rate = 1.0f;
  1129. frame = 0;
  1130. allowMove = true;
  1131. allowFrameCommands = true;
  1132. animNum = 0;
  1133. memset( animWeights, 0, sizeof( animWeights ) );
  1134. blendStartValue = 0.0f;
  1135. blendEndValue = 0.0f;
  1136. blendStartTime = 0;
  1137. blendDuration = 0;
  1138. }
  1139. /*
  1140. =====================
  1141. idAnimBlend::FullName
  1142. =====================
  1143. */
  1144. const char *idAnimBlend::AnimFullName( void ) const {
  1145. const idAnim *anim = Anim();
  1146. if ( !anim ) {
  1147. return "";
  1148. }
  1149. return anim->FullName();
  1150. }
  1151. /*
  1152. =====================
  1153. idAnimBlend::AnimName
  1154. =====================
  1155. */
  1156. const char *idAnimBlend::AnimName( void ) const {
  1157. const idAnim *anim = Anim();
  1158. if ( !anim ) {
  1159. return "";
  1160. }
  1161. return anim->Name();
  1162. }
  1163. /*
  1164. =====================
  1165. idAnimBlend::NumFrames
  1166. =====================
  1167. */
  1168. int idAnimBlend::NumFrames( void ) const {
  1169. const idAnim *anim = Anim();
  1170. if ( !anim ) {
  1171. return 0;
  1172. }
  1173. return anim->NumFrames();
  1174. }
  1175. /*
  1176. =====================
  1177. idAnimBlend::Length
  1178. =====================
  1179. */
  1180. int idAnimBlend::Length( void ) const {
  1181. const idAnim *anim = Anim();
  1182. if ( !anim ) {
  1183. return 0;
  1184. }
  1185. return anim->Length();
  1186. }
  1187. /*
  1188. =====================
  1189. idAnimBlend::GetWeight
  1190. =====================
  1191. */
  1192. float idAnimBlend::GetWeight( int currentTime ) const {
  1193. int timeDelta;
  1194. float frac;
  1195. float w;
  1196. timeDelta = currentTime - blendStartTime;
  1197. if ( timeDelta <= 0 ) {
  1198. w = blendStartValue;
  1199. } else if ( timeDelta >= blendDuration ) {
  1200. w = blendEndValue;
  1201. } else {
  1202. frac = ( float )timeDelta / ( float )blendDuration;
  1203. w = blendStartValue + ( blendEndValue - blendStartValue ) * frac;
  1204. }
  1205. return w;
  1206. }
  1207. /*
  1208. =====================
  1209. idAnimBlend::GetFinalWeight
  1210. =====================
  1211. */
  1212. float idAnimBlend::GetFinalWeight( void ) const {
  1213. return blendEndValue;
  1214. }
  1215. /*
  1216. =====================
  1217. idAnimBlend::SetWeight
  1218. =====================
  1219. */
  1220. void idAnimBlend::SetWeight( float newweight, int currentTime, int blendTime ) {
  1221. blendStartValue = GetWeight( currentTime );
  1222. blendEndValue = newweight;
  1223. blendStartTime = currentTime - 1;
  1224. blendDuration = blendTime;
  1225. if ( !newweight ) {
  1226. endtime = currentTime + blendTime;
  1227. }
  1228. }
  1229. /*
  1230. =====================
  1231. idAnimBlend::NumSyncedAnims
  1232. =====================
  1233. */
  1234. int idAnimBlend::NumSyncedAnims( void ) const {
  1235. const idAnim *anim = Anim();
  1236. if ( !anim ) {
  1237. return 0;
  1238. }
  1239. return anim->NumAnims();
  1240. }
  1241. /*
  1242. =====================
  1243. idAnimBlend::SetSyncedAnimWeight
  1244. =====================
  1245. */
  1246. bool idAnimBlend::SetSyncedAnimWeight( int num, float weight ) {
  1247. const idAnim *anim = Anim();
  1248. if ( !anim ) {
  1249. return false;
  1250. }
  1251. if ( ( num < 0 ) || ( num > anim->NumAnims() ) ) {
  1252. return false;
  1253. }
  1254. animWeights[ num ] = weight;
  1255. return true;
  1256. }
  1257. /*
  1258. =====================
  1259. idAnimBlend::SetFrame
  1260. =====================
  1261. */
  1262. void idAnimBlend::SetFrame( const idDeclModelDef *modelDef, int _animNum, int _frame, int currentTime, int blendTime ) {
  1263. Reset( modelDef );
  1264. if ( !modelDef ) {
  1265. return;
  1266. }
  1267. const idAnim *_anim = modelDef->GetAnim( _animNum );
  1268. if ( !_anim ) {
  1269. return;
  1270. }
  1271. const idMD5Anim *md5anim = _anim->MD5Anim( 0 );
  1272. if ( modelDef->Joints().Num() != md5anim->NumJoints() ) {
  1273. gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", modelDef->GetModelName(), md5anim->Name() );
  1274. return;
  1275. }
  1276. animNum = _animNum;
  1277. starttime = currentTime;
  1278. endtime = -1;
  1279. cycle = -1;
  1280. animWeights[ 0 ] = 1.0f;
  1281. frame = _frame;
  1282. // a frame of 0 means it's not a single frame blend, so we set it to frame + 1
  1283. if ( frame <= 0 ) {
  1284. frame = 1;
  1285. } else if ( frame > _anim->NumFrames() ) {
  1286. frame = _anim->NumFrames();
  1287. }
  1288. // set up blend
  1289. blendEndValue = 1.0f;
  1290. blendStartTime = currentTime - 1;
  1291. blendDuration = blendTime;
  1292. blendStartValue = 0.0f;
  1293. }
  1294. /*
  1295. =====================
  1296. idAnimBlend::CycleAnim
  1297. =====================
  1298. */
  1299. void idAnimBlend::CycleAnim( const idDeclModelDef *modelDef, int _animNum, int currentTime, int blendTime ) {
  1300. Reset( modelDef );
  1301. if ( !modelDef ) {
  1302. return;
  1303. }
  1304. const idAnim *_anim = modelDef->GetAnim( _animNum );
  1305. if ( !_anim ) {
  1306. return;
  1307. }
  1308. const idMD5Anim *md5anim = _anim->MD5Anim( 0 );
  1309. if ( modelDef->Joints().Num() != md5anim->NumJoints() ) {
  1310. gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", modelDef->GetModelName(), md5anim->Name() );
  1311. return;
  1312. }
  1313. animNum = _animNum;
  1314. animWeights[ 0 ] = 1.0f;
  1315. endtime = -1;
  1316. cycle = -1;
  1317. if ( _anim->GetAnimFlags().random_cycle_start ) {
  1318. // start the animation at a random time so that characters don't walk in sync
  1319. starttime = currentTime - gameLocal.random.RandomFloat() * _anim->Length();
  1320. } else {
  1321. starttime = currentTime;
  1322. }
  1323. // set up blend
  1324. blendEndValue = 1.0f;
  1325. blendStartTime = currentTime - 1;
  1326. blendDuration = blendTime;
  1327. blendStartValue = 0.0f;
  1328. }
  1329. /*
  1330. =====================
  1331. idAnimBlend::PlayAnim
  1332. =====================
  1333. */
  1334. void idAnimBlend::PlayAnim( const idDeclModelDef *modelDef, int _animNum, int currentTime, int blendTime ) {
  1335. Reset( modelDef );
  1336. if ( !modelDef ) {
  1337. return;
  1338. }
  1339. const idAnim *_anim = modelDef->GetAnim( _animNum );
  1340. if ( !_anim ) {
  1341. return;
  1342. }
  1343. const idMD5Anim *md5anim = _anim->MD5Anim( 0 );
  1344. if ( modelDef->Joints().Num() != md5anim->NumJoints() ) {
  1345. gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", modelDef->GetModelName(), md5anim->Name() );
  1346. return;
  1347. }
  1348. animNum = _animNum;
  1349. starttime = currentTime;
  1350. endtime = starttime + _anim->Length();
  1351. cycle = 1;
  1352. animWeights[ 0 ] = 1.0f;
  1353. // set up blend
  1354. blendEndValue = 1.0f;
  1355. blendStartTime = currentTime - 1;
  1356. blendDuration = blendTime;
  1357. blendStartValue = 0.0f;
  1358. }
  1359. /*
  1360. =====================
  1361. idAnimBlend::Clear
  1362. =====================
  1363. */
  1364. void idAnimBlend::Clear( int currentTime, int clearTime ) {
  1365. if ( !clearTime ) {
  1366. Reset( modelDef );
  1367. } else {
  1368. SetWeight( 0.0f, currentTime, clearTime );
  1369. }
  1370. }
  1371. /*
  1372. =====================
  1373. idAnimBlend::IsDone
  1374. =====================
  1375. */
  1376. bool idAnimBlend::IsDone( int currentTime ) const {
  1377. if ( !frame && ( endtime > 0 ) && ( currentTime >= endtime ) ) {
  1378. return true;
  1379. }
  1380. if ( ( blendEndValue <= 0.0f ) && ( currentTime >= ( blendStartTime + blendDuration ) ) ) {
  1381. return true;
  1382. }
  1383. return false;
  1384. }
  1385. /*
  1386. =====================
  1387. idAnimBlend::FrameHasChanged
  1388. =====================
  1389. */
  1390. bool idAnimBlend::FrameHasChanged( int currentTime ) const {
  1391. // if we don't have an anim, no change
  1392. if ( !animNum ) {
  1393. return false;
  1394. }
  1395. // if anim is done playing, no change
  1396. if ( ( endtime > 0 ) && ( currentTime > endtime ) ) {
  1397. return false;
  1398. }
  1399. // if our blend weight changes, we need to update
  1400. if ( ( currentTime < ( blendStartTime + blendDuration ) && ( blendStartValue != blendEndValue ) ) ) {
  1401. return true;
  1402. }
  1403. // if we're a single frame anim and this isn't the frame we started on, we don't need to update
  1404. if ( ( frame || ( NumFrames() == 1 ) ) && ( currentTime != starttime ) ) {
  1405. return false;
  1406. }
  1407. return true;
  1408. }
  1409. /*
  1410. =====================
  1411. idAnimBlend::GetCycleCount
  1412. =====================
  1413. */
  1414. int idAnimBlend::GetCycleCount( void ) const {
  1415. return cycle;
  1416. }
  1417. /*
  1418. =====================
  1419. idAnimBlend::SetCycleCount
  1420. =====================
  1421. */
  1422. void idAnimBlend::SetCycleCount( int count ) {
  1423. const idAnim *anim = Anim();
  1424. if ( !anim ) {
  1425. cycle = -1;
  1426. endtime = 0;
  1427. } else {
  1428. cycle = count;
  1429. if ( cycle < 0 ) {
  1430. cycle = -1;
  1431. endtime = -1;
  1432. } else if ( cycle == 0 ) {
  1433. cycle = 1;
  1434. // most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
  1435. if ( rate == 1.0f ) {
  1436. endtime = starttime - timeOffset + anim->Length();
  1437. } else if ( rate != 0.0f ) {
  1438. endtime = starttime - timeOffset + anim->Length() / rate;
  1439. } else {
  1440. endtime = -1;
  1441. }
  1442. } else {
  1443. // most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
  1444. if ( rate == 1.0f ) {
  1445. endtime = starttime - timeOffset + anim->Length() * cycle;
  1446. } else if ( rate != 0.0f ) {
  1447. endtime = starttime - timeOffset + ( anim->Length() * cycle ) / rate;
  1448. } else {
  1449. endtime = -1;
  1450. }
  1451. }
  1452. }
  1453. }
  1454. /*
  1455. =====================
  1456. idAnimBlend::SetPlaybackRate
  1457. =====================
  1458. */
  1459. void idAnimBlend::SetPlaybackRate( int currentTime, float newRate ) {
  1460. int animTime;
  1461. if ( rate == newRate ) {
  1462. return;
  1463. }
  1464. animTime = AnimTime( currentTime );
  1465. if ( newRate == 1.0f ) {
  1466. timeOffset = animTime - ( currentTime - starttime );
  1467. } else {
  1468. timeOffset = animTime - ( currentTime - starttime ) * newRate;
  1469. }
  1470. rate = newRate;
  1471. // update the anim endtime
  1472. SetCycleCount( cycle );
  1473. }
  1474. /*
  1475. =====================
  1476. idAnimBlend::GetPlaybackRate
  1477. =====================
  1478. */
  1479. float idAnimBlend::GetPlaybackRate( void ) const {
  1480. return rate;
  1481. }
  1482. /*
  1483. =====================
  1484. idAnimBlend::SetStartTime
  1485. =====================
  1486. */
  1487. void idAnimBlend::SetStartTime( int _startTime ) {
  1488. starttime = _startTime;
  1489. // update the anim endtime
  1490. SetCycleCount( cycle );
  1491. }
  1492. /*
  1493. =====================
  1494. idAnimBlend::GetStartTime
  1495. =====================
  1496. */
  1497. int idAnimBlend::GetStartTime( void ) const {
  1498. if ( !animNum ) {
  1499. return 0;
  1500. }
  1501. return starttime;
  1502. }
  1503. /*
  1504. =====================
  1505. idAnimBlend::GetEndTime
  1506. =====================
  1507. */
  1508. int idAnimBlend::GetEndTime( void ) const {
  1509. if ( !animNum ) {
  1510. return 0;
  1511. }
  1512. return endtime;
  1513. }
  1514. /*
  1515. =====================
  1516. idAnimBlend::PlayLength
  1517. =====================
  1518. */
  1519. int idAnimBlend::PlayLength( void ) const {
  1520. if ( !animNum ) {
  1521. return 0;
  1522. }
  1523. if ( endtime < 0 ) {
  1524. return -1;
  1525. }
  1526. return endtime - starttime + timeOffset;
  1527. }
  1528. /*
  1529. =====================
  1530. idAnimBlend::AllowMovement
  1531. =====================
  1532. */
  1533. void idAnimBlend::AllowMovement( bool allow ) {
  1534. allowMove = allow;
  1535. }
  1536. /*
  1537. =====================
  1538. idAnimBlend::AllowFrameCommands
  1539. =====================
  1540. */
  1541. void idAnimBlend::AllowFrameCommands( bool allow ) {
  1542. allowFrameCommands = allow;
  1543. }
  1544. /*
  1545. =====================
  1546. idAnimBlend::Anim
  1547. =====================
  1548. */
  1549. const idAnim *idAnimBlend::Anim( void ) const {
  1550. if ( !modelDef ) {
  1551. return NULL;
  1552. }
  1553. const idAnim *anim = modelDef->GetAnim( animNum );
  1554. return anim;
  1555. }
  1556. /*
  1557. =====================
  1558. idAnimBlend::AnimNum
  1559. =====================
  1560. */
  1561. int idAnimBlend::AnimNum( void ) const {
  1562. return animNum;
  1563. }
  1564. /*
  1565. =====================
  1566. idAnimBlend::AnimTime
  1567. =====================
  1568. */
  1569. int idAnimBlend::AnimTime( int currentTime ) const {
  1570. int time;
  1571. int length;
  1572. const idAnim *anim = Anim();
  1573. if ( anim ) {
  1574. if ( frame ) {
  1575. return FRAME2MS( frame - 1 );
  1576. }
  1577. // most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
  1578. if ( rate == 1.0f ) {
  1579. time = currentTime - starttime + timeOffset;
  1580. } else {
  1581. time = static_cast<int>( ( currentTime - starttime ) * rate ) + timeOffset;
  1582. }
  1583. // given enough time, we can easily wrap time around in our frame calculations, so
  1584. // keep cycling animations' time within the length of the anim.
  1585. length = anim->Length();
  1586. if ( ( cycle < 0 ) && ( length > 0 ) ) {
  1587. time %= length;
  1588. // time will wrap after 24 days (oh no!), resulting in negative results for the %.
  1589. // adding the length gives us the proper result.
  1590. if ( time < 0 ) {
  1591. time += length;
  1592. }
  1593. }
  1594. return time;
  1595. } else {
  1596. return 0;
  1597. }
  1598. }
  1599. /*
  1600. =====================
  1601. idAnimBlend::GetFrameNumber
  1602. =====================
  1603. */
  1604. int idAnimBlend::GetFrameNumber( int currentTime ) const {
  1605. const idMD5Anim *md5anim;
  1606. frameBlend_t frameinfo;
  1607. int animTime;
  1608. const idAnim *anim = Anim();
  1609. if ( !anim ) {
  1610. return 1;
  1611. }
  1612. if ( frame ) {
  1613. return frame;
  1614. }
  1615. md5anim = anim->MD5Anim( 0 );
  1616. animTime = AnimTime( currentTime );
  1617. md5anim->ConvertTimeToFrame( animTime, cycle, frameinfo );
  1618. return frameinfo.frame1 + 1;
  1619. }
  1620. /*
  1621. =====================
  1622. idAnimBlend::CallFrameCommands
  1623. =====================
  1624. */
  1625. void idAnimBlend::CallFrameCommands( idEntity *ent, int fromtime, int totime ) const {
  1626. const idMD5Anim *md5anim;
  1627. frameBlend_t frame1;
  1628. frameBlend_t frame2;
  1629. int fromFrameTime;
  1630. int toFrameTime;
  1631. if ( !allowFrameCommands || !ent || frame || ( ( endtime > 0 ) && ( fromtime > endtime ) ) ) {
  1632. return;
  1633. }
  1634. const idAnim *anim = Anim();
  1635. if ( !anim || !anim->HasFrameCommands() ) {
  1636. return;
  1637. }
  1638. if ( totime <= starttime ) {
  1639. // don't play until next frame or we'll play commands twice.
  1640. // this happens on the player sometimes.
  1641. return;
  1642. }
  1643. fromFrameTime = AnimTime( fromtime );
  1644. toFrameTime = AnimTime( totime );
  1645. if ( toFrameTime < fromFrameTime ) {
  1646. toFrameTime += anim->Length();
  1647. }
  1648. md5anim = anim->MD5Anim( 0 );
  1649. md5anim->ConvertTimeToFrame( fromFrameTime, cycle, frame1 );
  1650. md5anim->ConvertTimeToFrame( toFrameTime, cycle, frame2 );
  1651. if ( fromFrameTime <= 0 ) {
  1652. // make sure first frame is called
  1653. anim->CallFrameCommands( ent, -1, frame2.frame1 );
  1654. } else {
  1655. anim->CallFrameCommands( ent, frame1.frame1, frame2.frame1 );
  1656. }
  1657. }
  1658. /*
  1659. =====================
  1660. idAnimBlend::BlendAnim
  1661. =====================
  1662. */
  1663. bool idAnimBlend::BlendAnim( int currentTime, int channel, int numJoints, idJointQuat *blendFrame, float &blendWeight, bool removeOriginOffset, bool overrideBlend, bool printInfo ) const {
  1664. int i;
  1665. float lerp;
  1666. float mixWeight;
  1667. const idMD5Anim *md5anim;
  1668. idJointQuat *ptr;
  1669. frameBlend_t frametime;
  1670. idJointQuat *jointFrame;
  1671. idJointQuat *mixFrame;
  1672. int numAnims;
  1673. int time;
  1674. const idAnim *anim = Anim();
  1675. if ( !anim ) {
  1676. return false;
  1677. }
  1678. float weight = GetWeight( currentTime );
  1679. if ( blendWeight > 0.0f ) {
  1680. if ( ( endtime >= 0 ) && ( currentTime >= endtime ) ) {
  1681. return false;
  1682. }
  1683. if ( !weight ) {
  1684. return false;
  1685. }
  1686. if ( overrideBlend ) {
  1687. blendWeight = 1.0f - weight;
  1688. }
  1689. }
  1690. if ( ( channel == ANIMCHANNEL_ALL ) && !blendWeight ) {
  1691. // we don't need a temporary buffer, so just store it directly in the blend frame
  1692. jointFrame = blendFrame;
  1693. } else {
  1694. // allocate a temporary buffer to copy the joints from
  1695. jointFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( *jointFrame ) );
  1696. }
  1697. time = AnimTime( currentTime );
  1698. numAnims = anim->NumAnims();
  1699. if ( numAnims == 1 ) {
  1700. md5anim = anim->MD5Anim( 0 );
  1701. if ( frame ) {
  1702. md5anim->GetSingleFrame( frame - 1, jointFrame, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
  1703. } else {
  1704. md5anim->ConvertTimeToFrame( time, cycle, frametime );
  1705. md5anim->GetInterpolatedFrame( frametime, jointFrame, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
  1706. }
  1707. } else {
  1708. //
  1709. // need to mix the multipoint anim together first
  1710. //
  1711. // allocate a temporary buffer to copy the joints to
  1712. mixFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( *jointFrame ) );
  1713. if ( !frame ) {
  1714. anim->MD5Anim( 0 )->ConvertTimeToFrame( time, cycle, frametime );
  1715. }
  1716. ptr = jointFrame;
  1717. mixWeight = 0.0f;
  1718. for( i = 0; i < numAnims; i++ ) {
  1719. if ( animWeights[ i ] > 0.0f ) {
  1720. mixWeight += animWeights[ i ];
  1721. lerp = animWeights[ i ] / mixWeight;
  1722. md5anim = anim->MD5Anim( i );
  1723. if ( frame ) {
  1724. md5anim->GetSingleFrame( frame - 1, ptr, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
  1725. } else {
  1726. md5anim->GetInterpolatedFrame( frametime, ptr, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
  1727. }
  1728. // only blend after the first anim is mixed in
  1729. if ( ptr != jointFrame ) {
  1730. SIMDProcessor->BlendJoints( jointFrame, ptr, lerp, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
  1731. }
  1732. ptr = mixFrame;
  1733. }
  1734. }
  1735. if ( !mixWeight ) {
  1736. return false;
  1737. }
  1738. }
  1739. if ( removeOriginOffset ) {
  1740. if ( allowMove ) {
  1741. #ifdef VELOCITY_MOVE
  1742. jointFrame[ 0 ].t.x = 0.0f;
  1743. #else
  1744. jointFrame[ 0 ].t.Zero();
  1745. #endif
  1746. }
  1747. if ( anim->GetAnimFlags().anim_turn ) {
  1748. jointFrame[ 0 ].q.Set( -0.70710677f, 0.0f, 0.0f, 0.70710677f );
  1749. }
  1750. }
  1751. if ( !blendWeight ) {
  1752. blendWeight = weight;
  1753. if ( channel != ANIMCHANNEL_ALL ) {
  1754. const int *index = modelDef->GetChannelJoints( channel );
  1755. const int num = modelDef->NumJointsOnChannel( channel );
  1756. for( i = 0; i < num; i++ ) {
  1757. int j = index[i];
  1758. blendFrame[j].t = jointFrame[j].t;
  1759. blendFrame[j].q = jointFrame[j].q;
  1760. }
  1761. }
  1762. } else {
  1763. blendWeight += weight;
  1764. lerp = weight / blendWeight;
  1765. SIMDProcessor->BlendJoints( blendFrame, jointFrame, lerp, modelDef->GetChannelJoints( channel ), modelDef->NumJointsOnChannel( channel ) );
  1766. }
  1767. if ( printInfo ) {
  1768. if ( frame ) {
  1769. gameLocal.Printf( " %s: '%s', %d, %.2f%%\n", channelNames[ channel ], anim->FullName(), frame, weight * 100.0f );
  1770. } else {
  1771. gameLocal.Printf( " %s: '%s', %.3f, %.2f%%\n", channelNames[ channel ], anim->FullName(), ( float )frametime.frame1 + frametime.backlerp, weight * 100.0f );
  1772. }
  1773. }
  1774. return true;
  1775. }
  1776. /*
  1777. =====================
  1778. idAnimBlend::BlendOrigin
  1779. =====================
  1780. */
  1781. void idAnimBlend::BlendOrigin( int currentTime, idVec3 &blendPos, float &blendWeight, bool removeOriginOffset ) const {
  1782. float lerp;
  1783. idVec3 animpos;
  1784. idVec3 pos;
  1785. int time;
  1786. int num;
  1787. int i;
  1788. if ( frame || ( ( endtime > 0 ) && ( currentTime > endtime ) ) ) {
  1789. return;
  1790. }
  1791. const idAnim *anim = Anim();
  1792. if ( !anim ) {
  1793. return;
  1794. }
  1795. if ( allowMove && removeOriginOffset ) {
  1796. return;
  1797. }
  1798. float weight = GetWeight( currentTime );
  1799. if ( !weight ) {
  1800. return;
  1801. }
  1802. time = AnimTime( currentTime );
  1803. pos.Zero();
  1804. num = anim->NumAnims();
  1805. for( i = 0; i < num; i++ ) {
  1806. anim->GetOrigin( animpos, i, time, cycle );
  1807. pos += animpos * animWeights[ i ];
  1808. }
  1809. if ( !blendWeight ) {
  1810. blendPos = pos;
  1811. blendWeight = weight;
  1812. } else {
  1813. lerp = weight / ( blendWeight + weight );
  1814. blendPos += lerp * ( pos - blendPos );
  1815. blendWeight += weight;
  1816. }
  1817. }
  1818. /*
  1819. =====================
  1820. idAnimBlend::BlendDelta
  1821. =====================
  1822. */
  1823. void idAnimBlend::BlendDelta( int fromtime, int totime, idVec3 &blendDelta, float &blendWeight ) const {
  1824. idVec3 pos1;
  1825. idVec3 pos2;
  1826. idVec3 animpos;
  1827. idVec3 delta;
  1828. int time1;
  1829. int time2;
  1830. float lerp;
  1831. int num;
  1832. int i;
  1833. if ( frame || !allowMove || ( ( endtime > 0 ) && ( fromtime > endtime ) ) ) {
  1834. return;
  1835. }
  1836. const idAnim *anim = Anim();
  1837. if ( !anim ) {
  1838. return;
  1839. }
  1840. float weight = GetWeight( totime );
  1841. if ( !weight ) {
  1842. return;
  1843. }
  1844. time1 = AnimTime( fromtime );
  1845. time2 = AnimTime( totime );
  1846. if ( time2 < time1 ) {
  1847. time2 += anim->Length();
  1848. }
  1849. num = anim->NumAnims();
  1850. pos1.Zero();
  1851. pos2.Zero();
  1852. for( i = 0; i < num; i++ ) {
  1853. anim->GetOrigin( animpos, i, time1, cycle );
  1854. pos1 += animpos * animWeights[ i ];
  1855. anim->GetOrigin( animpos, i, time2, cycle );
  1856. pos2 += animpos * animWeights[ i ];
  1857. }
  1858. delta = pos2 - pos1;
  1859. if ( !blendWeight ) {
  1860. blendDelta = delta;
  1861. blendWeight = weight;
  1862. } else {
  1863. lerp = weight / ( blendWeight + weight );
  1864. blendDelta += lerp * ( delta - blendDelta );
  1865. blendWeight += weight;
  1866. }
  1867. }
  1868. /*
  1869. =====================
  1870. idAnimBlend::BlendDeltaRotation
  1871. =====================
  1872. */
  1873. void idAnimBlend::BlendDeltaRotation( int fromtime, int totime, idQuat &blendDelta, float &blendWeight ) const {
  1874. idQuat q1;
  1875. idQuat q2;
  1876. idQuat q3;
  1877. int time1;
  1878. int time2;
  1879. float lerp;
  1880. float mixWeight;
  1881. int num;
  1882. int i;
  1883. if ( frame || !allowMove || ( ( endtime > 0 ) && ( fromtime > endtime ) ) ) {
  1884. return;
  1885. }
  1886. const idAnim *anim = Anim();
  1887. if ( !anim || !anim->GetAnimFlags().anim_turn ) {
  1888. return;
  1889. }
  1890. float weight = GetWeight( totime );
  1891. if ( !weight ) {
  1892. return;
  1893. }
  1894. time1 = AnimTime( fromtime );
  1895. time2 = AnimTime( totime );
  1896. if ( time2 < time1 ) {
  1897. time2 += anim->Length();
  1898. }
  1899. q1.Set( 0.0f, 0.0f, 0.0f, 1.0f );
  1900. q2.Set( 0.0f, 0.0f, 0.0f, 1.0f );
  1901. mixWeight = 0.0f;
  1902. num = anim->NumAnims();
  1903. for( i = 0; i < num; i++ ) {
  1904. if ( animWeights[ i ] > 0.0f ) {
  1905. mixWeight += animWeights[ i ];
  1906. if ( animWeights[ i ] == mixWeight ) {
  1907. anim->GetOriginRotation( q1, i, time1, cycle );
  1908. anim->GetOriginRotation( q2, i, time2, cycle );
  1909. } else {
  1910. lerp = animWeights[ i ] / mixWeight;
  1911. anim->GetOriginRotation( q3, i, time1, cycle );
  1912. q1.Slerp( q1, q3, lerp );
  1913. anim->GetOriginRotation( q3, i, time2, cycle );
  1914. q2.Slerp( q1, q3, lerp );
  1915. }
  1916. }
  1917. }
  1918. q3 = q1.Inverse() * q2;
  1919. if ( !blendWeight ) {
  1920. blendDelta = q3;
  1921. blendWeight = weight;
  1922. } else {
  1923. lerp = weight / ( blendWeight + weight );
  1924. blendDelta.Slerp( blendDelta, q3, lerp );
  1925. blendWeight += weight;
  1926. }
  1927. }
  1928. /*
  1929. =====================
  1930. idAnimBlend::AddBounds
  1931. =====================
  1932. */
  1933. bool idAnimBlend::AddBounds( int currentTime, idBounds &bounds, bool removeOriginOffset ) const {
  1934. int i;
  1935. int num;
  1936. idBounds b;
  1937. int time;
  1938. idVec3 pos;
  1939. bool addorigin;
  1940. if ( ( endtime > 0 ) && ( currentTime > endtime ) ) {
  1941. return false;
  1942. }
  1943. const idAnim *anim = Anim();
  1944. if ( !anim ) {
  1945. return false;
  1946. }
  1947. float weight = GetWeight( currentTime );
  1948. if ( !weight ) {
  1949. return false;
  1950. }
  1951. time = AnimTime( currentTime );
  1952. num = anim->NumAnims();
  1953. addorigin = !allowMove || !removeOriginOffset;
  1954. for( i = 0; i < num; i++ ) {
  1955. if ( anim->GetBounds( b, i, time, cycle ) ) {
  1956. if ( addorigin ) {
  1957. anim->GetOrigin( pos, i, time, cycle );
  1958. b.TranslateSelf( pos );
  1959. }
  1960. bounds.AddBounds( b );
  1961. }
  1962. }
  1963. return true;
  1964. }
  1965. /***********************************************************************
  1966. idDeclModelDef
  1967. ***********************************************************************/
  1968. /*
  1969. =====================
  1970. idDeclModelDef::idDeclModelDef
  1971. =====================
  1972. */
  1973. idDeclModelDef::idDeclModelDef() {
  1974. modelHandle = NULL;
  1975. skin = NULL;
  1976. offset.Zero();
  1977. for ( int i = 0; i < ANIM_NumAnimChannels; i++ ) {
  1978. channelJoints[i].Clear();
  1979. }
  1980. }
  1981. /*
  1982. =====================
  1983. idDeclModelDef::~idDeclModelDef
  1984. =====================
  1985. */
  1986. idDeclModelDef::~idDeclModelDef() {
  1987. FreeData();
  1988. }
  1989. /*
  1990. =================
  1991. idDeclModelDef::Size
  1992. =================
  1993. */
  1994. size_t idDeclModelDef::Size( void ) const {
  1995. return sizeof( idDeclModelDef );
  1996. }
  1997. /*
  1998. =====================
  1999. idDeclModelDef::CopyDecl
  2000. =====================
  2001. */
  2002. void idDeclModelDef::CopyDecl( const idDeclModelDef *decl ) {
  2003. int i;
  2004. FreeData();
  2005. offset = decl->offset;
  2006. modelHandle = decl->modelHandle;
  2007. skin = decl->skin;
  2008. anims.SetNum( decl->anims.Num() );
  2009. for( i = 0; i < anims.Num(); i++ ) {
  2010. anims[ i ] = new idAnim( this, decl->anims[ i ] );
  2011. }
  2012. joints.SetNum( decl->joints.Num() );
  2013. memcpy( joints.Ptr(), decl->joints.Ptr(), decl->joints.Num() * sizeof( joints[0] ) );
  2014. jointParents.SetNum( decl->jointParents.Num() );
  2015. memcpy( jointParents.Ptr(), decl->jointParents.Ptr(), decl->jointParents.Num() * sizeof( jointParents[0] ) );
  2016. for ( i = 0; i < ANIM_NumAnimChannels; i++ ) {
  2017. channelJoints[i] = decl->channelJoints[i];
  2018. }
  2019. }
  2020. /*
  2021. =====================
  2022. idDeclModelDef::FreeData
  2023. =====================
  2024. */
  2025. void idDeclModelDef::FreeData( void ) {
  2026. anims.DeleteContents( true );
  2027. joints.Clear();
  2028. jointParents.Clear();
  2029. modelHandle = NULL;
  2030. skin = NULL;
  2031. offset.Zero();
  2032. for ( int i = 0; i < ANIM_NumAnimChannels; i++ ) {
  2033. channelJoints[i].Clear();
  2034. }
  2035. }
  2036. /*
  2037. ================
  2038. idDeclModelDef::DefaultDefinition
  2039. ================
  2040. */
  2041. const char *idDeclModelDef::DefaultDefinition( void ) const {
  2042. return "{ }";
  2043. }
  2044. /*
  2045. ====================
  2046. idDeclModelDef::FindJoint
  2047. ====================
  2048. */
  2049. const jointInfo_t *idDeclModelDef::FindJoint( const char *name ) const {
  2050. int i;
  2051. const idMD5Joint *joint;
  2052. if ( !modelHandle ) {
  2053. return NULL;
  2054. }
  2055. joint = modelHandle->GetJoints();
  2056. for( i = 0; i < joints.Num(); i++, joint++ ) {
  2057. if ( !joint->name.Icmp( name ) ) {
  2058. return &joints[ i ];
  2059. }
  2060. }
  2061. return NULL;
  2062. }
  2063. /*
  2064. =====================
  2065. idDeclModelDef::ModelHandle
  2066. =====================
  2067. */
  2068. idRenderModel *idDeclModelDef::ModelHandle( void ) const {
  2069. return ( idRenderModel * )modelHandle;
  2070. }
  2071. /*
  2072. =====================
  2073. idDeclModelDef::GetJointList
  2074. =====================
  2075. */
  2076. void idDeclModelDef::GetJointList( const char *jointnames, idList<jointHandle_t> &jointList ) const {
  2077. const char *pos;
  2078. idStr jointname;
  2079. const jointInfo_t *joint;
  2080. const jointInfo_t *child;
  2081. int i;
  2082. int num;
  2083. bool getChildren;
  2084. bool subtract;
  2085. if ( !modelHandle ) {
  2086. return;
  2087. }
  2088. jointList.Clear();
  2089. num = modelHandle->NumJoints();
  2090. // scan through list of joints and add each to the joint list
  2091. pos = jointnames;
  2092. while( *pos ) {
  2093. // skip over whitespace
  2094. while( ( *pos != 0 ) && isspace( *pos ) ) {
  2095. pos++;
  2096. }
  2097. if ( !*pos ) {
  2098. // no more names
  2099. break;
  2100. }
  2101. // copy joint name
  2102. jointname = "";
  2103. if ( *pos == '-' ) {
  2104. subtract = true;
  2105. pos++;
  2106. } else {
  2107. subtract = false;
  2108. }
  2109. if ( *pos == '*' ) {
  2110. getChildren = true;
  2111. pos++;
  2112. } else {
  2113. getChildren = false;
  2114. }
  2115. while( ( *pos != 0 ) && !isspace( *pos ) ) {
  2116. jointname += *pos;
  2117. pos++;
  2118. }
  2119. joint = FindJoint( jointname );
  2120. if ( !joint ) {
  2121. gameLocal.Warning( "Unknown joint '%s' in '%s' for model '%s'", jointname.c_str(), jointnames, GetName() );
  2122. continue;
  2123. }
  2124. if ( !subtract ) {
  2125. jointList.AddUnique( joint->num );
  2126. } else {
  2127. jointList.Remove( joint->num );
  2128. }
  2129. if ( getChildren ) {
  2130. // include all joint's children
  2131. child = joint + 1;
  2132. for( i = joint->num + 1; i < num; i++, child++ ) {
  2133. // all children of the joint should follow it in the list.
  2134. // once we reach a joint without a parent or with a parent
  2135. // who is earlier in the list than the specified joint, then
  2136. // we've gone through all it's children.
  2137. if ( child->parentNum < joint->num ) {
  2138. break;
  2139. }
  2140. if ( !subtract ) {
  2141. jointList.AddUnique( child->num );
  2142. } else {
  2143. jointList.Remove( child->num );
  2144. }
  2145. }
  2146. }
  2147. }
  2148. }
  2149. /*
  2150. =====================
  2151. idDeclModelDef::Touch
  2152. =====================
  2153. */
  2154. void idDeclModelDef::Touch( void ) const {
  2155. if ( modelHandle ) {
  2156. renderModelManager->FindModel( modelHandle->Name() );
  2157. }
  2158. }
  2159. /*
  2160. =====================
  2161. idDeclModelDef::GetDefaultSkin
  2162. =====================
  2163. */
  2164. const idDeclSkin *idDeclModelDef::GetDefaultSkin( void ) const {
  2165. return skin;
  2166. }
  2167. /*
  2168. =====================
  2169. idDeclModelDef::GetDefaultPose
  2170. =====================
  2171. */
  2172. const idJointQuat *idDeclModelDef::GetDefaultPose( void ) const {
  2173. return modelHandle->GetDefaultPose();
  2174. }
  2175. /*
  2176. =====================
  2177. idDeclModelDef::SetupJoints
  2178. =====================
  2179. */
  2180. void idDeclModelDef::SetupJoints( int *numJoints, idJointMat **jointList, idBounds &frameBounds, bool removeOriginOffset ) const {
  2181. int num;
  2182. const idJointQuat *pose;
  2183. idJointMat *list;
  2184. if ( !modelHandle || modelHandle->IsDefaultModel() ) {
  2185. Mem_Free16( (*jointList) );
  2186. (*jointList) = NULL;
  2187. frameBounds.Clear();
  2188. return;
  2189. }
  2190. // get the number of joints
  2191. num = modelHandle->NumJoints();
  2192. if ( !num ) {
  2193. gameLocal.Error( "model '%s' has no joints", modelHandle->Name() );
  2194. }
  2195. // set up initial pose for model (with no pose, model is just a jumbled mess)
  2196. list = (idJointMat *) Mem_Alloc16( num * sizeof( list[0] ) );
  2197. pose = GetDefaultPose();
  2198. // convert the joint quaternions to joint matrices
  2199. SIMDProcessor->ConvertJointQuatsToJointMats( list, pose, joints.Num() );
  2200. // check if we offset the model by the origin joint
  2201. if ( removeOriginOffset ) {
  2202. #ifdef VELOCITY_MOVE
  2203. list[ 0 ].SetTranslation( idVec3( offset.x, offset.y + pose[0].t.y, offset.z + pose[0].t.z ) );
  2204. #else
  2205. list[ 0 ].SetTranslation( offset );
  2206. #endif
  2207. } else {
  2208. list[ 0 ].SetTranslation( pose[0].t + offset );
  2209. }
  2210. // transform the joint hierarchy
  2211. SIMDProcessor->TransformJoints( list, jointParents.Ptr(), 1, joints.Num() - 1 );
  2212. *numJoints = num;
  2213. *jointList = list;
  2214. // get the bounds of the default pose
  2215. frameBounds = modelHandle->Bounds( NULL );
  2216. }
  2217. /*
  2218. =====================
  2219. idDeclModelDef::ParseAnim
  2220. =====================
  2221. */
  2222. bool idDeclModelDef::ParseAnim( idLexer &src, int numDefaultAnims ) {
  2223. int i;
  2224. int len;
  2225. idAnim *anim;
  2226. const idMD5Anim *md5anims[ ANIM_MaxSyncedAnims ];
  2227. const idMD5Anim *md5anim;
  2228. idStr alias;
  2229. idToken realname;
  2230. idToken token;
  2231. int numAnims;
  2232. animFlags_t flags;
  2233. numAnims = 0;
  2234. memset( md5anims, 0, sizeof( md5anims ) );
  2235. if( !src.ReadToken( &realname ) ) {
  2236. src.Warning( "Unexpected end of file" );
  2237. MakeDefault();
  2238. return false;
  2239. }
  2240. alias = realname;
  2241. for( i = 0; i < anims.Num(); i++ ) {
  2242. if ( !strcmp( anims[ i ]->FullName(), realname ) ) {
  2243. break;
  2244. }
  2245. }
  2246. if ( ( i < anims.Num() ) && ( i >= numDefaultAnims ) ) {
  2247. src.Warning( "Duplicate anim '%s'", realname.c_str() );
  2248. MakeDefault();
  2249. return false;
  2250. }
  2251. if ( i < numDefaultAnims ) {
  2252. anim = anims[ i ];
  2253. } else {
  2254. // create the alias associated with this animation
  2255. anim = new idAnim();
  2256. anims.Append( anim );
  2257. }
  2258. // random anims end with a number. find the numeric suffix of the animation.
  2259. len = alias.Length();
  2260. for( i = len - 1; i > 0; i-- ) {
  2261. if ( !isdigit( alias[ i ] ) ) {
  2262. break;
  2263. }
  2264. }
  2265. // check for zero length name, or a purely numeric name
  2266. if ( i <= 0 ) {
  2267. src.Warning( "Invalid animation name '%s'", alias.c_str() );
  2268. MakeDefault();
  2269. return false;
  2270. }
  2271. // remove the numeric suffix
  2272. alias.CapLength( i + 1 );
  2273. // parse the anims from the string
  2274. do {
  2275. if( !src.ReadToken( &token ) ) {
  2276. src.Warning( "Unexpected end of file" );
  2277. MakeDefault();
  2278. return false;
  2279. }
  2280. // lookup the animation
  2281. md5anim = animationLib.GetAnim( token );
  2282. if ( !md5anim ) {
  2283. src.Warning( "Couldn't load anim '%s'", token.c_str() );
  2284. MakeDefault();
  2285. return false;
  2286. }
  2287. md5anim->CheckModelHierarchy( modelHandle );
  2288. if ( numAnims > 0 ) {
  2289. // make sure it's the same length as the other anims
  2290. if ( md5anim->Length() != md5anims[ 0 ]->Length() ) {
  2291. src.Warning( "Anim '%s' does not match length of anim '%s'", md5anim->Name(), md5anims[ 0 ]->Name() );
  2292. MakeDefault();
  2293. return false;
  2294. }
  2295. }
  2296. if ( numAnims >= ANIM_MaxSyncedAnims ) {
  2297. src.Warning( "Exceeded max synced anims (%d)", ANIM_MaxSyncedAnims );
  2298. MakeDefault();
  2299. return false;
  2300. }
  2301. // add it to our list
  2302. md5anims[ numAnims ] = md5anim;
  2303. numAnims++;
  2304. } while ( src.CheckTokenString( "," ) );
  2305. if ( !numAnims ) {
  2306. src.Warning( "No animation specified" );
  2307. MakeDefault();
  2308. return false;
  2309. }
  2310. anim->SetAnim( this, realname, alias, numAnims, md5anims );
  2311. memset( &flags, 0, sizeof( flags ) );
  2312. // parse any frame commands or animflags
  2313. if ( src.CheckTokenString( "{" ) ) {
  2314. while( 1 ) {
  2315. if( !src.ReadToken( &token ) ) {
  2316. src.Warning( "Unexpected end of file" );
  2317. MakeDefault();
  2318. return false;
  2319. }
  2320. if ( token == "}" ) {
  2321. break;
  2322. }else if ( token == "prevent_idle_override" ) {
  2323. flags.prevent_idle_override = true;
  2324. } else if ( token == "random_cycle_start" ) {
  2325. flags.random_cycle_start = true;
  2326. } else if ( token == "ai_no_turn" ) {
  2327. flags.ai_no_turn = true;
  2328. } else if ( token == "anim_turn" ) {
  2329. flags.anim_turn = true;
  2330. } else if ( token == "frame" ) {
  2331. // create a frame command
  2332. int framenum;
  2333. const char *err;
  2334. // make sure we don't have any line breaks while reading the frame command so the error line # will be correct
  2335. if ( !src.ReadTokenOnLine( &token ) ) {
  2336. src.Warning( "Missing frame # after 'frame'" );
  2337. MakeDefault();
  2338. return false;
  2339. }
  2340. if ( token.type == TT_PUNCTUATION && token == "-" ) {
  2341. src.Warning( "Invalid frame # after 'frame'" );
  2342. MakeDefault();
  2343. return false;
  2344. } else if ( token.type != TT_NUMBER || token.subtype == TT_FLOAT ) {
  2345. src.Error( "expected integer value, found '%s'", token.c_str() );
  2346. }
  2347. // get the frame number
  2348. framenum = token.GetIntValue();
  2349. // put the command on the specified frame of the animation
  2350. err = anim->AddFrameCommand( this, framenum, src, NULL );
  2351. if ( err ) {
  2352. src.Warning( "%s", err );
  2353. MakeDefault();
  2354. return false;
  2355. }
  2356. } else {
  2357. src.Warning( "Unknown command '%s'", token.c_str() );
  2358. MakeDefault();
  2359. return false;
  2360. }
  2361. }
  2362. }
  2363. // set the flags
  2364. anim->SetAnimFlags( flags );
  2365. return true;
  2366. }
  2367. /*
  2368. ================
  2369. idDeclModelDef::Parse
  2370. ================
  2371. */
  2372. bool idDeclModelDef::Parse( const char *text, const int textLength ) {
  2373. int i;
  2374. int num;
  2375. idStr filename;
  2376. idStr extension;
  2377. const idMD5Joint *md5joint;
  2378. const idMD5Joint *md5joints;
  2379. idLexer src;
  2380. idToken token;
  2381. idToken token2;
  2382. idStr jointnames;
  2383. int channel;
  2384. jointHandle_t jointnum;
  2385. idList<jointHandle_t> jointList;
  2386. int numDefaultAnims;
  2387. src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
  2388. src.SetFlags( DECL_LEXER_FLAGS );
  2389. src.SkipUntilString( "{" );
  2390. numDefaultAnims = 0;
  2391. while( 1 ) {
  2392. if ( !src.ReadToken( &token ) ) {
  2393. break;
  2394. }
  2395. if ( !token.Icmp( "}" ) ) {
  2396. break;
  2397. }
  2398. if ( token == "inherit" ) {
  2399. if( !src.ReadToken( &token2 ) ) {
  2400. src.Warning( "Unexpected end of file" );
  2401. MakeDefault();
  2402. return false;
  2403. }
  2404. const idDeclModelDef *copy = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, token2, false ) );
  2405. if ( !copy ) {
  2406. common->Warning( "Unknown model definition '%s'", token2.c_str() );
  2407. } else if ( copy->GetState() == DS_DEFAULTED ) {
  2408. common->Warning( "inherited model definition '%s' defaulted", token2.c_str() );
  2409. MakeDefault();
  2410. return false;
  2411. } else {
  2412. CopyDecl( copy );
  2413. numDefaultAnims = anims.Num();
  2414. }
  2415. } else if ( token == "skin" ) {
  2416. if( !src.ReadToken( &token2 ) ) {
  2417. src.Warning( "Unexpected end of file" );
  2418. MakeDefault();
  2419. return false;
  2420. }
  2421. skin = declManager->FindSkin( token2 );
  2422. if ( !skin ) {
  2423. src.Warning( "Skin '%s' not found", token2.c_str() );
  2424. MakeDefault();
  2425. return false;
  2426. }
  2427. } else if ( token == "mesh" ) {
  2428. if( !src.ReadToken( &token2 ) ) {
  2429. src.Warning( "Unexpected end of file" );
  2430. MakeDefault();
  2431. return false;
  2432. }
  2433. filename = token2;
  2434. filename.ExtractFileExtension( extension );
  2435. if ( extension != MD5_MESH_EXT ) {
  2436. src.Warning( "Invalid model for MD5 mesh" );
  2437. MakeDefault();
  2438. return false;
  2439. }
  2440. modelHandle = renderModelManager->FindModel( filename );
  2441. if ( !modelHandle ) {
  2442. src.Warning( "Model '%s' not found", filename.c_str() );
  2443. MakeDefault();
  2444. return false;
  2445. }
  2446. if ( modelHandle->IsDefaultModel() ) {
  2447. src.Warning( "Model '%s' defaulted", filename.c_str() );
  2448. MakeDefault();
  2449. return false;
  2450. }
  2451. // get the number of joints
  2452. num = modelHandle->NumJoints();
  2453. if ( !num ) {
  2454. src.Warning( "Model '%s' has no joints", filename.c_str() );
  2455. }
  2456. // set up the joint hierarchy
  2457. joints.SetGranularity( 1 );
  2458. joints.SetNum( num );
  2459. jointParents.SetNum( num );
  2460. channelJoints[0].SetNum( num );
  2461. md5joints = modelHandle->GetJoints();
  2462. md5joint = md5joints;
  2463. for( i = 0; i < num; i++, md5joint++ ) {
  2464. joints[i].channel = ANIMCHANNEL_ALL;
  2465. joints[i].num = static_cast<jointHandle_t>( i );
  2466. if ( md5joint->parent ) {
  2467. joints[i].parentNum = static_cast<jointHandle_t>( md5joint->parent - md5joints );
  2468. } else {
  2469. joints[i].parentNum = INVALID_JOINT;
  2470. }
  2471. jointParents[i] = joints[i].parentNum;
  2472. channelJoints[0][i] = i;
  2473. }
  2474. } else if ( token == "remove" ) {
  2475. // removes any anims whos name matches
  2476. if( !src.ReadToken( &token2 ) ) {
  2477. src.Warning( "Unexpected end of file" );
  2478. MakeDefault();
  2479. return false;
  2480. }
  2481. num = 0;
  2482. for( i = 0; i < anims.Num(); i++ ) {
  2483. if ( ( token2 == anims[ i ]->Name() ) || ( token2 == anims[ i ]->FullName() ) ) {
  2484. delete anims[ i ];
  2485. anims.RemoveIndex( i );
  2486. if ( i >= numDefaultAnims ) {
  2487. src.Warning( "Anim '%s' was not inherited. Anim should be removed from the model def.", token2.c_str() );
  2488. MakeDefault();
  2489. return false;
  2490. }
  2491. i--;
  2492. numDefaultAnims--;
  2493. num++;
  2494. continue;
  2495. }
  2496. }
  2497. if ( !num ) {
  2498. src.Warning( "Couldn't find anim '%s' to remove", token2.c_str() );
  2499. MakeDefault();
  2500. return false;
  2501. }
  2502. } else if ( token == "anim" ) {
  2503. if ( !modelHandle ) {
  2504. src.Warning( "Must specify mesh before defining anims" );
  2505. MakeDefault();
  2506. return false;
  2507. }
  2508. if ( !ParseAnim( src, numDefaultAnims ) ) {
  2509. MakeDefault();
  2510. return false;
  2511. }
  2512. } else if ( token == "offset" ) {
  2513. if ( !src.Parse1DMatrix( 3, offset.ToFloatPtr() ) ) {
  2514. src.Warning( "Expected vector following 'offset'" );
  2515. MakeDefault();
  2516. return false;
  2517. }
  2518. } else if ( token == "channel" ) {
  2519. if ( !modelHandle ) {
  2520. src.Warning( "Must specify mesh before defining channels" );
  2521. MakeDefault();
  2522. return false;
  2523. }
  2524. // set the channel for a group of joints
  2525. if( !src.ReadToken( &token2 ) ) {
  2526. src.Warning( "Unexpected end of file" );
  2527. MakeDefault();
  2528. return false;
  2529. }
  2530. if ( !src.CheckTokenString( "(" ) ) {
  2531. src.Warning( "Expected { after '%s'\n", token2.c_str() );
  2532. MakeDefault();
  2533. return false;
  2534. }
  2535. for( i = ANIMCHANNEL_ALL + 1; i < ANIM_NumAnimChannels; i++ ) {
  2536. if ( !idStr::Icmp( channelNames[ i ], token2 ) ) {
  2537. break;
  2538. }
  2539. }
  2540. if ( i >= ANIM_NumAnimChannels ) {
  2541. src.Warning( "Unknown channel '%s'", token2.c_str() );
  2542. MakeDefault();
  2543. return false;
  2544. }
  2545. channel = i;
  2546. jointnames = "";
  2547. while( !src.CheckTokenString( ")" ) ) {
  2548. if( !src.ReadToken( &token2 ) ) {
  2549. src.Warning( "Unexpected end of file" );
  2550. MakeDefault();
  2551. return false;
  2552. }
  2553. jointnames += token2;
  2554. if ( ( token2 != "*" ) && ( token2 != "-" ) ) {
  2555. jointnames += " ";
  2556. }
  2557. }
  2558. GetJointList( jointnames, jointList );
  2559. channelJoints[ channel ].SetNum( jointList.Num() );
  2560. for( num = i = 0; i < jointList.Num(); i++ ) {
  2561. jointnum = jointList[ i ];
  2562. if ( joints[ jointnum ].channel != ANIMCHANNEL_ALL ) {
  2563. src.Warning( "Joint '%s' assigned to multiple channels", modelHandle->GetJointName( jointnum ) );
  2564. continue;
  2565. }
  2566. joints[ jointnum ].channel = channel;
  2567. channelJoints[ channel ][ num++ ] = jointnum;
  2568. }
  2569. channelJoints[ channel ].SetNum( num );
  2570. } else {
  2571. src.Warning( "unknown token '%s'", token.c_str() );
  2572. MakeDefault();
  2573. return false;
  2574. }
  2575. }
  2576. // shrink the anim list down to save space
  2577. anims.SetGranularity( 1 );
  2578. anims.SetNum( anims.Num() );
  2579. return true;
  2580. }
  2581. /*
  2582. =====================
  2583. idDeclModelDef::HasAnim
  2584. =====================
  2585. */
  2586. bool idDeclModelDef::HasAnim( const char *name ) const {
  2587. int i;
  2588. // find any animations with same name
  2589. for( i = 0; i < anims.Num(); i++ ) {
  2590. if ( !strcmp( anims[ i ]->Name(), name ) ) {
  2591. return true;
  2592. }
  2593. }
  2594. return false;
  2595. }
  2596. /*
  2597. =====================
  2598. idDeclModelDef::NumAnims
  2599. =====================
  2600. */
  2601. int idDeclModelDef::NumAnims( void ) const {
  2602. return anims.Num() + 1;
  2603. }
  2604. /*
  2605. =====================
  2606. idDeclModelDef::GetSpecificAnim
  2607. Gets the exact anim for the name, without randomization.
  2608. =====================
  2609. */
  2610. int idDeclModelDef::GetSpecificAnim( const char *name ) const {
  2611. int i;
  2612. // find a specific animation
  2613. for( i = 0; i < anims.Num(); i++ ) {
  2614. if ( !strcmp( anims[ i ]->FullName(), name ) ) {
  2615. return i + 1;
  2616. }
  2617. }
  2618. // didn't find it
  2619. return 0;
  2620. }
  2621. /*
  2622. =====================
  2623. idDeclModelDef::GetAnim
  2624. =====================
  2625. */
  2626. const idAnim *idDeclModelDef::GetAnim( int index ) const {
  2627. if ( ( index < 1 ) || ( index > anims.Num() ) ) {
  2628. return NULL;
  2629. }
  2630. return anims[ index - 1 ];
  2631. }
  2632. /*
  2633. =====================
  2634. idDeclModelDef::GetAnim
  2635. =====================
  2636. */
  2637. int idDeclModelDef::GetAnim( const char *name ) const {
  2638. int i;
  2639. int which;
  2640. const int MAX_ANIMS = 64;
  2641. int animList[ MAX_ANIMS ];
  2642. int numAnims;
  2643. int len;
  2644. len = strlen( name );
  2645. if ( len && idStr::CharIsNumeric( name[ len - 1 ] ) ) {
  2646. // find a specific animation
  2647. return GetSpecificAnim( name );
  2648. }
  2649. // find all animations with same name
  2650. numAnims = 0;
  2651. for( i = 0; i < anims.Num(); i++ ) {
  2652. if ( !strcmp( anims[ i ]->Name(), name ) ) {
  2653. animList[ numAnims++ ] = i;
  2654. if ( numAnims >= MAX_ANIMS ) {
  2655. break;
  2656. }
  2657. }
  2658. }
  2659. if ( !numAnims ) {
  2660. return 0;
  2661. }
  2662. // get a random anim
  2663. //FIXME: don't access gameLocal here?
  2664. which = gameLocal.random.RandomInt( numAnims );
  2665. return animList[ which ] + 1;
  2666. }
  2667. /*
  2668. =====================
  2669. idDeclModelDef::GetSkin
  2670. =====================
  2671. */
  2672. const idDeclSkin *idDeclModelDef::GetSkin( void ) const {
  2673. return skin;
  2674. }
  2675. /*
  2676. =====================
  2677. idDeclModelDef::GetModelName
  2678. =====================
  2679. */
  2680. const char *idDeclModelDef::GetModelName( void ) const {
  2681. if ( modelHandle ) {
  2682. return modelHandle->Name();
  2683. } else {
  2684. return "";
  2685. }
  2686. }
  2687. /*
  2688. =====================
  2689. idDeclModelDef::Joints
  2690. =====================
  2691. */
  2692. const idList<jointInfo_t> &idDeclModelDef::Joints( void ) const {
  2693. return joints;
  2694. }
  2695. /*
  2696. =====================
  2697. idDeclModelDef::JointParents
  2698. =====================
  2699. */
  2700. const int * idDeclModelDef::JointParents( void ) const {
  2701. return jointParents.Ptr();
  2702. }
  2703. /*
  2704. =====================
  2705. idDeclModelDef::NumJoints
  2706. =====================
  2707. */
  2708. int idDeclModelDef::NumJoints( void ) const {
  2709. return joints.Num();
  2710. }
  2711. /*
  2712. =====================
  2713. idDeclModelDef::GetJoint
  2714. =====================
  2715. */
  2716. const jointInfo_t *idDeclModelDef::GetJoint( int jointHandle ) const {
  2717. if ( ( jointHandle < 0 ) || ( jointHandle > joints.Num() ) ) {
  2718. gameLocal.Error( "idDeclModelDef::GetJoint : joint handle out of range" );
  2719. }
  2720. return &joints[ jointHandle ];
  2721. }
  2722. /*
  2723. ====================
  2724. idDeclModelDef::GetJointName
  2725. ====================
  2726. */
  2727. const char *idDeclModelDef::GetJointName( int jointHandle ) const {
  2728. const idMD5Joint *joint;
  2729. if ( !modelHandle ) {
  2730. return NULL;
  2731. }
  2732. if ( ( jointHandle < 0 ) || ( jointHandle > joints.Num() ) ) {
  2733. gameLocal.Error( "idDeclModelDef::GetJointName : joint handle out of range" );
  2734. }
  2735. joint = modelHandle->GetJoints();
  2736. return joint[ jointHandle ].name.c_str();
  2737. }
  2738. /*
  2739. =====================
  2740. idDeclModelDef::NumJointsOnChannel
  2741. =====================
  2742. */
  2743. int idDeclModelDef::NumJointsOnChannel( int channel ) const {
  2744. if ( ( channel < 0 ) || ( channel >= ANIM_NumAnimChannels ) ) {
  2745. gameLocal.Error( "idDeclModelDef::NumJointsOnChannel : channel out of range" );
  2746. }
  2747. return channelJoints[ channel ].Num();
  2748. }
  2749. /*
  2750. =====================
  2751. idDeclModelDef::GetChannelJoints
  2752. =====================
  2753. */
  2754. const int * idDeclModelDef::GetChannelJoints( int channel ) const {
  2755. if ( ( channel < 0 ) || ( channel >= ANIM_NumAnimChannels ) ) {
  2756. gameLocal.Error( "idDeclModelDef::GetChannelJoints : channel out of range" );
  2757. }
  2758. return channelJoints[ channel ].Ptr();
  2759. }
  2760. /*
  2761. =====================
  2762. idDeclModelDef::GetVisualOffset
  2763. =====================
  2764. */
  2765. const idVec3 &idDeclModelDef::GetVisualOffset( void ) const {
  2766. return offset;
  2767. }
  2768. /***********************************************************************
  2769. idAnimator
  2770. ***********************************************************************/
  2771. /*
  2772. =====================
  2773. idAnimator::idAnimator
  2774. =====================
  2775. */
  2776. idAnimator::idAnimator() {
  2777. int i, j;
  2778. modelDef = NULL;
  2779. entity = NULL;
  2780. numJoints = 0;
  2781. joints = NULL;
  2782. lastTransformTime = -1;
  2783. stoppedAnimatingUpdate = false;
  2784. removeOriginOffset = false;
  2785. forceUpdate = false;
  2786. frameBounds.Clear();
  2787. AFPoseJoints.SetGranularity( 1 );
  2788. AFPoseJointMods.SetGranularity( 1 );
  2789. AFPoseJointFrame.SetGranularity( 1 );
  2790. ClearAFPose();
  2791. for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
  2792. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
  2793. channels[ i ][ j ].Reset( NULL );
  2794. }
  2795. }
  2796. }
  2797. /*
  2798. =====================
  2799. idAnimator::~idAnimator
  2800. =====================
  2801. */
  2802. idAnimator::~idAnimator() {
  2803. FreeData();
  2804. }
  2805. /*
  2806. =====================
  2807. idAnimator::Allocated
  2808. =====================
  2809. */
  2810. size_t idAnimator::Allocated( void ) const {
  2811. size_t size;
  2812. size = jointMods.Allocated() + numJoints * sizeof( joints[0] ) + jointMods.Num() * sizeof( jointMods[ 0 ] ) + AFPoseJointMods.Allocated() + AFPoseJointFrame.Allocated() + AFPoseJoints.Allocated();
  2813. return size;
  2814. }
  2815. /*
  2816. =====================
  2817. idAnimator::Save
  2818. archives object for save game file
  2819. =====================
  2820. */
  2821. void idAnimator::Save( idSaveGame *savefile ) const {
  2822. int i;
  2823. int j;
  2824. savefile->WriteModelDef( modelDef );
  2825. savefile->WriteObject( entity );
  2826. savefile->WriteInt( jointMods.Num() );
  2827. for( i = 0; i < jointMods.Num(); i++ ) {
  2828. savefile->WriteInt( jointMods[ i ]->jointnum );
  2829. savefile->WriteMat3( jointMods[ i ]->mat );
  2830. savefile->WriteVec3( jointMods[ i ]->pos );
  2831. savefile->WriteInt( (int&)jointMods[ i ]->transform_pos );
  2832. savefile->WriteInt( (int&)jointMods[ i ]->transform_axis );
  2833. }
  2834. savefile->WriteInt( numJoints );
  2835. for ( i = 0; i < numJoints; i++ ) {
  2836. float *data = joints[i].ToFloatPtr();
  2837. for ( j = 0; j < 12; j++ ) {
  2838. savefile->WriteFloat( data[j] );
  2839. }
  2840. }
  2841. savefile->WriteInt( lastTransformTime );
  2842. savefile->WriteBool( stoppedAnimatingUpdate );
  2843. savefile->WriteBool( forceUpdate );
  2844. savefile->WriteBounds( frameBounds );
  2845. savefile->WriteFloat( AFPoseBlendWeight );
  2846. savefile->WriteInt( AFPoseJoints.Num() );
  2847. for ( i = 0; i < AFPoseJoints.Num(); i++ ) {
  2848. savefile->WriteInt( AFPoseJoints[i] );
  2849. }
  2850. savefile->WriteInt( AFPoseJointMods.Num() );
  2851. for ( i = 0; i < AFPoseJointMods.Num(); i++ ) {
  2852. savefile->WriteInt( (int&)AFPoseJointMods[i].mod );
  2853. savefile->WriteMat3( AFPoseJointMods[i].axis );
  2854. savefile->WriteVec3( AFPoseJointMods[i].origin );
  2855. }
  2856. savefile->WriteInt( AFPoseJointFrame.Num() );
  2857. for ( i = 0; i < AFPoseJointFrame.Num(); i++ ) {
  2858. savefile->WriteFloat( AFPoseJointFrame[i].q.x );
  2859. savefile->WriteFloat( AFPoseJointFrame[i].q.y );
  2860. savefile->WriteFloat( AFPoseJointFrame[i].q.z );
  2861. savefile->WriteFloat( AFPoseJointFrame[i].q.w );
  2862. savefile->WriteVec3( AFPoseJointFrame[i].t );
  2863. }
  2864. savefile->WriteBounds( AFPoseBounds );
  2865. savefile->WriteInt( AFPoseTime );
  2866. savefile->WriteBool( removeOriginOffset );
  2867. for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
  2868. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
  2869. channels[ i ][ j ].Save( savefile );
  2870. }
  2871. }
  2872. }
  2873. /*
  2874. =====================
  2875. idAnimator::Restore
  2876. unarchives object from save game file
  2877. =====================
  2878. */
  2879. void idAnimator::Restore( idRestoreGame *savefile ) {
  2880. int i;
  2881. int j;
  2882. int num;
  2883. savefile->ReadModelDef( modelDef );
  2884. savefile->ReadObject( reinterpret_cast<idClass *&>( entity ) );
  2885. savefile->ReadInt( num );
  2886. jointMods.SetNum( num );
  2887. for( i = 0; i < num; i++ ) {
  2888. jointMods[ i ] = new jointMod_t;
  2889. savefile->ReadInt( (int&)jointMods[ i ]->jointnum );
  2890. savefile->ReadMat3( jointMods[ i ]->mat );
  2891. savefile->ReadVec3( jointMods[ i ]->pos );
  2892. savefile->ReadInt( (int&)jointMods[ i ]->transform_pos );
  2893. savefile->ReadInt( (int&)jointMods[ i ]->transform_axis );
  2894. }
  2895. savefile->ReadInt( numJoints );
  2896. joints = (idJointMat *) Mem_Alloc16( numJoints * sizeof( joints[0] ) );
  2897. for ( i = 0; i < numJoints; i++ ) {
  2898. float *data = joints[i].ToFloatPtr();
  2899. for ( j = 0; j < 12; j++ ) {
  2900. savefile->ReadFloat( data[j] );
  2901. }
  2902. }
  2903. savefile->ReadInt( lastTransformTime );
  2904. savefile->ReadBool( stoppedAnimatingUpdate );
  2905. savefile->ReadBool( forceUpdate );
  2906. savefile->ReadBounds( frameBounds );
  2907. savefile->ReadFloat( AFPoseBlendWeight );
  2908. savefile->ReadInt( num );
  2909. AFPoseJoints.SetGranularity( 1 );
  2910. AFPoseJoints.SetNum( num );
  2911. for ( i = 0; i < AFPoseJoints.Num(); i++ ) {
  2912. savefile->ReadInt( AFPoseJoints[i] );
  2913. }
  2914. savefile->ReadInt( num );
  2915. AFPoseJointMods.SetGranularity( 1 );
  2916. AFPoseJointMods.SetNum( num );
  2917. for ( i = 0; i < AFPoseJointMods.Num(); i++ ) {
  2918. savefile->ReadInt( (int&)AFPoseJointMods[i].mod );
  2919. savefile->ReadMat3( AFPoseJointMods[i].axis );
  2920. savefile->ReadVec3( AFPoseJointMods[i].origin );
  2921. }
  2922. savefile->ReadInt( num );
  2923. AFPoseJointFrame.SetGranularity( 1 );
  2924. AFPoseJointFrame.SetNum( num );
  2925. for ( i = 0; i < AFPoseJointFrame.Num(); i++ ) {
  2926. savefile->ReadFloat( AFPoseJointFrame[i].q.x );
  2927. savefile->ReadFloat( AFPoseJointFrame[i].q.y );
  2928. savefile->ReadFloat( AFPoseJointFrame[i].q.z );
  2929. savefile->ReadFloat( AFPoseJointFrame[i].q.w );
  2930. savefile->ReadVec3( AFPoseJointFrame[i].t );
  2931. }
  2932. savefile->ReadBounds( AFPoseBounds );
  2933. savefile->ReadInt( AFPoseTime );
  2934. savefile->ReadBool( removeOriginOffset );
  2935. for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
  2936. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
  2937. channels[ i ][ j ].Restore( savefile, modelDef );
  2938. }
  2939. }
  2940. }
  2941. /*
  2942. =====================
  2943. idAnimator::FreeData
  2944. =====================
  2945. */
  2946. void idAnimator::FreeData( void ) {
  2947. int i, j;
  2948. if ( entity ) {
  2949. entity->BecomeInactive( TH_ANIMATE );
  2950. }
  2951. for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
  2952. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
  2953. channels[ i ][ j ].Reset( NULL );
  2954. }
  2955. }
  2956. jointMods.DeleteContents( true );
  2957. Mem_Free16( joints );
  2958. joints = NULL;
  2959. numJoints = 0;
  2960. modelDef = NULL;
  2961. ForceUpdate();
  2962. }
  2963. /*
  2964. =====================
  2965. idAnimator::PushAnims
  2966. =====================
  2967. */
  2968. void idAnimator::PushAnims( int channelNum, int currentTime, int blendTime ) {
  2969. int i;
  2970. idAnimBlend *channel;
  2971. channel = channels[ channelNum ];
  2972. if ( !channel[ 0 ].GetWeight( currentTime ) || ( channel[ 0 ].starttime == currentTime ) ) {
  2973. return;
  2974. }
  2975. for( i = ANIM_MaxAnimsPerChannel - 1; i > 0; i-- ) {
  2976. channel[ i ] = channel[ i - 1 ];
  2977. }
  2978. channel[ 0 ].Reset( modelDef );
  2979. channel[ 1 ].Clear( currentTime, blendTime );
  2980. ForceUpdate();
  2981. }
  2982. /*
  2983. =====================
  2984. idAnimator::SetModel
  2985. =====================
  2986. */
  2987. idRenderModel *idAnimator::SetModel( const char *modelname ) {
  2988. int i, j;
  2989. FreeData();
  2990. // check if we're just clearing the model
  2991. if ( !modelname || !*modelname ) {
  2992. return NULL;
  2993. }
  2994. modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelname, false ) );
  2995. if ( !modelDef ) {
  2996. return NULL;
  2997. }
  2998. idRenderModel *renderModel = modelDef->ModelHandle();
  2999. if ( !renderModel ) {
  3000. modelDef = NULL;
  3001. return NULL;
  3002. }
  3003. // make sure model hasn't been purged
  3004. modelDef->Touch();
  3005. modelDef->SetupJoints( &numJoints, &joints, frameBounds, removeOriginOffset );
  3006. modelDef->ModelHandle()->Reset();
  3007. // set the modelDef on all channels
  3008. for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
  3009. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++ ) {
  3010. channels[ i ][ j ].Reset( modelDef );
  3011. }
  3012. }
  3013. return modelDef->ModelHandle();
  3014. }
  3015. /*
  3016. =====================
  3017. idAnimator::Size
  3018. =====================
  3019. */
  3020. size_t idAnimator::Size( void ) const {
  3021. return sizeof( *this ) + Allocated();
  3022. }
  3023. /*
  3024. =====================
  3025. idAnimator::SetEntity
  3026. =====================
  3027. */
  3028. void idAnimator::SetEntity( idEntity *ent ) {
  3029. entity = ent;
  3030. }
  3031. /*
  3032. =====================
  3033. idAnimator::GetEntity
  3034. =====================
  3035. */
  3036. idEntity *idAnimator::GetEntity( void ) const {
  3037. return entity;
  3038. }
  3039. /*
  3040. =====================
  3041. idAnimator::RemoveOriginOffset
  3042. =====================
  3043. */
  3044. void idAnimator::RemoveOriginOffset( bool remove ) {
  3045. removeOriginOffset = remove;
  3046. }
  3047. /*
  3048. =====================
  3049. idAnimator::RemoveOrigin
  3050. =====================
  3051. */
  3052. bool idAnimator::RemoveOrigin( void ) const {
  3053. return removeOriginOffset;
  3054. }
  3055. /*
  3056. =====================
  3057. idAnimator::GetJointList
  3058. =====================
  3059. */
  3060. void idAnimator::GetJointList( const char *jointnames, idList<jointHandle_t> &jointList ) const {
  3061. if ( modelDef ) {
  3062. modelDef->GetJointList( jointnames, jointList );
  3063. }
  3064. }
  3065. /*
  3066. =====================
  3067. idAnimator::NumAnims
  3068. =====================
  3069. */
  3070. int idAnimator::NumAnims( void ) const {
  3071. if ( !modelDef ) {
  3072. return 0;
  3073. }
  3074. return modelDef->NumAnims();
  3075. }
  3076. /*
  3077. =====================
  3078. idAnimator::GetAnim
  3079. =====================
  3080. */
  3081. const idAnim *idAnimator::GetAnim( int index ) const {
  3082. if ( !modelDef ) {
  3083. return NULL;
  3084. }
  3085. return modelDef->GetAnim( index );
  3086. }
  3087. /*
  3088. =====================
  3089. idAnimator::GetAnim
  3090. =====================
  3091. */
  3092. int idAnimator::GetAnim( const char *name ) const {
  3093. if ( !modelDef ) {
  3094. return 0;
  3095. }
  3096. return modelDef->GetAnim( name );
  3097. }
  3098. /*
  3099. =====================
  3100. idAnimator::HasAnim
  3101. =====================
  3102. */
  3103. bool idAnimator::HasAnim( const char *name ) const {
  3104. if ( !modelDef ) {
  3105. return false;
  3106. }
  3107. return modelDef->HasAnim( name );
  3108. }
  3109. /*
  3110. =====================
  3111. idAnimator::NumJoints
  3112. =====================
  3113. */
  3114. int idAnimator::NumJoints( void ) const {
  3115. return numJoints;
  3116. }
  3117. /*
  3118. =====================
  3119. idAnimator::ModelHandle
  3120. =====================
  3121. */
  3122. idRenderModel *idAnimator::ModelHandle( void ) const {
  3123. if ( !modelDef ) {
  3124. return NULL;
  3125. }
  3126. return modelDef->ModelHandle();
  3127. }
  3128. /*
  3129. =====================
  3130. idAnimator::ModelDef
  3131. =====================
  3132. */
  3133. const idDeclModelDef *idAnimator::ModelDef( void ) const {
  3134. return modelDef;
  3135. }
  3136. /*
  3137. =====================
  3138. idAnimator::CurrentAnim
  3139. =====================
  3140. */
  3141. idAnimBlend *idAnimator::CurrentAnim( int channelNum ) {
  3142. if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
  3143. gameLocal.Error( "idAnimator::CurrentAnim : channel out of range" );
  3144. }
  3145. return &channels[ channelNum ][ 0 ];
  3146. }
  3147. /*
  3148. =====================
  3149. idAnimator::Clear
  3150. =====================
  3151. */
  3152. void idAnimator::Clear( int channelNum, int currentTime, int cleartime ) {
  3153. int i;
  3154. idAnimBlend *blend;
  3155. if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
  3156. gameLocal.Error( "idAnimator::Clear : channel out of range" );
  3157. }
  3158. blend = channels[ channelNum ];
  3159. for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
  3160. blend->Clear( currentTime, cleartime );
  3161. }
  3162. ForceUpdate();
  3163. }
  3164. /*
  3165. =====================
  3166. idAnimator::SetFrame
  3167. =====================
  3168. */
  3169. void idAnimator::SetFrame( int channelNum, int animNum, int frame, int currentTime, int blendTime ) {
  3170. if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
  3171. gameLocal.Error( "idAnimator::SetFrame : channel out of range" );
  3172. }
  3173. if ( !modelDef || !modelDef->GetAnim( animNum ) ) {
  3174. return;
  3175. }
  3176. PushAnims( channelNum, currentTime, blendTime );
  3177. channels[ channelNum ][ 0 ].SetFrame( modelDef, animNum, frame, currentTime, blendTime );
  3178. if ( entity ) {
  3179. entity->BecomeActive( TH_ANIMATE );
  3180. }
  3181. }
  3182. /*
  3183. =====================
  3184. idAnimator::CycleAnim
  3185. =====================
  3186. */
  3187. void idAnimator::CycleAnim( int channelNum, int animNum, int currentTime, int blendTime ) {
  3188. if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
  3189. gameLocal.Error( "idAnimator::CycleAnim : channel out of range" );
  3190. }
  3191. if ( !modelDef || !modelDef->GetAnim( animNum ) ) {
  3192. return;
  3193. }
  3194. PushAnims( channelNum, currentTime, blendTime );
  3195. channels[ channelNum ][ 0 ].CycleAnim( modelDef, animNum, currentTime, blendTime );
  3196. if ( entity ) {
  3197. entity->BecomeActive( TH_ANIMATE );
  3198. }
  3199. }
  3200. /*
  3201. =====================
  3202. idAnimator::PlayAnim
  3203. =====================
  3204. */
  3205. void idAnimator::PlayAnim( int channelNum, int animNum, int currentTime, int blendTime ) {
  3206. if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) ) {
  3207. gameLocal.Error( "idAnimator::PlayAnim : channel out of range" );
  3208. }
  3209. if ( !modelDef || !modelDef->GetAnim( animNum ) ) {
  3210. return;
  3211. }
  3212. PushAnims( channelNum, currentTime, blendTime );
  3213. channels[ channelNum ][ 0 ].PlayAnim( modelDef, animNum, currentTime, blendTime );
  3214. if ( entity ) {
  3215. entity->BecomeActive( TH_ANIMATE );
  3216. }
  3217. }
  3218. /*
  3219. =====================
  3220. idAnimator::SyncAnimChannels
  3221. =====================
  3222. */
  3223. void idAnimator::SyncAnimChannels( int channelNum, int fromChannelNum, int currentTime, int blendTime ) {
  3224. if ( ( channelNum < 0 ) || ( channelNum >= ANIM_NumAnimChannels ) || ( fromChannelNum < 0 ) || ( fromChannelNum >= ANIM_NumAnimChannels ) ) {
  3225. gameLocal.Error( "idAnimator::SyncToChannel : channel out of range" );
  3226. }
  3227. idAnimBlend &fromBlend = channels[ fromChannelNum ][ 0 ];
  3228. idAnimBlend &toBlend = channels[ channelNum ][ 0 ];
  3229. float weight = fromBlend.blendEndValue;
  3230. if ( ( fromBlend.Anim() != toBlend.Anim() ) || ( fromBlend.GetStartTime() != toBlend.GetStartTime() ) || ( fromBlend.GetEndTime() != toBlend.GetEndTime() ) ) {
  3231. PushAnims( channelNum, currentTime, blendTime );
  3232. toBlend = fromBlend;
  3233. toBlend.blendStartValue = 0.0f;
  3234. toBlend.blendEndValue = 0.0f;
  3235. }
  3236. toBlend.SetWeight( weight, currentTime - 1, blendTime );
  3237. // disable framecommands on the current channel so that commands aren't called twice
  3238. toBlend.AllowFrameCommands( false );
  3239. if ( entity ) {
  3240. entity->BecomeActive( TH_ANIMATE );
  3241. }
  3242. }
  3243. /*
  3244. =====================
  3245. idAnimator::SetJointPos
  3246. =====================
  3247. */
  3248. void idAnimator::SetJointPos( jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos ) {
  3249. int i;
  3250. jointMod_t *jointMod;
  3251. if ( !modelDef || !modelDef->ModelHandle() || ( jointnum < 0 ) || ( jointnum >= numJoints ) ) {
  3252. return;
  3253. }
  3254. jointMod = NULL;
  3255. for( i = 0; i < jointMods.Num(); i++ ) {
  3256. if ( jointMods[ i ]->jointnum == jointnum ) {
  3257. jointMod = jointMods[ i ];
  3258. break;
  3259. } else if ( jointMods[ i ]->jointnum > jointnum ) {
  3260. break;
  3261. }
  3262. }
  3263. if ( !jointMod ) {
  3264. jointMod = new jointMod_t;
  3265. jointMod->jointnum = jointnum;
  3266. jointMod->mat.Identity();
  3267. jointMod->transform_axis = JOINTMOD_NONE;
  3268. jointMods.Insert( jointMod, i );
  3269. }
  3270. jointMod->pos = pos;
  3271. jointMod->transform_pos = transform_type;
  3272. if ( entity ) {
  3273. entity->BecomeActive( TH_ANIMATE );
  3274. }
  3275. ForceUpdate();
  3276. }
  3277. /*
  3278. =====================
  3279. idAnimator::SetJointAxis
  3280. =====================
  3281. */
  3282. void idAnimator::SetJointAxis( jointHandle_t jointnum, jointModTransform_t transform_type, const idMat3 &mat ) {
  3283. int i;
  3284. jointMod_t *jointMod;
  3285. if ( !modelDef || !modelDef->ModelHandle() || ( jointnum < 0 ) || ( jointnum >= numJoints ) ) {
  3286. return;
  3287. }
  3288. jointMod = NULL;
  3289. for( i = 0; i < jointMods.Num(); i++ ) {
  3290. if ( jointMods[ i ]->jointnum == jointnum ) {
  3291. jointMod = jointMods[ i ];
  3292. break;
  3293. } else if ( jointMods[ i ]->jointnum > jointnum ) {
  3294. break;
  3295. }
  3296. }
  3297. if ( !jointMod ) {
  3298. jointMod = new jointMod_t;
  3299. jointMod->jointnum = jointnum;
  3300. jointMod->pos.Zero();
  3301. jointMod->transform_pos = JOINTMOD_NONE;
  3302. jointMods.Insert( jointMod, i );
  3303. }
  3304. jointMod->mat = mat;
  3305. jointMod->transform_axis = transform_type;
  3306. if ( entity ) {
  3307. entity->BecomeActive( TH_ANIMATE );
  3308. }
  3309. ForceUpdate();
  3310. }
  3311. /*
  3312. =====================
  3313. idAnimator::ClearJoint
  3314. =====================
  3315. */
  3316. void idAnimator::ClearJoint( jointHandle_t jointnum ) {
  3317. int i;
  3318. if ( !modelDef || !modelDef->ModelHandle() || ( jointnum < 0 ) || ( jointnum >= numJoints ) ) {
  3319. return;
  3320. }
  3321. for( i = 0; i < jointMods.Num(); i++ ) {
  3322. if ( jointMods[ i ]->jointnum == jointnum ) {
  3323. delete jointMods[ i ];
  3324. jointMods.RemoveIndex( i );
  3325. ForceUpdate();
  3326. break;
  3327. } else if ( jointMods[ i ]->jointnum > jointnum ) {
  3328. break;
  3329. }
  3330. }
  3331. }
  3332. /*
  3333. =====================
  3334. idAnimator::ClearAllJoints
  3335. =====================
  3336. */
  3337. void idAnimator::ClearAllJoints( void ) {
  3338. if ( jointMods.Num() ) {
  3339. ForceUpdate();
  3340. }
  3341. jointMods.DeleteContents( true );
  3342. }
  3343. /*
  3344. =====================
  3345. idAnimator::ClearAllAnims
  3346. =====================
  3347. */
  3348. void idAnimator::ClearAllAnims( int currentTime, int cleartime ) {
  3349. int i;
  3350. for( i = 0; i < ANIM_NumAnimChannels; i++ ) {
  3351. Clear( i, currentTime, cleartime );
  3352. }
  3353. ClearAFPose();
  3354. ForceUpdate();
  3355. }
  3356. /*
  3357. ====================
  3358. idAnimator::GetDelta
  3359. ====================
  3360. */
  3361. void idAnimator::GetDelta( int fromtime, int totime, idVec3 &delta ) const {
  3362. int i;
  3363. const idAnimBlend *blend;
  3364. float blendWeight;
  3365. if ( !modelDef || !modelDef->ModelHandle() || ( fromtime == totime ) ) {
  3366. delta.Zero();
  3367. return;
  3368. }
  3369. delta.Zero();
  3370. blendWeight = 0.0f;
  3371. blend = channels[ ANIMCHANNEL_ALL ];
  3372. for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
  3373. blend->BlendDelta( fromtime, totime, delta, blendWeight );
  3374. }
  3375. if ( modelDef->Joints()[ 0 ].channel ) {
  3376. blend = channels[ modelDef->Joints()[ 0 ].channel ];
  3377. for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
  3378. blend->BlendDelta( fromtime, totime, delta, blendWeight );
  3379. }
  3380. }
  3381. }
  3382. /*
  3383. ====================
  3384. idAnimator::GetDeltaRotation
  3385. ====================
  3386. */
  3387. bool idAnimator::GetDeltaRotation( int fromtime, int totime, idMat3 &delta ) const {
  3388. int i;
  3389. const idAnimBlend *blend;
  3390. float blendWeight;
  3391. idQuat q;
  3392. if ( !modelDef || !modelDef->ModelHandle() || ( fromtime == totime ) ) {
  3393. delta.Identity();
  3394. return false;
  3395. }
  3396. q.Set( 0.0f, 0.0f, 0.0f, 1.0f );
  3397. blendWeight = 0.0f;
  3398. blend = channels[ ANIMCHANNEL_ALL ];
  3399. for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
  3400. blend->BlendDeltaRotation( fromtime, totime, q, blendWeight );
  3401. }
  3402. if ( modelDef->Joints()[ 0 ].channel ) {
  3403. blend = channels[ modelDef->Joints()[ 0 ].channel ];
  3404. for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
  3405. blend->BlendDeltaRotation( fromtime, totime, q, blendWeight );
  3406. }
  3407. }
  3408. if ( blendWeight > 0.0f ) {
  3409. delta = q.ToMat3();
  3410. return true;
  3411. } else {
  3412. delta.Identity();
  3413. return false;
  3414. }
  3415. }
  3416. /*
  3417. ====================
  3418. idAnimator::GetOrigin
  3419. ====================
  3420. */
  3421. void idAnimator::GetOrigin( int currentTime, idVec3 &pos ) const {
  3422. int i;
  3423. const idAnimBlend *blend;
  3424. float blendWeight;
  3425. if ( !modelDef || !modelDef->ModelHandle() ) {
  3426. pos.Zero();
  3427. return;
  3428. }
  3429. pos.Zero();
  3430. blendWeight = 0.0f;
  3431. blend = channels[ ANIMCHANNEL_ALL ];
  3432. for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
  3433. blend->BlendOrigin( currentTime, pos, blendWeight, removeOriginOffset );
  3434. }
  3435. if ( modelDef->Joints()[ 0 ].channel ) {
  3436. blend = channels[ modelDef->Joints()[ 0 ].channel ];
  3437. for( i = 0; i < ANIM_MaxAnimsPerChannel; i++, blend++ ) {
  3438. blend->BlendOrigin( currentTime, pos, blendWeight, removeOriginOffset );
  3439. }
  3440. }
  3441. pos += modelDef->GetVisualOffset();
  3442. }
  3443. /*
  3444. ====================
  3445. idAnimator::GetBounds
  3446. ====================
  3447. */
  3448. bool idAnimator::GetBounds( int currentTime, idBounds &bounds ) {
  3449. int i, j;
  3450. const idAnimBlend *blend;
  3451. int count;
  3452. if ( !modelDef || !modelDef->ModelHandle() ) {
  3453. return false;
  3454. }
  3455. if ( AFPoseJoints.Num() ) {
  3456. bounds = AFPoseBounds;
  3457. count = 1;
  3458. } else {
  3459. bounds.Clear();
  3460. count = 0;
  3461. }
  3462. blend = channels[ 0 ];
  3463. for( i = ANIMCHANNEL_ALL; i < ANIM_NumAnimChannels; i++ ) {
  3464. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
  3465. if ( blend->AddBounds( currentTime, bounds, removeOriginOffset ) ) {
  3466. count++;
  3467. }
  3468. }
  3469. }
  3470. if ( !count ) {
  3471. if ( !frameBounds.IsCleared() ) {
  3472. bounds = frameBounds;
  3473. return true;
  3474. } else {
  3475. bounds.Zero();
  3476. return false;
  3477. }
  3478. }
  3479. bounds.TranslateSelf( modelDef->GetVisualOffset() );
  3480. if ( g_debugBounds.GetBool() ) {
  3481. if ( bounds[1][0] - bounds[0][0] > 2048 || bounds[1][1] - bounds[0][1] > 2048 ) {
  3482. if ( entity ) {
  3483. 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] );
  3484. } else {
  3485. gameLocal.Warning( "big frameBounds on model '%s': %f,%f", modelDef->ModelHandle()->Name(), bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1] );
  3486. }
  3487. }
  3488. }
  3489. frameBounds = bounds;
  3490. return true;
  3491. }
  3492. /*
  3493. =====================
  3494. idAnimator::InitAFPose
  3495. =====================
  3496. */
  3497. void idAnimator::InitAFPose( void ) {
  3498. if ( !modelDef ) {
  3499. return;
  3500. }
  3501. AFPoseJoints.SetNum( modelDef->Joints().Num(), false );
  3502. AFPoseJoints.SetNum( 0, false );
  3503. AFPoseJointMods.SetNum( modelDef->Joints().Num(), false );
  3504. AFPoseJointFrame.SetNum( modelDef->Joints().Num(), false );
  3505. }
  3506. /*
  3507. =====================
  3508. idAnimator::SetAFPoseJointMod
  3509. =====================
  3510. */
  3511. void idAnimator::SetAFPoseJointMod( const jointHandle_t jointNum, const AFJointModType_t mod, const idMat3 &axis, const idVec3 &origin ) {
  3512. AFPoseJointMods[jointNum].mod = mod;
  3513. AFPoseJointMods[jointNum].axis = axis;
  3514. AFPoseJointMods[jointNum].origin = origin;
  3515. int index = idBinSearch_GreaterEqual<int>( AFPoseJoints.Ptr(), AFPoseJoints.Num(), jointNum );
  3516. if ( index >= AFPoseJoints.Num() || jointNum != AFPoseJoints[index] ) {
  3517. AFPoseJoints.Insert( jointNum, index );
  3518. }
  3519. }
  3520. /*
  3521. =====================
  3522. idAnimator::FinishAFPose
  3523. =====================
  3524. */
  3525. void idAnimator::FinishAFPose( int animNum, const idBounds &bounds, const int time ) {
  3526. int i, j;
  3527. int numJoints;
  3528. int parentNum;
  3529. int jointMod;
  3530. int jointNum;
  3531. const int * jointParent;
  3532. if ( !modelDef ) {
  3533. return;
  3534. }
  3535. const idAnim *anim = modelDef->GetAnim( animNum );
  3536. if ( !anim ) {
  3537. return;
  3538. }
  3539. numJoints = modelDef->Joints().Num();
  3540. if ( !numJoints ) {
  3541. return;
  3542. }
  3543. idRenderModel *md5 = modelDef->ModelHandle();
  3544. const idMD5Anim *md5anim = anim->MD5Anim( 0 );
  3545. if ( numJoints != md5anim->NumJoints() ) {
  3546. gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", md5->Name(), md5anim->Name() );
  3547. return;
  3548. }
  3549. idJointQuat *jointFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( *jointFrame ) );
  3550. md5anim->GetSingleFrame( 0, jointFrame, modelDef->GetChannelJoints( ANIMCHANNEL_ALL ), modelDef->NumJointsOnChannel( ANIMCHANNEL_ALL ) );
  3551. if ( removeOriginOffset ) {
  3552. #ifdef VELOCITY_MOVE
  3553. jointFrame[ 0 ].t.x = 0.0f;
  3554. #else
  3555. jointFrame[ 0 ].t.Zero();
  3556. #endif
  3557. }
  3558. idJointMat *joints = ( idJointMat * )_alloca16( numJoints * sizeof( *joints ) );
  3559. // convert the joint quaternions to joint matrices
  3560. SIMDProcessor->ConvertJointQuatsToJointMats( joints, jointFrame, numJoints );
  3561. // first joint is always root of entire hierarchy
  3562. if ( AFPoseJoints.Num() && AFPoseJoints[0] == 0 ) {
  3563. switch( AFPoseJointMods[0].mod ) {
  3564. case AF_JOINTMOD_AXIS: {
  3565. joints[0].SetRotation( AFPoseJointMods[0].axis );
  3566. break;
  3567. }
  3568. case AF_JOINTMOD_ORIGIN: {
  3569. joints[0].SetTranslation( AFPoseJointMods[0].origin );
  3570. break;
  3571. }
  3572. case AF_JOINTMOD_BOTH: {
  3573. joints[0].SetRotation( AFPoseJointMods[0].axis );
  3574. joints[0].SetTranslation( AFPoseJointMods[0].origin );
  3575. break;
  3576. }
  3577. }
  3578. j = 1;
  3579. } else {
  3580. j = 0;
  3581. }
  3582. // pointer to joint info
  3583. jointParent = modelDef->JointParents();
  3584. // transform the child joints
  3585. for( i = 1; j < AFPoseJoints.Num(); j++, i++ ) {
  3586. jointMod = AFPoseJoints[j];
  3587. // transform any joints preceding the joint modifier
  3588. SIMDProcessor->TransformJoints( joints, jointParent, i, jointMod - 1 );
  3589. i = jointMod;
  3590. parentNum = jointParent[i];
  3591. switch( AFPoseJointMods[jointMod].mod ) {
  3592. case AF_JOINTMOD_AXIS: {
  3593. joints[i].SetRotation( AFPoseJointMods[jointMod].axis );
  3594. joints[i].SetTranslation( joints[parentNum].ToVec3() + joints[i].ToVec3() * joints[parentNum].ToMat3() );
  3595. break;
  3596. }
  3597. case AF_JOINTMOD_ORIGIN: {
  3598. joints[i].SetRotation( joints[i].ToMat3() * joints[parentNum].ToMat3() );
  3599. joints[i].SetTranslation( AFPoseJointMods[jointMod].origin );
  3600. break;
  3601. }
  3602. case AF_JOINTMOD_BOTH: {
  3603. joints[i].SetRotation( AFPoseJointMods[jointMod].axis );
  3604. joints[i].SetTranslation( AFPoseJointMods[jointMod].origin );
  3605. break;
  3606. }
  3607. }
  3608. }
  3609. // transform the rest of the hierarchy
  3610. SIMDProcessor->TransformJoints( joints, jointParent, i, numJoints - 1 );
  3611. // untransform hierarchy
  3612. SIMDProcessor->UntransformJoints( joints, jointParent, 1, numJoints - 1 );
  3613. // convert joint matrices back to joint quaternions
  3614. SIMDProcessor->ConvertJointMatsToJointQuats( AFPoseJointFrame.Ptr(), joints, numJoints );
  3615. // find all modified joints and their parents
  3616. bool *blendJoints = (bool *) _alloca16( numJoints * sizeof( bool ) );
  3617. memset( blendJoints, 0, numJoints * sizeof( bool ) );
  3618. // mark all modified joints and their parents
  3619. for( i = 0; i < AFPoseJoints.Num(); i++ ) {
  3620. for( jointNum = AFPoseJoints[i]; jointNum != INVALID_JOINT; jointNum = jointParent[jointNum] ) {
  3621. blendJoints[jointNum] = true;
  3622. }
  3623. }
  3624. // lock all parents of modified joints
  3625. AFPoseJoints.SetNum( 0, false );
  3626. for ( i = 0; i < numJoints; i++ ) {
  3627. if ( blendJoints[i] ) {
  3628. AFPoseJoints.Append( i );
  3629. }
  3630. }
  3631. AFPoseBounds = bounds;
  3632. AFPoseTime = time;
  3633. ForceUpdate();
  3634. }
  3635. /*
  3636. =====================
  3637. idAnimator::SetAFPoseBlendWeight
  3638. =====================
  3639. */
  3640. void idAnimator::SetAFPoseBlendWeight( float blendWeight ) {
  3641. AFPoseBlendWeight = blendWeight;
  3642. }
  3643. /*
  3644. =====================
  3645. idAnimator::BlendAFPose
  3646. =====================
  3647. */
  3648. bool idAnimator::BlendAFPose( idJointQuat *blendFrame ) const {
  3649. if ( !AFPoseJoints.Num() ) {
  3650. return false;
  3651. }
  3652. SIMDProcessor->BlendJoints( blendFrame, AFPoseJointFrame.Ptr(), AFPoseBlendWeight, AFPoseJoints.Ptr(), AFPoseJoints.Num() );
  3653. return true;
  3654. }
  3655. /*
  3656. =====================
  3657. idAnimator::ClearAFPose
  3658. =====================
  3659. */
  3660. void idAnimator::ClearAFPose( void ) {
  3661. if ( AFPoseJoints.Num() ) {
  3662. ForceUpdate();
  3663. }
  3664. AFPoseBlendWeight = 1.0f;
  3665. AFPoseJoints.SetNum( 0, false );
  3666. AFPoseBounds.Clear();
  3667. AFPoseTime = 0;
  3668. }
  3669. /*
  3670. =====================
  3671. idAnimator::ServiceAnims
  3672. =====================
  3673. */
  3674. void idAnimator::ServiceAnims( int fromtime, int totime ) {
  3675. int i, j;
  3676. idAnimBlend *blend;
  3677. if ( !modelDef ) {
  3678. return;
  3679. }
  3680. if ( modelDef->ModelHandle() ) {
  3681. blend = channels[ 0 ];
  3682. for( i = 0; i < ANIM_NumAnimChannels; i++ ) {
  3683. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
  3684. blend->CallFrameCommands( entity, fromtime, totime );
  3685. }
  3686. }
  3687. }
  3688. if ( !IsAnimating( totime ) ) {
  3689. stoppedAnimatingUpdate = true;
  3690. if ( entity ) {
  3691. entity->BecomeInactive( TH_ANIMATE );
  3692. // present one more time with stopped animations so the renderer can properly recreate interactions
  3693. entity->BecomeActive( TH_UPDATEVISUALS );
  3694. }
  3695. }
  3696. }
  3697. /*
  3698. =====================
  3699. idAnimator::IsAnimating
  3700. =====================
  3701. */
  3702. bool idAnimator::IsAnimating( int currentTime ) const {
  3703. int i, j;
  3704. const idAnimBlend *blend;
  3705. if ( !modelDef || !modelDef->ModelHandle() ) {
  3706. return false;
  3707. }
  3708. // if animating with an articulated figure
  3709. if ( AFPoseJoints.Num() && currentTime <= AFPoseTime ) {
  3710. return true;
  3711. }
  3712. blend = channels[ 0 ];
  3713. for( i = 0; i < ANIM_NumAnimChannels; i++ ) {
  3714. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
  3715. if ( !blend->IsDone( currentTime ) ) {
  3716. return true;
  3717. }
  3718. }
  3719. }
  3720. return false;
  3721. }
  3722. /*
  3723. =====================
  3724. idAnimator::FrameHasChanged
  3725. =====================
  3726. */
  3727. bool idAnimator::FrameHasChanged( int currentTime ) const {
  3728. int i, j;
  3729. const idAnimBlend *blend;
  3730. if ( !modelDef || !modelDef->ModelHandle() ) {
  3731. return false;
  3732. }
  3733. // if animating with an articulated figure
  3734. if ( AFPoseJoints.Num() && currentTime <= AFPoseTime ) {
  3735. return true;
  3736. }
  3737. blend = channels[ 0 ];
  3738. for( i = 0; i < ANIM_NumAnimChannels; i++ ) {
  3739. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
  3740. if ( blend->FrameHasChanged( currentTime ) ) {
  3741. return true;
  3742. }
  3743. }
  3744. }
  3745. if ( forceUpdate && IsAnimating( currentTime ) ) {
  3746. return true;
  3747. }
  3748. return false;
  3749. }
  3750. /*
  3751. =====================
  3752. idAnimator::CreateFrame
  3753. =====================
  3754. */
  3755. bool idAnimator::CreateFrame( int currentTime, bool force ) {
  3756. int i, j;
  3757. int numJoints;
  3758. int parentNum;
  3759. bool hasAnim;
  3760. bool debugInfo;
  3761. float baseBlend;
  3762. float blendWeight;
  3763. const idAnimBlend * blend;
  3764. const int * jointParent;
  3765. const jointMod_t * jointMod;
  3766. const idJointQuat * defaultPose;
  3767. static idCVar r_showSkel( "r_showSkel", "0", CVAR_RENDERER | CVAR_INTEGER, "", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  3768. if ( gameLocal.inCinematic && gameLocal.skipCinematic ) {
  3769. return false;
  3770. }
  3771. if ( !modelDef || !modelDef->ModelHandle() ) {
  3772. return false;
  3773. }
  3774. if ( !force && !r_showSkel.GetInteger() ) {
  3775. if ( lastTransformTime == currentTime ) {
  3776. return false;
  3777. }
  3778. if ( lastTransformTime != -1 && !stoppedAnimatingUpdate && !IsAnimating( currentTime ) ) {
  3779. return false;
  3780. }
  3781. }
  3782. lastTransformTime = currentTime;
  3783. stoppedAnimatingUpdate = false;
  3784. if ( entity && ( ( g_debugAnim.GetInteger() == entity->entityNumber ) || ( g_debugAnim.GetInteger() == -2 ) ) ) {
  3785. debugInfo = true;
  3786. gameLocal.Printf( "---------------\n%d: entity '%s':\n", gameLocal.time, entity->GetName() );
  3787. gameLocal.Printf( "model '%s':\n", modelDef->GetModelName() );
  3788. } else {
  3789. debugInfo = false;
  3790. }
  3791. // init the joint buffer
  3792. if ( AFPoseJoints.Num() ) {
  3793. // initialize with AF pose anim for the case where there are no other animations and no AF pose joint modifications
  3794. defaultPose = AFPoseJointFrame.Ptr();
  3795. } else {
  3796. defaultPose = modelDef->GetDefaultPose();
  3797. }
  3798. if ( !defaultPose ) {
  3799. //gameLocal.Warning( "idAnimator::CreateFrame: no defaultPose on '%s'", modelDef->Name() );
  3800. return false;
  3801. }
  3802. numJoints = modelDef->Joints().Num();
  3803. idJointQuat *jointFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( jointFrame[0] ) );
  3804. SIMDProcessor->Memcpy( jointFrame, defaultPose, numJoints * sizeof( jointFrame[0] ) );
  3805. hasAnim = false;
  3806. // blend the all channel
  3807. baseBlend = 0.0f;
  3808. blend = channels[ ANIMCHANNEL_ALL ];
  3809. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
  3810. if ( blend->BlendAnim( currentTime, ANIMCHANNEL_ALL, numJoints, jointFrame, baseBlend, removeOriginOffset, false, debugInfo ) ) {
  3811. hasAnim = true;
  3812. if ( baseBlend >= 1.0f ) {
  3813. break;
  3814. }
  3815. }
  3816. }
  3817. // only blend other channels if there's enough space to blend into
  3818. if ( baseBlend < 1.0f ) {
  3819. for( i = ANIMCHANNEL_ALL + 1; i < ANIM_NumAnimChannels; i++ ) {
  3820. if ( !modelDef->NumJointsOnChannel( i ) ) {
  3821. continue;
  3822. }
  3823. if ( i == ANIMCHANNEL_EYELIDS ) {
  3824. // eyelids blend over any previous anims, so skip it and blend it later
  3825. continue;
  3826. }
  3827. blendWeight = baseBlend;
  3828. blend = channels[ i ];
  3829. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
  3830. if ( blend->BlendAnim( currentTime, i, numJoints, jointFrame, blendWeight, removeOriginOffset, false, debugInfo ) ) {
  3831. hasAnim = true;
  3832. if ( blendWeight >= 1.0f ) {
  3833. // fully blended
  3834. break;
  3835. }
  3836. }
  3837. }
  3838. if ( debugInfo && !AFPoseJoints.Num() && !blendWeight ) {
  3839. gameLocal.Printf( "%d: %s using default pose in model '%s'\n", gameLocal.time, channelNames[ i ], modelDef->GetModelName() );
  3840. }
  3841. }
  3842. }
  3843. // blend in the eyelids
  3844. if ( modelDef->NumJointsOnChannel( ANIMCHANNEL_EYELIDS ) ) {
  3845. blend = channels[ ANIMCHANNEL_EYELIDS ];
  3846. blendWeight = baseBlend;
  3847. for( j = 0; j < ANIM_MaxAnimsPerChannel; j++, blend++ ) {
  3848. if ( blend->BlendAnim( currentTime, ANIMCHANNEL_EYELIDS, numJoints, jointFrame, blendWeight, removeOriginOffset, true, debugInfo ) ) {
  3849. hasAnim = true;
  3850. if ( blendWeight >= 1.0f ) {
  3851. // fully blended
  3852. break;
  3853. }
  3854. }
  3855. }
  3856. }
  3857. // blend the articulated figure pose
  3858. if ( BlendAFPose( jointFrame ) ) {
  3859. hasAnim = true;
  3860. }
  3861. if ( !hasAnim && !jointMods.Num() ) {
  3862. // no animations were updated
  3863. return false;
  3864. }
  3865. // convert the joint quaternions to rotation matrices
  3866. SIMDProcessor->ConvertJointQuatsToJointMats( joints, jointFrame, numJoints );
  3867. // check if we need to modify the origin
  3868. if ( jointMods.Num() && ( jointMods[0]->jointnum == 0 ) ) {
  3869. jointMod = jointMods[0];
  3870. switch( jointMod->transform_axis ) {
  3871. case JOINTMOD_NONE:
  3872. break;
  3873. case JOINTMOD_LOCAL:
  3874. joints[0].SetRotation( jointMod->mat * joints[0].ToMat3() );
  3875. break;
  3876. case JOINTMOD_WORLD:
  3877. joints[0].SetRotation( joints[0].ToMat3() * jointMod->mat );
  3878. break;
  3879. case JOINTMOD_LOCAL_OVERRIDE:
  3880. case JOINTMOD_WORLD_OVERRIDE:
  3881. joints[0].SetRotation( jointMod->mat );
  3882. break;
  3883. }
  3884. switch( jointMod->transform_pos ) {
  3885. case JOINTMOD_NONE:
  3886. break;
  3887. case JOINTMOD_LOCAL:
  3888. joints[0].SetTranslation( joints[0].ToVec3() + jointMod->pos );
  3889. break;
  3890. case JOINTMOD_LOCAL_OVERRIDE:
  3891. case JOINTMOD_WORLD:
  3892. case JOINTMOD_WORLD_OVERRIDE:
  3893. joints[0].SetTranslation( jointMod->pos );
  3894. break;
  3895. }
  3896. j = 1;
  3897. } else {
  3898. j = 0;
  3899. }
  3900. // add in the model offset
  3901. joints[0].SetTranslation( joints[0].ToVec3() + modelDef->GetVisualOffset() );
  3902. // pointer to joint info
  3903. jointParent = modelDef->JointParents();
  3904. // add in any joint modifications
  3905. for( i = 1; j < jointMods.Num(); j++, i++ ) {
  3906. jointMod = jointMods[j];
  3907. // transform any joints preceding the joint modifier
  3908. SIMDProcessor->TransformJoints( joints, jointParent, i, jointMod->jointnum - 1 );
  3909. i = jointMod->jointnum;
  3910. parentNum = jointParent[i];
  3911. // modify the axis
  3912. switch( jointMod->transform_axis ) {
  3913. case JOINTMOD_NONE:
  3914. joints[i].SetRotation( joints[i].ToMat3() * joints[ parentNum ].ToMat3() );
  3915. break;
  3916. case JOINTMOD_LOCAL:
  3917. joints[i].SetRotation( jointMod->mat * ( joints[i].ToMat3() * joints[parentNum].ToMat3() ) );
  3918. break;
  3919. case JOINTMOD_LOCAL_OVERRIDE:
  3920. joints[i].SetRotation( jointMod->mat * joints[parentNum].ToMat3() );
  3921. break;
  3922. case JOINTMOD_WORLD:
  3923. joints[i].SetRotation( ( joints[i].ToMat3() * joints[parentNum].ToMat3() ) * jointMod->mat );
  3924. break;
  3925. case JOINTMOD_WORLD_OVERRIDE:
  3926. joints[i].SetRotation( jointMod->mat );
  3927. break;
  3928. }
  3929. // modify the position
  3930. switch( jointMod->transform_pos ) {
  3931. case JOINTMOD_NONE:
  3932. joints[i].SetTranslation( joints[parentNum].ToVec3() + joints[i].ToVec3() * joints[parentNum].ToMat3() );
  3933. break;
  3934. case JOINTMOD_LOCAL:
  3935. joints[i].SetTranslation( joints[parentNum].ToVec3() + ( joints[i].ToVec3() + jointMod->pos ) * joints[parentNum].ToMat3() );
  3936. break;
  3937. case JOINTMOD_LOCAL_OVERRIDE:
  3938. joints[i].SetTranslation( joints[parentNum].ToVec3() + jointMod->pos * joints[parentNum].ToMat3() );
  3939. break;
  3940. case JOINTMOD_WORLD:
  3941. joints[i].SetTranslation( joints[parentNum].ToVec3() + joints[i].ToVec3() * joints[parentNum].ToMat3() + jointMod->pos );
  3942. break;
  3943. case JOINTMOD_WORLD_OVERRIDE:
  3944. joints[i].SetTranslation( jointMod->pos );
  3945. break;
  3946. }
  3947. }
  3948. // transform the rest of the hierarchy
  3949. SIMDProcessor->TransformJoints( joints, jointParent, i, numJoints - 1 );
  3950. return true;
  3951. }
  3952. /*
  3953. =====================
  3954. idAnimator::ForceUpdate
  3955. =====================
  3956. */
  3957. void idAnimator::ForceUpdate( void ) {
  3958. lastTransformTime = -1;
  3959. forceUpdate = true;
  3960. }
  3961. /*
  3962. =====================
  3963. idAnimator::ClearForceUpdate
  3964. =====================
  3965. */
  3966. void idAnimator::ClearForceUpdate( void ) {
  3967. forceUpdate = false;
  3968. }
  3969. /*
  3970. =====================
  3971. idAnimator::GetJointTransform> gamex86.dll!idAnimator::ForceUpdate() Line 4268 C++
  3972. =====================
  3973. */
  3974. bool idAnimator::GetJointTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ) {
  3975. if ( !modelDef || ( jointHandle < 0 ) || ( jointHandle >= modelDef->NumJoints() ) ) {
  3976. return false;
  3977. }
  3978. CreateFrame( currentTime, false );
  3979. offset = joints[ jointHandle ].ToVec3();
  3980. axis = joints[ jointHandle ].ToMat3();
  3981. return true;
  3982. }
  3983. /*
  3984. =====================
  3985. idAnimator::GetJointLocalTransform
  3986. =====================
  3987. */
  3988. bool idAnimator::GetJointLocalTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ) {
  3989. if ( !modelDef ) {
  3990. return false;
  3991. }
  3992. const idList<jointInfo_t> &modelJoints = modelDef->Joints();
  3993. if ( ( jointHandle < 0 ) || ( jointHandle >= modelJoints.Num() ) ) {
  3994. return false;
  3995. }
  3996. // FIXME: overkill
  3997. CreateFrame( currentTime, false );
  3998. if ( jointHandle > 0 ) {
  3999. idJointMat m = joints[ jointHandle ];
  4000. m /= joints[ modelJoints[ jointHandle ].parentNum ];
  4001. offset = m.ToVec3();
  4002. axis = m.ToMat3();
  4003. } else {
  4004. offset = joints[ jointHandle ].ToVec3();
  4005. axis = joints[ jointHandle ].ToMat3();
  4006. }
  4007. return true;
  4008. }
  4009. /*
  4010. =====================
  4011. idAnimator::GetJointHandle
  4012. =====================
  4013. */
  4014. jointHandle_t idAnimator::GetJointHandle( const char *name ) const {
  4015. if ( !modelDef || !modelDef->ModelHandle() ) {
  4016. return INVALID_JOINT;
  4017. }
  4018. return modelDef->ModelHandle()->GetJointHandle( name );
  4019. }
  4020. /*
  4021. =====================
  4022. idAnimator::GetJointName
  4023. =====================
  4024. */
  4025. const char *idAnimator::GetJointName( jointHandle_t handle ) const {
  4026. if ( !modelDef || !modelDef->ModelHandle() ) {
  4027. return "";
  4028. }
  4029. return modelDef->ModelHandle()->GetJointName( handle );
  4030. }
  4031. /*
  4032. =====================
  4033. idAnimator::GetChannelForJoint
  4034. =====================
  4035. */
  4036. int idAnimator::GetChannelForJoint( jointHandle_t joint ) const {
  4037. if ( !modelDef ) {
  4038. gameLocal.Error( "idAnimator::GetChannelForJoint: NULL model" );
  4039. }
  4040. if ( ( joint < 0 ) || ( joint >= numJoints ) ) {
  4041. gameLocal.Error( "idAnimator::GetChannelForJoint: invalid joint num (%d)", joint );
  4042. }
  4043. return modelDef->GetJoint( joint )->channel;
  4044. }
  4045. /*
  4046. =====================
  4047. idAnimator::GetFirstChild
  4048. =====================
  4049. */
  4050. jointHandle_t idAnimator::GetFirstChild( const char *name ) const {
  4051. return GetFirstChild( GetJointHandle( name ) );
  4052. }
  4053. /*
  4054. =====================
  4055. idAnimator::GetFirstChild
  4056. =====================
  4057. */
  4058. jointHandle_t idAnimator::GetFirstChild( jointHandle_t jointnum ) const {
  4059. int i;
  4060. int num;
  4061. const jointInfo_t *joint;
  4062. if ( !modelDef ) {
  4063. return INVALID_JOINT;
  4064. }
  4065. num = modelDef->NumJoints();
  4066. if ( !num ) {
  4067. return jointnum;
  4068. }
  4069. joint = modelDef->GetJoint( 0 );
  4070. for( i = 0; i < num; i++, joint++ ) {
  4071. if ( joint->parentNum == jointnum ) {
  4072. return ( jointHandle_t )joint->num;
  4073. }
  4074. }
  4075. return jointnum;
  4076. }
  4077. /*
  4078. =====================
  4079. idAnimator::GetJoints
  4080. =====================
  4081. */
  4082. void idAnimator::GetJoints( int *numJoints, idJointMat **jointsPtr ) {
  4083. *numJoints = this->numJoints;
  4084. *jointsPtr = this->joints;
  4085. }
  4086. /*
  4087. =====================
  4088. idAnimator::GetAnimFlags
  4089. =====================
  4090. */
  4091. const animFlags_t idAnimator::GetAnimFlags( int animNum ) const {
  4092. animFlags_t result;
  4093. const idAnim *anim = GetAnim( animNum );
  4094. if ( anim ) {
  4095. return anim->GetAnimFlags();
  4096. }
  4097. memset( &result, 0, sizeof( result ) );
  4098. return result;
  4099. }
  4100. /*
  4101. =====================
  4102. idAnimator::NumFrames
  4103. =====================
  4104. */
  4105. int idAnimator::NumFrames( int animNum ) const {
  4106. const idAnim *anim = GetAnim( animNum );
  4107. if ( anim ) {
  4108. return anim->NumFrames();
  4109. } else {
  4110. return 0;
  4111. }
  4112. }
  4113. /*
  4114. =====================
  4115. idAnimator::NumSyncedAnims
  4116. =====================
  4117. */
  4118. int idAnimator::NumSyncedAnims( int animNum ) const {
  4119. const idAnim *anim = GetAnim( animNum );
  4120. if ( anim ) {
  4121. return anim->NumAnims();
  4122. } else {
  4123. return 0;
  4124. }
  4125. }
  4126. /*
  4127. =====================
  4128. idAnimator::AnimName
  4129. =====================
  4130. */
  4131. const char *idAnimator::AnimName( int animNum ) const {
  4132. const idAnim *anim = GetAnim( animNum );
  4133. if ( anim ) {
  4134. return anim->Name();
  4135. } else {
  4136. return "";
  4137. }
  4138. }
  4139. /*
  4140. =====================
  4141. idAnimator::AnimFullName
  4142. =====================
  4143. */
  4144. const char *idAnimator::AnimFullName( int animNum ) const {
  4145. const idAnim *anim = GetAnim( animNum );
  4146. if ( anim ) {
  4147. return anim->FullName();
  4148. } else {
  4149. return "";
  4150. }
  4151. }
  4152. /*
  4153. =====================
  4154. idAnimator::AnimLength
  4155. =====================
  4156. */
  4157. int idAnimator::AnimLength( int animNum ) const {
  4158. const idAnim *anim = GetAnim( animNum );
  4159. if ( anim ) {
  4160. return anim->Length();
  4161. } else {
  4162. return 0;
  4163. }
  4164. }
  4165. /*
  4166. =====================
  4167. idAnimator::TotalMovementDelta
  4168. =====================
  4169. */
  4170. const idVec3 &idAnimator::TotalMovementDelta( int animNum ) const {
  4171. const idAnim *anim = GetAnim( animNum );
  4172. if ( anim ) {
  4173. return anim->TotalMovementDelta();
  4174. } else {
  4175. return vec3_origin;
  4176. }
  4177. }
  4178. /***********************************************************************
  4179. Util functions
  4180. ***********************************************************************/
  4181. /*
  4182. =====================
  4183. ANIM_GetModelDefFromEntityDef
  4184. =====================
  4185. */
  4186. const idDeclModelDef *ANIM_GetModelDefFromEntityDef( const idDict *args ) {
  4187. const idDeclModelDef *modelDef;
  4188. idStr name = args->GetString( "model" );
  4189. modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name, false ) );
  4190. if ( modelDef && modelDef->ModelHandle() ) {
  4191. return modelDef;
  4192. }
  4193. return NULL;
  4194. }
  4195. /*
  4196. =====================
  4197. idGameEdit::ANIM_GetModelFromEntityDef
  4198. =====================
  4199. */
  4200. idRenderModel *idGameEdit::ANIM_GetModelFromEntityDef( const idDict *args ) {
  4201. idRenderModel *model;
  4202. const idDeclModelDef *modelDef;
  4203. model = NULL;
  4204. idStr name = args->GetString( "model" );
  4205. modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name, false ) );
  4206. if ( modelDef ) {
  4207. model = modelDef->ModelHandle();
  4208. }
  4209. if ( !model ) {
  4210. model = renderModelManager->FindModel( name );
  4211. }
  4212. if ( model && model->IsDefaultModel() ) {
  4213. return NULL;
  4214. }
  4215. return model;
  4216. }
  4217. /*
  4218. =====================
  4219. idGameEdit::ANIM_GetModelFromEntityDef
  4220. =====================
  4221. */
  4222. idRenderModel *idGameEdit::ANIM_GetModelFromEntityDef( const char *classname ) {
  4223. const idDict *args;
  4224. args = gameLocal.FindEntityDefDict( classname, false );
  4225. if ( !args ) {
  4226. return NULL;
  4227. }
  4228. return ANIM_GetModelFromEntityDef( args );
  4229. }
  4230. /*
  4231. =====================
  4232. idGameEdit::ANIM_GetModelOffsetFromEntityDef
  4233. =====================
  4234. */
  4235. const idVec3 &idGameEdit::ANIM_GetModelOffsetFromEntityDef( const char *classname ) {
  4236. const idDict *args;
  4237. const idDeclModelDef *modelDef;
  4238. args = gameLocal.FindEntityDefDict( classname, false );
  4239. if ( !args ) {
  4240. return vec3_origin;
  4241. }
  4242. modelDef = ANIM_GetModelDefFromEntityDef( args );
  4243. if ( !modelDef ) {
  4244. return vec3_origin;
  4245. }
  4246. return modelDef->GetVisualOffset();
  4247. }
  4248. /*
  4249. =====================
  4250. idGameEdit::ANIM_GetModelFromName
  4251. =====================
  4252. */
  4253. idRenderModel *idGameEdit::ANIM_GetModelFromName( const char *modelName ) {
  4254. const idDeclModelDef *modelDef;
  4255. idRenderModel *model;
  4256. model = NULL;
  4257. modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelName, false ) );
  4258. if ( modelDef ) {
  4259. model = modelDef->ModelHandle();
  4260. }
  4261. if ( !model ) {
  4262. model = renderModelManager->FindModel( modelName );
  4263. }
  4264. return model;
  4265. }
  4266. /*
  4267. =====================
  4268. idGameEdit::ANIM_GetAnimFromEntityDef
  4269. =====================
  4270. */
  4271. const idMD5Anim *idGameEdit::ANIM_GetAnimFromEntityDef( const char *classname, const char *animname ) {
  4272. const idDict *args;
  4273. const idMD5Anim *md5anim;
  4274. const idAnim *anim;
  4275. int animNum;
  4276. const char *modelname;
  4277. const idDeclModelDef *modelDef;
  4278. args = gameLocal.FindEntityDefDict( classname, false );
  4279. if ( !args ) {
  4280. return NULL;
  4281. }
  4282. md5anim = NULL;
  4283. modelname = args->GetString( "model" );
  4284. modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelname, false ) );
  4285. if ( modelDef ) {
  4286. animNum = modelDef->GetAnim( animname );
  4287. if ( animNum ) {
  4288. anim = modelDef->GetAnim( animNum );
  4289. if ( anim ) {
  4290. md5anim = anim->MD5Anim( 0 );
  4291. }
  4292. }
  4293. }
  4294. return md5anim;
  4295. }
  4296. /*
  4297. =====================
  4298. idGameEdit::ANIM_GetNumAnimsFromEntityDef
  4299. =====================
  4300. */
  4301. int idGameEdit::ANIM_GetNumAnimsFromEntityDef( const idDict *args ) {
  4302. const char *modelname;
  4303. const idDeclModelDef *modelDef;
  4304. modelname = args->GetString( "model" );
  4305. modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelname, false ) );
  4306. if ( modelDef ) {
  4307. return modelDef->NumAnims();
  4308. }
  4309. return 0;
  4310. }
  4311. /*
  4312. =====================
  4313. idGameEdit::ANIM_GetAnimNameFromEntityDef
  4314. =====================
  4315. */
  4316. const char *idGameEdit::ANIM_GetAnimNameFromEntityDef( const idDict *args, int animNum ) {
  4317. const char *modelname;
  4318. const idDeclModelDef *modelDef;
  4319. modelname = args->GetString( "model" );
  4320. modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, modelname, false ) );
  4321. if ( modelDef ) {
  4322. const idAnim* anim = modelDef->GetAnim( animNum );
  4323. if ( anim ) {
  4324. return anim->FullName();
  4325. }
  4326. }
  4327. return "";
  4328. }
  4329. /*
  4330. =====================
  4331. idGameEdit::ANIM_GetAnim
  4332. =====================
  4333. */
  4334. const idMD5Anim *idGameEdit::ANIM_GetAnim( const char *fileName ) {
  4335. return animationLib.GetAnim( fileName );
  4336. }
  4337. /*
  4338. =====================
  4339. idGameEdit::ANIM_GetLength
  4340. =====================
  4341. */
  4342. int idGameEdit::ANIM_GetLength( const idMD5Anim *anim ) {
  4343. if ( !anim ) {
  4344. return 0;
  4345. }
  4346. return anim->Length();
  4347. }
  4348. /*
  4349. =====================
  4350. idGameEdit::ANIM_GetNumFrames
  4351. =====================
  4352. */
  4353. int idGameEdit::ANIM_GetNumFrames( const idMD5Anim *anim ) {
  4354. if ( !anim ) {
  4355. return 0;
  4356. }
  4357. return anim->NumFrames();
  4358. }
  4359. /*
  4360. =====================
  4361. idGameEdit::ANIM_CreateAnimFrame
  4362. =====================
  4363. */
  4364. void idGameEdit::ANIM_CreateAnimFrame( const idRenderModel *model, const idMD5Anim *anim, int numJoints, idJointMat *joints, int time, const idVec3 &offset, bool remove_origin_offset ) {
  4365. int i;
  4366. frameBlend_t frame;
  4367. const idMD5Joint *md5joints;
  4368. int *index;
  4369. if ( !model || model->IsDefaultModel() || !anim ) {
  4370. return;
  4371. }
  4372. if ( numJoints != model->NumJoints() ) {
  4373. gameLocal.Error( "ANIM_CreateAnimFrame: different # of joints in renderEntity_t than in model (%s)", model->Name() );
  4374. }
  4375. if ( !model->NumJoints() ) {
  4376. // FIXME: Print out a warning?
  4377. return;
  4378. }
  4379. if ( !joints ) {
  4380. gameLocal.Error( "ANIM_CreateAnimFrame: NULL joint frame pointer on model (%s)", model->Name() );
  4381. }
  4382. if ( numJoints != anim->NumJoints() ) {
  4383. gameLocal.Warning( "Model '%s' has different # of joints than anim '%s'", model->Name(), anim->Name() );
  4384. for( i = 0; i < numJoints; i++ ) {
  4385. joints[i].SetRotation( mat3_identity );
  4386. joints[i].SetTranslation( offset );
  4387. }
  4388. return;
  4389. }
  4390. // create index for all joints
  4391. index = ( int * )_alloca16( numJoints * sizeof( int ) );
  4392. for ( i = 0; i < numJoints; i++ ) {
  4393. index[i] = i;
  4394. }
  4395. // create the frame
  4396. anim->ConvertTimeToFrame( time, 1, frame );
  4397. idJointQuat *jointFrame = ( idJointQuat * )_alloca16( numJoints * sizeof( *jointFrame ) );
  4398. anim->GetInterpolatedFrame( frame, jointFrame, index, numJoints );
  4399. // convert joint quaternions to joint matrices
  4400. SIMDProcessor->ConvertJointQuatsToJointMats( joints, jointFrame, numJoints );
  4401. // first joint is always root of entire hierarchy
  4402. if ( remove_origin_offset ) {
  4403. joints[0].SetTranslation( offset );
  4404. } else {
  4405. joints[0].SetTranslation( joints[0].ToVec3() + offset );
  4406. }
  4407. // transform the children
  4408. md5joints = model->GetJoints();
  4409. for( i = 1; i < numJoints; i++ ) {
  4410. joints[i] *= joints[ md5joints[i].parent - md5joints ];
  4411. }
  4412. }
  4413. /*
  4414. =====================
  4415. idGameEdit::ANIM_CreateMeshForAnim
  4416. =====================
  4417. */
  4418. idRenderModel *idGameEdit::ANIM_CreateMeshForAnim( idRenderModel *model, const char *classname, const char *animname, int frame, bool remove_origin_offset ) {
  4419. renderEntity_t ent;
  4420. const idDict *args;
  4421. const char *temp;
  4422. idRenderModel *newmodel;
  4423. const idMD5Anim *md5anim;
  4424. idStr filename;
  4425. idStr extension;
  4426. const idAnim *anim;
  4427. int animNum;
  4428. idVec3 offset;
  4429. const idDeclModelDef *modelDef;
  4430. if ( !model || model->IsDefaultModel() ) {
  4431. return NULL;
  4432. }
  4433. args = gameLocal.FindEntityDefDict( classname, false );
  4434. if ( !args ) {
  4435. return NULL;
  4436. }
  4437. memset( &ent, 0, sizeof( ent ) );
  4438. ent.bounds.Clear();
  4439. ent.suppressSurfaceInViewID = 0;
  4440. modelDef = ANIM_GetModelDefFromEntityDef( args );
  4441. if ( modelDef ) {
  4442. animNum = modelDef->GetAnim( animname );
  4443. if ( !animNum ) {
  4444. return NULL;
  4445. }
  4446. anim = modelDef->GetAnim( animNum );
  4447. if ( !anim ) {
  4448. return NULL;
  4449. }
  4450. md5anim = anim->MD5Anim( 0 );
  4451. ent.customSkin = modelDef->GetDefaultSkin();
  4452. offset = modelDef->GetVisualOffset();
  4453. } else {
  4454. filename = animname;
  4455. filename.ExtractFileExtension( extension );
  4456. if ( !extension.Length() ) {
  4457. animname = args->GetString( va( "anim %s", animname ) );
  4458. }
  4459. md5anim = animationLib.GetAnim( animname );
  4460. offset.Zero();
  4461. }
  4462. if ( !md5anim ) {
  4463. return NULL;
  4464. }
  4465. temp = args->GetString( "skin", "" );
  4466. if ( temp[ 0 ] ) {
  4467. ent.customSkin = declManager->FindSkin( temp );
  4468. }
  4469. ent.numJoints = model->NumJoints();
  4470. ent.joints = ( idJointMat * )Mem_Alloc16( ent.numJoints * sizeof( *ent.joints ) );
  4471. ANIM_CreateAnimFrame( model, md5anim, ent.numJoints, ent.joints, FRAME2MS( frame ), offset, remove_origin_offset );
  4472. newmodel = model->InstantiateDynamicModel( &ent, NULL, NULL );
  4473. Mem_Free16( ent.joints );
  4474. ent.joints = NULL;
  4475. return newmodel;
  4476. }