123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Maya5.0/maya.h"
- //#include "Maya6.0/maya.h" // must also change include directory in project from "MayaImport\Maya4.5\include" to "MayaImport\Maya6.0\include" (requires MSDev 7.1)
- #include "exporter.h"
- #include "maya_main.h"
- idStr errorMessage;
- bool initialized = false;
- #define DEFAULT_ANIM_EPSILON 0.125f
- #define DEFAULT_QUAT_EPSILON ( 1.0f / 8192.0f )
- #define SLOP_VERTEX 0.01f // merge xyz coordinates this far apart
- #define SLOP_TEXCOORD 0.001f // merge texture coordinates this far apart
- const char *componentNames[ 6 ] = { "Tx", "Ty", "Tz", "Qx", "Qy", "Qz" };
- idSys * sys = NULL;
- idCommon * common = NULL;
- idCVarSystem * cvarSystem = NULL;
- idCVar * idCVar::staticVars = NULL;
- /*
- =================
- MayaError
- =================
- */
- void MayaError( const char *fmt, ... ) {
- va_list argptr;
- char text[ 8192 ];
- va_start( argptr, fmt );
- idStr::vsnPrintf( text, sizeof( text ), fmt, argptr );
- va_end( argptr );
- throw idException( text );
- }
- /*
- =================
- FS_WriteFloatString
- =================
- */
- #define MAX_PRINT_MSG 4096
- static int WriteFloatString( FILE *file, const char *fmt, ... ) {
- long i;
- unsigned long u;
- double f;
- char *str;
- int index;
- idStr tmp, format;
- va_list argPtr;
- va_start( argPtr, fmt );
- index = 0;
- while( *fmt ) {
- switch( *fmt ) {
- case '%':
- format = "";
- format += *fmt++;
- while ( (*fmt >= '0' && *fmt <= '9') ||
- *fmt == '.' || *fmt == '-' || *fmt == '+' || *fmt == '#') {
- format += *fmt++;
- }
- format += *fmt;
- switch( *fmt ) {
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- f = va_arg( argPtr, double );
- if ( format.Length() <= 2 ) {
- // high precision floating point number without trailing zeros
- sprintf( tmp, "%1.10f", f );
- tmp.StripTrailing( '0' );
- tmp.StripTrailing( '.' );
- index += fprintf( file, "%s", tmp.c_str() );
- }
- else {
- index += fprintf( file, format.c_str(), f );
- }
- break;
- case 'd':
- case 'i':
- i = va_arg( argPtr, long );
- index += fprintf( file, format.c_str(), i );
- break;
- case 'u':
- u = va_arg( argPtr, unsigned long );
- index += fprintf( file, format.c_str(), u );
- break;
- case 'o':
- u = va_arg( argPtr, unsigned long );
- index += fprintf( file, format.c_str(), u );
- break;
- case 'x':
- u = va_arg( argPtr, unsigned long );
- index += fprintf( file, format.c_str(), u );
- break;
- case 'X':
- u = va_arg( argPtr, unsigned long );
- index += fprintf( file, format.c_str(), u );
- break;
- case 'c':
- i = va_arg( argPtr, long );
- index += fprintf( file, format.c_str(), (char) i );
- break;
- case 's':
- str = va_arg( argPtr, char * );
- index += fprintf( file, format.c_str(), str );
- break;
- case '%':
- index += fprintf( file, format.c_str() );
- break;
- default:
- MayaError( "WriteFloatString: invalid format %s", format.c_str() );
- break;
- }
- fmt++;
- break;
- case '\\':
- fmt++;
- switch( *fmt ) {
- case 't':
- index += fprintf( file, "\t" );
- break;
- case 'n':
- index += fprintf( file, "\n" );
- default:
- MayaError( "WriteFloatString: unknown escape character \'%c\'", *fmt );
- break;
- }
- fmt++;
- break;
- default:
- index += fprintf( file, "%c", *fmt );
- fmt++;
- break;
- }
- }
- va_end( argPtr );
- return index;
- }
- /*
- ================
- OSPathToRelativePath
- takes a full OS path, as might be found in data from a media creation
- program, and converts it to a qpath by stripping off directories
- Returns false if the osPath tree doesn't match any of the existing
- search paths.
- ================
- */
- bool OSPathToRelativePath( const char *osPath, idStr &qpath, const char *game ) {
- char *s, *base;
- // skip a drive letter?
- // search for anything with BASE_GAMEDIR in it
- // Ase files from max may have the form of:
- // "//Purgatory/purgatory/doom/base/models/mapobjects/bitch/hologirl.tga"
- // which won't match any of our drive letter based search paths
- base = (char *)strstr( osPath, BASE_GAMEDIR );
- // _D3XP added mod support
- if ( base == NULL && strlen(game) > 0 ) {
- base = s = (char *)strstr( osPath, game );
- while( s = strstr( s, game ) ) {
- s += strlen( game );
- if ( s[0] == '/' || s[0] == '\\' ) {
- base = s;
- }
- }
- }
- if ( base ) {
- s = strstr( base, "/" );
- if ( !s ) {
- s = strstr( base, "\\" );
- }
- if ( s ) {
- qpath = s + 1;
- return true;
- }
- }
- common->Printf( "OSPathToRelativePath failed on %s\n", osPath );
- qpath = osPath;
- return false;
- }
- /*
- ===============
- ConvertFromIdSpace
- ===============
- */
- idMat3 ConvertFromIdSpace( const idMat3 &idmat ) {
- idMat3 mat;
- mat[ 0 ][ 0 ] = idmat[ 0 ][ 0 ];
- mat[ 0 ][ 2 ] = -idmat[ 0 ][ 1 ];
- mat[ 0 ][ 1 ] = idmat[ 0 ][ 2 ];
-
- mat[ 1 ][ 0 ] = idmat[ 1 ][ 0 ];
- mat[ 1 ][ 2 ] = -idmat[ 1 ][ 1 ];
- mat[ 1 ][ 1 ] = idmat[ 1 ][ 2 ];
-
- mat[ 2 ][ 0 ] = idmat[ 2 ][ 0 ];
- mat[ 2 ][ 2 ] = -idmat[ 2 ][ 1 ];
- mat[ 2 ][ 1 ] = idmat[ 2 ][ 2 ];
- return mat;
- }
- /*
- ===============
- ConvertFromIdSpace
- ===============
- */
- idVec3 ConvertFromIdSpace( const idVec3 &idpos ) {
- idVec3 pos;
- pos.x = idpos.x;
- pos.z = -idpos.y;
- pos.y = idpos.z;
- return pos;
- }
- /*
- ===============
- ConvertToIdSpace
- ===============
- */
- idMat3 ConvertToIdSpace( const idMat3 &mat ) {
- idMat3 idmat;
- idmat[ 0 ][ 0 ] = mat[ 0 ][ 0 ];
- idmat[ 0 ][ 1 ] = -mat[ 0 ][ 2 ];
- idmat[ 0 ][ 2 ] = mat[ 0 ][ 1 ];
- idmat[ 1 ][ 0 ] = mat[ 1 ][ 0 ];
- idmat[ 1 ][ 1 ] = -mat[ 1 ][ 2 ];
- idmat[ 1 ][ 2 ] = mat[ 1 ][ 1 ];
- idmat[ 2 ][ 0 ] = mat[ 2 ][ 0 ];
- idmat[ 2 ][ 1 ] = -mat[ 2 ][ 2 ];
- idmat[ 2 ][ 2 ] = mat[ 2 ][ 1 ];
- return idmat;
- }
- /*
- ===============
- ConvertToIdSpace
- ===============
- */
- idVec3 ConvertToIdSpace( const idVec3 &pos ) {
- idVec3 idpos;
- idpos.x = pos.x;
- idpos.y = -pos.z;
- idpos.z = pos.y;
- return idpos;
- }
- /*
- ===============
- idVec
- ===============
- */
- idVec3 idVec( const MFloatPoint &point ) {
- return idVec3( point[ 0 ], point[ 1 ], point[ 2 ] );
- }
- /*
- ===============
- idVec
- ===============
- */
- idVec3 idVec( const MMatrix &matrix ) {
- return idVec3( matrix[ 3 ][ 0 ], matrix[ 3 ][ 1 ], matrix[ 3 ][ 2 ] );
- }
- /*
- ===============
- idMat
- ===============
- */
- idMat3 idMat( const MMatrix &matrix ) {
- int j, k;
- idMat3 mat;
- for( j = 0; j < 3; j++ ) {
- for( k = 0; k < 3; k++ ) {
- mat[ j ][ k ] = matrix[ j ][ k ];
- }
- }
- return mat;
- }
- /*
- ===============
- GetParent
- ===============
- */
- MFnDagNode *GetParent( MFnDagNode *joint ) {
- MStatus status;
- MObject parentObject;
- parentObject = joint->parent( 0, &status );
- if ( !status && status.statusCode() == MStatus::kInvalidParameter ) {
- return NULL;
- }
- while( !parentObject.hasFn( MFn::kTransform ) ) {
- MFnDagNode parentNode( parentObject, &status );
- if ( !status ) {
- return NULL;
- }
- parentObject = parentNode.parent( 0, &status );
- if ( !status && status.statusCode() == MStatus::kInvalidParameter ) {
- return NULL;
- }
- }
- MFnDagNode *parentNode;
- parentNode = new MFnDagNode( parentObject, &status );
- if ( !status ) {
- delete parentNode;
- return NULL;
- }
- return parentNode;
- }
- /*
- ==============================================================================================
- idTokenizer
- ==============================================================================================
- */
- /*
- ====================
- idTokenizer::SetTokens
- ====================
- */
- int idTokenizer::SetTokens( const char *buffer ) {
- const char *cmd;
- Clear();
- // tokenize commandline
- cmd = buffer;
- while ( *cmd ) {
- // skip whitespace
- while( *cmd && isspace( *cmd ) ) {
- cmd++;
- }
- if ( !*cmd ) {
- break;
- }
-
- idStr ¤t = tokens.Alloc();
- while( *cmd && !isspace( *cmd ) ) {
- current += *cmd;
- cmd++;
- }
- }
- return tokens.Num();
- }
- /*
- ====================
- idTokenizer::NextToken
- ====================
- */
- const char *idTokenizer::NextToken( const char *errorstring ) {
- if ( currentToken < tokens.Num() ) {
- return tokens[ currentToken++ ];
- }
- if ( errorstring ) {
- MayaError( "Error: %s", errorstring );
- }
- return NULL;
- }
- /*
- ==============================================================================================
- idExportOptions
- ==============================================================================================
- */
- /*
- ====================
- idExportOptions::Reset
- ====================
- */
- void idExportOptions::Reset( const char *commandline ) {
- scale = 1.0f;
- type = WRITE_MESH;
- startframe = -1;
- endframe = -1;
- ignoreMeshes = false;
- clearOrigin = false;
- clearOriginAxis = false;
- framerate = 24;
- align = "";
- rotate = 0.0f;
- commandLine = commandline;
- prefix = "";
- jointThreshold = 0.05f;
- ignoreScale = false;
- xyzPrecision = DEFAULT_ANIM_EPSILON;
- quatPrecision = DEFAULT_QUAT_EPSILON;
- cycleStart = -1;
- src.Clear();
- dest.Clear();
- tokens.SetTokens( commandline );
- keepjoints.Clear();
- renamejoints.Clear();
- remapjoints.Clear();
- exportgroups.Clear();
- skipmeshes.Clear();
- keepmeshes.Clear();
- groups.Clear();
- }
- /*
- ====================
- idExportOptions::idExportOptions
- ====================
- */
- idExportOptions::idExportOptions( const char *commandline, const char *ospath ) {
- idStr token;
- idNamePair joints;
- int i;
- idAnimGroup *group;
- idStr sourceDir;
- idStr destDir;
- Reset( commandline );
- token = tokens.NextToken( "Missing export command" );
- if ( token == "mesh" ) {
- type = WRITE_MESH;
- } else if ( token == "anim" ) {
- type = WRITE_ANIM;
- } else if ( token == "camera" ) {
- type = WRITE_CAMERA;
- } else {
- MayaError( "Unknown export command '%s'", token.c_str() );
- }
- src = tokens.NextToken( "Missing source filename" );
- dest = src;
- for( token = tokens.NextToken(); token != ""; token = tokens.NextToken() ) {
- if ( token == "-force" ) {
- // skip
- } else if ( token == "-game" ) {
- // parse game name
- game = tokens.NextToken( "Expecting game name after -game" );
- } else if ( token == "-rename" ) {
- // parse joint to rename
- joints.from = tokens.NextToken( "Missing joint name for -rename. Usage: -rename [joint name] [new name]" );
- joints.to = tokens.NextToken( "Missing new name for -rename. Usage: -rename [joint name] [new name]" );
- renamejoints.Append( joints );
- } else if ( token == "-prefix" ) {
- prefix = tokens.NextToken( "Missing name for -prefix. Usage: -prefix [joint prefix]" );
- } else if ( token == "-parent" ) {
- // parse joint to reparent
- joints.from = tokens.NextToken( "Missing joint name for -parent. Usage: -parent [joint name] [new parent]" );
- joints.to = tokens.NextToken( "Missing new parent for -parent. Usage: -parent [joint name] [new parent]" );
- remapjoints.Append( joints );
- } else if ( !token.Icmp( "-sourcedir" ) ) {
- // parse source directory
- sourceDir = tokens.NextToken( "Missing filename for -sourcedir. Usage: -sourcedir [directory]" );
- } else if ( !token.Icmp( "-destdir" ) ) {
- // parse destination directory
- destDir = tokens.NextToken( "Missing filename for -destdir. Usage: -destdir [directory]" );
- } else if ( token == "-dest" ) {
- // parse destination filename
- dest = tokens.NextToken( "Missing filename for -dest. Usage: -dest [filename]" );
- } else if ( token == "-range" ) {
- // parse frame range to export
- token = tokens.NextToken( "Missing start frame for -range. Usage: -range [start frame] [end frame]" );
- startframe = atoi( token );
- token = tokens.NextToken( "Missing end frame for -range. Usage: -range [start frame] [end frame]" );
- endframe = atoi( token );
- if ( startframe > endframe ) {
- MayaError( "Start frame is greater than end frame." );
- }
- } else if ( !token.Icmp( "-cycleStart" ) ) {
- // parse start frame of cycle
- token = tokens.NextToken( "Missing cycle start frame for -cycleStart. Usage: -cycleStart [first frame of cycle]" );
- cycleStart = atoi( token );
- } else if ( token == "-scale" ) {
- // parse scale
- token = tokens.NextToken( "Missing scale amount for -scale. Usage: -scale [scale amount]" );
- scale = atof( token );
- } else if ( token == "-align" ) {
- // parse align joint
- align = tokens.NextToken( "Missing joint name for -align. Usage: -align [joint name]" );
- } else if ( token == "-rotate" ) {
- // parse angle rotation
- token = tokens.NextToken( "Missing value for -rotate. Usage: -rotate [yaw]" );
- rotate = -atof( token );
- } else if ( token == "-nomesh" ) {
- ignoreMeshes = true;
- } else if ( token == "-clearorigin" ) {
- clearOrigin = true;
- clearOriginAxis = true;
- } else if ( token == "-clearoriginaxis" ) {
- clearOriginAxis = true;
- } else if ( token == "-ignorescale" ) {
- ignoreScale = true;
- } else if ( token == "-xyzprecision" ) {
- // parse quaternion precision
- token = tokens.NextToken( "Missing value for -xyzprecision. Usage: -xyzprecision [precision]" );
- xyzPrecision = atof( token );
- if ( xyzPrecision < 0.0f ) {
- MayaError( "Invalid value for -xyzprecision. Must be >= 0" );
- }
- } else if ( token == "-quatprecision" ) {
- // parse quaternion precision
- token = tokens.NextToken( "Missing value for -quatprecision. Usage: -quatprecision [precision]" );
- quatPrecision = atof( token );
- if ( quatPrecision < 0.0f ) {
- MayaError( "Invalid value for -quatprecision. Must be >= 0" );
- }
-
- } else if ( token == "-jointthreshold" ) {
- // parse joint threshold
- token = tokens.NextToken( "Missing weight for -jointthreshold. Usage: -jointthreshold [minimum joint weight]" );
- jointThreshold = atof( token );
- } else if ( token == "-skipmesh" ) {
- token = tokens.NextToken( "Missing name for -skipmesh. Usage: -skipmesh [name of mesh to skip]" );
- skipmeshes.AddUnique( token );
- } else if ( token == "-keepmesh" ) {
- token = tokens.NextToken( "Missing name for -keepmesh. Usage: -keepmesh [name of mesh to keep]" );
- keepmeshes.AddUnique( token );
- } else if ( token == "-jointgroup" ) {
- token = tokens.NextToken( "Missing name for -jointgroup. Usage: -jointgroup [group name] [joint1] [joint2]...[joint n]" );
- group = groups.Ptr();
- for( i = 0; i < groups.Num(); i++, group++ ) {
- if ( group->name == token ) {
- break;
- }
- }
- if ( i >= groups.Num() ) {
- // create a new group
- group = &groups.Alloc();
- group->name = token;
- }
- while( tokens.TokenAvailable() ) {
- token = tokens.NextToken();
- if ( token[ 0 ] == '-' ) {
- tokens.UnGetToken();
- break;
- }
- group->joints.AddUnique( token );
- }
- } else if ( token == "-group" ) {
- // add the list of groups to export (these don't affect the hierarchy)
- while( tokens.TokenAvailable() ) {
- token = tokens.NextToken();
- if ( token[ 0 ] == '-' ) {
- tokens.UnGetToken();
- break;
- }
- group = groups.Ptr();
- for( i = 0; i < groups.Num(); i++, group++ ) {
- if ( group->name == token ) {
- break;
- }
- }
- if ( i >= groups.Num() ) {
- MayaError( "Unknown group '%s'", token.c_str() );
- }
- exportgroups.AddUnique( group );
- }
- } else if ( token == "-keep" ) {
- // add joints that are kept whether they're used by a mesh or not
- while( tokens.TokenAvailable() ) {
- token = tokens.NextToken();
- if ( token[ 0 ] == '-' ) {
- tokens.UnGetToken();
- break;
- }
- keepjoints.AddUnique( token );
- }
- } else {
- MayaError( "Unknown option '%s'", token.c_str() );
- }
- }
- token = src;
- src = ospath;
- src.BackSlashesToSlashes();
- src.AppendPath( sourceDir );
- src.AppendPath( token );
- token = dest;
- dest = ospath;
- dest.BackSlashesToSlashes();
- dest.AppendPath( destDir );
- dest.AppendPath( token );
- // Maya only accepts unix style path separators
- src.BackSlashesToSlashes();
- dest.BackSlashesToSlashes();
- if ( skipmeshes.Num() && keepmeshes.Num() ) {
- MayaError( "Can't use -keepmesh and -skipmesh together." );
- }
- }
- /*
- ====================
- idExportOptions::jointInExportGroup
- ====================
- */
- bool idExportOptions::jointInExportGroup( const char *jointname ) {
- int i;
- int j;
- idAnimGroup *group;
- if ( !exportgroups.Num() ) {
- // if we don't have any groups specified as export then export every joint
- return true;
- }
- // search through all exported groups to see if this joint is exported
- for( i = 0; i < exportgroups.Num(); i++ ) {
- group = exportgroups[ i ];
- for( j = 0; j < group->joints.Num(); j++ ) {
- if ( group->joints[ j ] == jointname ) {
- return true;
- }
- }
- }
- return false;
- }
- /*
- ==============================================================================
- idExportJoint
- ==============================================================================
- */
- idExportJoint::idExportJoint() {
- index = 0;
- exportNum = 0;
- mayaNode.SetOwner( this );
- exportNode.SetOwner( this );
- dagnode = NULL;
-
- t = vec3_zero;
- wm = mat3_default;
- bindpos = vec3_zero;
- bindmat = mat3_default;
- keep = false;
- scale = 1.0f;
- invscale = 1.0f;
- animBits = 0;
- firstComponent = 0;
- baseFrame.q.Set( 0.0f, 0.0f, 0.0f );
- baseFrame.t.Zero();
- }
- idExportJoint &idExportJoint::operator=( const idExportJoint &other ) {
- name = other.name;
- realname = other.realname;
- longname = other.longname;
- index = other.index;
- exportNum = other.exportNum;
- keep = other.keep;
-
- scale = other.scale;
- invscale = other.invscale;
-
- dagnode = other.dagnode;
- mayaNode = other.mayaNode;
- exportNode = other.exportNode;
-
- t = other.t;
- idt = other.idt;
- wm = other.wm;
- idwm = other.idwm;
- bindpos = other.bindpos;
- bindmat = other.bindmat;
- animBits = other.animBits;
- firstComponent = other.firstComponent;
- baseFrame = other.baseFrame;
- mayaNode.SetOwner( this );
- exportNode.SetOwner( this );
- return *this;
- }
- /*
- ==============================================================================
- idExportMesh
- ==============================================================================
- */
- void idExportMesh::ShareVerts( void ) {
- int i, j, k;
- exportVertex_t vert;
- idList<exportVertex_t> v;
- v = verts;
- verts.Clear();
- for( i = 0; i < tris.Num(); i++ ) {
- for( j = 0; j < 3; j++ ) {
- vert = v[ tris[ i ].indexes[ j ] ];
- vert.texCoords[ 0 ] = uv[ i ].uv[ j ][ 0 ];
- vert.texCoords[ 1 ] = 1.0f - uv[ i ].uv[ j ][ 1 ];
- for( k = 0; k < verts.Num(); k++ ) {
- if ( vert.numWeights != verts[ k ].numWeights ) {
- continue;
- }
- if ( vert.startweight != verts[ k ].startweight ) {
- continue;
- }
- if ( !vert.pos.Compare( verts[ k ].pos, SLOP_VERTEX ) ) {
- continue;
- }
- if ( !vert.texCoords.Compare( verts[ k ].texCoords, SLOP_TEXCOORD ) ) {
- continue;
- }
- break;
- }
- if ( k < verts.Num() ) {
- tris[ i ].indexes[ j ] = k;
- } else {
- tris[ i ].indexes[ j ] = verts.Append( vert );
- }
- }
- }
- }
- void idExportMesh::Merge( idExportMesh *mesh ) {
- int i;
- int numverts;
- int numtris;
- int numweights;
- int numuvs;
- // merge name
- sprintf( name, "%s, %s", name.c_str(), mesh->name.c_str() );
- // merge verts
- numverts = verts.Num();
- verts.SetNum( numverts + mesh->verts.Num() );
- for( i = 0; i < mesh->verts.Num(); i++ ) {
- verts[ numverts + i ] = mesh->verts[ i ];
- verts[ numverts + i ].startweight += weights.Num();
- }
- // merge triangles
- numtris = tris.Num();
- tris.SetNum( numtris + mesh->tris.Num() );
- for( i = 0; i < mesh->tris.Num(); i++ ) {
- tris[ numtris + i ].indexes[ 0 ] = mesh->tris[ i ].indexes[ 0 ] + numverts;
- tris[ numtris + i ].indexes[ 1 ] = mesh->tris[ i ].indexes[ 1 ] + numverts;
- tris[ numtris + i ].indexes[ 2 ] = mesh->tris[ i ].indexes[ 2 ] + numverts;
- }
- // merge weights
- numweights = weights.Num();
- weights.SetNum( numweights + mesh->weights.Num() );
- for( i = 0; i < mesh->weights.Num(); i++ ) {
- weights[ numweights + i ] = mesh->weights[ i ];
- }
- // merge uvs
- numuvs = uv.Num();
- uv .SetNum( numuvs + mesh->uv.Num() );
- for( i = 0; i < mesh->uv.Num(); i++ ) {
- uv[ numuvs + i ] = mesh->uv[ i ];
- }
- }
- void idExportMesh::GetBounds( idBounds &bounds ) const {
- int i;
- int j;
- idVec3 pos;
- const exportWeight_t *weight;
- const exportVertex_t *vert;
- bounds.Clear();
- weight = weights.Ptr();
- vert = verts.Ptr();
- for( i = 0; i < verts.Num(); i++, vert++ ) {
- pos.Zero();
- weight = &weights[ vert->startweight ];
- for( j = 0; j < vert->numWeights; j++, weight++ ) {
- pos += weight->jointWeight * ( weight->joint->idwm * weight->offset + weight->joint->idt );
- }
- bounds.AddPoint( pos );
- }
- }
- /*
- ==============================================================================
- idExportModel
- ==============================================================================
- */
- /*
- ====================
- idExportModel::idExportModel
- ====================
- */
- ID_INLINE idExportModel::idExportModel() {
- export_joints = 0;
- skipjoints = 0;
- frameRate = 24;
- numFrames = 0;
- exportOrigin = NULL;
- }
- /*
- ====================
- idExportModel::~idExportModel
- ====================
- */
- ID_INLINE idExportModel::~idExportModel() {
- meshes.DeleteContents( true );
- }
- idExportJoint *idExportModel::FindJointReal( const char *name ) {
- idExportJoint *joint;
- int i;
- joint = joints.Ptr();
- for( i = 0; i < joints.Num(); i++, joint++ ) {
- if ( joint->realname == name ) {
- return joint;
- }
- }
- return NULL;
- }
- idExportJoint *idExportModel::FindJoint( const char *name ) {
- idExportJoint *joint;
- int i;
- joint = joints.Ptr();
- for( i = 0; i < joints.Num(); i++, joint++ ) {
- if ( joint->name == name ) {
- return joint;
- }
- }
- return NULL;
- }
- bool idExportModel::WriteMesh( const char *filename, idExportOptions &options ) {
- int i, j;
- int numMeshes;
- idExportMesh *mesh;
- idExportJoint *joint;
- idExportJoint *parent;
- idExportJoint *sibling;
- FILE *file;
- const char *parentName;
- int parentNum;
- idList<idExportJoint *> jointList;
- file = fopen( filename, "w" );
- if ( !file ) {
- return false;
- }
- for( joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- jointList.Append( joint );
- }
- for( i = 0; i < jointList.Num(); i++ ) {
- joint = jointList[ i ];
- sibling = joint->exportNode.GetSibling();
- while( sibling ) {
- if ( idStr::Cmp( joint->name, sibling->name ) > 0 ) {
- joint->exportNode.MakeSiblingAfter( sibling->exportNode );
- sibling = joint->exportNode.GetSibling();
- } else {
- sibling = sibling->exportNode.GetSibling();
- }
- }
- }
- jointList.Clear();
- for( joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- joint->exportNum = jointList.Append( joint );
- }
- numMeshes = 0;
- if ( !options.ignoreMeshes ) {
- for( i = 0; i < meshes.Num(); i++ ) {
- if ( meshes[ i ]->keep ) {
- numMeshes++;
- }
- }
- }
- // write version info
- WriteFloatString( file, MD5_VERSION_STRING " %d\n", MD5_VERSION );
- WriteFloatString( file, "commandline \"%s\"\n\n", options.commandLine.c_str() );
- // write joints
- WriteFloatString( file, "numJoints %d\n", jointList.Num() );
- WriteFloatString( file, "numMeshes %d\n\n", numMeshes );
- WriteFloatString( file, "joints {\n" );
- for( i = 0; i < jointList.Num(); i++ ) {
- joint = jointList[ i ];
- parent = joint->exportNode.GetParent();
- if ( parent ) {
- parentNum = parent->exportNum;
- parentName = parent->name.c_str();
- } else {
- parentNum = -1;
- parentName = "";
- }
- idCQuat bindQuat = joint->bindmat.ToQuat().ToCQuat();
- WriteFloatString( file, "\t\"%s\"\t%d ( %f %f %f ) ( %f %f %f )\t\t// %s\n", joint->name.c_str(), parentNum,
- joint->bindpos.x, joint->bindpos.y, joint->bindpos.z, bindQuat[ 0 ], bindQuat[ 1 ], bindQuat[ 2 ], parentName );
- }
- WriteFloatString( file, "}\n" );
- // write meshes
- for( i = 0; i < meshes.Num(); i++ ) {
- mesh = meshes[ i ];
- if ( !mesh->keep ) {
- continue;
- }
- WriteFloatString( file, "\nmesh {\n" );
- WriteFloatString( file, "\t// meshes: %s\n", mesh->name.c_str() );
- WriteFloatString( file, "\tshader \"%s\"\n", mesh->shader.c_str() );
-
- WriteFloatString( file, "\n\tnumverts %d\n", mesh->verts.Num() );
- for( j = 0; j < mesh->verts.Num(); j++ ) {
- WriteFloatString( file, "\tvert %d ( %f %f ) %d %d\n", j, mesh->verts[ j ].texCoords[ 0 ], mesh->verts[ j ].texCoords[ 1 ],
- mesh->verts[ j ].startweight, mesh->verts[ j ].numWeights );
- }
- WriteFloatString( file, "\n\tnumtris %d\n", mesh->tris.Num() );
- for( j = 0; j < mesh->tris.Num(); j++ ) {
- WriteFloatString( file, "\ttri %d %d %d %d\n", j, mesh->tris[ j ].indexes[ 2 ], mesh->tris[ j ].indexes[ 1 ], mesh->tris[ j ].indexes[ 0 ] );
- }
- WriteFloatString( file, "\n\tnumweights %d\n", mesh->weights.Num() );
- for( j = 0; j < mesh->weights.Num(); j++ ) {
- exportWeight_t *weight;
- weight = &mesh->weights[ j ];
- WriteFloatString( file, "\tweight %d %d %f ( %f %f %f )\n", j,
- weight->joint->exportNum, weight->jointWeight, weight->offset.x, weight->offset.y, weight->offset.z );
- }
- WriteFloatString( file, "}\n" );
- }
- fclose( file );
- return true;
- }
- bool idExportModel::WriteAnim( const char *filename, idExportOptions &options ) {
- int i, j;
- idExportJoint *joint;
- idExportJoint *parent;
- idExportJoint *sibling;
- jointFrame_t *frame;
- FILE *file;
- int numAnimatedComponents;
- idList<idExportJoint *> jointList;
- file = fopen( filename, "w" );
- if ( !file ) {
- return false;
- }
- for( joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- jointList.Append( joint );
- }
- for( i = 0; i < jointList.Num(); i++ ) {
- joint = jointList[ i ];
- sibling = joint->exportNode.GetSibling();
- while( sibling ) {
- if ( idStr::Cmp( joint->name, sibling->name ) > 0 ) {
- joint->exportNode.MakeSiblingAfter( sibling->exportNode );
- sibling = joint->exportNode.GetSibling();
- } else {
- sibling = sibling->exportNode.GetSibling();
- }
- }
- }
- jointList.Clear();
- for( joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- joint->exportNum = jointList.Append( joint );
- }
- numAnimatedComponents = 0;
- for( i = 0; i < jointList.Num(); i++ ) {
- joint = jointList[ i ];
- joint->exportNum = i;
- joint->baseFrame = frames[ 0 ][ joint->index ];
- joint->animBits = 0;
- for( j = 1; j < numFrames; j++ ) {
- frame = &frames[ j ][ joint->index ];
- if ( fabs( frame->t[ 0 ] - joint->baseFrame.t[ 0 ] ) > options.xyzPrecision ) {
- joint->animBits |= ANIM_TX;
- }
- if ( fabs( frame->t[ 1 ] - joint->baseFrame.t[ 1 ] ) > options.xyzPrecision ) {
- joint->animBits |= ANIM_TY;
- }
- if ( fabs( frame->t[ 2 ] - joint->baseFrame.t[ 2 ] ) > options.xyzPrecision ) {
- joint->animBits |= ANIM_TZ;
- }
- if ( fabs( frame->q[ 0 ] - joint->baseFrame.q[ 0 ] ) > options.quatPrecision ) {
- joint->animBits |= ANIM_QX;
- }
- if ( fabs( frame->q[ 1 ] - joint->baseFrame.q[ 1 ] ) > options.quatPrecision ) {
- joint->animBits |= ANIM_QY;
- }
- if ( fabs( frame->q[ 2 ] - joint->baseFrame.q[ 2 ] ) > options.quatPrecision ) {
- joint->animBits |= ANIM_QZ;
- }
- if ( ( joint->animBits & 63 ) == 63 ) {
- break;
- }
- }
- if ( joint->animBits ) {
- joint->firstComponent = numAnimatedComponents;
- for( j = 0; j < 6; j++ ) {
- if ( joint->animBits & BIT( j ) ) {
- numAnimatedComponents++;
- }
- }
- }
- }
- // write version info
- WriteFloatString( file, MD5_VERSION_STRING " %d\n", MD5_VERSION );
- WriteFloatString( file, "commandline \"%s\"\n\n", options.commandLine.c_str() );
- WriteFloatString( file, "numFrames %d\n", numFrames );
- WriteFloatString( file, "numJoints %d\n", jointList.Num() );
- WriteFloatString( file, "frameRate %d\n", frameRate );
- WriteFloatString( file, "numAnimatedComponents %d\n", numAnimatedComponents );
-
- // write out the hierarchy
- WriteFloatString( file, "\nhierarchy {\n" );
- for( i = 0; i < jointList.Num(); i++ ) {
- joint = jointList[ i ];
- parent = joint->exportNode.GetParent();
- if ( parent ) {
- WriteFloatString( file, "\t\"%s\"\t%d %d %d\t// %s", joint->name.c_str(), parent->exportNum, joint->animBits, joint->firstComponent, parent->name.c_str() );
- } else {
- WriteFloatString( file, "\t\"%s\"\t-1 %d %d\t//", joint->name.c_str(), joint->animBits, joint->firstComponent );
- }
- if ( !joint->animBits ) {
- WriteFloatString( file, "\n" );
- } else {
- WriteFloatString( file, " ( " );
- for( j = 0; j < 6; j++ ) {
- if ( joint->animBits & BIT( j ) ) {
- WriteFloatString( file, "%s ", componentNames[ j ] );
- }
- }
- WriteFloatString( file, ")\n" );
- }
- }
- WriteFloatString( file, "}\n" );
- // write the frame bounds
- WriteFloatString( file, "\nbounds {\n" );
- for( i = 0; i < numFrames; i++ ) {
- WriteFloatString( file, "\t( %f %f %f ) ( %f %f %f )\n", bounds[ i ][ 0 ].x, bounds[ i ][ 0 ].y, bounds[ i ][ 0 ].z, bounds[ i ][ 1 ].x, bounds[ i ][ 1 ].y, bounds[ i ][ 1 ].z );
- }
- WriteFloatString( file, "}\n" );
- // write the base frame
- WriteFloatString( file, "\nbaseframe {\n" );
- for( i = 0; i < jointList.Num(); i++ ) {
- joint = jointList[ i ];
- WriteFloatString( file, "\t( %f %f %f ) ( %f %f %f )\n", joint->baseFrame.t[ 0 ], joint->baseFrame.t[ 1 ], joint->baseFrame.t[ 2 ],
- joint->baseFrame.q[ 0 ], joint->baseFrame.q[ 1 ], joint->baseFrame.q[ 2 ] );
- }
- WriteFloatString( file, "}\n" );
- // write the frames
- for( i = 0; i < numFrames; i++ ) {
- WriteFloatString( file, "\nframe %d {\n", i );
- for( j = 0; j < jointList.Num(); j++ ) {
- joint = jointList[ j ];
- frame = &frames[ i ][ joint->index ];
- if ( joint->animBits ) {
- WriteFloatString( file, "\t" );
- if ( joint->animBits & ANIM_TX ) {
- WriteFloatString( file, " %f", frame->t[ 0 ] );
- }
- if ( joint->animBits & ANIM_TY ) {
- WriteFloatString( file, " %f", frame->t[ 1 ] );
- }
- if ( joint->animBits & ANIM_TZ ) {
- WriteFloatString( file, " %f", frame->t[ 2 ] );
- }
- if ( joint->animBits & ANIM_QX ) {
- WriteFloatString( file, " %f", frame->q[ 0 ] );
- }
- if ( joint->animBits & ANIM_QY ) {
- WriteFloatString( file, " %f", frame->q[ 1 ] );
- }
- if ( joint->animBits & ANIM_QZ ) {
- WriteFloatString( file, " %f", frame->q[ 2 ] );
- }
- WriteFloatString( file, "\n" );
- }
- }
- WriteFloatString( file, "}\n" );
- }
- fclose( file );
- return true;
- }
- bool idExportModel::WriteCamera( const char *filename, idExportOptions &options ) {
- int i;
- FILE *file;
- file = fopen( filename, "w" );
- if ( !file ) {
- return false;
- }
- // write version info
- WriteFloatString( file, MD5_VERSION_STRING " %d\n", MD5_VERSION );
- WriteFloatString( file, "commandline \"%s\"\n\n", options.commandLine.c_str() );
- WriteFloatString( file, "numFrames %d\n", camera.Num() );
- WriteFloatString( file, "frameRate %d\n", frameRate );
- WriteFloatString( file, "numCuts %d\n", cameraCuts.Num() );
-
- // write out the cuts
- WriteFloatString( file, "\ncuts {\n" );
- for( i = 0; i < cameraCuts.Num(); i++ ) {
- WriteFloatString( file, "\t%d\n", cameraCuts[ i ] );
- }
- WriteFloatString( file, "}\n" );
- // write out the frames
- WriteFloatString( file, "\ncamera {\n" );
- cameraFrame_t *frame = camera.Ptr();
- for( i = 0; i < camera.Num(); i++, frame++ ) {
- WriteFloatString( file, "\t( %f %f %f ) ( %f %f %f ) %f\n", frame->t.x, frame->t.y, frame->t.z, frame->q[ 0 ], frame->q[ 1 ], frame->q[ 2 ], frame->fov );
- }
- WriteFloatString( file, "}\n" );
- fclose( file );
- return true;
- }
- /*
- ==============================================================================
- Maya
- ==============================================================================
- */
- /*
- ===============
- idMayaExport::~idMayaExport
- ===============
- */
- idMayaExport::~idMayaExport() {
- FreeDagNodes();
- // free up the file in Maya
- MFileIO::newFile( true );
- }
- /*
- ===============
- idMayaExport::TimeForFrame
- ===============
- */
- float idMayaExport::TimeForFrame( int num ) const {
- MTime time;
- // set time unit to 24 frames per second
- time.setUnit( MTime::kFilm );
- time.setValue( num );
- return time.as( MTime::kSeconds );
- }
- /*
- ===============
- idMayaExport::GetMayaFrameNum
- ===============
- */
- int idMayaExport::GetMayaFrameNum( int num ) const {
- int frameNum;
- if ( options.cycleStart > options.startframe ) {
- // in cycles, the last frame is a duplicate of the first frame, so with cycleStart we need to
- // duplicate one of the interior frames instead and chop off the first frame.
- frameNum = options.cycleStart + num;
- if ( frameNum > options.endframe ) {
- frameNum -= options.endframe - options.startframe;
- }
- if ( frameNum < options.startframe ) {
- frameNum = options.startframe + 1;
- }
- } else {
- frameNum = options.startframe + num;
- if ( frameNum > options.endframe ) {
- frameNum -= options.endframe + 1 - options.startframe;
- }
- if ( frameNum < options.startframe ) {
- frameNum = options.startframe;
- }
- }
- return frameNum;
- }
- /*
- ===============
- idMayaExport::SetFrame
- ===============
- */
- void idMayaExport::SetFrame( int num ) {
- MTime time;
- int frameNum;
- frameNum = GetMayaFrameNum( num );
- // set time unit to 24 frames per second
- time.setUnit( MTime::kFilm );
- time.setValue( frameNum );
- MGlobal::viewFrame( time );
- }
- /*
- ===============
- idMayaExport::PruneJoints
- ===============
- */
- void idMayaExport::PruneJoints( idStrList &keepjoints, idStr &prefix ) {
- int i;
- int j;
- idExportMesh *mesh;
- idExportJoint *joint;
- idExportJoint *joint2;
- idExportJoint *parent;
- int num_weights;
- // if we don't have any joints specified to keep, mark the ones used by the meshes as keep
- if ( !keepjoints.Num() && !prefix.Length() ) {
- if ( !model.meshes.Num() || options.ignoreMeshes ) {
- // export all joints
- joint = model.joints.Ptr();
- for( i = 0; i < model.joints.Num(); i++, joint++ ) {
- joint->keep = true;
- }
- } else {
- for( i = 0; i < model.meshes.Num(); i++, mesh++ ) {
- mesh = model.meshes[ i ];
- for( j = 0; j < mesh->weights.Num(); j++ ) {
- mesh->weights[ j ].joint->keep = true;
- }
- }
- }
- } else {
- // mark the joints to keep
- for( i = 0; i < keepjoints.Num(); i++ ) {
- joint = model.FindJoint( keepjoints[ i ] );
- if ( joint ) {
- joint->keep = true;
- }
- }
- // count valid meshes
- for( i = 0; i < model.meshes.Num(); i++ ) {
- mesh = model.meshes[ i ];
- num_weights = 0;
- for( j = 0; j < mesh->weights.Num(); j++ ) {
- if ( mesh->weights[ j ].joint->keep ) {
- num_weights++;
- } else if ( prefix.Length() && !mesh->weights[ j ].joint->realname.Cmpn( prefix, prefix.Length() ) ) {
- // keep the joint if it's used by the mesh and it has the right prefix
- mesh->weights[ j ].joint->keep = true;
- num_weights++;
- }
- }
- if ( num_weights != mesh->weights.Num() ) {
- mesh->keep = false;
- }
- }
- }
- // find all joints aren't exported and reparent joint's children
- model.export_joints = 0;
- joint = model.joints.Ptr();
- for( i = 0; i < model.joints.Num(); i++, joint++ ) {
- if ( !joint->keep ) {
- joint->exportNode.RemoveFromHierarchy();
- } else {
- joint->index = model.export_joints;
- model.export_joints++;
- // make sure we are parented to an exported joint
- for( parent = joint->exportNode.GetParent(); parent != NULL; parent = parent->exportNode.GetParent() ) {
- if ( parent->keep ) {
- break;
- }
- }
- if ( parent != NULL ) {
- joint->exportNode.ParentTo( parent->exportNode );
- } else {
- joint->exportNode.ParentTo( model.exportHead );
- }
- }
- }
- // check if we have any duplicate joint names
- for( joint = model.exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- if ( !joint->keep ) {
- MayaError( "Non-kept joint in export tree ('%s')", joint->name.c_str() );
- }
- for( joint2 = model.exportHead.GetNext(); joint2 != NULL; joint2 = joint2->exportNode.GetNext() ) {
- if ( ( joint2 != joint ) && ( joint2->name == joint->name ) ) {
- MayaError( "Two joints found with the same name ('%s')", joint->name.c_str() );
- }
- }
- }
- }
- /*
- ===============
- idMayaExport::FreeDagNodes
- ===============
- */
- void idMayaExport::FreeDagNodes( void ) {
- int i;
- for( i = 0; i < model.joints.Num(); i++ ) {
- delete model.joints[ i ].dagnode;
- model.joints[ i ].dagnode = NULL;
- }
- }
- /*
- ===============
- idMayaExport::GetBindPose
- ===============
- */
- void idMayaExport::GetBindPose( MObject &jointNode, idExportJoint *joint, float scale ) {
- MStatus status;
- MFnDependencyNode fnJoint( jointNode );
- MObject aBindPose = fnJoint.attribute( "bindPose", &status );
- joint->bindpos = vec3_zero;
- joint->bindmat = mat3_default;
- if ( MS::kSuccess == status ) {
- unsigned ii;
- unsigned jointIndex;
- unsigned connLength;
- MPlugArray connPlugs;
- MPlug pBindPose( jointNode, aBindPose );
- pBindPose.connectedTo( connPlugs, false, true );
- connLength = connPlugs.length();
- for( ii = 0; ii < connLength; ++ii ) {
- if ( connPlugs[ ii ].node().apiType() == MFn::kDagPose ) {
- MObject aMember = connPlugs[ ii ].attribute();
- MFnAttribute fnAttr( aMember );
- if ( fnAttr.name() == "worldMatrix" ) {
- jointIndex = connPlugs[ ii ].logicalIndex();
- MFnDependencyNode nDagPose( connPlugs[ ii ].node() );
- // construct plugs for this joint's world matrix
- MObject aWorldMatrix = nDagPose.attribute( "worldMatrix" );
- MPlug pWorldMatrix( connPlugs[ ii ].node(), aWorldMatrix );
- pWorldMatrix.selectAncestorLogicalIndex( jointIndex, aWorldMatrix );
- // get the world matrix data
- MObject worldMatrix;
- MStatus status = pWorldMatrix.getValue( worldMatrix );
- if ( MS::kSuccess != status ) {
- // Problem retrieving world matrix
- return;
- }
- MFnMatrixData dMatrix( worldMatrix );
- MMatrix wMatrix = dMatrix.matrix( &status );
- joint->bindmat = ConvertToIdSpace( idMat( wMatrix ) );
- joint->bindpos = ConvertToIdSpace( idVec( wMatrix ) ) * scale;
- if ( !options.ignoreScale ) {
- joint->bindpos *= joint->scale;
- } else {
- joint->bindmat[ 0 ].Normalize();
- joint->bindmat[ 1 ].Normalize();
- joint->bindmat[ 2 ].Normalize();
- }
- return;
- }
- }
- }
- }
- }
- /*
- ===============
- idMayaExport::GetLocalTransform
- ===============
- */
- void idMayaExport::GetLocalTransform( idExportJoint *joint, idVec3 &pos, idMat3 &mat ) {
- MStatus status;
- MDagPath dagPath;
- pos.Zero();
- mat.Identity();
- if ( !joint->dagnode ) {
- return;
- }
- status = joint->dagnode->getPath( dagPath );
- if ( !status ) {
- return;
- }
- MObject transformNode = dagPath.transform( &status );
- if ( !status && ( status.statusCode () == MStatus::kInvalidParameter ) ) {
- return;
- }
- MFnDagNode transform( transformNode, &status );
- if ( !status ) {
- return;
- }
- pos = idVec( transform.transformationMatrix() );
- mat = idMat( transform.transformationMatrix() );
- }
- /*
- ===============
- idMayaExport::GetWorldTransform
- ===============
- */
- void idMayaExport::GetWorldTransform( idExportJoint *joint, idVec3 &pos, idMat3 &mat, float scale ) {
- idExportJoint *parent;
- GetLocalTransform( joint, pos, mat );
- mat.OrthoNormalizeSelf();
- pos *= scale;
- parent = joint->mayaNode.GetParent();
- if ( parent ) {
- idVec3 parentpos;
- idMat3 parentmat;
- GetWorldTransform( parent, parentpos, parentmat, scale );
- pos = parentpos + ( parentmat * ( pos * parent->scale ) );
- mat = mat * parentmat;
- }
- }
- /*
- ===============
- idMayaExport::CreateJoints
- ===============
- */
- void idMayaExport::CreateJoints( float scale ) {
- int i;
- int j;
- idExportJoint *joint;
- idExportJoint *parent;
- MStatus status;
- MDagPath dagPath;
- MFnDagNode *parentNode;
- SetFrame( 0 );
- // create an initial list with all of the transformable nodes in the scene
- MItDag dagIterator( MItDag::kDepthFirst, MFn::kTransform, &status );
- for ( ; !dagIterator.isDone(); dagIterator.next() ) {
- status = dagIterator.getPath( dagPath );
- if ( !status ) {
- MayaError( "CreateJoints: MItDag::getPath failed (%s)", status.errorString().asChar() );
- continue;
- }
- joint = &model.joints.Alloc();
- joint->index = model.joints.Num() - 1;
- joint->dagnode = new MFnDagNode( dagPath, &status );
- if ( !status ) {
- MayaError( "CreateJoints: MFnDagNode constructor failed (%s)", status.errorString().asChar() );
- continue;
- }
- joint->name = joint->dagnode->name().asChar();
- joint->realname = joint->name;
- }
- // allocate an extra joint in case we need to add an origin later
- model.exportOrigin = &model.joints.Alloc();
- model.exportOrigin->index = model.joints.Num() - 1;
- // create scene hierarchy
- joint = model.joints.Ptr();
- for( i = 0; i < model.joints.Num(); i++, joint++ ) {
- if ( !joint->dagnode ) {
- continue;
- }
- joint->mayaNode.ParentTo( model.mayaHead );
- joint->exportNode.ParentTo( model.exportHead );
- parentNode = GetParent( joint->dagnode );
- if ( parentNode ) {
- // find the parent joint in our jointlist
- for( j = 0; j < model.joints.Num(); j++ ) {
- if ( !model.joints[ j ].dagnode ) {
- continue;
- }
- if ( model.joints[ j ].dagnode->name() == parentNode->name() ) {
- joint->mayaNode.ParentTo( model.joints[ j ].mayaNode );
- joint->exportNode.ParentTo( model.joints[ j ].exportNode );
- break;
- }
- }
- delete parentNode;
- }
-
- // create long name
- parent = joint->mayaNode.GetParent();
- if ( parent ) {
- joint->longname = parent->longname + "/" + joint->name;
- } else {
- joint->longname = joint->name;
- }
- // get the joint's scale
- GetLocalTransform( &model.joints[ i ], joint->t, joint->wm );
- joint->scale = joint->wm[ 0 ].Length();
- if ( parent ) {
- joint->scale *= parent->scale;
- if ( joint->scale != 0 ) {
- joint->invscale = 1.0f / joint->scale;
- } else {
- joint->invscale = 0;
- }
- }
- joint->dagnode->getPath( dagPath );
- GetBindPose( dagPath.node( &status ), joint, scale );
- }
- }
- /*
- ===============
- idMayaExport::RenameJoints
- ===============
- */
- void idMayaExport::RenameJoints( idList<idNamePair> &renamejoints, idStr &prefix ) {
- int i;
- idExportJoint *joint;
- // rename joints that match the prefix
- if ( prefix.Length() ) {
- joint = model.joints.Ptr();
- for( i = 0; i < model.joints.Num(); i++, joint++ ) {
- if ( !joint->name.Cmpn( prefix, prefix.Length() ) ) {
- // remove the prefix from the name
- joint->name = joint->name.Right( joint->name.Length() - prefix.Length() );
- }
- }
- }
- // rename joints if necessary
- for( i = 0; i < renamejoints.Num(); i++ ) {
- joint = model.FindJoint( renamejoints[ i ].from );
- if ( joint ) {
- joint->name = renamejoints[ i ].to;
- }
- }
- }
- /*
- ===============
- idMayaExport::RemapParents
- ===============
- */
- bool idMayaExport::RemapParents( idList<idNamePair> &remapjoints ) {
- int i;
- idExportJoint *joint;
- idExportJoint *parent;
- idExportJoint *origin;
- idExportJoint *sibling;
- for( i = 0; i < remapjoints.Num(); i++ ) {
- // find joint to reparent
- joint = model.FindJoint( remapjoints[ i ].from );
- if ( !joint ) {
- // couldn't find joint, fail
- MayaError( "Couldn't find joint '%s' to reparent\n", remapjoints[ i ].from.c_str() );
- }
- // find new parent joint
- parent = model.FindJoint( remapjoints[ i ].to );
- if ( !parent ) {
- // couldn't find parent, fail
- MayaError( "Couldn't find joint '%s' to be new parent for '%s'\n", remapjoints[ i ].to.c_str(), remapjoints[ i ].from.c_str() );
- }
- if ( parent->exportNode.ParentedBy( joint->exportNode ) ) {
- MayaError( "Joint '%s' is a child of joint '%s' and can't become the parent.", joint->name.c_str(), parent->name.c_str() );
- }
- joint->exportNode.ParentTo( parent->exportNode );
- }
- // if we have an origin, make it the first node in the export list, otherwise add one
- origin = model.FindJoint( "origin" );
- if ( !origin ) {
- origin = model.exportOrigin;
- origin->dagnode = NULL;
- origin->name = "origin";
- origin->realname = "origin";
- origin->bindmat.Identity();
- origin->bindpos.Zero();
- }
- origin->exportNode.ParentTo( model.exportHead );
- // force the joint to be kept
- origin->keep = true;
-
- // make all root joints children of the origin joint
- joint = model.exportHead.GetChild();
- while( joint ) {
- sibling = joint->exportNode.GetSibling();
- if ( joint != origin ) {
- joint->exportNode.ParentTo( origin->exportNode );
- }
- joint = sibling;
- }
- return true;
- }
- /*
- ===============
- idMayaExport::FindShader
- Find the shading node for the given shading group set node.
- ===============
- */
- MObject idMayaExport::FindShader( MObject& setNode ) {
- MStatus status;
- MFnDependencyNode fnNode( setNode );
- MPlug shaderPlug;
-
- shaderPlug = fnNode.findPlug( "surfaceShader" );
- if ( !shaderPlug.isNull() ) {
- MPlugArray connectedPlugs;
- bool asSrc = false;
- bool asDst = true;
- shaderPlug.connectedTo( connectedPlugs, asDst, asSrc, &status );
- if ( connectedPlugs.length() != 1 ) {
- MayaError( "FindShader: Error getting shader (%s)", status.errorString().asChar() );
- } else {
- return connectedPlugs[ 0 ].node();
- }
- }
-
- return MObject::kNullObj;
- }
- /*
- ===============
- idMayaExport::GetTextureForMesh
- Find the texture files that apply to the color of each polygon of
- a selected shape if the shape has its polygons organized into sets.
- ===============
- */
- void idMayaExport::GetTextureForMesh( idExportMesh *mesh, MFnDagNode &dagNode ) {
- MStatus status;
- MDagPath path;
- int i;
- int instanceNum;
-
- status = dagNode.getPath( path );
- if ( !status ) {
- return;
- }
- path.extendToShape();
- // If the shape is instanced then we need to determine which
- // instance this path refers to.
- //
- instanceNum = 0;
- if ( path.isInstanced() ) {
- instanceNum = path.instanceNumber();
- }
- // Get a list of all sets pertaining to the selected shape and the
- // members of those sets.
- //
- MFnMesh fnMesh( path );
- MObjectArray sets;
- MObjectArray comps;
- status = fnMesh.getConnectedSetsAndMembers( instanceNum, sets, comps, true );
- if ( !status ) {
- MayaError( "GetTextureForMesh: MFnMesh::getConnectedSetsAndMembers failed (%s)", status.errorString().asChar() );
- }
- // Loop through all the sets. If the set is a polygonal set, find the
- // shader attached to the and print out the texture file name for the
- // set along with the polygons in the set.
- //
- for ( i = 0; i < ( int )sets.length(); i++ ) {
- MObject set = sets[i];
- MObject comp = comps[i];
- MFnSet fnSet( set, &status );
- if ( status == MS::kFailure ) {
- MayaError( "GetTextureForMesh: MFnSet constructor failed (%s)", status.errorString().asChar() );
- continue;
- }
- // Make sure the set is a polygonal set. If not, continue.
- MItMeshPolygon piter(path, comp, &status);
- if (status == MS::kFailure) {
- continue;
- }
- // Find the texture that is applied to this set. First, get the
- // shading node connected to the set. Then, if there is an input
- // attribute called "color", search upstream from it for a texture
- // file node.
- //
- MObject shaderNode = FindShader( set );
- if ( shaderNode == MObject::kNullObj ) {
- continue;
- }
- MPlug colorPlug = MFnDependencyNode(shaderNode).findPlug("color", &status);
- if ( status == MS::kFailure ) {
- continue;
- }
- MItDependencyGraph dgIt(colorPlug, MFn::kFileTexture,
- MItDependencyGraph::kUpstream,
- MItDependencyGraph::kBreadthFirst,
- MItDependencyGraph::kNodeLevel,
- &status);
- if ( status == MS::kFailure ) {
- continue;
- }
-
- dgIt.disablePruningOnFilter();
- // If no texture file node was found, just continue.
- //
- if ( dgIt.isDone() ) {
- continue;
- }
-
- // Print out the texture node name and texture file that it references.
- //
- MObject textureNode = dgIt.thisNode();
- MPlug filenamePlug = MFnDependencyNode( textureNode ).findPlug( "fileTextureName" );
- MString textureName;
- filenamePlug.getValue( textureName );
- // remove the OS path and save it in the mesh
- OSPathToRelativePath( textureName.asChar(), mesh->shader, options.game );
- mesh->shader.StripFileExtension();
- return;
- }
- }
- /*
- ===============
- idMayaExport::CopyMesh
- ===============
- */
- idExportMesh *idMayaExport::CopyMesh( MFnSkinCluster &skinCluster, float scale ) {
- MStatus status;
- MObjectArray objarray;
- MObjectArray outputarray;
- int nGeom;
- int i, j, k;
- idExportMesh *mesh;
- float uv_u, uv_v;
- idStr name, altname;
- int pos;
- status = skinCluster.getInputGeometry( objarray );
- if ( !status ) {
- MayaError( "CopyMesh: Error getting input geometry (%s)", status.errorString().asChar() );
- return NULL;
- }
- nGeom = objarray.length();
- for( i = 0; i < nGeom; i++ ) {
- MFnDagNode dagNode( objarray[ i ], &status );
- if ( !status ) {
- common->Printf( "CopyMesh: MFnDagNode Constructor failed (%s)", status.errorString().asChar() );
- continue;
- }
- MFnMesh fnmesh( objarray[ i ], &status );
- if ( !status ) {
- // object isn't an MFnMesh
- continue;
- }
- status = skinCluster.getOutputGeometry( outputarray );
- if ( !status ) {
- common->Printf( "CopyMesh: Error getting output geometry (%s)", status.errorString().asChar() );
- return NULL;
- }
- if ( outputarray.length() < 1 ) {
- return NULL;
- }
- name = fnmesh.name().asChar();
- if ( options.prefix.Length() ) {
- if ( !name.Cmpn( options.prefix, options.prefix.Length() ) ) {
- // remove the prefix from the name
- name = name.Right( name.Length() - options.prefix.Length() );
- } else {
- // name doesn't match prefix, so don't use this mesh
- //return NULL;
- }
- }
- pos = name.Find( "ShapeOrig" );
- if ( pos >= 0 ) {
- name.CapLength( pos );
- }
- MFnDagNode dagNode2( outputarray[ 0 ], &status );
- if ( !status ) {
- common->Printf( "CopyMesh: MFnDagNode Constructor failed (%s)", status.errorString().asChar() );
- continue;
- }
- altname = name;
- MObject parent = fnmesh.parent( 0, &status );
- if ( status ) {
- MFnDagNode parentNode( parent, &status );
- if ( status ) {
- altname = parentNode.name().asChar();
- }
- }
- name.StripLeadingOnce( options.prefix );
- altname.StripLeadingOnce( options.prefix );
- if ( options.keepmeshes.Num() ) {
- if ( !options.keepmeshes.Find( name ) && !options.keepmeshes.Find( altname ) ) {
- if ( altname != name ) {
- common->Printf( "Skipping mesh '%s' ('%s')\n", name.c_str(), altname.c_str() );
- } else {
- common->Printf( "Skipping mesh '%s'\n", name.c_str() );
- }
- return NULL;
- }
- }
-
- if ( options.skipmeshes.Find( name ) || options.skipmeshes.Find( altname ) ) {
- common->Printf( "Skipping mesh '%s' ('%s')\n", name.c_str(), altname.c_str() );
- return NULL;
- }
- mesh = new idExportMesh();
- model.meshes.Append( mesh );
- if ( altname.Length() ) {
- mesh->name = altname;
- } else {
- mesh->name = name;
- }
- GetTextureForMesh( mesh, dagNode2 );
- int v = fnmesh.numVertices( &status );
- mesh->verts.SetNum( v );
- MFloatPointArray vertexArray;
- fnmesh.getPoints( vertexArray, MSpace::kPreTransform );
- for( j = 0; j < v; j++ ) {
- memset( &mesh->verts[ j ], 0, sizeof( mesh->verts[ j ] ) );
- mesh->verts[ j ].pos = ConvertToIdSpace( idVec( vertexArray[ j ] ) ) * scale;
- }
- MIntArray vertexList;
- int p;
-
- p = fnmesh.numPolygons( &status );
- mesh->tris.SetNum( p );
- mesh->uv.SetNum( p );
- MString setName;
-
- status = fnmesh.getCurrentUVSetName( setName );
- if ( !status ) {
- MayaError( "CopyMesh: MFnMesh::getCurrentUVSetName failed (%s)", status.errorString().asChar() );
- }
- for( j = 0; j < p; j++ ) {
- fnmesh.getPolygonVertices( j, vertexList );
- if ( vertexList.length() != 3 ) {
- MayaError( "CopyMesh: Too many vertices on a face (%d)\n", vertexList.length() );
- }
- for( k = 0; k < 3; k++ ) {
- mesh->tris[ j ].indexes[ k ] = vertexList[ k ];
-
- status = fnmesh.getPolygonUV( j, k, uv_u, uv_v, &setName );
- if ( !status ) {
- MayaError( "CopyMesh: MFnMesh::getPolygonUV failed (%s)", status.errorString().asChar() );
- }
-
- mesh->uv[ j ].uv[ k ][ 0 ] = uv_u;
- mesh->uv[ j ].uv[ k ][ 1 ] = uv_v;
- }
- }
- return mesh;
- }
- return NULL;
- }
- /*
- ===============
- idMayaExport::CreateMesh
- ===============
- */
- void idMayaExport::CreateMesh( float scale ) {
- size_t count;
- idExportMesh *mesh;
- MStatus status;
- exportWeight_t weight;
- unsigned int nGeoms;
- // Iterate through graph and search for skinCluster nodes
- MItDependencyNodes iter( MFn::kSkinClusterFilter );
- count = 0;
- for ( ; !iter.isDone(); iter.next() ) {
- MObject object = iter.item();
-
- count++;
-
- // For each skinCluster node, get the list of influence objects
- MFnSkinCluster skinCluster( object, &status );
- if ( !status ) {
- MayaError( "%s: Error getting skin cluster (%s)", object.apiTypeStr(), status.errorString().asChar() );
- }
- mesh = CopyMesh( skinCluster, scale );
- if ( !mesh ) {
- continue;
- }
- MDagPathArray infs;
- unsigned int nInfs = skinCluster.influenceObjects(infs, &status);
- if ( !status ) {
- MayaError( "Mesh '%s': Error getting influence objects (%s)", mesh->name.c_str(), status.errorString().asChar() );
- }
- if ( 0 == nInfs ) {
- MayaError( "Mesh '%s': No influence objects found", mesh->name.c_str() );
- }
-
- // loop through the geometries affected by this cluster
- nGeoms = skinCluster.numOutputConnections();
- for (size_t ii = 0; ii < nGeoms; ++ii) {
- unsigned int index = skinCluster.indexForOutputConnection(ii,&status);
- if ( !status ) {
- MayaError( "Mesh '%s': Error getting geometry index (%s)", mesh->name.c_str(), status.errorString().asChar() );
- }
- // get the dag path of the ii'th geometry
- MDagPath skinPath;
- status = skinCluster.getPathAtIndex(index,skinPath);
- if ( !status ) {
- MayaError( "Mesh '%s': Error getting geometry path (%s)", mesh->name.c_str(), status.errorString().asChar() );
- }
- // iterate through the components of this geometry
- MItGeometry gIter( skinPath );
- // print out the influence objects
- idList<idExportJoint *> joints;
- idExportJoint *joint;
- exportVertex_t *vert;
- joints.Resize( nInfs );
- for (size_t kk = 0; kk < nInfs; ++kk) {
- const char *c;
- MString s;
- s = infs[kk].partialPathName();
- c = s.asChar();
- joint = model.FindJointReal( c );
- if ( !joint ) {
- MayaError( "Mesh '%s': joint %s not found", mesh->name.c_str(), c );
- }
- joints.Append( joint );
- }
- for ( /* nothing */ ; !gIter.isDone(); gIter.next() ) {
- MObject comp = gIter.component( &status );
- if ( !status ) {
- MayaError( "Mesh '%s': Error getting component (%s)", mesh->name.c_str(), status.errorString().asChar() );
- }
- // Get the weights for this vertex (one per influence object)
- MFloatArray wts;
- unsigned infCount;
- status = skinCluster.getWeights(skinPath,comp,wts,infCount);
- if ( !status ) {
- MayaError( "Mesh '%s': Error getting weights (%s)", mesh->name.c_str(), status.errorString().asChar() );
- }
- if (0 == infCount) {
- MayaError( "Mesh '%s': Error: 0 influence objects.", mesh->name.c_str() );
- }
- int num = gIter.index();
- vert = &mesh->verts[ num ];
- vert->startweight = mesh->weights.Num();
- float totalweight = 0.0f;
- // copy the weight data for this vertex
- int numNonZeroWeights = 0;
- int jj;
- for ( jj = 0; jj < (int)infCount ; ++jj ) {
- float w = ( float )wts[ jj ];
- if ( w > 0.0f ) {
- numNonZeroWeights++;
- }
- if ( w > options.jointThreshold ) {
- weight.joint = joints[ jj ];
- weight.jointWeight = wts[ jj ];
-
- if ( !options.ignoreScale ) {
- weight.joint->bindmat.ProjectVector( vert->pos - ( weight.joint->bindpos * weight.joint->invscale ), weight.offset );
- weight.offset *= weight.joint->scale;
- } else {
- weight.joint->bindmat.ProjectVector( vert->pos - weight.joint->bindpos, weight.offset );
- }
- mesh->weights.Append( weight );
- totalweight += weight.jointWeight;
- }
- }
- vert->numWeights = mesh->weights.Num() - vert->startweight;
- if ( !vert->numWeights ) {
- if ( numNonZeroWeights ) {
- MayaError( "Error on mesh '%s': Vertex %d doesn't have any joint weights exceeding jointThreshold (%f).", mesh->name.c_str(), num, options.jointThreshold );
- } else {
- MayaError( "Error on mesh '%s': Vertex %d doesn't have any joint weights.", mesh->name.c_str(), num );
- }
- } else if ( !totalweight ) {
- MayaError( "Error on mesh '%s': Combined weight of 0 on vertex %d.", mesh->name.c_str(), num );
- }
- //if ( numNonZeroWeights ) {
- // common->Printf( "Mesh '%s': skipped %d out of %d weights on vertex %d\n", mesh->name.c_str(), numNonZeroWeights, numNonZeroWeights + vert->numWeights, num );
- //}
- // normalize the joint weights
- for( jj = 0; jj < vert->numWeights; jj++ ) {
- mesh->weights[ vert->startweight + jj ].jointWeight /= totalweight;
- }
- }
- break;
- }
- }
- if ( !count && !options.ignoreMeshes ) {
- MayaError( "CreateMesh: No skinClusters found in this scene.\n" );
- }
- }
- /*
- ===============
- idMayaExport::CombineMeshes
- combine surfaces with the same shader.
- ===============
- */
- void idMayaExport::CombineMeshes( void ) {
- int i, j;
- int count;
- idExportMesh *mesh;
- idExportMesh *combine;
- idList<idExportMesh *> oldmeshes;
- oldmeshes = model.meshes;
- model.meshes.Clear();
- count = 0;
- for( i = 0; i < oldmeshes.Num(); i++ ) {
- mesh = oldmeshes[ i ];
- if ( !mesh->keep ) {
- delete mesh;
- continue;
- }
- combine = NULL;
- for( j = 0; j < model.meshes.Num(); j++ ) {
- if ( model.meshes[ j ]->shader == mesh->shader ) {
- combine = model.meshes[ j ];
- break;
- }
- }
- if ( combine ) {
- combine->Merge( mesh );
- delete mesh;
- count++;
- } else {
- model.meshes.Append( mesh );
- }
- }
- // share verts
- for( i = 0; i < model.meshes.Num(); i++ ) {
- model.meshes[ i ]->ShareVerts();
- }
- common->Printf( "Merged %d meshes\n", count );
- }
- /*
- ===============
- idMayaExport::GetAlignment
- ===============
- */
- void idMayaExport::GetAlignment( idStr &alignName, idMat3 &align, float rotate, int startframe ) {
- idVec3 pos;
- idExportJoint *joint;
- idAngles ang( 0, rotate, 0 );
- idMat3 mat;
- align.Identity();
- if ( alignName.Length() ) {
- SetFrame( 0 );
- joint = model.FindJoint( alignName );
- if ( !joint ) {
- MayaError( "could not find joint '%s' to align model to.\n", alignName.c_str() );
- }
- // found it
- GetWorldTransform( joint, pos, mat, 1.0f );
- align[ 0 ][ 0 ] = mat[ 2 ][ 0 ];
- align[ 0 ][ 1 ] = -mat[ 2 ][ 2 ];
- align[ 0 ][ 2 ] = mat[ 2 ][ 1 ];
- align[ 1 ][ 0 ] = mat[ 0 ][ 0 ];
- align[ 1 ][ 1 ] = -mat[ 0 ][ 2 ];
- align[ 1 ][ 2 ] = mat[ 0 ][ 1 ];
- align[ 2 ][ 0 ] = mat[ 1 ][ 0 ];
- align[ 2 ][ 1 ] = -mat[ 1 ][ 2 ];
- align[ 2 ][ 2 ] = mat[ 1 ][ 1 ];
- if ( rotate ) {
- align *= ang.ToMat3();
- }
- } else if ( rotate ) {
- align = ang.ToMat3();
- }
- align.TransposeSelf();
- }
- /*
- ===============
- idMayaExport::GetObjectType
- return the type of the object
- ===============
- */
- const char *idMayaExport::GetObjectType( MObject object ) {
- if( object.isNull() ) {
- return "(Null)";
- }
- MStatus stat;
- MFnDependencyNode dgNode;
- MString typeName;
- stat = dgNode.setObject( object );
- typeName = dgNode.typeName( &stat );
- if( MS::kSuccess != stat ) {
- // can not get the type name of this object
- return "(Unknown)";
- }
- return typeName.asChar();
- }
- /*
- ===============
- idMayaExport::GetCameraFov
- ===============
- */
- float idMayaExport::GetCameraFov( idExportJoint *joint ) {
- int childCount;
- int j;
- double horiz;
- double focal;
- MStatus status;
- const char *n1, *n2;
- MFnDagNode *dagnode;
- float fov;
- dagnode = joint->dagnode;
- MObject cameraNode = dagnode->object();
- childCount = dagnode->childCount();
- fov = 90.0f;
- for( j = 0; j < childCount; j++ ) {
- MObject childNode = dagnode->child( j );
-
- n1 = GetObjectType( cameraNode );
- n2 = GetObjectType( childNode );
- if ( ( !strcmp( "transform", n1 ) ) && ( !strcmp( "camera", n2 ) ) ) {
- MFnCamera camera( childNode );
- focal = camera.focalLength();
- horiz = camera.horizontalFilmAperture();
- fov = RAD2DEG( 2 * atan( ( horiz * 0.5 ) / ( focal / 25.4 ) ) );
- break;
- }
- }
- return fov;
- }
- /*
- ===============
- idMayaExport::GetCameraFrame
- ===============
- */
- void idMayaExport::GetCameraFrame( idExportJoint *camera, idMat3 &align, cameraFrame_t *cam ) {
- idMat3 mat;
- idMat3 axis;
- idVec3 pos;
- // get the worldspace positions of the joint
- GetWorldTransform( camera, pos, axis, 1.0f );
-
- // convert to id coordinates
- cam->t = ConvertToIdSpace( pos ) * align;
- // correct the orientation for the game
- axis = ConvertToIdSpace( axis ) * align;
- mat[ 0 ] = -axis[ 2 ];
- mat[ 1 ] = -axis[ 0 ];
- mat[ 2 ] = axis[ 1 ];
- cam->q = mat.ToQuat().ToCQuat();
- // get it's fov
- cam->fov = GetCameraFov( camera );
- }
- /*
- ===============
- idMayaExport::CreateCameraAnim
- ===============
- */
- void idMayaExport::CreateCameraAnim( idMat3 &align ) {
- float start, end;
- MDagPath dagPath;
- int frameNum;
- short v;
- MStatus status;
- cameraFrame_t cam;
- idExportJoint *refCam;
- idExportJoint *camJoint;
- idStr currentCam;
- idStr newCam;
- MPlug plug;
- MFnEnumAttribute cameraAttribute;
- start = TimeForFrame( options.startframe );
- end = TimeForFrame( options.endframe );
- #if 0
- options.framerate = 60;
- model.numFrames = ( int )( ( end - start ) * ( float )options.framerate ) + 1;
- model.frameRate = options.framerate;
- #else
- model.numFrames = options.endframe + 1 - options.startframe;
- model.frameRate = options.framerate;
- #endif
- common->Printf( "start frame = %d\n end frame = %d\n", options.startframe, options.endframe );
- common->Printf( " start time = %f\n end time = %f\n total time = %f\n", start, end, end - start );
- if ( start > end ) {
- MayaError( "Start frame is greater than end frame." );
- }
- refCam = model.FindJoint( "refcam" );
- if ( refCam == NULL ) {
- currentCam = MAYA_DEFAULT_CAMERA;
- } else {
- MObject cameraNode = refCam->dagnode->object();
- MFnDependencyNode cameraDG( cameraNode, &status );
- if( MS::kSuccess != status ) {
- MayaError( "Can't find 'refcam' dependency node." );
- return;
- }
- MObject attr = cameraDG.attribute( MString( "Camera" ), &status );
- if( MS::kSuccess != status ) {
- MayaError( "Can't find 'Camera' attribute on 'refcam'." );
- return;
- }
- plug = MPlug( cameraNode, attr );
- status = cameraAttribute.setObject( attr );
- if( MS::kSuccess != status ) {
- MayaError( "Bad 'Camera' attribute on 'refcam'." );
- return;
- }
- model.camera.Clear();
- model.cameraCuts.Clear();
- SetFrame( 0 );
- status = plug.getValue( v );
- currentCam = cameraAttribute.fieldName( v, &status ).asChar();
- if( MS::kSuccess != status ) {
- MayaError( "Error getting camera name on frame %d", GetMayaFrameNum( 0 ) );
- }
- }
- camJoint = model.FindJoint( currentCam );
- if ( !camJoint ) {
- MayaError( "Couldn't find camera '%s'", currentCam.c_str() );
- }
- for( frameNum = 0; frameNum < model.numFrames; frameNum++ ) {
- common->Printf( "\rFrame %d/%d...", options.startframe + frameNum, options.endframe );
- #if 0
- MTime time;
- time.setUnit( MTime::kSeconds );
- time.setValue( start + ( ( float )frameNum / ( float )options.framerate ) );
- MGlobal::viewFrame( time );
- #else
- SetFrame( frameNum );
- #endif
- // get the position for this frame
- GetCameraFrame( camJoint, align, &model.camera.Alloc() );
- if ( refCam != NULL ) {
- status = plug.getValue( v );
- newCam = cameraAttribute.fieldName( v, &status ).asChar();
- if( MS::kSuccess != status ) {
- MayaError( "Error getting camera name on frame %d", GetMayaFrameNum( frameNum ) );
- }
- if ( newCam != currentCam ) {
- // place a cut at our last frame
- model.cameraCuts.Append( model.camera.Num() - 1 );
- currentCam = newCam;
- camJoint = model.FindJoint( currentCam );
- if ( !camJoint ) {
- MayaError( "Couldn't find camera '%s'", currentCam.c_str() );
- }
- // get the position for this frame
- GetCameraFrame( camJoint, align, &model.camera.Alloc() );
- }
- }
- }
- common->Printf( "\n" );
- }
- /*
- ===============
- idMayaExport::GetDefaultPose
- ===============
- */
- void idMayaExport::GetDefaultPose( idMat3 &align ) {
- float start;
- MDagPath dagPath;
- idMat3 jointaxis;
- idVec3 jointpos;
- idExportJoint *joint, *parent;
- idBounds bnds;
- idBounds meshBounds;
- idList<jointFrame_t> frame;
- start = TimeForFrame( options.startframe );
- common->Printf( "default pose frame = %d\n", options.startframe );
- common->Printf( " default pose time = %f\n", start );
- frame.SetNum( model.joints.Num() );
- SetFrame( 0 );
- // convert joints into local coordinates and save in channels
- for( joint = model.exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- if ( !joint->dagnode ) {
- // custom origin joint
- joint->idwm.Identity();
- joint->idt.Zero();
- frame[ joint->index ].t.Zero();
- frame[ joint->index ].q.Set( 0.0f, 0.0f, 0.0f );
- continue;
- }
- // get the worldspace positions of the joint
- GetWorldTransform( joint, jointpos, jointaxis, options.scale );
-
- // convert to id coordinates
- jointaxis = ConvertToIdSpace( jointaxis ) * align;
- jointpos = ConvertToIdSpace( jointpos ) * align;
- // save worldspace position of joint for children
- joint->idwm = jointaxis;
- joint->idt = jointpos;
- parent = joint->exportNode.GetParent();
- if ( parent ) {
- // convert to local coordinates
- jointpos = ( jointpos - parent->idt ) * parent->idwm.Transpose();
- jointaxis = jointaxis * parent->idwm.Transpose();
- } else if ( joint->name == "origin" ) {
- if ( options.clearOrigin ) {
- jointpos.Zero();
- }
- if ( options.clearOriginAxis ) {
- jointaxis.Identity();
- }
- }
- frame[ joint->index ].t = jointpos;
- frame[ joint->index ].q = jointaxis.ToQuat().ToCQuat();
- }
- // relocate origin to start at 0, 0, 0 for first frame
- joint = model.FindJoint( "origin" );
- if ( joint ) {
- frame[ joint->index ].t.Zero();
- }
- // transform the hierarchy
- for( joint = model.exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- jointpos = frame[ joint->index ].t;
- jointaxis = frame[ joint->index ].q.ToQuat().ToMat3();
- parent = joint->exportNode.GetParent();
- if ( parent ) {
- joint->idwm = jointaxis * parent->idwm;
- joint->idt = parent->idt + jointpos * parent->idwm;
- } else {
- joint->idwm = jointaxis;
- joint->idt = jointpos;
- }
- joint->bindmat = joint->idwm;
- joint->bindpos = joint->idt;
- }
- common->Printf( "\n" );
- }
- /*
- ===============
- idMayaExport::CreateAnimation
- ===============
- */
- void idMayaExport::CreateAnimation( idMat3 &align ) {
- int i;
- float start, end;
- MDagPath dagPath;
- idMat3 jointaxis;
- idVec3 jointpos;
- int frameNum;
- idExportJoint *joint, *parent;
- idBounds bnds;
- idBounds meshBounds;
- jointFrame_t *frame;
- int cycleStart;
- idVec3 totalDelta;
- idList<jointFrame_t> copyFrames;
- start = TimeForFrame( options.startframe );
- end = TimeForFrame( options.endframe );
- model.numFrames = options.endframe + 1 - options.startframe;
- model.frameRate = options.framerate;
- common->Printf( "start frame = %d\n end frame = %d\n", options.startframe, options.endframe );
- common->Printf( " start time = %f\n end time = %f\n total time = %f\n", start, end, end - start );
- if ( start > end ) {
- MayaError( "Start frame is greater than end frame." );
- }
- model.bounds.SetNum( model.numFrames );
- model.jointFrames.SetNum( model.numFrames * model.joints.Num() );
- model.frames.SetNum( model.numFrames );
- for( i = 0; i < model.numFrames; i++ ) {
- model.frames[ i ] = &model.jointFrames[ model.joints.Num() * i ];
- }
- // *sigh*. cyclestart doesn't work nicely with the anims.
- // may just want to not do it in SetTime anymore.
- cycleStart = options.cycleStart;
- options.cycleStart = options.startframe;
- for( frameNum = 0; frameNum < model.numFrames; frameNum++ ) {
- common->Printf( "\rFrame %d/%d...", options.startframe + frameNum, options.endframe );
- frame = model.frames[ frameNum ];
- SetFrame( frameNum );
- // convert joints into local coordinates and save in channels
- for( joint = model.exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- if ( !joint->dagnode ) {
- // custom origin joint
- joint->idwm.Identity();
- joint->idt.Zero();
- frame[ joint->index ].t.Zero();
- frame[ joint->index ].q.Set( 0.0f, 0.0f, 0.0f );
- continue;
- }
- // get the worldspace positions of the joint
- GetWorldTransform( joint, jointpos, jointaxis, options.scale );
-
- // convert to id coordinates
- jointaxis = ConvertToIdSpace( jointaxis ) * align;
- jointpos = ConvertToIdSpace( jointpos ) * align;
- // save worldspace position of joint for children
- joint->idwm = jointaxis;
- joint->idt = jointpos;
- parent = joint->exportNode.GetParent();
- if ( parent ) {
- // convert to local coordinates
- jointpos = ( jointpos - parent->idt ) * parent->idwm.Transpose();
- jointaxis = jointaxis * parent->idwm.Transpose();
- } else if ( joint->name == "origin" ) {
- if ( options.clearOrigin ) {
- jointpos.Zero();
- }
- if ( options.clearOriginAxis ) {
- jointaxis.Identity();
- }
- }
- frame[ joint->index ].t = jointpos;
- frame[ joint->index ].q = jointaxis.ToQuat().ToCQuat();
- }
- }
- options.cycleStart = cycleStart;
- totalDelta.Zero();
- joint = model.FindJoint( "origin" );
- if ( joint ) {
- frame = model.frames[ 0 ];
- idVec3 origin = frame[ joint->index ].t;
- frame = model.frames[ model.numFrames - 1 ];
- totalDelta = frame[ joint->index ].t - origin;
- }
- // shift the frames when cycleStart is used
- if ( options.cycleStart > options.startframe ) {
- copyFrames = model.jointFrames;
- for( i = 0; i < model.numFrames; i++ ) {
- bool shiftorigin = false;
- frameNum = i + ( options.cycleStart - options.startframe );
- if ( frameNum >= model.numFrames ) {
- // wrap around, skipping the first frame, since it's a dupe of the last frame
- frameNum -= model.numFrames - 1;
- shiftorigin = true;
- }
- memcpy( &model.jointFrames[ model.joints.Num() * i ], ©Frames[ model.joints.Num() * frameNum ], model.joints.Num() * sizeof( copyFrames[ 0 ] ) );
- if ( joint && shiftorigin ) {
- model.frames[ i ][ joint->index ].t += totalDelta;
- }
- }
- }
- if ( joint ) {
- // relocate origin to start at 0, 0, 0 for first frame
- frame = model.frames[ 0 ];
- idVec3 origin = frame[ joint->index ].t;
- for( i = 0; i < model.numFrames; i++ ) {
- frame = model.frames[ i ];
- frame[ joint->index ].t -= origin;
- }
- }
- // get the bounds for each frame
- for( frameNum = 0; frameNum < model.numFrames; frameNum++ ) {
- frame = model.frames[ frameNum ];
- // transform the hierarchy
- for( joint = model.exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) {
- jointpos = frame[ joint->index ].t;
- jointaxis = frame[ joint->index ].q.ToQuat().ToMat3();
- parent = joint->exportNode.GetParent();
- if ( parent ) {
- joint->idwm = jointaxis * parent->idwm;
- joint->idt = parent->idt + jointpos * parent->idwm;
- } else {
- joint->idwm = jointaxis;
- joint->idt = jointpos;
- }
- }
- // get bounds for this frame
- bnds.Clear();
- for( i = 0; i < model.meshes.Num(); i++ ) {
- if ( model.meshes[ i ]->keep ) {
- model.meshes[ i ]->GetBounds( meshBounds );
- bnds.AddBounds( meshBounds );
- }
- }
- model.bounds[ frameNum ][ 0 ] = bnds[ 0 ];
- model.bounds[ frameNum ][ 1 ] = bnds[ 1 ];
- }
- common->Printf( "\n" );
- }
- /*
- ===============
- idMayaExport::ConvertModel
- ===============
- */
- void idMayaExport::ConvertModel( void ) {
- MStatus status;
- idMat3 align;
- common->Printf( "Converting %s to %s...\n", options.src.c_str(), options.dest.c_str() );
- // see if the destination file exists
- FILE *file = fopen( options.dest, "r" );
- if ( file ) {
- fclose( file );
- // make sure we can write to the destination
- FILE *file = fopen( options.dest, "r+" );
- if ( !file ) {
- MayaError( "Unable to write to the file '%s'", options.dest.c_str() );
- }
- fclose( file );
- }
- MString filename( options.src );
- MFileIO::newFile( true );
- // Load the file into Maya
- common->Printf( "Loading file...\n" );
- status = MFileIO::open( filename, NULL, true );
- if ( !status ) {
- MayaError( "Error loading '%s': '%s'\n", filename.asChar(), status.errorString().asChar() );
- }
- // force Maya to update the frame. When using references, sometimes
- // the model is posed the way it is in the source. Since Maya only
- // updates it when the frame time changes to a value other than the
- // current, just setting the time to the min time doesn't guarantee
- // that the model gets updated.
- MGlobal::viewFrame( MAnimControl::maxTime() );
- MGlobal::viewFrame( MAnimControl::minTime() );
- if ( options.startframe < 0 ) {
- options.startframe = MAnimControl::minTime().as( MTime::kFilm );
- }
- if ( options.endframe < 0 ) {
- options.endframe = MAnimControl::maxTime().as( MTime::kFilm );
- }
- if ( options.cycleStart < 0 ) {
- options.cycleStart = options.startframe;
- } else if ( ( options.cycleStart < options.startframe ) || ( options.cycleStart > options.endframe ) ) {
- MayaError( "cycleStart (%d) out of frame range (%d to %d)\n", options.cycleStart, options.startframe, options.endframe );
- } else if ( options.cycleStart == options.endframe ) {
- // end frame is a duplicate of the first frame in cycles, so just disable cycleStart
- options.cycleStart = options.startframe;
- }
- // create a list of the transform nodes that will make up our heirarchy
- common->Printf( "Creating joints...\n" );
- CreateJoints( options.scale );
- if ( options.type != WRITE_CAMERA ) {
- common->Printf( "Creating meshes...\n" );
- CreateMesh( options.scale );
- common->Printf( "Renaming joints...\n" );
- RenameJoints( options.renamejoints, options.prefix );
- common->Printf( "Remapping parents...\n" );
- RemapParents( options.remapjoints );
- common->Printf( "Pruning joints...\n" );
- PruneJoints( options.keepjoints, options.prefix );
- common->Printf( "Combining meshes...\n" );
- CombineMeshes();
- }
- common->Printf( "Align model...\n" );
- GetAlignment( options.align, align, options.rotate, 0 );
- switch( options.type ) {
- case WRITE_MESH :
- common->Printf( "Grabbing default pose:\n" );
- GetDefaultPose( align );
- common->Printf( "Writing file...\n" );
- if ( !model.WriteMesh( options.dest, options ) ) {
- MayaError( "error writing to '%s'", options.dest.c_str() );
- }
- break;
- case WRITE_ANIM :
- common->Printf( "Creating animation frames:\n" );
- CreateAnimation( align );
- common->Printf( "Writing file...\n" );
- if ( !model.WriteAnim( options.dest, options ) ) {
- MayaError( "error writing to '%s'", options.dest.c_str() );
- }
- break;
- case WRITE_CAMERA :
- common->Printf( "Creating camera frames:\n" );
- CreateCameraAnim( align );
- common->Printf( "Writing file...\n" );
- if ( !model.WriteCamera( options.dest, options ) ) {
- MayaError( "error writing to '%s'", options.dest.c_str() );
- }
- break;
- }
- common->Printf( "done\n\n" );
- }
- /*
- ===============
- idMayaExport::ConvertToMD3
- ===============
- */
- void idMayaExport::ConvertToMD3( void ) {
- #if 0
- int i, j;
- md3Header_t *pinmodel;
- md3Frame_t *frame;
- md3Surface_t *surf;
- md3Shader_t *shader;
- md3Triangle_t *tri;
- md3St_t *st;
- md3XyzNormal_t *xyz;
- md3Tag_t *tag;
- int version;
- int size;
- //model_t *mod, int lod, void *buffer, const char *mod_name
- pinmodel = (md3Header_t *)buffer;
- version = LittleLong (pinmodel->version);
- if (version != MD3_VERSION) {
- common->Printf( "R_LoadMD3: %s has wrong version (%i should be %i)\n",
- mod_name, version, MD3_VERSION);
- return qfalse;
- }
- mod->type = MOD_MESH;
- size = LittleLong(pinmodel->ofsEnd);
- mod->dataSize += size;
- mod->md3[lod] = ri.Hunk_Alloc( size );
- memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) );
- LL(mod->md3[lod]->ident);
- LL(mod->md3[lod]->version);
- LL(mod->md3[lod]->numFrames);
- LL(mod->md3[lod]->numTags);
- LL(mod->md3[lod]->numSurfaces);
- LL(mod->md3[lod]->ofsFrames);
- LL(mod->md3[lod]->ofsTags);
- LL(mod->md3[lod]->ofsSurfaces);
- LL(mod->md3[lod]->ofsEnd);
- if ( mod->md3[lod]->numFrames < 1 ) {
- common->Printf( "R_LoadMD3: %s has no frames\n", mod_name );
- return qfalse;
- }
-
- // swap all the frames
- frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames );
- for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) {
- frame->radius = LittleFloat( frame->radius );
- for ( j = 0 ; j < 3 ; j++ ) {
- frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
- frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
- frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
- }
- }
- // swap all the tags
- tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags );
- for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) {
- for ( j = 0 ; j < 3 ; j++ ) {
- tag->origin[j] = LittleFloat( tag->origin[j] );
- tag->axis[0][j] = LittleFloat( tag->axis[0][j] );
- tag->axis[1][j] = LittleFloat( tag->axis[1][j] );
- tag->axis[2][j] = LittleFloat( tag->axis[2][j] );
- }
- }
- // swap all the surfaces
- surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces );
- for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) {
- LL(surf->ident);
- LL(surf->flags);
- LL(surf->numFrames);
- LL(surf->numShaders);
- LL(surf->numTriangles);
- LL(surf->ofsTriangles);
- LL(surf->numVerts);
- LL(surf->ofsShaders);
- LL(surf->ofsSt);
- LL(surf->ofsXyzNormals);
- LL(surf->ofsEnd);
-
- if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
- ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
- mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
- }
- if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
- ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
- mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
- }
-
- // change to surface identifier
- surf->ident = SF_MD3;
- // lowercase the surface name so skin compares are faster
- Q_strlwr( surf->name );
- // strip off a trailing _1 or _2
- // this is a crutch for q3data being a mess
- j = strlen( surf->name );
- if ( j > 2 && surf->name[j-2] == '_' ) {
- surf->name[j-2] = 0;
- }
- // register the shaders
- shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
- for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) {
- shader_t *sh;
- sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue );
- if ( sh->defaultShader ) {
- shader->shaderIndex = 0;
- } else {
- shader->shaderIndex = sh->index;
- }
- }
- // swap all the triangles
- tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
- for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
- LL(tri->indexes[0]);
- LL(tri->indexes[1]);
- LL(tri->indexes[2]);
- }
- // swap all the ST
- st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
- for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
- st->st[0] = LittleFloat( st->st[0] );
- st->st[1] = LittleFloat( st->st[1] );
- }
- // swap all the XyzNormals
- xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
- for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )
- {
- xyz->xyz[0] = LittleShort( xyz->xyz[0] );
- xyz->xyz[1] = LittleShort( xyz->xyz[1] );
- xyz->xyz[2] = LittleShort( xyz->xyz[2] );
- xyz->normal = LittleShort( xyz->normal );
- }
- // find the next surface
- surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
- }
- return true;
- #endif
- }
- /*
- ==============================================================================
- dll setup
- ==============================================================================
- */
- /*
- ===============
- Maya_Shutdown
- ===============
- */
- void Maya_Shutdown( void ) {
- if ( initialized ) {
- errorMessage.Clear();
- initialized = false;
- // This shuts down the entire app somehow, so just ignore it.
- //MLibrary::cleanup();
- }
- }
- /*
- ===============
- Maya_ConvertModel
- ===============
- */
- const char *Maya_ConvertModel( const char *ospath, const char *commandline ) {
-
- errorMessage = "Ok";
-
- try {
- idExportOptions options( commandline, ospath );
- idMayaExport exportM( options );
- exportM.ConvertModel();
- }
-
- catch( idException &exception ) {
- errorMessage = exception.error;
- }
- return errorMessage;
- }
- /*
- ===============
- dllEntry
- ===============
- */
- bool dllEntry( int version, idCommon *common, idSys *sys ) {
- if ( !common || !sys ) {
- return false;
- }
- ::common = common;
- ::sys = sys;
- ::cvarSystem = NULL;
- idLib::sys = sys;
- idLib::common = common;
- idLib::cvarSystem = NULL;
- idLib::fileSystem = NULL;
- idLib::Init();
- if ( version != MD5_VERSION ) {
- common->Printf( "Error initializing Maya exporter: DLL version %d different from .exe version %d\n", MD5_VERSION, version );
- return false;
- }
- if ( !initialized ) {
- MStatus status;
- status = MLibrary::initialize( GAME_NAME, true );
- if ( !status ) {
- common->Printf( "Error calling MLibrary::initialize (%s)\n", status.errorString().asChar() );
- return false;
- }
- initialized = true;
- }
- return true;
- }
- // Force type checking on the interface functions to help ensure that they match the ones in the .exe
- const exporterDLLEntry_t ValidateEntry = &dllEntry;
- const exporterInterface_t ValidateConvert = &Maya_ConvertModel;
- const exporterShutdown_t ValidateShutdown = &Maya_Shutdown;
|