1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-28 07:07:45 +00:00

clean up some includes in pcb_reader

- fix deadlock
This commit is contained in:
Tahir Akhlaq 2019-01-20 20:14:40 +00:00
parent fb99dfc915
commit 3348cc9c47
7 changed files with 277 additions and 224 deletions

View file

@ -2,13 +2,17 @@
#define EXPORTMGR_H #define EXPORTMGR_H
#include "exporter.h" #include "exporter.h"
#include "navmesh_exporter.h"
#include "obj_exporter.h" #include "obj_exporter.h"
#include "threadpool.h" #include "threadpool.h"
class ExportMgr class ExportMgr
{ {
public: public:
ExportMgr(){} ExportMgr( unsigned int maxJobs = 0 )
{
m_threadpool.addWorkers( maxJobs );
}
~ExportMgr() ~ExportMgr()
{ {
waitForTasks(); waitForTasks();
@ -20,6 +24,10 @@ public:
{ {
m_threadpool.queue( [zone](){ ObjExporter::exportZone( zone ); } ); m_threadpool.queue( [zone](){ ObjExporter::exportZone( zone ); } );
} }
if( exportFileTypes & ExportFileType::Navmesh )
{
m_threadpool.queue( [zone](){ NavmeshExporter::exportZone( zone ); } );
}
} }
void exportGroup( const std::string& zoneName, const ExportedGroup& group, ExportFileType exportFileTypes ) void exportGroup( const std::string& zoneName, const ExportedGroup& group, ExportFileType exportFileTypes )
@ -28,6 +36,10 @@ public:
{ {
m_threadpool.queue( [zoneName, group](){ ObjExporter::exportGroup( zoneName, group ); } ); m_threadpool.queue( [zoneName, group](){ ObjExporter::exportGroup( zoneName, group ); } );
} }
if( exportFileTypes & ExportFileType::Navmesh )
{
m_threadpool.queue( [zoneName, group](){ NavmeshExporter::exportGroup( zoneName, group ); } );
}
} }
void waitForTasks() void waitForTasks()

View file

@ -295,7 +295,7 @@ struct LGB_GROUP
} }
catch( std::exception& e ) catch( std::exception& e )
{ {
std::cout << name << " " << e.what() << std::endl; std::cout << ( name + " " + e.what() + "\n" );
} }
} }
}; };

View file

