00001 //--------------------------------------------------------------------------------------------- 00002 // This file is a part of "DinoKod". 00003 // Copyright © 2003 Dino Productions. All Rights Reserved. 00004 // 00005 // File : MAPMaxExporter.cpp 00006 // Author : Sebastien LEIX sebastien.leix@wanadoo.fr 00007 // Date : 04/01/2003 00008 // Modification : 00009 // 00010 //--------------------------------------------------------------------------------------------- 00011 #include "resource.h" 00012 #include "mapMaxExporter.h" 00013 #include "Common/Console.h" 00014 #include "Common/Vertex.h" 00015 00016 #define PLUGIN_NAME "3Dino MAP Exporter" 00017 00018 int g_ControlsInit = FALSE; 00019 HINSTANCE g_hInstance = NULL; 00020 HWND g_hWnd = NULL; 00021 00022 //--------------------------------------------------------------------------------------------- 00023 BOOL WINAPI DllMain( HINSTANCE hinstDLL, ULONG fdwReason, LPVOID lpvReserved ) 00024 { 00025 g_hInstance = hinstDLL; 00026 // Hang on to this DLL's instance handle. 00027 if( !g_ControlsInit ) 00028 { 00029 g_ControlsInit = TRUE; 00030 00031 // Initialize MAX's custom controls 00032 InitCustomControls( hinstDLL ); 00033 00034 // Initialize Win95 controls 00035 InitCommonControls(); 00036 } 00037 00038 return TRUE; 00039 } 00040 00041 //--------------------------------------------------------------------------------------------- 00042 __declspec( dllexport ) int LibNumberClasses() 00043 { 00044 return 1; 00045 } 00046 00047 //--------------------------------------------------------------------------------------------- 00048 __declspec( dllexport ) ClassDesc* LibClassDesc( int i ) 00049 { 00050 switch( i ) 00051 { 00052 case 0: 00053 return (ClassDesc*)&MapExporterClassDesc; 00054 default: 00055 return 0; 00056 } 00057 } 00058 00059 //--------------------------------------------------------------------------------------------- 00060 __declspec( dllexport ) const TCHAR* LibDescription() 00061 { 00062 return _T( PLUGIN_NAME ); 00063 } 00064 00065 //--------------------------------------------------------------------------------------------- 00066 extern "C" __declspec( dllexport ) ULONG LibVersion() 00067 { 00068 return VERSION_3DSMAX; 00069 } 00070 00071 //--------------------------------------------------------------------------------------------- 00072 //--------------------------------------------------------------------------------------------- 00073 //--------------------------------------------------------------------------------------------- 00074 KMapExporter::KMapExporter() 00075 : SceneExport() 00076 { 00077 #if _DEBUG 00078 g_Console.Create( "MapExporter" ); 00079 #endif _DEBUG 00080 } 00081 00082 //--------------------------------------------------------------------------------------------- 00083 KMapExporter::~KMapExporter() 00084 { 00085 #if _DEBUG 00086 g_Console.Close(); 00087 #endif _DEBUG 00088 } 00089 00090 //--------------------------------------------------------------------------------------------- 00091 void KMapExporter::ShowAbout( HWND hWnd ) 00092 { 00093 } 00094 00095 //--------------------------------------------------------------------------------------------- 00096 int KMapExporter::DoExport( const TCHAR *pName, ExpInterface *pExtInterface, Interface *pInterface, BOOL bSuppressPrompts, DWORD Options ) 00097 { 00098 // s32 AnimStart; 00099 // s32 AnimEnd; 00100 // s32 AnimStep; 00101 // KMapLoader Loader; 00102 00103 g_hWnd = pInterface->GetMAXHWnd(); 00104 00105 g_Console << "===============================================================" << KENDL; 00106 g_Console << "Prompt options... " << (char*)pName << "..." << KENDL; 00107 00108 if( !bSuppressPrompts ) 00109 { 00110 /* if( !DialogBoxParam( g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_EXPORT), pInterface->GetMAXHWnd(), ExportDlgProc, (LPARAM)this ) ) 00111 { 00112 g_Console << "Canceled." << KENDL; 00113 return 1; 00114 }*/ 00115 } 00116 00117 g_Console << "Exporting " << (char*)pName << "..." << KENDL; 00118 /* 00119 // Exporte les materiaux 00120 if( !ExportMaterials( Loader, pInterface->GetSceneMtls() ) ) 00121 return 1; 00122 00123 // Exporte les nodes 00124 if( !ExportNode( Loader, NULL, pInterface->GetRootNode(), (Options & SCENE_EXPORT_SELECTED) ? TRUE : FALSE, 0 ) ) 00125 return 1; 00126 00127 // Sauve le fichier 00128 Loader.SaveMAP( (char*)pName ); 00129 */ 00130 g_Console << "Done." << KENDL; 00131 00132 char pText[256]; 00133 sprintf( pText, "File [%s] successfully exported!", pName ); 00134 MessageBox( g_hWnd, pText, "MAP Export", MB_OK ); 00135 00136 return 1; 00137 } 00138 00139 //--------------------------------------------------------------------------------------------- 00140 INT_PTR CALLBACK KMapExporter::ExportDlgProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) 00141 { 00142 KMapExporter *pExporter = (KMapExporter*)GetWindowLongPtr( hWnd, GWLP_USERDATA ); 00143 00144 switch( Msg ) 00145 { 00146 case WM_INITDIALOG: 00147 break; 00148 case WM_COMMAND: 00149 switch( LOWORD( wParam ) ) 00150 { 00151 case IDOK: 00152 EndDialog( hWnd, 1 ); 00153 break; 00154 case IDCANCEL: 00155 EndDialog( hWnd, 0 ); 00156 break; 00157 } 00158 break; 00159 default: 00160 return FALSE; 00161 } 00162 00163 return TRUE; 00164 } 00165 /* 00166 //--------------------------------------------------------------------------------------------- 00167 bool KMapExporter::ExportMaterials( KMapLoader& Loader, MtlBaseLib* pMtlBaseLib ) 00168 { 00169 if( !pMtlBaseLib ) 00170 { 00171 MessageBox( g_hWnd, "No material set.\nYou need one material!", "MAP Export Error", MB_OK | MB_ICONSTOP ); 00172 return false; 00173 } 00174 00175 if( pMtlBaseLib->Count() != 1 ) 00176 { 00177 char pText[256]; 00178 sprintf( pText, "%i material(s) detected.\nYou need only one material!", pMtlBaseLib->Count() ); 00179 MessageBox( g_hWnd, pText, "MAP Export Error", MB_OK | MB_ICONSTOP ); 00180 return false; 00181 } 00182 00183 Mtl* pMtl; 00184 00185 pMtl = (Mtl*)(*pMtlBaseLib)[0]; 00186 00187 int NumMat = pMtl->NumSubMtls(); 00188 00189 if( NumMat < 1 ) 00190 { 00191 char pText[256]; 00192 sprintf( pText, "0 sub-material detected.\nYou need a least one sub-material!" ); 00193 MessageBox( g_hWnd, pText, "MAP Export Error", MB_OK | MB_ICONSTOP ); 00194 return false; 00195 } 00196 00197 00198 for( int mat = 0; mat < NumMat; mat ++ ) 00199 { 00200 Mtl* pSubMat = pMtl->GetSubMtl( mat ); 00201 00202 // Ajoute le materiel 00203 Loader.AddTexture( (char*)pSubMat->GetName() ); 00204 g_Console << "Shader " << mat << " : " << (char*)pSubMat->GetName() << KENDL; 00205 } 00206 00207 return true; 00208 } 00209 00210 //--------------------------------------------------------------------------------------------- 00211 bool KMapExporter::ExportNode( KMapLoader& Loader, KMapMesh* pMesh, INode* pNode, bool bSelected, TimeValue Time ) 00212 { 00213 KMapMesh* pCurrentMesh = pMesh; 00214 00215 g_Console << "Node Name : " << pNode->GetName() << KENDL; 00216 00217 if( !bSelected || pNode->Selected() ) 00218 { 00219 // Exporte la node 00220 ObjectState ObjState = pNode->EvalWorldState( Time ); 00221 if( ObjState.obj ) 00222 { 00223 switch( ObjState.obj->SuperClassID() ) 00224 { 00225 case GEOMOBJECT_CLASS_ID: 00226 { 00227 KMapMesh* pNodeMesh = ExportGeomObject( Loader, pNode, Time ); 00228 if( pNodeMesh ) 00229 { 00230 // Ajoute le mesh au modele 00231 Loader.AddMesh( pNodeMesh ); 00232 } 00233 else 00234 return false; 00235 pCurrentMesh = pNodeMesh; 00236 } 00237 break; 00238 case CAMERA_CLASS_ID: 00239 break; 00240 case LIGHT_CLASS_ID: 00241 break; 00242 case SHAPE_CLASS_ID: 00243 break; 00244 case HELPER_CLASS_ID: 00245 break; 00246 } 00247 } 00248 } 00249 00250 // Exporte les fils 00251 for( int i = 0; i < pNode->NumberOfChildren(); i ++ ) 00252 { 00253 if( !ExportNode( Loader, pCurrentMesh, pNode->GetChildNode( i ), bSelected, Time ) ) 00254 return false; 00255 } 00256 00257 return true; 00258 } 00259 00260 //--------------------------------------------------------------------------------------------- 00261 KMapMesh* KMapExporter::ExportGeomObject( KMapLoader& Loader, INode* pNode, TimeValue Time ) 00262 { 00263 TriObject* pTriObject; 00264 Object* pObject; 00265 00266 pObject = pNode->EvalWorldState( Time ).obj; 00267 00268 if( !pObject->CanConvertToType( Class_ID( TRIOBJ_CLASS_ID, 0 ) ) ) 00269 { 00270 char pText[256]; 00271 sprintf( pText, "Cannot convert node [%] to TriObject", pNode->GetName() ); 00272 MessageBox( g_hWnd, pText, "MAP Export Error", MB_OK | MB_ICONSTOP ); 00273 return NULL; 00274 } 00275 00276 pTriObject = (TriObject*)pObject->ConvertToType( Time, Class_ID( TRIOBJ_CLASS_ID, 0) ); 00277 if( !pTriObject ) 00278 { 00279 char pText[256]; 00280 sprintf( pText, "Cannot convert node [%] to TriObject", pNode->GetName() ); 00281 MessageBox( g_hWnd, pText, "MAP Export Error", MB_OK | MB_ICONSTOP ); 00282 return NULL; 00283 } 00284 00285 KMapMesh* pMapMesh = new KMapMesh(); 00286 Mesh* pMesh = &pTriObject->GetMesh(); 00287 int NumFaces = pMesh->getNumFaces(); 00288 int Face; 00289 00290 00291 // Nom 00292 pMapMesh->m_Name = KStr( pNode->GetName() ); 00293 pMapMesh->m_FatherName = ( pNode->GetParentNode()->IsRootNode() ) ? KStr( "" ) : KStr( pNode->GetParentNode()->GetName() ); 00294 00295 // 00296 // Matrice de transformation 00297 // 00298 Matrix3 m = pNode->GetNodeTM( Time ); 00299 Point3 r; 00300 KMatrix Matrix; 00301 00302 r = m.GetRow( 0 ); 00303 Matrix._11 = r.x; Matrix._12 = r.y; Matrix._13 = r.z; Matrix._14 = 0.0f; 00304 r = m.GetRow( 1 ); 00305 Matrix._21 = r.x; Matrix._22 = r.y; Matrix._23 = r.z; Matrix._24 = 0.0f; 00306 r = m.GetRow( 2 ); 00307 Matrix._31 = r.x; Matrix._32 = r.y; Matrix._33 = r.z; Matrix._34 = 0.0f; 00308 r = m.GetRow( 3 ); 00309 Matrix._41 = r.x; Matrix._42 = r.y; Matrix._43 = r.z; Matrix._44 = 1.0f; 00310 00311 KMapFrameMatrix* pFrameMatrix = new KMapFrameMatrix(); 00312 pFrameMatrix->m_FrameId = 0; 00313 pFrameMatrix->m_Matrix = Matrix; 00314 pMapMesh->m_FrameMatrix.Add( pFrameMatrix ); 00315 pMapMesh->m_nFrames ++; 00316 00317 00318 00319 pMesh->buildNormals(); 00320 00321 if( !pMesh->tVerts ) 00322 { 00323 char pText[256]; 00324 sprintf( pText, "Object [%s] need texture coordinate", pNode->GetName() ); 00325 MessageBox( g_hWnd, pText, "MAP Export Error", MB_OK | MB_ICONSTOP ); 00326 return NULL; 00327 } 00328 00329 // 00330 // Calcul et alloue le nombre de primitives 00331 // 00332 MtlID Mtl; 00333 bool bAlready; 00334 for( Face = 0; Face < NumFaces; Face ++ ) 00335 { 00336 Mtl = pMesh->getFaceMtlIndex( Face ); 00337 00338 // Max utilise un modulo pour recupere le id de materiau 00339 Mtl %= Loader.GetnTextures(); 00340 00341 // Regarde s'il est deja dans la liste 00342 bAlready = false; 00343 for( int m = 0; m < (int)pMapMesh->m_Primitives.GetSize(); m ++ ) 00344 { 00345 // Oui, on l'a déja 00346 if( pMapMesh->m_Primitives[m]->m_ShaderId == Mtl ) 00347 { 00348 // Ajoute 1 face de plus 00349 pMapMesh->m_Primitives[m]->m_nIndices += 3; 00350 bAlready = true; 00351 break; 00352 } 00353 } 00354 // Non, on l'ajoute 00355 if( !bAlready ) 00356 { 00357 KMapPrimitive* pPrimitive = new KMapPrimitive(); 00358 pPrimitive->m_ShaderId = Mtl; 00359 pPrimitive->m_nIndices += 3; 00360 pMapMesh->m_Primitives.Add( pPrimitive ); 00361 pMapMesh->m_nPrimitives ++; 00362 } 00363 } 00364 00365 // DUMP 00366 for( int m = 0; m < (int)pMapMesh->m_Primitives.GetSize(); m ++ ) 00367 { 00368 g_Console << "Shader " << pMapMesh->m_Primitives[m]->m_ShaderId << " : " << pMapMesh->m_Primitives[m]->m_nIndices / 3 << " Faces." << KENDL; 00369 } 00370 00371 00372 // 00373 // Index/Vertex 00374 // 00375 // Aloue les index et vertex 00376 for( int p = 0; p < (int)pMapMesh->m_Primitives.GetSize(); p ++ ) 00377 { 00378 // Alloue le maximum possible, de toute facon on s'en fou, au reload l'allocation se fera au plus juste 00379 pMapMesh->m_Primitives[p]->m_nIndices = 0; 00380 pMapMesh->m_Primitives[p]->m_pIndices = new u16[NumFaces*3]; 00381 00382 KMapFrameVertex* pFrameVertex = new KMapFrameVertex(); 00383 pFrameVertex->m_FrameId = 0; 00384 pFrameVertex->m_nVertices = 0; 00385 pFrameVertex->m_pVertices = new KMapVertex[NumFaces*3]; 00386 pMapMesh->m_Primitives[p]->m_FrameVertices.Add( pFrameVertex ); 00387 pMapMesh->m_Primitives[p]->m_nFrames ++; 00388 } 00389 00390 00391 00392 int v2; 00393 KMapVertex Vertex; 00394 for( Face = 0; Face < NumFaces; Face ++ ) 00395 { 00396 // Recherche la primitive qui correspond a ce materiel 00397 Mtl = pMesh->getFaceMtlIndex( Face ); 00398 00399 // Max utilise un modulo pour recupere le id de materiau 00400 Mtl %= Loader.GetnTextures(); 00401 00402 for( int m = 0; m < (int)pMapMesh->m_Primitives.GetSize(); m ++ ) 00403 { 00404 KMapPrimitive* pPrimitive = pMapMesh->m_Primitives[m]; 00405 KMapFrameVertex* pFrameVertex = pPrimitive->m_FrameVertices[0]; 00406 00407 if( pPrimitive->m_ShaderId == Mtl ) 00408 { 00409 // Ajoute les vertex 00410 for( int i = 0; i < 3; i ++ ) 00411 { 00412 // Vertex id 00413 v2 = pMesh->faces[Face].v[i]; 00414 00415 // Position 00416 Vertex.Position.x = pMesh->verts[v2].x; 00417 Vertex.Position.y = pMesh->verts[v2].y; 00418 Vertex.Position.z = pMesh->verts[v2].z; 00419 00420 // Normal 00421 Point3 Normal = GetVertexNormal( pMesh, Face, pMesh->getRVertPtr( v2 ) ); 00422 Vertex.Normal.x = Normal.x; 00423 Vertex.Normal.y = Normal.y; 00424 Vertex.Normal.z = Normal.z; 00425 00426 // Texture coordonnées 00427 Vertex.tu1 = pMesh->tVerts[pMesh->tvFace[Face].t[i]].x; 00428 Vertex.tv1 = pMesh->tVerts[pMesh->tvFace[Face].t[i]].y; 00429 Vertex.tu2 = 0.0; 00430 Vertex.tv2 = 0.0; 00431 00432 // Ajoute le vertex 00433 pFrameVertex->m_pVertices[pFrameVertex->m_nVertices] = Vertex; 00434 pFrameVertex->m_nVertices ++; 00435 pPrimitive->m_nVertices ++; 00436 } 00437 00438 // Ajoute les index 00439 // vertex 0 00440 pPrimitive->m_pIndices[pPrimitive->m_nIndices + 0] = pPrimitive->m_nIndices + 0; 00441 // vertex 1 00442 pPrimitive->m_pIndices[pPrimitive->m_nIndices + 1] = pPrimitive->m_nIndices + 1; 00443 // vertex 2 00444 pPrimitive->m_pIndices[pPrimitive->m_nIndices + 2] = pPrimitive->m_nIndices + 2; 00445 pPrimitive->m_nIndices += 3; 00446 } 00447 } 00448 } 00449 00450 return pMapMesh; 00451 } 00452 00453 //--------------------------------------------------------------------------------------------- 00454 Point3 KMapExporter::GetVertexNormal(Mesh* mesh, int faceNo, RVertex* rv) 00455 { 00456 Face* f = &mesh->faces[faceNo]; 00457 DWORD smGroup = f->smGroup; 00458 int numNormals; 00459 Point3 vertexNormal; 00460 00461 // Is normal specified 00462 // SPCIFIED is not currently used, but may be used in future versions. 00463 if (rv->rFlags & SPECIFIED_NORMAL) { 00464 vertexNormal = rv->rn.getNormal(); 00465 } 00466 // If normal is not specified it's only available if the face belongs 00467 // to a smoothing group 00468 else if ((numNormals = rv->rFlags & NORCT_MASK) && smGroup) { 00469 // If there is only one vertex is found in the rn member. 00470 if (numNormals == 1) { 00471 vertexNormal = rv->rn.getNormal(); 00472 } 00473 else { 00474 // If two or more vertices are there you need to step through them 00475 // and find the vertex with the same smoothing group as the current face. 00476 // You will find multiple normals in the ern member. 00477 for (int i = 0; i < numNormals; i++) { 00478 if (rv->ern[i].getSmGroup() & smGroup) { 00479 vertexNormal = rv->ern[i].getNormal(); 00480 } 00481 } 00482 } 00483 } 00484 else { 00485 // Get the normal from the Face if no smoothing groups are there 00486 vertexNormal = mesh->getFaceNormal(faceNo); 00487 } 00488 00489 return vertexNormal; 00490 } 00491 */
1.5.1-p1