00001 #include <windows.h>
00002
00003 #include <maya/MStatus.h>
00004 #include <maya/MObject.h>
00005 #include <maya/MFnPlugin.h>
00006 #include <maya/MString.h>
00007 #include <maya/MStringArray.h>
00008 #include <maya/MPxFileTranslator.h>
00009 #include <maya/MGlobal.h>
00010 #include <maya/MObject.h>
00011 #include <maya/MPlug.h>
00012 #include <maya/MItSelectionList.h>
00013 #include <maya/MSelectionList.h>
00014 #include <maya/M3DView.h>
00015
00016 #include <maya/MArgList.h>
00017 #include <maya/MAnimControl.h>
00018
00019 #include <MDt.h>
00020 #include <MDtExt.h>
00021
00022 #include "ExportWnd.h"
00023 #include "Common/File.h"
00024 #include "Common/Error.h"
00025 #include "Model/Model.h"
00026 #include "MDLExporter.h"
00027
00028 #define PLUGIN_NAME "3Dino MODEL"
00029
00030
00031 void* KMDLExporter::creator()
00032 {
00033 return new KMDLExporter();
00034 }
00035
00036
00037 KMDLExporter::KMDLExporter()
00038 : MPxFileTranslator()
00039 {
00040 #ifdef _DEBUG
00041 m_Console.Create();
00042 #endif
00043 }
00044
00045
00046 KMDLExporter::~KMDLExporter()
00047 {
00048 #ifdef _DEBUG
00049 m_Console.Close();
00050 #endif
00051 }
00052
00053
00054 MStatus KMDLExporter::reader(const MFileObject & file,
00055 const MString & options,
00056 MPxFileTranslator::FileAccessMode mode)
00057 {
00058 return MS::kSuccess;
00059 }
00060
00061
00062 MStatus KMDLExporter::writer( const MFileObject & fileObject,
00063 const MString & options,
00064 MPxFileTranslator::FileAccessMode mode)
00065 {
00066 HWND hWnd = NULL;
00067
00068 M3dView m3dView;
00069 MStatus status;
00070
00071 hWnd = m3dView.applicationShell( &status );
00072
00073 ExportWnd_Create( MhInstPlugin, hWnd );
00074
00075 m_Console << "===============================================================" << KENDL;
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 s32 AnimStart;
00094 s32 AnimEnd;
00095 s32 AnimStep;
00096
00097 DtExt_setWalkMode( ALL_Nodes );
00098 DtExt_setOutputTransforms( kTRANSFORMALL );
00099 DtExt_setJointHierarchy( 1 );
00100 DtExt_setParents( 1 );
00101
00102 DtExt_SceneInit( (char*)fileObject.name().asChar() );
00103
00104 DtExt_dbInit();
00105
00106 m_Console << "Options : " << (char*)options.asChar() << KENDL;
00107 m_Console << "Exporting " << (char*)fileObject.fullName().asChar() << "..." << KENDL;
00108
00109 if(options.length () > 0)
00110 {
00111 MStringArray optionList;
00112 MStringArray theOption;
00113
00114 options.split (';', optionList);
00115
00116 for( u32 i = 0; i < optionList.length (); ++i)
00117 {
00118 theOption.clear ();
00119 optionList[i].split ('=', theOption);
00120 if (theOption.length () > 1)
00121 {
00122 if( theOption[0] == MString ("AnimStart"))
00123 {
00124 AnimStart = theOption[1].asInt();
00125 }
00126 else
00127 if( theOption[0] == MString ("AnimEnd"))
00128 {
00129 AnimEnd = theOption[1].asInt();
00130 }
00131 else
00132 if( theOption[0] == MString ("AnimStep"))
00133 {
00134 AnimStep = theOption[1].asInt();
00135 }
00136 }
00137 }
00138 }
00139
00140
00141
00142
00143
00144
00145 KMdlLoader Loader;
00146
00147
00148 s32 nFrames;
00149
00150 if( AnimEnd < AnimStart )
00151 AnimEnd = AnimStart;
00152
00153 DtFrameSetStart( AnimStart );
00154 DtFrameSetEnd( AnimEnd );
00155 DtFrameSetBy( AnimStep );
00156 DtFrameSet( 0 );
00157
00158 nFrames = AnimEnd - AnimStart + 1;
00159
00160 m_Console << "ANIM : [" << AnimStart << "-" << AnimEnd << "," << AnimStep << "]" << KENDL;
00161
00162
00163 s32 nShaders;
00164
00165 DtTextureGetSceneCount( (int*)&nShaders );
00166
00167 char* pTextureName;
00168 for( s32 t = 0; t < nShaders; t ++ )
00169 {
00170 if( DtTextureGetFileNameID( t, &pTextureName ) )
00171 {
00172 char* pChar = pTextureName;
00173
00174 for( s32 p = 0; p < (s32)strlen( pTextureName ); p ++ )
00175 {
00176 if( ( pTextureName[p] == '\\' ) || ( pTextureName[p] == '/' ) )
00177 pChar = &pTextureName[p + 1];
00178 }
00179 Loader.AddShader( pChar );
00180 m_Console << "SHADER " << t << " " << pChar << KENDL;
00181 }
00182 ExportWnd_SetnMaterials( t + 1 );
00183 }
00184
00185
00186
00187 s32 nMeshes;
00188 s32 Frame;
00189 s32 nCountMeshes = 0;
00190 s32 nCountVertices = 0;
00191 s32 nCountIndices = 0;
00192 s32 nCountFaces = 0;
00193 KMdlMesh* pMesh = NULL;
00194
00195 nMeshes = DtShapeGetCount();
00196
00197 for( s32 m = 0; m < nMeshes; m ++ )
00198 {
00199 pMesh = new KMdlMesh();
00200
00201
00202
00203 char* pMeshName;
00204 DtShapeGetName( m, &pMeshName );
00205 pMesh->m_Name = pMeshName;
00206
00207 m_Console << "MESH " << m << " NAME " << pMeshName << KENDL;
00208
00209 DtShapeGetName( DtShapeGetParentID( m ), &pMeshName );
00210 pMesh->m_FatherName = pMeshName;
00211
00212 for( u32 mm = 0; mm < Loader.GetnMeshes(); mm ++ )
00213 {
00214 if( Loader.GetpMesh( mm )->m_Name == pMesh->m_Name )
00215 {
00216 char pText[1024];
00217
00218 sprintf( pText, "Duplicate mesh [%s] found, the behaviour would be unexpected.", pMesh->m_Name.GetpString() );
00219 MessageBox( hWnd, pText, "Dino's MDL Exporter", MB_ICONWARNING | MB_OK );
00220 }
00221 }
00222
00223
00224
00225 s32 nVertices;
00226 s32 nPrimitives;
00227 int bIsAnimated;
00228
00229 DtShapeGetVertexCount( m, (int*)&nVertices );
00230 nPrimitives = DtGroupGetCount( m );
00231 bIsAnimated = DtExt_ShapeIsAnim( m );
00232
00233 m_Console << " " << nVertices << " vertices" << KENDL;
00234 m_Console << " " << nPrimitives << " primitives" << KENDL;
00235 m_Console << " " << (char*)(bIsAnimated ? "Mesh animated" : "Static mesh") << KENDL;
00236
00237
00238
00239
00240
00241
00242
00243
00244 ExportWnd_SetnMeshes( ++nCountMeshes );
00245
00246 pMesh->m_nPrimitives = 0;
00247
00248 KMdlPrimitive* pPrimitive;
00249
00250 for( s32 p = 0; p < nPrimitives; p ++ )
00251 {
00252 char* pPrimitiveName;
00253
00254 s32 MaterialId;
00255 s32 TextureId;
00256 KVector PriVertices;
00257 KVector PriNormal;
00258
00259
00260 pPrimitive = new KMdlPrimitive();
00261 pMesh->m_Primitives.Add( pPrimitive );
00262 pMesh->m_nPrimitives ++;
00263
00264
00265 DtGroupGetName( m, p, &pPrimitiveName );
00266 m_Console << " PRIMITIVE NAME : " << pPrimitiveName << KENDL;
00267
00268
00269 DtMtlGetID( m, p, (int*)&MaterialId );
00270 DtTextureGetID( MaterialId, (int*)&TextureId );
00271 pPrimitive->m_ShaderId = TextureId;
00272
00273
00274 s32 nIndices;
00275 s32* pIndices;
00276
00277 DtFaceGetIndexByGroup( m, p, (int*)&nIndices, (int**)&pIndices );
00278
00279 s32 l;
00280 s32 j;
00281 s32 k;
00282 s32 nReelIndices = 0;
00283 s32 nReelVertices = 0;
00284
00285
00286 l = j = k = 0;
00287 while( l < nIndices )
00288 {
00289 j = DtIndexCount( (int*)&pIndices[l] );
00290 if( j < 3 )
00291 m_Console << " Not enough vertices for this faces !" << KENDL;
00292 else
00293 for( s32 n = 2; n < j; n ++ )
00294 nReelIndices += 3;
00295 nReelVertices += j;
00296 l += j + 1;
00297 }
00298
00299
00300 m_Console << " " << nReelVertices << " vertices" << KENDL;
00301
00302 nCountVertices += nReelVertices;
00303 ExportWnd_SetnVertices( nCountVertices );
00304 pPrimitive->m_nVertices = (u16)nReelVertices;
00305
00306
00307
00308
00309 m_Console << " " << nReelIndices << " indices" << KENDL;
00310
00311 nCountIndices += nReelIndices;
00312 ExportWnd_SetnIndices( nCountIndices );
00313
00314 pPrimitive->m_nIndices = (u16)nReelIndices;
00315 pPrimitive->m_pIndices = new u16[nReelIndices];
00316
00317 l = j = k = nReelIndices = 0;
00318 while( l < nIndices )
00319 {
00320 j = DtIndexCount( (int*)&pIndices[l] );
00321 if( j < 3 )
00322 m_Console << " Not enough vertices for this faces !" << KENDL;
00323 else
00324 {
00325 for( s32 n = 2; n < j; n ++ )
00326 {
00327
00328
00329
00330 pPrimitive->m_pIndices[nReelIndices + 0] = (u16)k;
00331 pPrimitive->m_pIndices[nReelIndices + 1] = (u16)(k + n - 0);
00332 pPrimitive->m_pIndices[nReelIndices + 2] = (u16)(k + n - 1);
00333 nReelIndices += 3;
00334 ExportWnd_SetnFaces( ++nCountFaces );
00335 }
00336 }
00337 l += j + 1;
00338 k += j;
00339 }
00340 }
00341
00342 Loader.AddMesh( pMesh );
00343 }
00344
00345
00346 u32 FrameId = 0;
00347
00348 for( Frame = AnimStart; Frame < AnimEnd + 1; Frame += AnimStep, FrameId ++ )
00349 {
00350 ExportWnd_SetFrames( Frame + 1, AnimEnd + 1 );
00351
00352 m_Console << "FRAME : " << Frame << KENDL;
00353
00354 if( DtFrameGet() != Frame )
00355 DtFrameSet( Frame );
00356
00357 u32 MeshId = 0;
00358
00359 for( s32 m = 0; m < nMeshes; m ++ )
00360 {
00361 s32 nVertices;
00362 s32 nPrimitives;
00363
00364 DtShapeGetVertexCount( m, (int*)&nVertices );
00365 nPrimitives = DtGroupGetCount( m );
00366
00367
00368 pMesh = Loader.GetpMesh( MeshId ++ );
00369
00370
00371 KMatrix* pMatrix;
00372 DtShapeGetMatrix( m, (float**)&pMatrix );
00373
00374 KMdlFrameMatrix* pLastFrameMatrix = pMesh->GetSlowFrameMatrix( FrameId );
00375 if( !pLastFrameMatrix || ( pLastFrameMatrix->m_Matrix != *pMatrix ) )
00376 {
00377 KMdlFrameMatrix* pFrameMatrix = new KMdlFrameMatrix();
00378 pFrameMatrix->m_FrameId = FrameId;
00379 pFrameMatrix->m_Matrix = *pMatrix;
00380 pMesh->m_FrameMatrix.Add( pFrameMatrix );
00381 pMesh->m_nFrames ++;
00382 }
00383
00384 KMdlPrimitive* pPrimitive;
00385 for( s32 p = 0; p < nPrimitives; p ++ )
00386 {
00387 pPrimitive = pMesh->m_Primitives[p];
00388
00389 KMdlVertex* pVertex;
00390 KVector PriVertices;
00391 KVector PriNormal;
00392 float uv[2];
00393
00394 s32 nPolys;
00395 u32 VertexId;
00396 DtPolygonGetCount( m, p, (int*)&nPolys );
00397
00398 s32 Count;
00399 s32* vIdx;
00400 s32* nIdx;
00401 s32* tIdx;
00402 s32 Poly;
00403
00404 VertexId = 0;
00405 KMdlVertex* pVertices = new KMdlVertex[pPrimitive->m_nVertices];
00406
00407 for( Poly = 0; Poly < nPolys; Poly ++ )
00408 {
00409 DtPolygonGetIndices( Poly, (int*)&Count, (int**)&vIdx, (int**)&nIdx, (int**)&tIdx );
00410
00411 for( s32 n = 0; n < Count; n ++ )
00412 {
00413 pVertex = &pVertices[VertexId];
00414
00415 DtShapeGetVertex( m, vIdx[n], (DtVec3f*)&PriVertices );
00416 DtShapeGetNormal( m, nIdx[n], (DtVec3f*)&PriNormal );
00417 DtShapeGetTextureVertex( m, tIdx[n], (DtVec2f*)&uv );
00418
00419 PriNormal.Normalize();
00420
00421 pVertex->Position.x = PriVertices.x;
00422 pVertex->Position.y = PriVertices.y;
00423 pVertex->Position.z = PriVertices.z;
00424 pVertex->Normal.x = PriNormal.x;
00425 pVertex->Normal.y = PriNormal.y;
00426 pVertex->Normal.z = PriNormal.z;
00427 pVertex->tu1 = uv[0];
00428 pVertex->tv1 = -uv[1];
00429 pVertex->tu2 = 0.0f;
00430 pVertex->tv2 = 0.0f;
00431
00432
00433
00434
00435
00436
00437 VertexId ++;
00438 }
00439 }
00440
00441 KASSERT( VertexId == pPrimitive->m_nVertices );
00442
00443
00444 KMdlFrameVertex* pLastFrameVertices = pPrimitive->GetSlowFrameVertex( FrameId );
00445 KMdlVertex* pLastVertices = pLastFrameVertices ? pLastFrameVertices->m_pVertices : NULL;
00446 bool bNewFrame = false;
00447
00448 m_Console << "BITE" << KENDL;
00449 if( pLastVertices )
00450 {
00451 for( u32 v = 0; v < pPrimitive->m_nVertices; v ++ )
00452 {
00453 if( pVertices[v] != pLastVertices[v] )
00454 {
00455 m_Console << "MESH : " << pMesh->m_Name << KENDL;
00456 m_Console << "PRIMITIVE : " << p << KENDL;
00457 m_Console << "pVertex " << v << KENDL;
00458 m_Console << pVertex[v].Position.x << ";" << pVertex[v].Position.z << ";" << pVertex[v].Position.z << KENDL;
00459 m_Console << pVertex[v].Normal.x << ";" << pVertex[v].Normal.z << ";" << pVertex[v].Normal.z << KENDL;
00460 m_Console << pVertex[v].tu1 << ";" << pVertex[v].tv1 << ";" << pVertex[v].tu2 << ";" << pVertex[v].tv2 << KENDL;
00461
00462 m_Console << "pLastVertices " << v << KENDL;
00463 m_Console << pLastVertices[v].Position.x << ";" << pLastVertices[v].Position.z << ";" << pLastVertices[v].Position.z << KENDL;
00464 m_Console << pLastVertices[v].Normal.x << ";" << pLastVertices[v].Normal.z << ";" << pLastVertices[v].Normal.z << KENDL;
00465 m_Console << pLastVertices[v].tu1 << ";" << pLastVertices[v].tv1 << ";" << pLastVertices[v].tu2 << ";" << pLastVertices[v].tv2 << KENDL;
00466
00467 m_Console << "Cumpare " << (pLastFrameVertices ? pLastFrameVertices->m_FrameId : -1) << " != " << FrameId << KENDL;
00468 m_Console << "NewFrame" << KENDL;
00469 bNewFrame = true;
00470 break;
00471 }
00472 }
00473
00474 }
00475 else
00476 {
00477 bNewFrame = true;
00478 m_Console << "No Last Vertex => Frame " << FrameId << KENDL;
00479
00480
00481
00482
00483
00484
00485 }
00486
00487 if( bNewFrame )
00488 {
00489 KMdlFrameVertex* pFrameVertex = new KMdlFrameVertex();
00490 pFrameVertex->m_FrameId = FrameId;
00491 pFrameVertex->m_nVertices = pPrimitive->m_nVertices;
00492 pFrameVertex->m_pVertices = pVertices;
00493 pPrimitive->m_FrameVertices.Add( pFrameVertex );
00494 pPrimitive->m_nFrames ++;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504 }
00505 }
00506 }
00507
00508 DtExt_CleanUp();
00509
00510 m_Console << "Saving file " << (char*)fileObject.name().asChar() << "..." << KENDL;
00511 if( !Loader.SaveMDL( (char*)fileObject.name().asChar() ) )
00512 {
00513 ExportWnd_Destroy();
00514 return MS::kFailure;
00515 }
00516
00517 m_Console << "Done." << KENDL;
00518
00519 ExportWnd_WaitClose();
00520 ExportWnd_Destroy();
00521
00522 return MS::kSuccess;
00523 }
00524
00525
00526 bool KMDLExporter::haveReadMethod() const
00527 {
00528 return false;
00529 }
00530
00531
00532 bool KMDLExporter::haveWriteMethod() const
00533 {
00534 return true;
00535 }
00536
00537
00538 MString KMDLExporter::defaultExtension() const
00539 {
00540 return MString( "mdl" );
00541 }
00542
00543
00544 bool KMDLExporter::canBeOpened() const
00545 {
00546 return true;
00547 }
00548
00549
00550 MPxFileTranslator::MFileKind KMDLExporter::identifyFile( const MFileObject& fileName, const char* buffer, short size ) const
00551 {
00552 if( ( size >= (short)strlen( HEADER_MAGIC ) ) && ( strncmp( buffer, HEADER_MAGIC, strlen( HEADER_MAGIC ) ) == 0 ) )
00553 return kIsMyFileType;
00554
00555 return kNotMyFileType;
00556 }
00557
00558
00559 __declspec( dllexport ) MStatus initializePlugin( MObject obj )
00560 {
00561 MStatus status;
00562
00563 MFnPlugin plugin(obj, "MDL Exporter for Maya (c) 2001 Dino Productions", "V0.1", "Any");
00564
00565
00566 status = plugin.registerFileTranslator( PLUGIN_NAME,
00567 "MDLExporter.rgb",
00568 KMDLExporter::creator,
00569 "MDLExporterOpts",
00570 "",
00571 true );
00572 if (!status)
00573 {
00574 status.perror ("registerFileTranslator");
00575 }
00576
00577 return status;
00578 }
00579
00580
00581 __declspec( dllexport ) MStatus uninitializePlugin( MObject obj )
00582 {
00583 MStatus status;
00584 MFnPlugin plugin( obj );
00585
00586 status = plugin.deregisterFileTranslator( PLUGIN_NAME );
00587 if (!status)
00588 {
00589 status.perror ("deregisterFileTranslator");
00590 }
00591
00592 return status;
00593 }