@ -29,12 +29,6 @@
#include <ExdCat.h> #include <ExdCat.h>
#include <Exd.h> #include <Exd.h>
#include <condition_variable>
#include <recastnavigation/Recast/Include/Recast.h>
#include <recastnavigation/Recast/Include/RecastAlloc.h>
// garbage to ignore models // garbage to ignore models
bool noObj = false; bool noObj = false;
@ -42,6 +36,7 @@ std::string gamePath( "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\
std::unordered_map< uint16_t, std::string > zoneNameMap; std::unordered_map< uint16_t, std::string > zoneNameMap;
uint32_t zoneId; uint32_t zoneId;
std::set< std::string > zoneDumpList; std::set< std::string > zoneDumpList;
std::shared_ptr< Cache > pCache; std::shared_ptr< Cache > pCache;
@ -96,12 +91,12 @@ std::string zoneNameToPath( const std::string& name )
//path = path.substr( path.find_first_of( "/" ) + 1, path.size() - path.find_first_of( "/" )); //path = path.substr( path.find_first_of( "/" ) + 1, path.size() - path.find_first_of( "/" ));
//path = std::string( "ffxiv/" ) + path; //path = std::string( "ffxiv/" ) + path;
path = std::string( "bg/" ) + path.substr( 0, path.find( "/level/" ) ); path = std::string( "bg/" ) + path.substr( 0, path.find( "/level/" ) );
std::cout << "[Info] " << "Found path for " << name << ": " << path << std::endl; printf( "[Info] Found path for %s\n", name.c_str() );
} }
else else
{ {
throw std::runtime_error( "Unable to find path for " + name + throw std::runtime_error( "Unable to find path for " + name +
".\n\tPlease double check spelling or open 0a0000.win32.index with FFXIV Explorer and extract territorytype.exh as CSV\n\tand copy territorytype.exh.csv into pcb_reader.exe directory if using standalone" ); ".\n\tPlease double check spelling." );
} }
return path; return path;
@ -145,7 +140,7 @@ int main( int argc, char* argv[] )
} }
catch( std::exception& e ) catch( std::exception& e )
{ {
std::cout << "Unable to initialise EXD! Usage: pcb_reader <teri> \"path/to/FINAL FANTASY XIV - A REALM REBORN/game/sqpack\"" << std::endl; printf( "Unable to initialise EXD! Usage: pcb_reader <teri> \"path/to/FINAL FANTASY XIV - A REALM REBORN/game/sqpack\" [--no-obj, --dump-all, --navmesh]" );
return -1; return -1;
} }
ExportMgr exportMgr; ExportMgr exportMgr;
@ -221,7 +216,7 @@ int main( int argc, char* argv[] )
uint32_t max_index = 0; uint32_t max_index = 0;
int totalModels = 0; int totalModels = 0;
{
auto buildModelEntry = [ & ]( std::shared_ptr< PCB_FILE > pPcbFile, ExportedGroup& exportedGroup, auto buildModelEntry = [ & ]( std::shared_ptr< PCB_FILE > pPcbFile, ExportedGroup& exportedGroup,
const std::string& name, const std::string& groupName, const std::string& name, const std::string& groupName,
@ -237,13 +232,11 @@ int main( int argc, char* argv[] )
model.name = name + "_" + std::to_string( totalModels++ ); model.name = name + "_" + std::to_string( totalModels++ );
model.meshes.resize( pcb_file.entries.size() ); model.meshes.resize( pcb_file.entries.size() );
uint32_t groupCount = 0; uint32_t meshCount = 0;
for( const auto& entry : pcb_file.entries ) for( const auto& entry : pcb_file.entries )
{ {
ExportedMesh mesh; ExportedMesh mesh;
int verts = 0;
int indices = 0;
mesh.verts.resize( ( entry.header.num_vertices + entry.header.num_v16 ) * 3 ); mesh.verts.resize( ( entry.header.num_vertices + entry.header.num_v16 ) * 3 );
mesh.indices.resize( entry.header.num_indices * 3 ); mesh.indices.resize( entry.header.num_indices * 3 );
@ -284,6 +277,8 @@ int main( int argc, char* argv[] )
} }
}; };
int verts = 0;
int indices = 0;
for( auto& vertex : entry.data.vertices ) for( auto& vertex : entry.data.vertices )
{ {
@ -310,7 +305,6 @@ int main( int argc, char* argv[] )
mesh.verts[ verts++ ] = v.z; mesh.verts[ verts++ ] = v.z;
} }
//fprintf( fp_out, "g %s_", (name2 + "_" + std::to_string( groupCount++ )).c_str() );
for( const auto& index : entry.data.indices ) for( const auto& index : entry.data.indices )
{ {
mesh.indices[ indices++ ] = index.index[ 0 ]; mesh.indices[ indices++ ] = index.index[ 0 ];
@ -319,17 +313,18 @@ int main( int argc, char* argv[] )
// std::cout << std::to_string( index.unknown[0] )<< " " << std::to_string( index.unknown[1] )<< " " << std::to_string( index.unknown[2]) << std::endl; // std::cout << std::to_string( index.unknown[0] )<< " " << std::to_string( index.unknown[1] )<< " " << std::to_string( index.unknown[2]) << std::endl;
} }
max_index += entry.data.vertices.size() + entry.data.vertices_i16.size(); max_index += entry.data.vertices.size() + entry.data.vertices_i16.size();
model.meshes.push_back( mesh ); model.meshes[ meshCount++ ] = mesh;
} }
exportedGroup.models[model.name] = model; exportedGroup.models[model.name] = model;
}; };
ExportedGroup exportedTerrainGroup; ExportedGroup exportedTerrainGroup;
exportedTerrainGroup.name = zoneName; exportedTerrainGroup.name = zoneName + "_terrain";
for( const auto& fileName : stringList ) for( const auto& fileName : stringList )
{ {
if( auto pPcbFile = pCache->getPcbFile( fileName ) ) if( auto pPcbFile = pCache->getPcbFile( fileName ) )
buildModelEntry( pPcbFile, exportedTerrainGroup, fileName, zoneName ); buildModelEntry( pPcbFile, exportedTerrainGroup, fileName, zoneName );
} }
exportMgr.exportGroup( zoneName, exportedTerrainGroup, ( ExportFileType )exportFileType );
for( const auto& lgb : lgbList ) for( const auto& lgb : lgbList )
{ {
@ -347,7 +342,7 @@ int main( int argc, char* argv[] )
fileName.resize( 256 ); fileName.resize( 256 );
// write files // write files
auto writeOutput = [&](const std::string& fileName, const vec3* scale, const vec3* rotation, auto pcbTransformModel = [&]( const std::string& fileName, const vec3* scale, const vec3* rotation,
const vec3* translation, const SGB_MODEL_ENTRY* pModel = nullptr )-> bool const vec3* translation, const SGB_MODEL_ENTRY* pModel = nullptr )-> bool
{ {
if( auto pPcbFile = pCache->getPcbFile( fileName ) ) if( auto pPcbFile = pCache->getPcbFile( fileName ) )
@ -363,7 +358,7 @@ int main( int argc, char* argv[] )
{ {
auto pBgParts = static_cast<LGB_BGPARTS_ENTRY*>(pEntry.get()); auto pBgParts = static_cast<LGB_BGPARTS_ENTRY*>(pEntry.get());
fileName = pBgParts->collisionFileName; fileName = pBgParts->collisionFileName;
writeOutput( fileName, &pBgParts->header.scale, &pBgParts->header.rotation, pcbTransformModel( fileName, &pBgParts->header.scale, &pBgParts->header.rotation,
&pBgParts->header.translation ); &pBgParts->header.translation );
} }
break; break;
@ -381,7 +376,7 @@ int main( int argc, char* argv[] )
{ {
auto pModel = dynamic_cast< SGB_MODEL_ENTRY* >( pEntry.get() ); auto pModel = dynamic_cast< SGB_MODEL_ENTRY* >( pEntry.get() );
fileName = pModel->collisionFileName; fileName = pModel->collisionFileName;
writeOutput( fileName, &pGimmick->header.scale, &pGimmick->header.rotation, pcbTransformModel( fileName, &pGimmick->header.scale, &pGimmick->header.rotation,
&pGimmick->header.translation, pModel ); &pGimmick->header.translation, pModel );
} }
} }
@ -390,7 +385,7 @@ int main( int argc, char* argv[] )
case LgbEntryType::EventObject: case LgbEntryType::EventObject:
{ {
writeOutput( fileName, &pEntry->header.scale, &pEntry->header.rotation, &pEntry->header.translation ); pcbTransformModel( fileName, &pEntry->header.scale, &pEntry->header.rotation, &pEntry->header.translation );
} }
break; break;
default: default:
@ -402,30 +397,24 @@ int main( int argc, char* argv[] )
} }
} }
//exportMgr.exportZone( exportedZone, ( ExportFileType )exportFileType ); //exportMgr.exportZone( exportedZone, ( ExportFileType )exportFileType );
//std::cout << "[Info] " << "Loaded " << pcbFiles.size() << " PCB Files \n";
std::cout << "[Info] " << "Total Groups " << totalGroups << "\n";
}
std::cout << "[Success] " << "Exported " << zoneName << " in " <<
std::chrono::duration_cast< std::chrono::seconds >( printf( "Exported %s in %u seconds \n",
std::chrono::high_resolution_clock::now() - entryStartTime ).count() << " seconds\n"; zoneName.c_str(),
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::high_resolution_clock::now() - entryStartTime ) );
} }
catch( std::exception& e ) catch( std::exception& e )
{ {
std::cout << "[Error] " << e.what() << std::endl; printf( ( std::string( e.what() ) + "\n" ).c_str() );
std::cout << "[Error] " printf( "Unable to extract collision data.\n" );
<< "Unable to extract collision data.\n" printf( "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\"\n" );
<< std::endl;
std::cout << std::endl;
std::cout << "[Info] " << "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\" " << std::endl;
} }
} }
exportMgr.waitForTasks(); exportMgr.waitForTasks();
std::cout << "\n\n\n"; std::cout << "\n\n\n";
std::cout << "\n\n\n[Success] Finished all tasks in " << printf( "Finished all tasks in %u seconds\n",
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::high_resolution_clock::now() - startTime ).count() std::chrono::duration_cast< std::chrono::seconds >( std::chrono::high_resolution_clock::now() - startTime ).count() );
<< " seconds\n";
getchar(); getchar();

