VCNModel* D3DConverter::ConvertD3DModel(const D3DModel& d3dmodel, LPDIRECT3DDEVICE9 device) { VCNNode* root = 0; if ( d3dmodel.m_MeshContainers.size() > 1 ) { root = VCNNodeCore::GetInstance()->CreateNode<VCNNode>(); } for (auto it = d3dmodel.m_MeshContainers.begin(),end = d3dmodel.m_MeshContainers.end(); it != end; ++it) { LPD3DXMESHCONTAINER meshContainer = *it; std::wstring name = StringBuilder() << d3dmodel.m_Name << "_Mesh_" << meshContainer->Name; VCNNode* nodepart = ConvertMesh(name, meshContainer, d3dmodel.m_FrameRoot, d3dmodel.m_AnimController, device); if ( d3dmodel.m_MeshContainers.size() > 1 ) { root->AttachChild( nodepart->GetNodeID() ); } else { root = nodepart; } } VCNModel* model = new VCNModel( root ); model->SetName( d3dmodel.m_Name ); model->SetVersion( 1.0f ); VCNResourceCore::GetInstance()->AddResource( d3dmodel.m_Name, model ); return model; }
bool SGMExporter::GetMeshes(std::vector<Scene3DMesh*> &meshes, BinaryWriter *bw) { // get only mesh nodes std::vector<IGameNode*> meshNodes; for (int i = 0; i < scene ->GetTopLevelNodeCount(); i++) FilterMeshNodes(scene ->GetTopLevelNode(i), meshNodes); SetProgressSteps((int)meshNodes.size()); for (int i = 0; i < (int)meshNodes.size(); i++) { Scene3DMesh *mesh = ConvertMesh(meshNodes[i]); if (mesh != NULL) { GMatrix m = meshNodes[i]->GetWorldTM().Inverse(); mesh->m_worldInverseMatrix.a[0] = m.GetRow(0).x; mesh->m_worldInverseMatrix.a[1] = m.GetRow(0).y; mesh->m_worldInverseMatrix.a[2] = m.GetRow(0).z; mesh->m_worldInverseMatrix.a[3] = m.GetRow(0).w; mesh->m_worldInverseMatrix.a[4] = m.GetRow(1).x; mesh->m_worldInverseMatrix.a[5] = m.GetRow(1).y; mesh->m_worldInverseMatrix.a[6] = m.GetRow(1).z; mesh->m_worldInverseMatrix.a[7] = m.GetRow(1).w; mesh->m_worldInverseMatrix.a[8] = m.GetRow(2).x; mesh->m_worldInverseMatrix.a[9] = m.GetRow(2).y; mesh->m_worldInverseMatrix.a[10] = m.GetRow(2).z; mesh->m_worldInverseMatrix.a[11] = m.GetRow(2).w; mesh->m_worldInverseMatrix.a[12] = m.GetRow(3).x; mesh->m_worldInverseMatrix.a[13] = m.GetRow(3).y; mesh->m_worldInverseMatrix.a[14] = m.GetRow(3).z; mesh->m_worldInverseMatrix.a[15] = m.GetRow(3).w; meshesCount++; GeoSaver::SaveMesh(mesh, *bw); delete mesh; } //meshes.push_back(mesh); StepProgress(); } scene ->ReleaseIGame(); return true; }
// save mesh list file BOOL CSeriousSkaStudioApp::SaveMeshListFile(MeshInstance &mshi, BOOL bConvert) { DisableRendering(); // get mesh list filename CTFileName fnMeshList = mshi.mi_pMesh->GetName(); fnMeshList = fnMeshList.NoExt() + ".aml"; try { fnMeshList.RemoveApplicationPath_t(); } catch(char *){} CTString strBackUp; try { // back up current mesh list file strBackUp.Load_t(fnMeshList); } catch(char*){} // save mesh instance in new mesh list file CTFileStream ostrFile; try { ostrFile.Create_t(fnMeshList,CTStream::CM_TEXT); SaveMeshInstance_t(mshi,ostrFile); ostrFile.Close(); } catch(char *strError) { ErrorMessage(strError); EnableRendering(); return FALSE; } // if new mesh list file needs to be converted if(bConvert) { if(!ConvertMesh(fnMeshList)) { // convert failed if(strBackUp.Length()>0) { // try returning old mesh list file try { strBackUp.Save_t(fnMeshList); } catch(char*){} } } } EnableRendering(); return TRUE; }
void CSeriousSkaStudioApp::OnImportConvert() { CSeriousSkaStudioDoc *pDoc = GetDocument(); CDynamicArray<CTFileName> afnCovert; _EngineGUI.FileRequester( "Open ASCII intermediate files", FILTER_ASCII FILTER_MESH_LIST FILTER_SKELETON_LIST FILTER_ANIMSET_LISTS FILTER_ALL, "Open directory", "Models\\", "", &afnCovert); INDEX ctMeshes = 0; INDEX ctSkeletons = 0; INDEX ctAnimSets = 0; CTimerValue tvStartOptimizer = _pTimer->GetHighPrecisionTimer(); ctMeshVxBeforeOpt = 0; ctMeshVxAfterOpt = 0; FOREACHINDYNAMICARRAY( afnCovert, CTFileName, itConvert) { char fnCurent[256]; strcpy(fnCurent,itConvert.Current()); char *pchDot = strrchr(fnCurent, '.'); if (pchDot==NULL) continue; else if(strcmp((_strlwr(pchDot)),".aml")==0) { if(ConvertMesh(itConvert.Current())) { ctMeshes++; } } else if(strcmp((_strlwr(pchDot)),".asl")==0) { if(ConvertSkeleton(itConvert.Current())) ctSkeletons++; } else if(strcmp((_strlwr(pchDot)),".aal")==0) { if(ConvertAnimSet(itConvert.Current())) ctAnimSets++; } }
void USkeletalMesh::SerializeSCell(FArchive &Ar) { if (Version >= 2) Ar << Version; // interesting code Ar << Points2; if (Ar.ArLicenseeVer >= 48) { TArray<FVector> unk1; Ar << unk1; } if (Ar.ArLicenseeVer >= 49 && Ar.ArLicenseeVer < 67) { TArray<byte> unk2; Ar << unk2; } Ar << RefSkeleton; Ar << Animation; if (Ar.ArLicenseeVer >= 155) { UObject* unk218; Ar << unk218; } Ar << SkeletalDepth << WeightIndices << BoneInfluences; Ar << AttachAliases << AttachBoneNames << AttachCoords; DROP_REMAINING_DATA(Ar); UpgradeMesh(); ConvertMesh(); /* TArray<FSCellUnk1> tmp1; TArray<FSCellUnk2> tmp2; TArray<FSCellUnk3> tmp3; TArray<FLODMeshSection> tmp4, tmp5; TArray<word> tmp6; FSCellUnk4 complex; Ar << tmp1 << tmp2 << tmp3 << tmp4 << tmp5 << tmp6 << complex; */ }
void LeftHandConvertor::ProcessScene() { ConvertNode( mAssimpScene->mRootNode ); for( std::size_t i=0; i < mAssimpScene->mNumMeshes; ++i ) { ConvertMesh( mAssimpScene->mMeshes[i] ); } for( std::size_t i=0; i < mAssimpScene->mNumMaterials; ++i ) { ConvertMaterial( mAssimpScene->mMaterials[i] ); } for ( std::size_t i=0; i < mAssimpScene->mNumAnimations; ++i ) { aiAnimation* animation = mAssimpScene->mAnimations[i]; for( std::size_t j=0; j < animation->mNumChannels; ++j ) { aiNodeAnim* nodeAnimation = animation->mChannels[j]; ConvertAnimation( nodeAnimation ); } } }
void USkeletalMesh::Serialize(FArchive &Ar) { guard(USkeletalMesh::Serialize); assert(Ar.Game < GAME_UE3); #if UNREAL1 if (Ar.Engine() == GAME_UE1) { SerializeSkelMesh1(Ar); return; } #endif #if BIOSHOCK if (Ar.Game == GAME_Bioshock) { SerializeBioshockMesh(Ar); return; } #endif Super::Serialize(Ar); #if SPLINTER_CELL if (Ar.Game == GAME_SplinterCell) { SerializeSCell(Ar); return; } #endif // SPLINTER_CELL #if TRIBES3 TRIBES_HDR(Ar, 4); #endif Ar << Points2; #if BATTLE_TERR if (Ar.Game == GAME_BattleTerr && Ar.ArVer >= 134) { TArray<FVector> Points3; Ar << Points3; } #endif // BATTLE_TERR Ar << RefSkeleton; #if DEBUG_SKELMESH appPrintf("RefSkeleton: %d bones\n", RefSkeleton.Num()); for (int i1 = 0; i1 < RefSkeleton.Num(); i1++) appPrintf(" [%d] n=%s p=%d\n", i1, *RefSkeleton[i1].Name, RefSkeleton[i1].ParentIndex); #endif // DEBUG_SKELMESH #if SWRC if (Ar.Game == GAME_RepCommando && Ar.ArVer >= 142) { for (int i = 0; i < RefSkeleton.Num(); i++) { FMeshBone &B = RefSkeleton[i]; B.BonePos.Orientation.X *= -1; B.BonePos.Orientation.Y *= -1; B.BonePos.Orientation.Z *= -1; } } if (Ar.Game == GAME_RepCommando && Version >= 5) { TArray<FMeshAnimLinkSWRC> Anims; Ar << Anims; if (Anims.Num() >= 1) Animation = Anims[0].Anim; } else #endif // SWRC Ar << Animation; #if AA2 if (Ar.Game == GAME_AA2 && Ar.ArLicenseeVer >= 22) { TArray<UObject*> unk230; Ar << unk230; } #endif // AA2 Ar << SkeletalDepth << WeightIndices << BoneInfluences; #if SWRC if (Ar.Game == GAME_RepCommando && Ar.ArVer >= 140) { TArray<FAttachSocketSWRC> Sockets; Ar << Sockets; //?? convert } else #endif // SWRC { Ar << AttachAliases << AttachBoneNames << AttachCoords; } if (Version <= 1) { // appNotify("SkeletalMesh of version %d\n", Version); TArray<FLODMeshSection> tmp1, tmp2; TArray<word> tmp3; Ar << tmp1 << tmp2 << tmp3; // copy and convert data from old mesh format UpgradeMesh(); } else { #if UC2 if (Ar.Engine() == GAME_UE2X && Ar.ArVer >= 136) { int f338; Ar << f338; } #endif // UC2 #if SWRC if (Ar.Game == GAME_RepCommando) { int f1C4; if (Version >= 6) Ar << f1C4; Ar << LODModels; if (Version < 5) Ar << f224; Ar << Points << Wedges << Triangles << VertInfluences; Ar << CollapseWedge << f1C8; goto skip_remaining; } #endif // SWRC #if EOS if (Ar.Game == GAME_EOS) { int unk1; UObject* unk2; UObject* unk3; if (Version >= 6) Ar << unk1 << unk2; if (Version >= 7) Ar << unk3; Ar << LODModels; goto skip_remaining; } #endif // EOS #if 0 // Shui Hu Q Zhuan 2 Online if (Ar.ArVer == 126 && Ar.ArLicenseeVer == 1) { // skip LOD models int Num; Ar << AR_INDEX(Num); for (int i = 0; i < Num; i++) { int Pos; Ar << Pos; Ar.Seek(Ar.Tell() + Pos - 4); } goto after_lods; } #endif Ar << LODModels; after_lods: Ar << f224 << Points; #if BATTLE_TERR if (Ar.Game == GAME_BattleTerr && Ar.ArVer >= 134) { TLazyArray<int> unk15C; Ar << unk15C; } #endif // BATTLE_TERR Ar << Wedges << Triangles << VertInfluences; Ar << CollapseWedge << f1C8; } #if TRIBES3 if ((Ar.Game == GAME_Tribes3 || Ar.Game == GAME_Swat4) && t3_hdrSV >= 3) { #if 0 // it looks like format of following data was chenged sinse // data was prepared, and game executeble does not load these // LazyArrays (otherwise error should occur) -- so we are // simply skipping these arrays TLazyArray<FT3Unk1> unk1; TLazyArray<FMeshWedge> unk2; TLazyArray<word> unk3; Ar << unk1 << unk2 << unk3; #else SkipLazyArray(Ar); SkipLazyArray(Ar); SkipLazyArray(Ar); #endif // nothing interesting below ... goto skip_remaining; } #endif // TRIBES3 #if BATTLE_TERR if (Ar.Game == GAME_BattleTerr) goto skip_remaining; #endif #if UC2 if (Ar.Engine() == GAME_UE2X) goto skip_remaining; #endif #if LINEAGE2 if (Ar.Game == GAME_Lineage2) { int unk1, unk3, unk4; TArray<float> unk2; if (Ar.ArVer >= 118 && Ar.ArLicenseeVer >= 3) Ar << unk1; if (Ar.ArVer >= 123 && Ar.ArLicenseeVer >= 0x12) Ar << unk2; if (Ar.ArVer >= 120) Ar << unk3; // AuthKey ? if (Ar.ArLicenseeVer >= 0x23) Ar << unk4; ConvertMesh(); return; } #endif // LINEAGE2 if (Ar.ArVer >= 120) { Ar << AuthKey; } #if LOCO if (Ar.Game == GAME_Loco) goto skip_remaining; // Loco codepath is similar to UT2004, but sometimes has different version switches #endif #if UT2 if (Ar.Game == GAME_UT2) { // UT2004 has branched version of UE2, which is slightly different // in comparison with generic UE2, which is used in all other UE2 games. if (Ar.ArVer >= 122) Ar << KarmaProps << BoundingSpheres << BoundingBoxes << f32C; if (Ar.ArVer >= 127) Ar << CollisionMesh; ConvertMesh(); return; } #endif // UT2 // generic UE2 code if (Ar.ArVer >= 124) Ar << KarmaProps << BoundingSpheres << BoundingBoxes; if (Ar.ArVer >= 125) Ar << f32C; #if XIII if (Ar.Game == GAME_XIII) goto skip_remaining; #endif #if RAGNAROK2 if (Ar.Game == GAME_Ragnarok2 && Ar.ArVer >= 131) { float unk1, unk2; Ar << unk1 << unk2; } #endif // RAGNAROK2 if (Ar.ArLicenseeVer && (Ar.Tell() != Ar.GetStopper())) { appPrintf("Serializing SkeletalMesh'%s' of unknown game: %d unreal bytes\n", Name, Ar.GetStopper() - Ar.Tell()); skip_remaining: DROP_REMAINING_DATA(Ar); } ConvertMesh(); unguard; }
//==================================================================================== // メッシュコンテナの作成(XFileの各パーツの集合)ようはスキンメッシュモデルをここで作る //==================================================================================== HRESULT CInheritanceHierarchy::CreateMeshContainer(LPCSTR Name, CONST D3DXMESHDATA* pMeshData, CONST D3DXMATERIAL* pMaterials, CONST D3DXEFFECTINSTANCE* pEffectInstances, DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppMeshContainer ) { //======================================================================== // コンテナ作成に当たって必要な変数を用意 //======================================================================== MYMESHCONTAINER *pMeshContainer = NULL; int iFacesAmount; DWORD iMaterial; LPDIRECT3DDEVICE9 pDevice = NULL; LPD3DXMESH pMesh = NULL; *ppMeshContainer = NULL; DWORD dwBoneNum=0; //======================================================================== // コンテナを動的確保して値を入れていく作業へ //======================================================================== pMesh = pMeshData->pMesh; pMeshContainer = new MYMESHCONTAINER; //メモリ不足のときは終了 if (pMeshContainer == NULL) { return E_OUTOFMEMORY; } //作成に成功したら中身を0で初期化しておく ZeroMemory(pMeshContainer, sizeof(MYMESHCONTAINER)); //メッシュコンテナとしてXFileでつけられてる名前を拾う pMeshContainer->Name=new TCHAR[lstrlen(Name) + 1]; // \0分の+1 //名前がなかったらおかしいので終了 if (!pMeshContainer->Name) { return E_FAIL; } //名前があるならそれにする strcpy(pMeshContainer->Name,Name); // デバイスゲット pMesh->GetDevice(&pDevice); // 面の数ゲット iFacesAmount = pMesh->GetNumFaces(); pMeshContainer->MeshData.pMesh = pMesh; pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH; //通常メッシュの場合はこれが必要。スキンの場合、これをするとメモリリークになる。 if (pSkinInfo == NULL) { pMesh->AddRef(); } //メッシュのマテリアル設定 pMeshContainer->NumMaterials = max(1, NumMaterials); pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials]; pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials]; pMeshContainer->pAdjacency = new DWORD[iFacesAmount * NUM_POLYGON_CREATE_TRIANGLE]; //隣接性情報またはマテリアルがなければ終了 if( pMeshContainer->pAdjacency == NULL || pMeshContainer->pMaterials == NULL ) { return E_FAIL; } //情報をメッシュコンテナに流し込む memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * iFacesAmount * NUM_POLYGON_CREATE_TRIANGLE); memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials); //======================================================================== //該当メッシュがスキン情報を持っている場合 //======================================================================== if (pSkinInfo != NULL) { pMeshContainer->pSkinInfo = pSkinInfo; pSkinInfo->AddRef(); dwBoneNum = pSkinInfo->GetNumBones(); pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[dwBoneNum]; for (DWORD i = 0; i < dwBoneNum; i++) { memcpy(&pMeshContainer->pBoneOffsetMatrices[i], pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i), sizeof(D3DMATRIX)); } // インデックスつきのものに変換 シェーダー使わないやつとは別なので注意 if (FAILED(pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh(pMesh, NULL, dwBoneNum, pMeshContainer->pAdjacency, NULL, NULL, NULL, &pMeshContainer->dwWeight, &pMeshContainer->dwBoneNum, &pMeshContainer->pBoneBuffer, &pMeshContainer->MeshData.pMesh))) { return E_FAIL; } // コンバート ConvertMesh(&pMeshContainer->MeshData.pMesh); D3DVERTEXELEMENT9 elements[] = { // 頂点ストリーム(パイプライン)番号, オフセット(頂点の型の先頭からのバイト数), データ型, DEFAULTでOK, 使用用途, 使用用途が同じものを複数使うときに仕分ける番号 { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0 }, { 0, 24, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0 }, { 0, 28, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, 40, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, { 0, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, D3DDECL_END() // 定義終了 絶対必要 }; pMeshContainer->pSkinInfo->SetDeclaration(elements); } //======================================================================== // モデルのマテリアル情報 //======================================================================== if (NumMaterials > 0) { memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials); for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++) { // マテリアルのディフーズ色を強制的に変更 pMeshContainer->pMaterials[iMaterial].MatD3D.Diffuse = DEFAULT_POLYGON_COLOR; if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL) { TCHAR strTexturePath[MAX_PATH]; strcpy( strTexturePath,TEX_FOLDER_PATH); strcat_s( strTexturePath, sizeof( char ) * MAX_LENGTH_FILE_PATH, pMeshContainer->pMaterials[iMaterial].pTextureFilename ); if (FAILED(D3DXCreateTextureFromFile(pDevice, strTexturePath, &pMeshContainer->ppTextures[iMaterial]))) { pMeshContainer->ppTextures[iMaterial] = NULL; pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL; } } } } else { pMeshContainer->pMaterials[0].pTextureFilename = NULL; memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9)); pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = COLOR_OF_NOT_EXIST_MATERIAL.r; pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = COLOR_OF_NOT_EXIST_MATERIAL.g; pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = COLOR_OF_NOT_EXIST_MATERIAL.b; pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse; } //ローカルに生成したメッシュコンテナーを呼び出し側にコピーする (コピーじゃないけど・・・) *ppMeshContainer = pMeshContainer; //参照カウンタを増やしたので減らす SAFE_RELEASE(pDevice); return S_OK; }
BOOL CMeshConverter::Convert(CGraphicsObject** ppcGraphicsObject, CMeshObject** ppcMeshObject, CMesh* pcMesh, CArrayIntAndPointer* pcConnectionAndIndex) { //This assumes mpcMesh is already touched mpcMesh = pcMesh; mpcConnectionsAndIndices = pcConnectionAndIndex; mpcGraphicsObject = NULL; mpcMeshObject = NULL; if (mpcSceneConverter->GetMapper()->GetMesh(pcMesh->GetOI(), ppcGraphicsObject, ppcMeshObject)) { return TRUE; } //Get the Position array, also make sure it has one. if (pcMesh->TestNumPositions() == 0) { CChars sz; sz.Init("The Mesh ["); sz.Append(pcMesh->GetName()); sz.Append("] has no vertex position channel"); gcUserError.Set(sz.Text()); sz.Kill(); return FALSE; } maiMatrixIndices.Init(256); //Create the graphics object for the conversion destination. mpcGraphicsObject = mpcSceneConverter->GetWorld()->CreateGraphicsObject(FALSE); mpcMeshObject = mpcSceneConverter->GetWorld()->CreateMeshObject(); FillUniqueMatricies(); if (!ConvertMaterials()) { return FALSE; } if (!ConvertMesh()) { return FALSE; } if (!CreateLinkNodes()) { return FALSE; } if (!SetObjectMatricies()) { return FALSE; } maiMatrixIndices.Kill(); //Optimise the vertex and index buffers in the graphics object according to current hardware. OptimiseGraphicsObject(); mpcSceneConverter->GetMapper()->AddGraphicsObject(pcMesh->GetOI(), mpcGraphicsObject, mpcMeshObject); SafeAssign(ppcGraphicsObject, mpcGraphicsObject); SafeAssign(ppcMeshObject, mpcMeshObject); return TRUE; }