View file

@ -1,5 +1,5 @@
#ifndef OBJ_EXPORTER_H #ifndef NAVMESH_EXPORTER_H
#define OBJ_EXPORTER_H #define NAVMESH_EXPORTER_H
#include <iostream> #include <iostream>
#include <cstdint> #include <cstdint>
@ -10,7 +10,12 @@
#include "exporter.h" #include "exporter.h"
static class ObjExporter : public Exporter #include <recastnavigation/Recast/Include/Recast.h>
#include <recastnavigation/Recast/Include/RecastAlloc.h>
#include <recastnavigation/Detour/Include/DetourNavMesh.h>
#include <recastnavigation/Detour/Include/DetourNavMeshBuilder.h>
class NavmeshExporter : public Exporter
{ {
public: public:
static void exportZone( const ExportedZone& zone ) static void exportZone( const ExportedZone& zone )
@ -20,8 +25,9 @@ public:
auto fileName = zone.name + ".obj"; auto fileName = zone.name + ".obj";
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();
std::cout << ( "Finished exporting " + fileName + " in " + printf( "[Navmesh] Finished exporting %s in %u ms\n",
std::to_string( std::chrono::duration_cast< std::chrono::seconds >( end - start ).count() ) + " seconds\n" ); fileName,
std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() );
} }
static void exportGroup( const std::string& zoneName, const ExportedGroup& group ) static void exportGroup( const std::string& zoneName, const ExportedGroup& group )
@ -32,8 +38,9 @@ public:
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();
std::cout << ( "Finished exporting " + fileName + " in " + printf( "[Navmesh] Finished exporting %s in %u ms\n",
std::to_string( std::chrono::duration_cast< std::chrono::seconds >( end - start ).count() ) + " seconds\n" ); fileName,
std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() );
} }
private: private:
static void exportGroup( const ExportedGroup& group, std::ofstream& of, int& indicesOffset, int& modelCount ) static void exportGroup( const ExportedGroup& group, std::ofstream& of, int& indicesOffset, int& modelCount )

View file

@ -1,22 +1,38 @@
#ifndef OBJ_EXPORTER_H #ifndef OBJ_EXPORTER_H
#define OBJ_EXPORTER_H #define OBJ_EXPORTER_H
#include <chrono>
#include <cstdint> #include <cstdint>
#include <experimental/filesystem>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <chrono>
#include "exporter.h" #include "exporter.h"
class ObjExporter : public Exporter class ObjExporter : public Exporter
{ {
public: public:
static void exportZone( const ExportedZone& zone ) static void exportZone( const ExportedZone& zone )
{ {
static std::string currPath = std::experimental::filesystem::current_path().string();
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
auto fileName = zone.name + ".obj"; auto dir = currPath + "/" + zone.name + "/";
auto fileName = dir + "/" + zone.name + ".obj";
std::error_code e;
if( !std::experimental::filesystem::exists( dir, e ) )
{
if( !std::experimental::filesystem::create_directory( dir, e ) )
{
printf( "Unable to create directory '%s'", ( dir ).c_str() );
return;
}
}
std::ofstream of( fileName, std::ios::trunc ); std::ofstream of( fileName, std::ios::trunc );
int indicesOffset = 0; int indicesOffset = 0;
int meshesCount = 0; int meshesCount = 0;
@ -34,15 +50,29 @@ public:
} }
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();
std::cout << ( "Finished exporting " + fileName + " in " + printf( "[Obj] Finished exporting %s in %u ms\n",
std::to_string( std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() ) + "ms \n" ); fileName,
std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() );
} }
static void exportGroup( const std::string& zoneName, const ExportedGroup& group ) static void exportGroup( const std::string& zoneName, const ExportedGroup& group )
{ {
static std::string currPath = std::experimental::filesystem::current_path().string();
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
auto fileName = zoneName + "_" + group.name + ".obj"; auto dir = currPath + "/" + zoneName + "/";
auto fileName = dir + "/" + group.name + ".obj";
std::error_code e;
if( !std::experimental::filesystem::exists( dir, e ) )
{
if( !std::experimental::filesystem::create_directory( dir, e ) )
{
printf( "Unable to create directory '%s'", ( dir ).c_str() );
return;
}
}
std::ofstream of( fileName, std::ios::trunc ); std::ofstream of( fileName, std::ios::trunc );
int indicesOffset = 0; int indicesOffset = 0;
int modelCount = 0; int modelCount = 0;
@ -57,42 +87,47 @@ public:
} }
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();
std::cout << ( "Finished exporting " + fileName + " in " + printf( "[Obj] Finished exporting %s in %u ms\n",
std::to_string( std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() ) + "ms\n" ); fileName.c_str(),
std::chrono::duration_cast< std::chrono::milliseconds >( end - start ).count() );
} }
private: private:
static void exportGroup( const ExportedGroup& group, std::ofstream& of, int& indicesOffset, int& modelCount ) static void exportGroup( const ExportedGroup& group, std::ofstream& of, int& indicesOffset, int& modelCount )
{ {
int currModelCount = modelCount; int currModelCount = modelCount;
//of << ( "o " + group.name + "_" + std::to_string( currModelCount ) + "\n" ); of << "o " << group.name << '_' << std::to_string( currModelCount ) << '\n';
for( const auto& model : group.models ) for( const auto& model : group.models )
{ {
of << ( "o " + model.second.name + "_" + std::to_string( currModelCount ) + "_" + std::to_string( modelCount++ ) + "\n" ); modelCount++;
of << "o " << model.second.name << '_' << std::to_string( currModelCount ) << '_' << std::to_string( modelCount ) << '\n';
int meshCount = 0; int meshCount = 0;
for( const auto& mesh : model.second.meshes ) for( const auto& mesh : model.second.meshes )
{ {
for( int i = 0; i + 2 < mesh.verts.size(); i += 3 ) for( int i = 0; i < mesh.verts.size(); i += 3 )
{ {
of << ( of << "v " <<
"v " + std::to_string( mesh.verts[ i ] ) + " " + std::to_string( mesh.verts[ i ] ) << ' ' <<
std::to_string( mesh.verts[ i + 1 ] ) + " " + std::to_string( mesh.verts[ i + 1 ] ) << ' ' <<
std::to_string( mesh.verts[ i + 2 ] ) + "\n" std::to_string( mesh.verts[ i + 2 ] ) << '\n';
);
} }
//of << ( "g " + model.second.name + "_" + std::to_string( currModelCount ) + "_" + std::to_string( modelCount ) + "_" + std::to_string( meshCount++ ) + "\n" );
for( int i = 0; i + 2 < mesh.indices.size(); i += 3 ) of << "g " <<
model.second.name << '_' <<
std::to_string( currModelCount ) << '_' << std::to_string( modelCount ) << '_' << std::to_string( meshCount++ ) << '\n';
for( int i = 0; i < mesh.indices.size(); i += 3 )
{ {
of << ( of << "f " <<
"f " + std::to_string( mesh.indices[ i ] + indicesOffset + 1 ) + " " + std::to_string( mesh.indices[ i ] + indicesOffset + 1 ) << ' ' <<
std::to_string( mesh.indices[i + 1] + indicesOffset + 1 ) + " " + std::to_string( mesh.indices[ i + 1 ] + indicesOffset + 1 ) << ' ' +
std::to_string( mesh.indices[i + 2] + indicesOffset + 1 ) + "\n" std::to_string( mesh.indices[ i + 2 ] + indicesOffset + 1 ) << '\n';
);
} }
indicesOffset += mesh.indices.size(); indicesOffset += mesh.verts.size() / 3;
} }
} }
//of.flush();
} }
}; };
#endif // !OBJ_EXPORTER_H #endif // !OBJ_EXPORTER_H

View file

@ -213,7 +213,7 @@ struct SGB_FILE
} }
catch( std::exception& e ) catch( std::exception& e )
{ {
std::cout << e.what() << "\n"; std::cout << ( std::string( e.what() ) + "\n" );
} }
}; };
}; };

View file

@ -13,12 +13,9 @@
class ThreadPool class ThreadPool
{ {
public: public:
ThreadPool( unsigned int numJobs = std::thread::hardware_concurrency() ) ThreadPool()
{ {
for( auto i = 0; i < numJobs; ++i )
{
m_workers.push_back( std::async( std::launch::async, [this]{ run(); } ) );
}
} }
~ThreadPool() ~ThreadPool()
@ -26,6 +23,17 @@ public:
complete(); complete();
} }
void addWorkers( unsigned int num )
{
if( num == 0 )
num = std::thread::hardware_concurrency() - 1;
for( auto i = 0; i < num; ++i )
{
m_workers.push_back( std::async( std::launch::async, [this]{ run(); } ) );
}
}
template< class Func, class Ret = std::result_of_t< Func&() > > template< class Func, class Ret = std::result_of_t< Func&() > >
std::future< Ret > queue( Func&& f ) std::future< Ret > queue( Func&& f )
{ {
@ -50,11 +58,13 @@ public:
bool complete() bool complete()
{ {
std::unique_lock lock( m_mutex ); {
std::scoped_lock lock( m_mutex );
for( auto&& worker : m_workers ) for( auto&& worker : m_workers )
{ {
m_pendingJobs.push_back( {} ); m_pendingJobs.push_back( {} );
} }
}
m_cv.notify_all(); m_cv.notify_all();
m_workers.clear(); m_workers.clear();
return true; return true;